• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • KDevelop Platform Libraries
  • Sitemap
  • Contact Us
 

sublime

controller.cpp

00001 /***************************************************************************
00002  *   Copyright 2006-2007 Alexander Dymo  <adymo@kdevelop.org>       *
00003  *                                                                         *
00004  *   This program is free software; you can redistribute it and/or modify  *
00005  *   it under the terms of the GNU Library General Public License as       *
00006  *   published by the Free Software Foundation; either version 2 of the    *
00007  *   License, or (at your option) any later version.                       *
00008  *                                                                         *
00009  *   This program is distributed in the hope that it will be useful,       *
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00012  *   GNU General Public License for more details.                          *
00013  *                                                                         *
00014  *   You should have received a copy of the GNU Library General Public     *
00015  *   License along with this program; if not, write to the                 *
00016  *   Free Software Foundation, Inc.,                                       *
00017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
00018  ***************************************************************************/
00019 #include "controller.h"
00020 
00021 #include <QMap>
00022 #include <QList>
00023 #include <QEvent>
00024 #include <QMouseEvent>
00025 #include <QApplication>
00026 
00027 #include <kdebug.h>
00028 
00029 #include "area.h"
00030 #include "view.h"
00031 #include "document.h"
00032 #include "mainwindow.h"
00033 
00034 namespace Sublime {
00035 
00036 struct WidgetFinder {
00037     WidgetFinder(QWidget *_w) :w(_w), view(0) {}
00038     Area::WalkerMode operator()(AreaIndex *index)
00039     {
00040         foreach (View *v, index->views())
00041         {
00042             if (v->hasWidget() && (v->widget() == w))
00043             {
00044                 view = v;
00045                 return Area::StopWalker;
00046             }
00047         }
00048         return Area::ContinueWalker;
00049     }
00050 
00051     QWidget *w;
00052     View *view;
00053 };
00054 
00055 struct ToolWidgetFinder {
00056     ToolWidgetFinder(QWidget *_w) :w(_w), view(0) {}
00057     Area::WalkerMode operator()(View *v, Sublime::Position /*position*/)
00058     {
00059         if (v->hasWidget() && (v->widget() == w))
00060         {
00061             view = v;
00062             return Area::StopWalker;
00063         }
00064         return Area::ContinueWalker;
00065     }
00066 
00067     QWidget *w;
00068     View *view;
00069 };
00070 
00071 
00072 // struct ControllerPrivate
00073 
00074 struct ControllerPrivate {
00075     ControllerPrivate()
00076     {
00077     }
00078 
00079     void removeArea(QObject *obj)
00080     {
00081         areas.removeAll(reinterpret_cast<Area*>(obj));
00082     }
00083 
00084     void removeDocument(QObject *obj)
00085     {
00086         documents.removeAll(reinterpret_cast<Document*>(obj));
00087     }
00088 
00089     QList<Document*> documents;
00090     QList<Area*> areas;
00091     QList<Area*> allAreas;
00092     QMap<QString, Area*> namedAreas;
00093     // FIXME: remove this.
00094     QMap<Area*, MainWindow*> shownAreas;
00095     QList<MainWindow*> controlledWindows;
00096     QVector< QList<Area*> > mainWindowAreas;
00097 };
00098 
00099 
00100 
00101 // class Controller
00102 
00103 Controller::Controller(QObject *parent)
00104     :QObject(parent), MainWindowOperator(), d( new ControllerPrivate() )
00105 {
00106     init();
00107 }
00108 
00109 void Controller::init()
00110 {
00111 
00112     qApp->installEventFilter(this);
00113 }
00114 
00115 Controller::~Controller()
00116 {
00117     // FIXME:
00118 //    foreach (MainWindow *w, d->controlledWindows)
00119 //        delete w;
00120     delete d;
00121 }
00122 
00123 void Controller::showArea(Area *area, MainWindow *mainWindow)
00124 {
00125     Area *areaToShow = 0;
00126     //if the area is already shown in another mainwindow then we need to clone it
00127     if (d->shownAreas.contains(area) && (mainWindow != d->shownAreas[area]))
00128         areaToShow = new Area(*area);
00129     else
00130         areaToShow = area;
00131     d->shownAreas[areaToShow] = mainWindow;
00132 
00133     showAreaInternal(areaToShow, mainWindow);
00134 }
00135 
00136 void Controller::showAreaInternal(Area* area, MainWindow *mainWindow)
00137 {
00138     /* Disconnect the previous area.  We really don't want to mess with
00139        main window if an area not visible now is modified.  Further,
00140        if showAreaInternal is called with the same area as is current
00141        now, we don't want to connect the same signals twice.  */
00142     if (mainWindow->area())
00143         disconnect(mainWindow->area(), 0, mainWindow, 0);
00144     MainWindowOperator::setArea(mainWindow, area);
00145     connect(area, SIGNAL(viewAdded(Sublime::AreaIndex*, Sublime::View*)),
00146         mainWindow, SLOT(viewAdded(Sublime::AreaIndex*, Sublime::View*)));
00147     connect(area, SIGNAL(requestToolViewRaise(Sublime::View*)),
00148         mainWindow, SLOT(raiseToolView(Sublime::View*)));
00149     connect(area, SIGNAL(aboutToRemoveView(Sublime::AreaIndex*, Sublime::View*)),
00150         mainWindow, SLOT(aboutToRemoveView(Sublime::AreaIndex*, Sublime::View*)));
00151     connect(area, SIGNAL(toolViewAdded(Sublime::View*, Sublime::Position)),
00152         mainWindow, SLOT(toolViewAdded(Sublime::View*, Sublime::Position)));
00153     connect(area, SIGNAL(aboutToRemoveToolView(Sublime::View*, Sublime::Position)),
00154         mainWindow, SLOT(aboutToRemoveToolView(Sublime::View*, Sublime::Position)));
00155     connect(area, SIGNAL(toolViewMoved(Sublime::View*, Sublime::Position)),
00156         mainWindow, SLOT(toolViewMoved(Sublime::View*, Sublime::Position)));
00157 }
00158 
00159 void Controller::showArea(const QString& areaTypeId, MainWindow *mainWindow)
00160 {
00161     int index = d->controlledWindows.indexOf(mainWindow);
00162     Q_ASSERT(index != -1);
00163 
00164     Area* area = NULL;
00165     foreach (Area* a, d->mainWindowAreas[index])
00166     {
00167         kDebug() << "Object name: " << a->objectName() << " id "
00168                      << areaTypeId;
00169         if (a->objectName() == areaTypeId)
00170         {
00171             area = a;
00172             break;
00173         }
00174     }
00175     Q_ASSERT (area);
00176 
00177     showAreaInternal(area, mainWindow);
00178 }
00179 
00180 void Controller::resetCurrentArea(MainWindow *mainWindow)
00181 {
00182     QString id = mainWindow->area()->objectName();
00183 
00184     int areaIndex = 0;
00185     Area* def = NULL;
00186     foreach (Area* a, d->areas) {
00187         if (a->objectName() == id)
00188         {
00189             def = a;
00190             break;
00191         }
00192         ++areaIndex;
00193     }
00194     Q_ASSERT(def);
00195 
00196     int index = d->controlledWindows.indexOf(mainWindow);
00197     Q_ASSERT(index != -1);
00198 
00199     Area* prev = d->mainWindowAreas[index][areaIndex];
00200     d->mainWindowAreas[index][areaIndex] = new Area(*def);
00201     showAreaInternal(d->mainWindowAreas[index][areaIndex], mainWindow);
00202     delete prev;
00203 }
00204 
00205 const QList<Area*> &Controller::defaultAreas() const
00206 {
00207     return d->areas;
00208 }
00209 
00210 const QList<Area*> &Controller::areas(int mainWindow) const
00211 {
00212     return d->mainWindowAreas[mainWindow];
00213 }
00214 
00215 const QList<Area*> &Controller::allAreas() const
00216 {
00217     return d->allAreas;
00218 }
00219 
00220 const QList<Document*> &Controller::documents() const
00221 {
00222     return d->documents;
00223 }
00224 
00225 void Controller::addDefaultArea(Area *area)
00226 {
00227     d->areas.append(area);
00228     d->allAreas.append(area);
00229     d->namedAreas[area->objectName()] = area;
00230 }
00231 
00232 void Controller::addMainWindow(MainWindow* mainWindow)
00233 {
00234     Q_ASSERT (!d->controlledWindows.contains(mainWindow));
00235     d->controlledWindows << mainWindow;
00236     d->mainWindowAreas.resize(d->controlledWindows.size());
00237     int index = d->controlledWindows.size()-1;
00238 
00239     foreach (Area* area, defaultAreas())
00240     {
00241         Area *na = new Area(*area);
00242         d->allAreas.append(na);
00243         d->mainWindowAreas[index].push_back(na);
00244     }
00245     showAreaInternal(d->mainWindowAreas[index][0], mainWindow);
00246 }
00247 
00248 void Controller::addDocument(Document *document)
00249 {
00250     d->documents.append(document);
00251 }
00252 
00253 void Controller::areaReleased()
00254 {
00255     MainWindow *w = reinterpret_cast<Sublime::MainWindow*>(sender());
00256     kDebug() << "marking areas as mainwindow-free";
00257     foreach (Area *area, d->shownAreas.keys(w))
00258     {
00259         kDebug() << "" << area->objectName();
00260         areaReleased(area);
00261         disconnect(area, 0, w, 0);
00262     }
00263 }
00264 
00265 void Controller::areaReleased(Sublime::Area *area)
00266 {
00267     d->controlledWindows.removeAll(d->shownAreas[area]);
00268     d->shownAreas.remove(area);
00269     d->namedAreas.remove(area->objectName());
00270 }
00271 
00272 Area *Controller::defaultArea(const QString &id)
00273 {
00274     return d->namedAreas[id];
00275 }
00276 
00277 Area *Controller::area(int mainWindow, const QString& id)
00278 {
00279     foreach (Area* area, areas(mainWindow))
00280     {
00281         if (area->objectName() == id)
00282             return area;
00283     }
00284     return 0;
00285 }
00286 
00287 /*We need this to catch activation of views and toolviews
00288 so that we can always tell what view and toolview is active.
00289 "Active" doesn't mean focused. It means that it is focused now
00290 or was focused before and no other view/toolview wasn't focused
00291 after that."*/
00292 //implementation is based upon KParts::PartManager::eventFilter
00293 bool Controller::eventFilter(QObject *obj, QEvent *ev)
00294 {
00295 
00296     if (ev->type() != QEvent::MouseButtonPress &&
00297         ev->type() != QEvent::MouseButtonDblClick &&
00298         ev->type() != QEvent::FocusIn)
00299         return false;
00300 
00301     //not a widget? - return
00302     if (!obj->isWidgetType())
00303         return false;
00304 
00305     //is dialog or popup? - return
00306     QWidget *w = static_cast<QWidget*>(obj);
00307     if (((w->windowFlags().testFlag(Qt::Dialog)) && w->isModal()) ||
00308             (w->windowFlags().testFlag(Qt::Popup)) || (w->windowFlags().testFlag(Qt::Tool)))
00309         return false;
00310 
00311     //not a mouse button that should activate the widget? - return
00312     QMouseEvent *mev = 0;
00313     if (ev->type() == QEvent::MouseButtonPress || ev->type() == QEvent::MouseButtonDblClick)
00314     {
00315         mev = static_cast<QMouseEvent*>(ev);
00316         int activationButtonMask = Qt::LeftButton | Qt::MidButton | Qt::RightButton;
00317         if ((mev->button() & activationButtonMask) == 0)
00318             return false;
00319     }
00320 
00321     while (w)
00322     {
00323         //not inside sublime mainwindow
00324         MainWindow *mw = qobject_cast<Sublime::MainWindow*>(w->topLevelWidget());
00325         if (!mw || !d->controlledWindows.contains(mw))
00326             return false;
00327 
00328         Area *area = mw->area();
00329 
00331         //find this widget in views
00332         WidgetFinder widgetFinder(w);
00333         area->walkViews(widgetFinder, area->rootIndex());
00334         if (widgetFinder.view && widgetFinder.view != mw->activeView())
00335         {
00336             setActiveView(mw, widgetFinder.view);
00338             return false;
00339         }
00340 
00341         //find this widget in toolviews
00342         ToolWidgetFinder toolFinder(w);
00343         area->walkToolViews(toolFinder, Sublime::AllPositions);
00344         if (toolFinder.view && toolFinder.view != mw->activeToolView())
00345         {
00346             setActiveToolView(mw, toolFinder.view);
00348             return false;
00349         }
00350 
00351         w = w->parentWidget();
00352     }
00353 
00354     return false;
00355 }
00356 
00357 const QList< MainWindow * > & Controller::mainWindows() const
00358 {
00359     return d->controlledWindows;
00360 }
00361 
00362 
00363 void Controller::notifyToolViewRemoved(Sublime::View *view, Sublime::Position)
00364 {
00365     emit aboutToRemoveToolView(view);
00366 }
00367 
00368 void Controller::notifyToolViewAdded(Sublime::View *view, Sublime::Position)
00369 {
00370     emit toolViewAdded(view);
00371 }
00372 
00373 void Controller::notifyViewRemoved(Sublime::AreaIndex*, Sublime::View *view)
00374 {
00375     emit aboutToRemoveView(view);
00376 }
00377 
00378 void Controller::notifyViewAdded(Sublime::AreaIndex*, Sublime::View *view)
00379 {
00380     emit viewAdded(view);
00381 }
00382 
00383 void Controller::setStatusIcon(Document * document, const QIcon & icon)
00384 {
00385     foreach (MainWindow* mw, mainWindows())
00386         if (mw->area())
00387             foreach (View* view, mw->area()->views())
00388                 if (view->document() == document)
00389                     MainWindowOperator::setStatusIcon(mw, view, icon);
00390 }
00391 
00392 }
00393 
00394 #include "controller.moc"

sublime

Skip menu "sublime"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

KDevelop Platform Libraries

Skip menu "KDevelop Platform Libraries"
  • interfaces
  • language
  •   duchain
  •   editor
  • outputview
  • project
  • shell
  • sublime
  • util
  • vcs
Generated for KDevelop Platform Libraries by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal