From: Peter Penz Date: Sat, 12 Apr 2008 15:09:46 +0000 (+0000) Subject: "New Tab" menu + some related code ;-) X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/3b06c2120dad8efc79471a82b81c08f2d5834062?ds=inline "New Tab" menu + some related code ;-) BUG: 143995 svn path=/trunk/KDE/kdebase/apps/; revision=796101 --- diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 126591b6c..623634f9e 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -72,6 +72,7 @@ #include #include #include +#include #include #include @@ -85,15 +86,17 @@ DolphinMainWindow::DolphinMainWindow(int id) : KXmlGuiWindow(0), m_newMenu(0), m_showMenuBar(0), - m_splitter(0), + m_tabBar(0), m_activeViewContainer(0), + m_centralWidgetLayout(0), m_id(id), - m_viewContainer(), + m_tabIndex(0), + m_viewTab(), m_actionHandler(0) { setObjectName("Dolphin#"); - m_viewContainer[PrimaryView] = 0; - m_viewContainer[SecondaryView] = 0; + + m_viewTab.append(ViewTab()); new MainWindowAdaptor(this); QDBusConnection::sessionBus().registerObject(QString("/dolphin/MainWindow%1").arg(m_id), this); @@ -119,17 +122,17 @@ DolphinMainWindow::~DolphinMainWindow() void DolphinMainWindow::toggleViews() { - if (m_viewContainer[SecondaryView] == 0) { + if (m_viewTab[m_tabIndex].primaryView == 0) { return; } // move secondary view from the last position of the splitter // to the first position - m_splitter->insertWidget(0, m_viewContainer[SecondaryView]); + m_viewTab[m_tabIndex].splitter->insertWidget(0, m_viewTab[m_tabIndex].secondaryView); - DolphinViewContainer* container = m_viewContainer[PrimaryView]; - m_viewContainer[PrimaryView] = m_viewContainer[SecondaryView]; - m_viewContainer[SecondaryView] = container; + DolphinViewContainer* container = m_viewTab[m_tabIndex].primaryView; + m_viewTab[m_tabIndex].primaryView = m_viewTab[m_tabIndex].secondaryView; + m_viewTab[m_tabIndex].secondaryView = container; } void DolphinMainWindow::slotDoingOperation(KonqFileUndoManager::CommandType commandType) @@ -140,16 +143,16 @@ void DolphinMainWindow::slotDoingOperation(KonqFileUndoManager::CommandType comm void DolphinMainWindow::refreshViews() { - Q_ASSERT(m_viewContainer[PrimaryView] != 0); + Q_ASSERT(m_viewTab[m_tabIndex].primaryView != 0); // remember the current active view, as because of // the refreshing the active view might change to // the secondary view DolphinViewContainer* activeViewContainer = m_activeViewContainer; - m_viewContainer[PrimaryView]->view()->refresh(); - if (m_viewContainer[SecondaryView] != 0) { - m_viewContainer[SecondaryView]->view()->refresh(); + m_viewTab[m_tabIndex].primaryView->view()->refresh(); + if (m_viewTab[m_tabIndex].secondaryView != 0) { + m_viewTab[m_tabIndex].secondaryView->view()->refresh(); } setActiveViewContainer(activeViewContainer); @@ -177,7 +180,11 @@ void DolphinMainWindow::changeUrl(const KUrl& url) updateEditActions(); updateViewActions(); updateGoActions(); - setCaption(url.fileName()); + const QString caption = url.fileName(); + setCaption(caption); + if (m_viewTab.count() > 1) { + m_tabBar->setTabText(m_tabIndex, caption); + } emit urlChanged(url); } } @@ -198,10 +205,10 @@ void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection) { updateEditActions(); - Q_ASSERT(m_viewContainer[PrimaryView] != 0); - int selectedUrlsCount = m_viewContainer[PrimaryView]->view()->selectedUrls().count(); - if (m_viewContainer[SecondaryView] != 0) { - selectedUrlsCount += m_viewContainer[SecondaryView]->view()->selectedUrls().count(); + Q_ASSERT(m_viewTab[m_tabIndex].primaryView != 0); + int selectedUrlsCount = m_viewTab[m_tabIndex].primaryView->view()->selectedUrls().count(); + if (m_viewTab[m_tabIndex].secondaryView != 0) { + selectedUrlsCount += m_viewTab[m_tabIndex].secondaryView->view()->selectedUrls().count(); } QAction* compareFilesAction = actionCollection()->action("compare_files"); @@ -249,18 +256,24 @@ void DolphinMainWindow::openNewMainWindow() DolphinApplication::app()->createMainWindow()->show(); } +void DolphinMainWindow::openNewTab() +{ + openNewTab(m_activeViewContainer->url()); + m_tabBar->setCurrentIndex(m_viewTab.count() - 1); +} + void DolphinMainWindow::toggleActiveView() { - if (m_viewContainer[SecondaryView] == 0) { + if (m_viewTab[m_tabIndex].secondaryView == 0) { // only one view is available return; } Q_ASSERT(m_activeViewContainer != 0); - Q_ASSERT(m_viewContainer[PrimaryView] != 0); + Q_ASSERT(m_viewTab[m_tabIndex].primaryView != 0); - DolphinViewContainer* left = m_viewContainer[PrimaryView]; - DolphinViewContainer* right = m_viewContainer[SecondaryView]; + DolphinViewContainer* left = m_viewTab[m_tabIndex].primaryView; + DolphinViewContainer* right = m_viewTab[m_tabIndex].secondaryView; setActiveViewContainer(m_activeViewContainer == right ? left : right); } @@ -277,11 +290,12 @@ void DolphinMainWindow::closeEvent(QCloseEvent* event) void DolphinMainWindow::saveProperties(KConfigGroup& group) { - DolphinViewContainer* cont = m_viewContainer[PrimaryView]; + // TODO: remember tabs + DolphinViewContainer* cont = m_viewTab[m_tabIndex].primaryView; group.writeEntry("Primary Url", cont->url().url()); group.writeEntry("Primary Editable Url", cont->isUrlEditable()); - cont = m_viewContainer[SecondaryView]; + cont = m_viewTab[m_tabIndex].secondaryView; if (cont != 0) { group.writeEntry("Secondary Url", cont->url().url()); group.writeEntry("Secondary Editable Url", cont->isUrlEditable()); @@ -290,20 +304,21 @@ void DolphinMainWindow::saveProperties(KConfigGroup& group) void DolphinMainWindow::readProperties(const KConfigGroup& group) { - DolphinViewContainer* cont = m_viewContainer[PrimaryView]; + // TODO: read tabs + DolphinViewContainer* cont = m_viewTab[m_tabIndex].primaryView; cont->setUrl(group.readEntry("Primary Url")); bool editable = group.readEntry("Primary Editable Url", false); cont->urlNavigator()->setUrlEditable(editable); - cont = m_viewContainer[SecondaryView]; + cont = m_viewTab[m_tabIndex].secondaryView; const QString secondaryUrl = group.readEntry("Secondary Url"); if (!secondaryUrl.isEmpty()) { if (cont == 0) { // a secondary view should be shown, but no one is available // currently -> create a new view toggleSplitView(); - cont = m_viewContainer[SecondaryView]; + cont = m_viewTab[m_tabIndex].secondaryView; Q_ASSERT(cont != 0); } @@ -458,35 +473,37 @@ void DolphinMainWindow::invertSelection() void DolphinMainWindow::toggleSplitView() { - if (m_viewContainer[SecondaryView] == 0) { + if (m_viewTab[m_tabIndex].secondaryView == 0) { // create a secondary view - const int newWidth = (m_viewContainer[PrimaryView]->width() - m_splitter->handleWidth()) / 2; - - const DolphinView* view = m_viewContainer[PrimaryView]->view(); - m_viewContainer[SecondaryView] = new DolphinViewContainer(this, 0, view->rootUrl()); - connectViewSignals(SecondaryView); - m_splitter->addWidget(m_viewContainer[SecondaryView]); - m_splitter->setSizes(QList() << newWidth << newWidth); - m_viewContainer[SecondaryView]->view()->reload(); - m_viewContainer[SecondaryView]->setActive(false); - m_viewContainer[SecondaryView]->show(); - } else if (m_activeViewContainer == m_viewContainer[PrimaryView]) { + QSplitter* splitter = m_viewTab[m_tabIndex].splitter; + const int newWidth = (m_viewTab[m_tabIndex].primaryView->width() - splitter->handleWidth()) / 2; + + const DolphinView* view = m_viewTab[m_tabIndex].primaryView->view(); + m_viewTab[m_tabIndex].secondaryView = new DolphinViewContainer(this, 0, view->rootUrl()); + connectViewSignals(m_viewTab[m_tabIndex].secondaryView); + splitter->addWidget(m_viewTab[m_tabIndex].secondaryView); + splitter->setSizes(QList() << newWidth << newWidth); + m_viewTab[m_tabIndex].secondaryView->view()->reload(); + m_viewTab[m_tabIndex].secondaryView->setActive(false); + m_viewTab[m_tabIndex].secondaryView->show(); + } else if (m_activeViewContainer == m_viewTab[m_tabIndex].primaryView) { // remove secondary view - m_viewContainer[SecondaryView]->close(); - m_viewContainer[SecondaryView]->deleteLater(); - m_viewContainer[SecondaryView] = 0; + m_viewTab[m_tabIndex].secondaryView->close(); + m_viewTab[m_tabIndex].secondaryView->deleteLater(); + m_viewTab[m_tabIndex].secondaryView = 0; } else { // The secondary view is active, hence from a users point of view // the content of the secondary view should be moved to the primary view. // From an implementation point of view it is more efficient to close // the primary view and exchange the internal pointers afterwards. - m_viewContainer[PrimaryView]->close(); - m_viewContainer[PrimaryView]->deleteLater(); - m_viewContainer[PrimaryView] = m_viewContainer[SecondaryView]; - m_viewContainer[SecondaryView] = 0; + + m_viewTab[m_tabIndex].primaryView->close(); + m_viewTab[m_tabIndex].primaryView->deleteLater(); + m_viewTab[m_tabIndex].primaryView = m_viewTab[m_tabIndex].secondaryView; + m_viewTab[m_tabIndex].secondaryView = 0; } - setActiveViewContainer(m_viewContainer[PrimaryView]); + setActiveViewContainer(m_viewTab[m_tabIndex].primaryView); updateViewActions(); } @@ -570,16 +587,16 @@ void DolphinMainWindow::compareFiles() // - both in the secondary view // - one in the primary view and the other in the secondary // view - Q_ASSERT(m_viewContainer[PrimaryView] != 0); + Q_ASSERT(m_viewTab[m_tabIndex].primaryView != 0); KUrl urlA; KUrl urlB; - KUrl::List urls = m_viewContainer[PrimaryView]->view()->selectedUrls(); + KUrl::List urls = m_viewTab[m_tabIndex].primaryView->view()->selectedUrls(); switch (urls.count()) { case 0: { - Q_ASSERT(m_viewContainer[SecondaryView] != 0); - urls = m_viewContainer[SecondaryView]->view()->selectedUrls(); + Q_ASSERT(m_viewTab[m_tabIndex].secondaryView != 0); + urls = m_viewTab[m_tabIndex].secondaryView->view()->selectedUrls(); Q_ASSERT(urls.count() == 2); urlA = urls[0]; urlB = urls[1]; @@ -588,8 +605,8 @@ void DolphinMainWindow::compareFiles() case 1: { urlA = urls[0]; - Q_ASSERT(m_viewContainer[SecondaryView] != 0); - urls = m_viewContainer[SecondaryView]->view()->selectedUrls(); + Q_ASSERT(m_viewTab[m_tabIndex].secondaryView != 0); + urls = m_viewTab[m_tabIndex].secondaryView->view()->selectedUrls(); Q_ASSERT(urls.count() == 1); urlB = urls[0]; break; @@ -614,7 +631,6 @@ void DolphinMainWindow::compareFiles() command.append(urlB.pathOrUrl()); command.append('\"'); KRun::runCommand(command, "Kompare", "kompare", this); - } void DolphinMainWindow::toggleShowMenuBar() @@ -629,6 +645,33 @@ void DolphinMainWindow::editSettings() dialog.exec(); } +void DolphinMainWindow::setActiveTab(int index) +{ + Q_ASSERT(index >= 0); + Q_ASSERT(index < m_viewTab.count()); + if (index == m_tabIndex) { + return; + } + + // hide current tab content + QSplitter* splitter = m_viewTab[m_tabIndex].splitter; + m_centralWidgetLayout->removeWidget(splitter); + splitter->hide(); + + // show active tab content + m_tabIndex = index; + + ViewTab& viewTab = m_viewTab[index]; + m_centralWidgetLayout->addWidget(viewTab.splitter); + viewTab.splitter->show(); + viewTab.primaryView->show(); + if (viewTab.secondaryView != 0) { + viewTab.secondaryView->show(); + } + + setActiveViewContainer(viewTab.primaryView); +} + void DolphinMainWindow::init() { DolphinSettings& settings = DolphinSettings::instance(); @@ -643,7 +686,7 @@ void DolphinMainWindow::init() setAcceptDrops(true); - m_splitter = new QSplitter(this); + m_viewTab[m_tabIndex].splitter = new QSplitter(this); setupActions(); @@ -652,18 +695,31 @@ void DolphinMainWindow::init() m_actionHandler = new DolphinViewActionHandler(actionCollection(), this); connect(m_actionHandler, SIGNAL(actionBeingHandled()), SLOT(clearStatusBar())); ViewProperties props(homeUrl); - m_viewContainer[PrimaryView] = new DolphinViewContainer(this, - m_splitter, - homeUrl); + m_viewTab[m_tabIndex].primaryView = new DolphinViewContainer(this, + m_viewTab[m_tabIndex].splitter, + homeUrl); - m_activeViewContainer = m_viewContainer[PrimaryView]; - connectViewSignals(PrimaryView); - DolphinView* view = m_viewContainer[PrimaryView]->view(); + m_activeViewContainer = m_viewTab[m_tabIndex].primaryView; + connectViewSignals(m_activeViewContainer); + DolphinView* view = m_activeViewContainer->view(); view->reload(); - m_viewContainer[PrimaryView]->show(); + m_activeViewContainer->show(); m_actionHandler->setCurrentView(view); - setCentralWidget(m_splitter); + m_tabBar = new KTabBar(this); + m_tabBar->setHoverCloseButton(true); + connect(m_tabBar, SIGNAL(currentChanged(int)), + this, SLOT(setActiveTab(int))); + + QWidget* centralWidget = new QWidget(this); + m_centralWidgetLayout = new QVBoxLayout(centralWidget); + m_centralWidgetLayout->setSpacing(0); + m_centralWidgetLayout->setMargin(0); + m_centralWidgetLayout->addWidget(m_tabBar); + m_centralWidgetLayout->addWidget(m_viewTab[m_tabIndex].splitter); + + + setCentralWidget(centralWidget); setupDockWidgets(); setupGUI(Keys | Save | Create | ToolBar); @@ -694,7 +750,8 @@ void DolphinMainWindow::init() void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContainer) { Q_ASSERT(viewContainer != 0); - Q_ASSERT((viewContainer == m_viewContainer[PrimaryView]) || (viewContainer == m_viewContainer[SecondaryView])); + Q_ASSERT((viewContainer == m_viewTab[m_tabIndex].primaryView) || + (viewContainer == m_viewTab[m_tabIndex].secondaryView)); if (m_activeViewContainer == viewContainer) { return; } @@ -711,7 +768,11 @@ void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContain updateGoActions(); const KUrl& url = m_activeViewContainer->url(); - setCaption(url.fileName()); + const QString caption = url.fileName(); + setCaption(caption); + if (m_viewTab.count() > 1) { + m_tabBar->setTabText(m_tabIndex, caption); + } emit urlChanged(url); } @@ -732,6 +793,12 @@ void DolphinMainWindow::setupActions() newWindow->setShortcut(Qt::CTRL | Qt::Key_N); connect(newWindow, SIGNAL(triggered()), this, SLOT(openNewMainWindow())); + KAction* newTab = actionCollection()->addAction("new_tab"); + newTab->setIcon(KIcon("tab-new")); + newTab->setText(i18nc("@action:inmenu File", "New Tab")); + newTab->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_N); + connect(newTab, SIGNAL(triggered()), this, SLOT(openNewTab())); + KAction* properties = actionCollection()->addAction("properties"); properties->setText(i18nc("@action:inmenu File", "Properties")); properties->setShortcut(Qt::ALT | Qt::Key_Return); @@ -977,9 +1044,8 @@ void DolphinMainWindow::clearStatusBar() m_activeViewContainer->statusBar()->clear(); } -void DolphinMainWindow::connectViewSignals(int viewIndex) +void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container) { - DolphinViewContainer* container = m_viewContainer[viewIndex]; connect(container, SIGNAL(showFilterBarChanged(bool)), this, SLOT(updateFilterBarAction(bool))); @@ -1005,8 +1071,8 @@ void DolphinMainWindow::connectViewSignals(int viewIndex) void DolphinMainWindow::updateSplitAction() { QAction* splitAction = actionCollection()->action("split_view"); - if (m_viewContainer[SecondaryView] != 0) { - if (m_activeViewContainer == m_viewContainer[PrimaryView]) { + if (m_viewTab[m_tabIndex].secondaryView != 0) { + if (m_activeViewContainer == m_viewTab[m_tabIndex].primaryView) { splitAction->setText(i18nc("@action:intoolbar Close right view", "Close")); splitAction->setIcon(KIcon("view-right-close")); } else { @@ -1019,6 +1085,25 @@ void DolphinMainWindow::updateSplitAction() } } +void DolphinMainWindow::openNewTab(const KUrl& url) +{ + if (m_viewTab.count() == 1) { + // Only one view is open currently and hence no tab is shown at + // all. Before creating a tab for 'url', provide a tab for the current URL. + m_tabBar->addTab(KIcon("folder"), m_activeViewContainer->url().fileName()); + } + + m_tabBar->addTab(KIcon("folder"), url.fileName()); + + ViewTab viewTab; + viewTab.splitter = new QSplitter(this); + viewTab.primaryView = new DolphinViewContainer(this, viewTab.splitter, url); + connectViewSignals(viewTab.primaryView); + viewTab.primaryView->view()->reload(); + + m_viewTab.append(viewTab); +} + DolphinMainWindow::UndoUiInterface::UndoUiInterface(DolphinMainWindow* mainWin) : KonqFileUndoManager::UiInterface(mainWin), m_mainWin(mainWin) diff --git a/src/dolphinmainwindow.h b/src/dolphinmainwindow.h index 2fbb742fd..5a50f3dbf 100644 --- a/src/dolphinmainwindow.h +++ b/src/dolphinmainwindow.h @@ -39,6 +39,7 @@ class DolphinViewActionHandler; class DolphinApplication; class DolphinViewContainer; class KNewMenu; +class KTabBar; class KUrl; class QSplitter; @@ -310,12 +311,21 @@ private slots: /** Open a new main window. */ void openNewMainWindow(); + /** Opens a new empty view that is part of a tab. */ + void openNewTab(); + /** Toggles the active view if two views are shown within the main window. */ void toggleActiveView(); /** Called when the view is doing a file operation, like renaming, copying, moving etc. */ void slotDoingOperation(KonqFileUndoManager::CommandType type); + /** + * Activates the tab with the index \a index, which means that the current view + * is replaced by the view of the given tab. + */ + void setActiveTab(int index); + private: DolphinMainWindow(int id); void init(); @@ -336,11 +346,11 @@ private: /** * Connects the signals from the created DolphinView with - * the index \a viewIndex with the corresponding slots of + * the DolphinViewContainer \a container with the corresponding slots of * the DolphinMainWindow. This method must be invoked each * time a DolphinView has been created. */ - void connectViewSignals(int viewIndex); + void connectViewSignals(DolphinViewContainer* container); /** * Updates the text of the split action: @@ -350,16 +360,12 @@ private: */ void updateSplitAction(); -private: /** - * DolphinMainWindow supports up to two views beside each other. + * Opens a new tab showing the URL \a url. */ - enum ViewIndex - { - PrimaryView = 0, ///< View shown on the left side of the main window. - SecondaryView = 1 ///< View shown on the left side of the main window. - }; + void openNewTab(const KUrl& url); +private: /** * Implements a custom error handling for the undo manager. This * assures that all errors are shown in the status bar of Dolphin @@ -378,11 +384,21 @@ private: KNewMenu* m_newMenu; KAction* m_showMenuBar; - QSplitter* m_splitter; + KTabBar* m_tabBar; DolphinViewContainer* m_activeViewContainer; + QVBoxLayout* m_centralWidgetLayout; int m_id; - DolphinViewContainer* m_viewContainer[SecondaryView + 1]; + struct ViewTab + { + ViewTab() : primaryView(0), secondaryView(0), splitter(0) {} + DolphinViewContainer* primaryView; + DolphinViewContainer* secondaryView; + QSplitter* splitter; + }; + + int m_tabIndex; + QList m_viewTab; DolphinViewActionHandler* m_actionHandler; @@ -397,7 +413,7 @@ inline DolphinViewContainer* DolphinMainWindow::activeViewContainer() const inline bool DolphinMainWindow::isSplit() const { - return m_viewContainer[SecondaryView] != 0; + return m_viewTab[m_tabIndex].secondaryView != 0; } inline KNewMenu* DolphinMainWindow::newMenu() const diff --git a/src/dolphinui.rc b/src/dolphinui.rc index 8aaddcd26..efee42a0f 100644 --- a/src/dolphinui.rc +++ b/src/dolphinui.rc @@ -4,6 +4,7 @@ +