diff --git a/sublime/mainwindow.cpp b/sublime/mainwindow.cpp index 38c7d72450..57ef1c297a 100644 --- a/sublime/mainwindow.cpp +++ b/sublime/mainwindow.cpp @@ -1,441 +1,441 @@ /*************************************************************************** * Copyright 2006-2007 Alexander Dymo * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "mainwindow.h" #include "mainwindow_p.h" #include #include #include #include #include #include #include #include #include "area.h" #include "view.h" #include "controller.h" #include "container.h" #include "idealbuttonbarwidget.h" #include "idealcontroller.h" #include "holdupdates.h" #include "sublimedebug.h" Q_LOGGING_CATEGORY(SUBLIME, "kdevplatform.sublime") namespace Sublime { MainWindow::MainWindow(Controller *controller, Qt::WindowFlags flags) : KParts::MainWindow(nullptr, flags), d(new MainWindowPrivate(this, controller)) { connect(this, &MainWindow::destroyed, controller, static_cast(&Controller::areaReleased)); loadGeometry(KSharedConfig::openConfig()->group("Main Window")); // don't allow AllowTabbedDocks - that doesn't make sense for "ideal" UI setDockOptions(QMainWindow::AnimatedDocks); } bool MainWindow::containsView(View* view) const { foreach(Area* area, areas()) if(area->views().contains(view)) return true; return false; } QList< Area* > MainWindow::areas() const { QList< Area* > areas = controller()->areas(const_cast(this)); if(areas.isEmpty()) areas = controller()->defaultAreas(); return areas; } MainWindow::~MainWindow() { qCDebug(SUBLIME) << "destroying mainwindow"; delete d; } void MainWindow::reconstructViews(QList topViews) { d->reconstructViews(topViews); } QList MainWindow::getTopViews() const { QList topViews; foreach(View* view, d->area->views()) { if(view->hasWidget()) { QWidget* widget = view->widget(); if(widget->parent() && widget->parent()->parent()) { Container* container = qobject_cast(widget->parent()->parent()); if(container->currentWidget() == widget) topViews << view; } } } return topViews; } QList MainWindow::containers() const { return d->viewContainers.values(); } void MainWindow::setArea(Area *area) { if (d->area) disconnect(d->area, nullptr, d, nullptr); bool differentArea = (area != d->area); /* All views will be removed from dock area now. However, this does not mean those are removed from area, so prevent slotDockShown from recording those views as no longer shown in the area. */ d->ignoreDockShown = true; if (d->autoAreaSettingsSave && differentArea) saveSettings(); HoldUpdates hu(this); if (d->area) clearArea(); d->area = area; d->reconstruct(); if(d->area->activeView()) activateView(d->area->activeView()); else d->activateFirstVisibleView(); initializeStatusBar(); emit areaChanged(area); d->ignoreDockShown = false; hu.stop(); loadSettings(); connect(area, &Area::viewAdded, d, &MainWindowPrivate::viewAdded); connect(area, &Area::viewRemoved, d, &MainWindowPrivate::viewRemovedInternal); connect(area, &Area::requestToolViewRaise, d, &MainWindowPrivate::raiseToolView); connect(area, &Area::aboutToRemoveView, d, &MainWindowPrivate::aboutToRemoveView); connect(area, &Area::toolViewAdded, d, &MainWindowPrivate::toolViewAdded); connect(area, &Area::aboutToRemoveToolView, d, &MainWindowPrivate::aboutToRemoveToolView); connect(area, &Area::toolViewMoved, d, &MainWindowPrivate::toolViewMoved); } void MainWindow::initializeStatusBar() { //nothing here, reimplement in the subclasses if you want to have status bar //inside the bottom toolview buttons row } void MainWindow::resizeEvent(QResizeEvent* event) { return KParts::MainWindow::resizeEvent(event); } void MainWindow::clearArea() { emit areaCleared(d->area); d->clearArea(); } QList MainWindow::toolDocks() const { return d->docks; } Area *Sublime::MainWindow::area() const { return d->area; } Controller *MainWindow::controller() const { return d->controller; } View *MainWindow::activeView() const { return d->activeView; } View *MainWindow::activeToolView() const { return d->activeToolView; } void MainWindow::activateView(Sublime::View* view, bool focus) { if (!d->viewContainers.contains(view)) return; d->viewContainers[view]->setCurrentWidget(view->widget()); setActiveView(view, focus); d->area->setActiveView(view); } void MainWindow::setActiveView(View *view, bool focus) { View* oldActiveView = d->activeView; d->activeView = view; if (focus && view && !view->widget()->hasFocus()) view->widget()->setFocus(); if(d->activeView != oldActiveView) emit activeViewChanged(view); } void Sublime::MainWindow::setActiveToolView(View *view) { d->activeToolView = view; emit activeToolViewChanged(view); } void MainWindow::saveSettings() { d->disableConcentrationMode(); QString group = QStringLiteral("MainWindow"); if (area()) group += '_' + area()->objectName(); KConfigGroup cg = KSharedConfig::openConfig()->group(group); /* This will try to save window size, too. But it's OK, since we won't use this information when loading. */ saveMainWindowSettings(cg); //debugToolBar visibility is stored separately to allow a area dependent default value foreach (KToolBar* toolbar, toolBars()) { if (toolbar->objectName() == QLatin1String("debugToolBar")) { cg.writeEntry("debugToolBarVisibility", toolbar->isVisibleTo(this)); } } d->idealController->leftBarWidget->saveOrderSettings(cg); d->idealController->bottomBarWidget->saveOrderSettings(cg); d->idealController->rightBarWidget->saveOrderSettings(cg); cg.sync(); } void MainWindow::loadSettings() { HoldUpdates hu(this); qCDebug(SUBLIME) << "loading settings for " << (area() ? area()->objectName() : QLatin1String("")); QString group = QStringLiteral("MainWindow"); if (area()) group += '_' + area()->objectName(); KConfigGroup cg = KSharedConfig::openConfig()->group(group); // What follows is copy-paste from applyMainWindowSettings. Unfortunately, // we don't really want that one to try restoring window size, and we also // cannot stop it from doing that in any clean way. QStatusBar* sb = findChild(); if (sb) { QString entry = cg.readEntry("StatusBar", "Enabled"); if ( entry == QLatin1String("Disabled") ) sb->hide(); else sb->show(); } QMenuBar* mb = findChild(); if (mb) { QString entry = cg.readEntry ("MenuBar", "Enabled"); if ( entry == QLatin1String("Disabled") ) mb->hide(); else mb->show(); } if ( !autoSaveSettings() || cg.name() == autoSaveGroup() ) { QString entry = cg.readEntry ("ToolBarsMovable", "Enabled"); if ( entry == QLatin1String("Disabled") ) KToolBar::setToolBarsLocked(true); else KToolBar::setToolBarsLocked(false); } // Utilise the QMainWindow::restoreState() functionality // Note that we're fixing KMainWindow bug here -- the original // code has this fragment above restoring toolbar properties. // As result, each save/restore would move the toolbar a bit to // the left. if (cg.hasKey("State")) { QByteArray state; state = cg.readEntry("State", state); state = QByteArray::fromBase64(state); // One day will need to load the version number, but for now, assume 0 restoreState(state); } else { // If there's no state we use a default size of 870x650 // Resize only when showing "code" area. If we do that for other areas, // then we'll hit bug https://bugs.kde.org/show_bug.cgi?id=207990 // TODO: adymo: this is more like a hack, we need a proper first-start initialization if (area() && area()->objectName() == QLatin1String("code")) resize(870,650); } int n = 1; // Toolbar counter. toolbars are counted from 1, foreach (KToolBar* toolbar, toolBars()) { QString group(QStringLiteral("Toolbar")); // Give a number to the toolbar, but prefer a name if there is one, // because there's no real guarantee on the ordering of toolbars group += (toolbar->objectName().isEmpty() ? QString::number(n) : QStringLiteral(" ")+toolbar->objectName()); KConfigGroup toolbarGroup(&cg, group); toolbar->applySettings(toolbarGroup); if (toolbar->objectName() == QLatin1String("debugToolBar")) { //debugToolBar visibility is stored separately to allow a area dependent default value bool visibility = cg.readEntry("debugToolBarVisibility", area()->objectName() == QLatin1String("debug")); toolbar->setVisible(visibility); } n++; } const bool tabBarHidden = !Container::configTabBarVisible(); foreach (Container *container, d->viewContainers) { container->setTabBarHidden(tabBarHidden); } hu.stop(); d->idealController->leftBarWidget->loadOrderSettings(cg); d->idealController->bottomBarWidget->loadOrderSettings(cg); d->idealController->rightBarWidget->loadOrderSettings(cg); emit settingsLoaded(); d->disableConcentrationMode(); } bool MainWindow::queryClose() { // saveSettings(); KConfigGroup config(KSharedConfig::openConfig(), "Main Window"); saveGeometry(config); config.sync(); return KParts::MainWindow::queryClose(); } QString MainWindow::screenKey() const { const int scnum = QApplication::desktop()->screenNumber(parentWidget()); QRect desk = QApplication::desktop()->screenGeometry(scnum); // if the desktop is virtual then use virtual screen size if (QApplication::desktop()->isVirtualDesktop()) desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen()); return QStringLiteral("Desktop %1 %2") .arg(desk.width()).arg(desk.height()); } void MainWindow::saveGeometry(KConfigGroup &config) { config.writeEntry(screenKey(), geometry()); } void MainWindow::loadGeometry(const KConfigGroup &config) { // The below code, essentially, is copy-paste from // KMainWindow::restoreWindowSize. Right now, that code is buggy, // as per http://permalink.gmane.org/gmane.comp.kde.devel.core/52423 // so we implement a less theoretically correct, but working, version // below QRect g = config.readEntry(screenKey(), QRect()); if (!g.isEmpty()) setGeometry(g); } void MainWindow::enableAreaSettingsSave() { d->autoAreaSettingsSave = true; } -QWidget *MainWindow::statusBarLocation() +QWidget *MainWindow::statusBarLocation() const { return d->idealController->statusBarLocation(); } void MainWindow::setTabBarLeftCornerWidget(QWidget* widget) { d->setTabBarLeftCornerWidget(widget); } void MainWindow::tabDoubleClicked(View* view) { Q_UNUSED(view); d->toggleDocksShown(); } void MainWindow::tabContextMenuRequested(View* , QMenu* ) { // do nothing } void MainWindow::tabToolTipRequested(View*, Container*, int) { // do nothing } void MainWindow::newTabRequested() { } void MainWindow::dockBarContextMenuRequested(Qt::DockWidgetArea , const QPoint& ) { // do nothing } View* MainWindow::viewForPosition(QPoint globalPos) const { foreach(Container* container, d->viewContainers) { QRect globalGeom = QRect(container->mapToGlobal(QPoint(0,0)), container->mapToGlobal(QPoint(container->width(), container->height()))); if(globalGeom.contains(globalPos)) { return d->widgetToView[container->currentWidget()]; } } return nullptr; } void MainWindow::setBackgroundCentralWidget(QWidget* w) { d->setBackgroundCentralWidget(w); } } #include "moc_mainwindow.cpp" diff --git a/sublime/mainwindow.h b/sublime/mainwindow.h index 46f600edb7..cbad74d51c 100644 --- a/sublime/mainwindow.h +++ b/sublime/mainwindow.h @@ -1,182 +1,181 @@ /*************************************************************************** * Copyright 2006-2007 Alexander Dymo * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KDEVPLATFORM_SUBLIMEMAINWINDOW_H #define KDEVPLATFORM_SUBLIMEMAINWINDOW_H #include #include #include #include "sublimeexport.h" class QDockWidget; namespace Sublime { class Container; class Area; class View; class Controller; class MainWindowOperator; /** @short Sublime Main Window The area-enabled mainwindow to show Sublime views and toolviews. To use, a controller and constructed areas are necessary: @code MainWindow w(controller); controller->showArea(area, &w); @endcode */ class KDEVPLATFORMSUBLIME_EXPORT MainWindow: public KParts::MainWindow { Q_OBJECT public: /**Creates a mainwindow and adds it to the controller.*/ explicit MainWindow(Controller *controller, Qt::WindowFlags flags = KDE_DEFAULT_WINDOWFLAGS); ~MainWindow() override; /**@return the list of dockwidgets that contain area's toolviews.*/ QList toolDocks() const; /**@return area which mainwindow currently shows or 0 if no area has been set.*/ Area *area() const; /**@return controller for this mainwindow.*/ Controller *controller() const; /**@return active view inside this mainwindow.*/ View *activeView() const; /**@return active toolview inside this mainwindow.*/ View *activeToolView() const; /**Enable saving of per-area UI settings (like toolbar properties and position) whenever area is changed. This should be called after all areas are restored, and main window area is set, to prevent saving a half-broken state. */ void enableAreaSettingsSave(); /** Allows setting an additional widget that will be inserted left to the document tab-bar. * The ownership goes to the target. */ void setTabBarLeftCornerWidget(QWidget* widget); /**Sets the area of main window and fills it with views. *The contents is reconstructed, even if the area equals the currently set area. */ void setArea(Area *area); /** * Reconstruct the view structure. This is required after significant untracked changes to the * area-index structure. * Views listed in topViews will be on top of their view stacks. * */ void reconstructViews(QList topViews = QList()); /**Returns a list of all views which are on top of their corresponding view stacks*/ QList getTopViews() const; QList containers() const; /**Returns the view that is closest to the given global position, or zero.*/ View* viewForPosition(QPoint globalPos) const; /**Returns true if this main-window contains this view*/ bool containsView(View* view) const; /**Returns all areas that belong to this main-window*/ QList areas() const; /** Sets a @p w widget that will be shown when there are no opened documents. * This method takes the ownership of @p w. */ void setBackgroundCentralWidget(QWidget* w); public Q_SLOTS: /**Shows the @p view and makes it active, focusing it by default).*/ void activateView(Sublime::View *view, bool focus = true); /**Loads size/toolbar/menu/statusbar settings to the global configuration file. Reimplement in subclasses to load more and don't forget to call inherited method.*/ virtual void loadSettings(); Q_SIGNALS: /**Emitted before the area is cleared from this mainwindow.*/ void areaCleared(Sublime::Area*); /**Emitted after the new area has been shown in this mainwindow.*/ void areaChanged(Sublime::Area*); /**Emitted when the active view is changed.*/ void activeViewChanged(Sublime::View*); /**Emitted when the active toolview is changed.*/ void activeToolViewChanged(Sublime::View*); /**Emitted when the user interface settings have changed.*/ void settingsLoaded(); /**Emitted when a new view is added to the mainwindow.*/ void viewAdded(Sublime::View*); /**Emitted when a view is going to be removed from the mainwindow.*/ void aboutToRemoveView(Sublime::View*); - protected: - QWidget *statusBarLocation(); + QWidget *statusBarLocation() const; virtual void initializeStatusBar(); protected Q_SLOTS: virtual void tabDoubleClicked(Sublime::View* view); virtual void tabContextMenuRequested(Sublime::View*, QMenu*); virtual void tabToolTipRequested(Sublime::View* view, Sublime::Container* container, int tab); virtual void newTabRequested(); /**Called whenever the user requests a context menu on a dockwidget bar. You can then e.g. add actions to add dockwidgets. Default implementation does nothing.**/ virtual void dockBarContextMenuRequested(Qt::DockWidgetArea, const QPoint&); public: // FIXME? /**Saves size/toolbar/menu/statusbar settings to the global configuration file. Reimplement in subclasses to save more and don't forget to call inherited method.*/ virtual void saveSettings(); /**Reimplemented to save settings.*/ bool queryClose() override; /** Allow connecting to activateView without the need for a lambda for the default parameter */ void activateViewAndFocus(Sublime::View *view) { activateView(view, true); } private: QString screenKey() const; //Inherit MainWindowOperator to access four methods below /**Unsets the area clearing main window.*/ void clearArea(); /**Sets the active view.*/ void setActiveView(Sublime::View* view, bool focus = true); /**Sets the active toolview and focuses it.*/ void setActiveToolView(View *view); void resizeEvent(QResizeEvent* event) override; void saveGeometry(KConfigGroup &config); void loadGeometry(const KConfigGroup &config); class MainWindowPrivate *const d; friend class MainWindowOperator; friend class MainWindowPrivate; }; } #endif