Fix no newlines warnings. Patch by Peter Oberndorfer
[kdevelopdvcssupport.git] / sublime / controller.cpp
blobe0799963650a50d089a74b709edd2de71f1fc56a
1 /***************************************************************************
2 * Copyright 2006-2007 Alexander Dymo <adymo@kdevelop.org> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU Library General Public License as *
6 * published by the Free Software Foundation; either version 2 of the *
7 * License, or (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU Library General Public *
15 * License along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
19 #include "controller.h"
21 #include <QMap>
22 #include <QList>
23 #include <QEvent>
24 #include <QMouseEvent>
25 #include <QApplication>
27 #include <kdebug.h>
29 #include "area.h"
30 #include "view.h"
31 #include "document.h"
32 #include "mainwindow.h"
34 namespace Sublime {
36 struct WidgetFinder {
37 WidgetFinder(QWidget *_w) :w(_w), view(0) {}
38 Area::WalkerMode operator()(AreaIndex *index)
40 foreach (View *v, index->views())
42 if (v->hasWidget() && (v->widget() == w))
44 view = v;
45 return Area::StopWalker;
48 return Area::ContinueWalker;
51 QWidget *w;
52 View *view;
55 struct ToolWidgetFinder {
56 ToolWidgetFinder(QWidget *_w) :w(_w), view(0) {}
57 Area::WalkerMode operator()(View *v, Sublime::Position /*position*/)
59 if (v->hasWidget() && (v->widget() == w))
61 view = v;
62 return Area::StopWalker;
64 return Area::ContinueWalker;
67 QWidget *w;
68 View *view;
72 // struct ControllerPrivate
74 struct ControllerPrivate {
75 ControllerPrivate()
79 void removeArea(QObject *obj)
81 areas.removeAll(reinterpret_cast<Area*>(obj));
84 void removeDocument(QObject *obj)
86 documents.removeAll(reinterpret_cast<Document*>(obj));
89 QList<Document*> documents;
90 QList<Area*> areas;
91 QList<Area*> allAreas;
92 QMap<QString, Area*> namedAreas;
93 // FIXME: remove this.
94 QMap<Area*, MainWindow*> shownAreas;
95 QList<MainWindow*> controlledWindows;
96 QVector< QList<Area*> > mainWindowAreas;
101 // class Controller
103 Controller::Controller(QObject *parent)
104 :QObject(parent), MainWindowOperator(), d( new ControllerPrivate() )
106 init();
109 void Controller::init()
112 qApp->installEventFilter(this);
115 Controller::~Controller()
117 // FIXME:
118 // foreach (MainWindow *w, d->controlledWindows)
119 // delete w;
120 delete d;
123 void Controller::showArea(Area *area, MainWindow *mainWindow)
125 Area *areaToShow = 0;
126 //if the area is already shown in another mainwindow then we need to clone it
127 if (d->shownAreas.contains(area) && (mainWindow != d->shownAreas[area]))
128 areaToShow = new Area(*area);
129 else
130 areaToShow = area;
131 d->shownAreas[areaToShow] = mainWindow;
133 showAreaInternal(areaToShow, mainWindow);
136 void Controller::showAreaInternal(Area* area, MainWindow *mainWindow)
138 /* Disconnect the previous area. We really don't want to mess with
139 main window if an area not visible now is modified. Further,
140 if showAreaInternal is called with the same area as is current
141 now, we don't want to connect the same signals twice. */
142 if (mainWindow->area())
143 disconnect(mainWindow->area(), 0, mainWindow, 0);
144 MainWindowOperator::setArea(mainWindow, area);
145 connect(area, SIGNAL(viewAdded(Sublime::AreaIndex*, Sublime::View*)),
146 mainWindow, SLOT(viewAdded(Sublime::AreaIndex*, Sublime::View*)));
147 connect(area, SIGNAL(requestToolViewRaise(Sublime::View*)),
148 mainWindow, SLOT(raiseToolView(Sublime::View*)));
149 connect(area, SIGNAL(aboutToRemoveView(Sublime::AreaIndex*, Sublime::View*)),
150 mainWindow, SLOT(aboutToRemoveView(Sublime::AreaIndex*, Sublime::View*)));
151 connect(area, SIGNAL(toolViewAdded(Sublime::View*, Sublime::Position)),
152 mainWindow, SLOT(toolViewAdded(Sublime::View*, Sublime::Position)));
153 connect(area, SIGNAL(aboutToRemoveToolView(Sublime::View*, Sublime::Position)),
154 mainWindow, SLOT(aboutToRemoveToolView(Sublime::View*, Sublime::Position)));
155 connect(area, SIGNAL(toolViewMoved(Sublime::View*, Sublime::Position)),
156 mainWindow, SLOT(toolViewMoved(Sublime::View*, Sublime::Position)));
159 void Controller::showArea(const QString& areaTypeId, MainWindow *mainWindow)
161 int index = d->controlledWindows.indexOf(mainWindow);
162 Q_ASSERT(index != -1);
164 Area* area = NULL;
165 foreach (Area* a, d->mainWindowAreas[index])
167 kDebug() << "Object name: " << a->objectName() << " id "
168 << areaTypeId;
169 if (a->objectName() == areaTypeId)
171 area = a;
172 break;
175 Q_ASSERT (area);
177 showAreaInternal(area, mainWindow);
180 void Controller::resetCurrentArea(MainWindow *mainWindow)
182 QString id = mainWindow->area()->objectName();
184 int areaIndex = 0;
185 Area* def = NULL;
186 foreach (Area* a, d->areas) {
187 if (a->objectName() == id)
189 def = a;
190 break;
192 ++areaIndex;
194 Q_ASSERT(def);
196 int index = d->controlledWindows.indexOf(mainWindow);
197 Q_ASSERT(index != -1);
199 Area* prev = d->mainWindowAreas[index][areaIndex];
200 d->mainWindowAreas[index][areaIndex] = new Area(*def);
201 showAreaInternal(d->mainWindowAreas[index][areaIndex], mainWindow);
202 delete prev;
205 const QList<Area*> &Controller::defaultAreas() const
207 return d->areas;
210 const QList<Area*> &Controller::areas(int mainWindow) const
212 return d->mainWindowAreas[mainWindow];
215 const QList<Area*> &Controller::allAreas() const
217 return d->allAreas;
220 const QList<Document*> &Controller::documents() const
222 return d->documents;
225 void Controller::addDefaultArea(Area *area)
227 d->areas.append(area);
228 d->allAreas.append(area);
229 d->namedAreas[area->objectName()] = area;
232 void Controller::addMainWindow(MainWindow* mainWindow)
234 Q_ASSERT (!d->controlledWindows.contains(mainWindow));
235 d->controlledWindows << mainWindow;
236 d->mainWindowAreas.resize(d->controlledWindows.size());
237 int index = d->controlledWindows.size()-1;
239 foreach (Area* area, defaultAreas())
241 Area *na = new Area(*area);
242 d->allAreas.append(na);
243 d->mainWindowAreas[index].push_back(na);
245 showAreaInternal(d->mainWindowAreas[index][0], mainWindow);
248 void Controller::addDocument(Document *document)
250 d->documents.append(document);
253 void Controller::areaReleased()
255 MainWindow *w = reinterpret_cast<Sublime::MainWindow*>(sender());
256 kDebug() << "marking areas as mainwindow-free";
257 foreach (Area *area, d->shownAreas.keys(w))
259 kDebug() << "" << area->objectName();
260 areaReleased(area);
261 disconnect(area, 0, w, 0);
265 void Controller::areaReleased(Sublime::Area *area)
267 d->controlledWindows.removeAll(d->shownAreas[area]);
268 d->shownAreas.remove(area);
269 d->namedAreas.remove(area->objectName());
272 Area *Controller::defaultArea(const QString &id)
274 return d->namedAreas[id];
277 Area *Controller::area(int mainWindow, const QString& id)
279 foreach (Area* area, areas(mainWindow))
281 if (area->objectName() == id)
282 return area;
284 return 0;
287 /*We need this to catch activation of views and toolviews
288 so that we can always tell what view and toolview is active.
289 "Active" doesn't mean focused. It means that it is focused now
290 or was focused before and no other view/toolview wasn't focused
291 after that."*/
292 //implementation is based upon KParts::PartManager::eventFilter
293 bool Controller::eventFilter(QObject *obj, QEvent *ev)
296 if (ev->type() != QEvent::MouseButtonPress &&
297 ev->type() != QEvent::MouseButtonDblClick &&
298 ev->type() != QEvent::FocusIn)
299 return false;
301 //not a widget? - return
302 if (!obj->isWidgetType())
303 return false;
305 //is dialog or popup? - return
306 QWidget *w = static_cast<QWidget*>(obj);
307 if (((w->windowFlags().testFlag(Qt::Dialog)) && w->isModal()) ||
308 (w->windowFlags().testFlag(Qt::Popup)) || (w->windowFlags().testFlag(Qt::Tool)))
309 return false;
311 //not a mouse button that should activate the widget? - return
312 QMouseEvent *mev = 0;
313 if (ev->type() == QEvent::MouseButtonPress || ev->type() == QEvent::MouseButtonDblClick)
315 mev = static_cast<QMouseEvent*>(ev);
316 int activationButtonMask = Qt::LeftButton | Qt::MidButton | Qt::RightButton;
317 if ((mev->button() & activationButtonMask) == 0)
318 return false;
321 while (w)
323 //not inside sublime mainwindow
324 MainWindow *mw = qobject_cast<Sublime::MainWindow*>(w->topLevelWidget());
325 if (!mw || !d->controlledWindows.contains(mw))
326 return false;
328 Area *area = mw->area();
330 ///@todo adymo: this is extra slow - optimize
331 //find this widget in views
332 WidgetFinder widgetFinder(w);
333 area->walkViews(widgetFinder, area->rootIndex());
334 if (widgetFinder.view && widgetFinder.view != mw->activeView())
336 setActiveView(mw, widgetFinder.view);
337 ///@todo adymo: shall we filter out the event?
338 return false;
341 //find this widget in toolviews
342 ToolWidgetFinder toolFinder(w);
343 area->walkToolViews(toolFinder, Sublime::AllPositions);
344 if (toolFinder.view && toolFinder.view != mw->activeToolView())
346 setActiveToolView(mw, toolFinder.view);
347 ///@todo adymo: shall we filter out the event?
348 return false;
351 w = w->parentWidget();
354 return false;
357 const QList< MainWindow * > & Controller::mainWindows() const
359 return d->controlledWindows;
363 void Controller::notifyToolViewRemoved(Sublime::View *view, Sublime::Position)
365 emit aboutToRemoveToolView(view);
368 void Controller::notifyToolViewAdded(Sublime::View *view, Sublime::Position)
370 emit toolViewAdded(view);
373 void Controller::notifyViewRemoved(Sublime::AreaIndex*, Sublime::View *view)
375 emit aboutToRemoveView(view);
378 void Controller::notifyViewAdded(Sublime::AreaIndex*, Sublime::View *view)
380 emit viewAdded(view);
383 void Controller::setStatusIcon(Document * document, const QIcon & icon)
385 foreach (MainWindow* mw, mainWindows())
386 if (mw->area())
387 foreach (View* view, mw->area()->views())
388 if (view->document() == document)
389 MainWindowOperator::setStatusIcon(mw, view, icon);
394 #include "controller.moc"