From 94815093253e5db99aa100f0834cd6c74c96a91a Mon Sep 17 00:00:00 2001 From: Peter Penz Date: Fri, 31 Dec 2010 10:59:46 +0000 Subject: [PATCH] Lock panels per default and allow to unlock them like in Amarok. BUG: 229811 FIXED-IN: 4.7.0 svn path=/trunk/KDE/kdebase/apps/; revision=1210424 --- src/CMakeLists.txt | 1 + src/dolphindockwidget.cpp | 82 +++++++++++++++++++ src/dolphindockwidget.h | 50 +++++++++++ src/dolphinmainwindow.cpp | 63 +++++++++++--- src/dolphinmainwindow.h | 5 ++ src/panels/filter/filterpanel.cpp | 13 +++ src/panels/filter/filterpanel.h | 3 + src/panels/folders/treeviewcontextmenu.cpp | 4 + src/panels/information/informationpanel.cpp | 3 +- .../information/informationpanelcontent.cpp | 7 +- .../information/informationpanelcontent.h | 4 +- src/panels/panel.cpp | 13 ++- src/panels/panel.h | 12 +++ src/settings/dolphin_generalsettings.kcfg | 4 + 14 files changed, 248 insertions(+), 16 deletions(-) create mode 100644 src/dolphindockwidget.cpp create mode 100644 src/dolphindockwidget.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4d442bbcd..a8bcce252 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -96,6 +96,7 @@ install(FILES views/versioncontrol/fileviewversioncontrolplugin.desktop DESTINAT set(dolphin_SRCS dolphinapplication.cpp + dolphindockwidget.cpp dolphinmainwindow.cpp dolphinnewfilemenu.cpp dolphinviewcontainer.cpp diff --git a/src/dolphindockwidget.cpp b/src/dolphindockwidget.cpp new file mode 100644 index 000000000..f7ee16fdc --- /dev/null +++ b/src/dolphindockwidget.cpp @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (C) 2010 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU 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 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 "dolphindockwidget.h" + +#include + + // Empty titlebar for the dock widgets when "Lock Layout" has been activated. +class DolphinDockTitleBar : public QWidget +{ +public: + DolphinDockTitleBar(QWidget* parent = 0) : QWidget(parent) {} + virtual ~DolphinDockTitleBar() {} + + virtual QSize minimumSizeHint() const + { + const int border = style()->pixelMetric(QStyle::PM_DockWidgetTitleBarButtonMargin); + return QSize(border, border); + } + + virtual QSize sizeHint() const + { + return minimumSizeHint(); + } +}; + +DolphinDockWidget::DolphinDockWidget(const QString& title, QWidget* parent, Qt::WindowFlags flags) : + QDockWidget(title, parent, flags), + m_locked(false), + m_dockTitleBar(0) +{ +} + +DolphinDockWidget::DolphinDockWidget(QWidget* parent, Qt::WindowFlags flags) : + QDockWidget(parent, flags), + m_locked(false), + m_dockTitleBar(0) +{ +} + +DolphinDockWidget::~DolphinDockWidget() +{ +} + +void DolphinDockWidget::setLocked(bool lock) +{ + if (lock != m_locked) { + m_locked = lock; + + if (lock) { + if (m_dockTitleBar == 0) { + m_dockTitleBar = new DolphinDockTitleBar(this); + } + setTitleBarWidget(m_dockTitleBar); + } else { + setTitleBarWidget(0); + } + } +} + +bool DolphinDockWidget::isLocked() const +{ + return m_locked; +} + +#include "dolphindockwidget.moc" diff --git a/src/dolphindockwidget.h b/src/dolphindockwidget.h new file mode 100644 index 000000000..8f110c697 --- /dev/null +++ b/src/dolphindockwidget.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2010 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU 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 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 DOLPHIN_DOCK_WIDGET_H +#define DOLPHIN_DOCK_WIDGET_H + +#include + +/** + * @brief Extends QDockWidget to be able to get locked. + */ +class DolphinDockWidget : public QDockWidget +{ + Q_OBJECT + +public: + DolphinDockWidget(const QString& title, QWidget* parent = 0, Qt::WindowFlags flags = 0); + DolphinDockWidget(QWidget* parent = 0, Qt::WindowFlags flags = 0); + virtual ~DolphinDockWidget(); + + /** + * @param lock If \a lock is true, the title bar of the dock-widget will get hidden so + * that it is not possible for the user anymore to move or undock the dock-widget. + */ + void setLocked(bool lock); + bool isLocked() const; + +private: + bool m_locked; + QWidget* m_dockTitleBar; +}; + +#endif diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 46b28cada..64f26387f 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -24,6 +24,7 @@ #include #include "dolphinapplication.h" +#include "dolphindockwidget.h" #include "dolphincontextmenu.h" #include "dolphinnewfilemenu.h" #include "dolphinviewcontainer.h" @@ -56,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -89,7 +91,6 @@ #include #include #include -#include #include /* @@ -866,6 +867,21 @@ void DolphinMainWindow::replaceLocation() lineEdit->setSelection(0, text.length()); } +void DolphinMainWindow::togglePanelLockState() +{ + GeneralSettings* generalSettings = DolphinSettings::instance().generalSettings(); + + const bool newLockState = !generalSettings->lockPanels(); + foreach (QObject* child, children()) { + DolphinDockWidget* dock = qobject_cast(child); + if (dock != 0) { + dock->setLocked(newLockState); + } + } + + generalSettings->setLockPanels(newLockState); +} + void DolphinMainWindow::goBack() { clearStatusBar(); @@ -1580,11 +1596,23 @@ void DolphinMainWindow::setupActions() void DolphinMainWindow::setupDockWidgets() { - // setup "Information" - QDockWidget* infoDock = new QDockWidget(i18nc("@title:window", "Information")); + const bool lock = DolphinSettings::instance().generalSettings()->lockPanels(); + + KDualAction* lockLayoutAction = actionCollection()->add("lock_panels"); + lockLayoutAction->setActiveText(i18nc("@action:inmenu Panels", "Unlock Panels")); + lockLayoutAction->setActiveIcon(KIcon("object-unlocked")); + lockLayoutAction->setInactiveText(i18nc("@action:inmenu Panels", "Lock Panels")); + lockLayoutAction->setInactiveIcon(KIcon("object-locked")); + lockLayoutAction->setActive(lock); + connect(lockLayoutAction, SIGNAL(triggered()), this, SLOT(togglePanelLockState())); + + // Setup "Information" + DolphinDockWidget* infoDock = new DolphinDockWidget(i18nc("@title:window", "Information")); + infoDock->setLocked(lock); infoDock->setObjectName("infoDock"); infoDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); Panel* infoPanel = new InformationPanel(infoDock); + infoPanel->setCustomContextMenuActions(QList() << lockLayoutAction); connect(infoPanel, SIGNAL(urlActivated(KUrl)), this, SLOT(handleUrl(KUrl))); infoDock->setWidget(infoPanel); @@ -1601,11 +1629,13 @@ void DolphinMainWindow::setupDockWidgets() connect(this, SIGNAL(requestItemInfo(KFileItem)), infoPanel, SLOT(requestDelayedItemInfo(KFileItem))); - // setup "Folders" - QDockWidget* foldersDock = new QDockWidget(i18nc("@title:window", "Folders")); + // Setup "Folders" + DolphinDockWidget* foldersDock = new DolphinDockWidget(i18nc("@title:window", "Folders")); + foldersDock->setLocked(lock); foldersDock->setObjectName("foldersDock"); foldersDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); FoldersPanel* foldersPanel = new FoldersPanel(foldersDock); + foldersPanel->setCustomContextMenuActions(QList() << lockLayoutAction); foldersDock->setWidget(foldersPanel); QAction* foldersAction = foldersDock->toggleViewAction(); @@ -1619,12 +1649,14 @@ void DolphinMainWindow::setupDockWidgets() connect(foldersPanel, SIGNAL(changeUrl(KUrl, Qt::MouseButtons)), this, SLOT(handlePlacesClick(KUrl, Qt::MouseButtons))); - // setup "Terminal" + // Setup "Terminal" #ifndef Q_OS_WIN - QDockWidget* terminalDock = new QDockWidget(i18nc("@title:window Shell terminal", "Terminal")); + DolphinDockWidget* terminalDock = new DolphinDockWidget(i18nc("@title:window Shell terminal", "Terminal")); + terminalDock->setLocked(lock); terminalDock->setObjectName("terminalDock"); terminalDock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); Panel* terminalPanel = new TerminalPanel(terminalDock); + terminalPanel->setCustomContextMenuActions(QList() << lockLayoutAction); terminalDock->setWidget(terminalPanel); connect(terminalPanel, SIGNAL(hideTerminalPanel()), terminalDock, SLOT(hide())); @@ -1639,12 +1671,14 @@ void DolphinMainWindow::setupDockWidgets() terminalPanel, SLOT(setUrl(KUrl))); #endif - // setup "Filter" + // Setup "Filter" #ifdef HAVE_NEPOMUK - QDockWidget* filterDock = new QDockWidget(i18nc("@title:window", "Filter")); + DolphinDockWidget* filterDock = new DolphinDockWidget(i18nc("@title:window", "Filter")); + filterDock->setLocked(lock); filterDock->setObjectName("filterDock"); filterDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); Panel* filterPanel = new FilterPanel(filterDock); + filterPanel->setCustomContextMenuActions(QList() << lockLayoutAction); connect(filterPanel, SIGNAL(urlActivated(KUrl)), this, SLOT(handleUrl(KUrl))); filterDock->setWidget(filterPanel); @@ -1669,15 +1703,17 @@ void DolphinMainWindow::setupDockWidgets() #endif } - // setup "Places" - QDockWidget* placesDock = new QDockWidget(i18nc("@title:window", "Places")); + // Setup "Places" + DolphinDockWidget* placesDock = new DolphinDockWidget(i18nc("@title:window", "Places")); + placesDock->setLocked(lock); placesDock->setObjectName("placesDock"); placesDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); PlacesPanel* placesPanel = new PlacesPanel(placesDock); - placesDock->setWidget(placesPanel); placesPanel->setModel(DolphinSettings::instance().placesModel()); placesPanel->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + connect(placesPanel, SIGNAL(lockChangeRequested(bool)), this, SLOT(slotPanelLockChangeRequested(bool))); + placesDock->setWidget(placesPanel); QAction* placesAction = placesDock->toggleViewAction(); placesAction->setShortcut(Qt::Key_F9); @@ -1690,6 +1726,7 @@ void DolphinMainWindow::setupDockWidgets() connect(this, SIGNAL(urlChanged(KUrl)), placesPanel, SLOT(setUrl(KUrl))); + // Add actions into the "Panels" menu KActionMenu* panelsMenu = new KActionMenu(i18nc("@action:inmenu View", "Panels"), this); actionCollection()->addAction("panels", panelsMenu); panelsMenu->setDelayed(false); @@ -1702,6 +1739,8 @@ void DolphinMainWindow::setupDockWidgets() #ifdef HAVE_NEPOMUK panelsMenu->addAction(filterAction); #endif + panelsMenu->addSeparator(); + panelsMenu->addAction(lockLayoutAction); } void DolphinMainWindow::updateEditActions() diff --git a/src/dolphinmainwindow.h b/src/dolphinmainwindow.h index 9a57b5452..4d45d2d65 100644 --- a/src/dolphinmainwindow.h +++ b/src/dolphinmainwindow.h @@ -264,6 +264,11 @@ private slots: */ void replaceLocation(); + /** + * Toggles the state of the panels between a locked and unlocked layout. + */ + void togglePanelLockState(); + /** Goes back on step of the URL history. */ void goBack(); diff --git a/src/panels/filter/filterpanel.cpp b/src/panels/filter/filterpanel.cpp index 021a2d3b8..d13d6e520 100644 --- a/src/panels/filter/filterpanel.cpp +++ b/src/panels/filter/filterpanel.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -140,6 +141,18 @@ void FilterPanel::showEvent(QShowEvent* event) Panel::showEvent(event); } +void FilterPanel::contextMenuEvent(QContextMenuEvent* event) +{ + Panel::contextMenuEvent(event); + + QWeakPointer popup = new KMenu(this); + foreach (QAction* action, customContextMenuActions()) { + popup.data()->addAction(action); + } + popup.data()->exec(QCursor::pos()); + delete popup.data(); +} + void FilterPanel::slotSetUrlStatFinished(KJob* job) { m_lastSetUrlStatJob = 0; diff --git a/src/panels/filter/filterpanel.h b/src/panels/filter/filterpanel.h index c574d618e..574a9f389 100644 --- a/src/panels/filter/filterpanel.h +++ b/src/panels/filter/filterpanel.h @@ -52,6 +52,9 @@ protected: /** @see QWidget::showEvent() */ virtual void showEvent(QShowEvent* event); + /** @see QWidget::contextMenuEvent() */ + virtual void contextMenuEvent(QContextMenuEvent* event); + private slots: void slotSetUrlStatFinished(KJob*); void slotQueryTermChanged(const Nepomuk::Query::Term& term); diff --git a/src/panels/folders/treeviewcontextmenu.cpp b/src/panels/folders/treeviewcontextmenu.cpp index de93e096c..5c9151df0 100644 --- a/src/panels/folders/treeviewcontextmenu.cpp +++ b/src/panels/folders/treeviewcontextmenu.cpp @@ -128,6 +128,10 @@ void TreeViewContextMenu::open() popup->addAction(autoScrollingAction); connect(autoScrollingAction, SIGNAL(toggled(bool)), this, SLOT(setAutoScrolling(bool))); + popup->addSeparator(); + foreach (QAction* action, m_parent->customContextMenuActions()) { + popup->addAction(action); + } popup->exec(QCursor::pos()); popup->deleteLater(); diff --git a/src/panels/information/informationpanel.cpp b/src/panels/information/informationpanel.cpp index 0fd67b2b6..6681dc30d 100644 --- a/src/panels/information/informationpanel.cpp +++ b/src/panels/information/informationpanel.cpp @@ -167,7 +167,8 @@ void InformationPanel::resizeEvent(QResizeEvent* event) void InformationPanel::contextMenuEvent(QContextMenuEvent* event) { - m_content->configureSettings(); + // TODO: Move code from InformationPanelContent::configureSettings() here + m_content->configureSettings(customContextMenuActions()); Panel::contextMenuEvent(event); } diff --git a/src/panels/information/informationpanelcontent.cpp b/src/panels/information/informationpanelcontent.cpp index 371bdaf96..f8a72fb70 100644 --- a/src/panels/information/informationpanelcontent.cpp +++ b/src/panels/information/informationpanelcontent.cpp @@ -265,7 +265,7 @@ bool InformationPanelContent::eventFilter(QObject* obj, QEvent* event) return QWidget::eventFilter(obj, event); } -void InformationPanelContent::configureSettings() +void InformationPanelContent::configureSettings(const QList& customContextMenuActions) { KMenu popup(this); @@ -277,6 +277,11 @@ void InformationPanelContent::configureSettings() QAction* configureAction = popup.addAction(i18nc("@action:inmenu", "Configure...")); configureAction->setIcon(KIcon("configure")); + popup.addSeparator(); + foreach (QAction* action, customContextMenuActions) { + popup.addAction(action); + } + // Open the popup and adjust the settings for the // selected action. QAction* action = popup.exec(QCursor::pos()); diff --git a/src/panels/information/informationpanelcontent.h b/src/panels/information/informationpanelcontent.h index f918b8582..c41f4043f 100644 --- a/src/panels/information/informationpanelcontent.h +++ b/src/panels/information/informationpanelcontent.h @@ -61,8 +61,10 @@ public: /** * Opens a menu which allows to configure which meta information * should be shown. + * + * TODO: Move this code to the class InformationPanel */ - void configureSettings(); + void configureSettings(const QList& customContextMenuActions); signals: void urlActivated( const KUrl& url ); diff --git a/src/panels/panel.cpp b/src/panels/panel.cpp index 6d11422d8..e90970c6e 100644 --- a/src/panels/panel.cpp +++ b/src/panels/panel.cpp @@ -23,7 +23,8 @@ Panel::Panel(QWidget* parent) : QWidget(parent), - m_url(KUrl()) + m_url(), + m_customContextMenuActions() { } @@ -36,6 +37,16 @@ KUrl Panel::url() const return m_url; } +void Panel::setCustomContextMenuActions(const QList& actions) +{ + m_customContextMenuActions = actions; +} + +QList Panel::customContextMenuActions() const +{ + return m_customContextMenuActions; +} + void Panel::setUrl(const KUrl& url) { if (url.equals(m_url, KUrl::CompareWithoutTrailingSlash)) { diff --git a/src/panels/panel.h b/src/panels/panel.h index 11558e2de..83ed3da3b 100644 --- a/src/panels/panel.h +++ b/src/panels/panel.h @@ -27,6 +27,9 @@ /** * @brief Base widget for all panels that can be docked on the window borders. + * + * Derived panels should provide a context menu that at least offers the + * actions from Panel::customContextMenuActions(). */ class Panel : public QWidget { @@ -39,6 +42,14 @@ public: /** Returns the current set URL of the active Dolphin view. */ KUrl url() const; + /** + * Sets custom context menu actions that are added to the panel specific + * context menu actions. Allows an application to apply custom actions to + * the panel. + */ + void setCustomContextMenuActions(const QList& actions); + QList customContextMenuActions() const; + public slots: /** * This is invoked every time the folder being displayed in the @@ -58,6 +69,7 @@ protected: private: KUrl m_url; + QList m_customContextMenuActions; }; #endif // PANEL_H diff --git a/src/settings/dolphin_generalsettings.kcfg b/src/settings/dolphin_generalsettings.kcfg index b80b90442..ee219d953 100644 --- a/src/settings/dolphin_generalsettings.kcfg +++ b/src/settings/dolphin_generalsettings.kcfg @@ -83,5 +83,9 @@ false + + + true + -- 2.47.3