X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/c33b01efb2aed904af9ffaef27fb3b0b4bdda37b..b3beb9e0c2ff8cdc77f9a48e3416877e5bad0918:/src/dolphinmainwindow.cpp diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 126591b6c..85ff9f7f5 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -32,11 +32,11 @@ #include "dolphinsettingsdialog.h" #include "dolphinstatusbar.h" #include "dolphinviewcontainer.h" +#include "fileitemcapabilities.h" #include "infosidebarpage.h" #include "metadatawidget.h" #include "mainwindowadaptor.h" #include "treeviewsidebarpage.h" -#include "viewpropertiesdialog.h" #include "viewproperties.h" #ifndef Q_OS_WIN @@ -72,6 +72,7 @@ #include #include #include +#include #include #include @@ -85,23 +86,23 @@ 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); - KonqFileUndoManager::incRef(); - - KonqFileUndoManager* undoManager = KonqFileUndoManager::self(); - undoManager->setUiInterface(new UndoUiInterface(this)); + KIO::FileUndoManager* undoManager = KIO::FileUndoManager::self(); + undoManager->setUiInterface(new UndoUiInterface()); connect(undoManager, SIGNAL(undoAvailable(bool)), this, SLOT(slotUndoAvailable(bool))); @@ -113,26 +114,25 @@ DolphinMainWindow::DolphinMainWindow(int id) : DolphinMainWindow::~DolphinMainWindow() { - KonqFileUndoManager::decRef(); DolphinApplication::app()->removeMainWindow(this); } 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) +void DolphinMainWindow::slotDoingOperation(KIO::FileUndoManager::CommandType commandType) { clearStatusBar(); m_undoCommandTypes.append(commandType); @@ -140,16 +140,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); @@ -159,8 +159,8 @@ void DolphinMainWindow::dropUrls(const KUrl::List& urls, const KUrl& destination) { DolphinDropController dropController(this); - connect(&dropController, SIGNAL(doingOperation(KonqFileUndoManager::CommandType)), - this, SLOT(slotDoingOperation(KonqFileUndoManager::CommandType))); + connect(&dropController, SIGNAL(doingOperation(KIO::FileUndoManager::CommandType)), + this, SLOT(slotDoingOperation(KIO::FileUndoManager::CommandType))); dropController.dropUrls(urls, destination); } @@ -178,6 +178,9 @@ void DolphinMainWindow::changeUrl(const KUrl& url) updateViewActions(); updateGoActions(); setCaption(url.fileName()); + if (m_viewTab.count() > 1) { + m_tabBar->setTabText(m_tabIndex, tabName(url)); + } emit urlChanged(url); } } @@ -198,10 +201,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 +252,44 @@ void DolphinMainWindow::openNewMainWindow() DolphinApplication::app()->createMainWindow()->show(); } +void DolphinMainWindow::openNewTab() +{ + openNewTab(m_activeViewContainer->url()); + m_tabBar->setCurrentIndex(m_viewTab.count() - 1); +} + +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"), tabName(m_activeViewContainer->url())); + m_tabBar->blockSignals(false); + } + + m_tabBar->addTab(KIcon("folder"), tabName(url)); + + 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); +} + 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 +306,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 +320,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); } @@ -355,31 +386,31 @@ void DolphinMainWindow::slotUndoAvailable(bool available) } if (available && (m_undoCommandTypes.count() > 0)) { - const KonqFileUndoManager::CommandType command = m_undoCommandTypes.takeFirst(); + const KIO::FileUndoManager::CommandType command = m_undoCommandTypes.takeFirst(); DolphinStatusBar* statusBar = m_activeViewContainer->statusBar(); switch (command) { - case KonqFileUndoManager::COPY: + case KIO::FileUndoManager::Copy: statusBar->setMessage(i18nc("@info:status", "Copy operation completed."), DolphinStatusBar::OperationCompleted); break; - case KonqFileUndoManager::MOVE: + case KIO::FileUndoManager::Move: statusBar->setMessage(i18nc("@info:status", "Move operation completed."), DolphinStatusBar::OperationCompleted); break; - case KonqFileUndoManager::LINK: + case KIO::FileUndoManager::Link: statusBar->setMessage(i18nc("@info:status", "Link operation completed."), DolphinStatusBar::OperationCompleted); break; - case KonqFileUndoManager::TRASH: + case KIO::FileUndoManager::Trash: statusBar->setMessage(i18nc("@info:status", "Move to trash operation completed."), DolphinStatusBar::OperationCompleted); break; - case KonqFileUndoManager::RENAME: + case KIO::FileUndoManager::Rename: statusBar->setMessage(i18nc("@info:status", "Renaming operation completed."), DolphinStatusBar::OperationCompleted); break; - case KonqFileUndoManager::MKDIR: + case KIO::FileUndoManager::Mkdir: statusBar->setMessage(i18nc("@info:status", "Created folder."), DolphinStatusBar::OperationCompleted); break; @@ -402,7 +433,8 @@ void DolphinMainWindow::slotUndoTextChanged(const QString& text) void DolphinMainWindow::undo() { clearStatusBar(); - KonqFileUndoManager::self()->undo(); + KIO::FileUndoManager::self()->uiInterface()->setParentWidget(this); + KIO::FileUndoManager::self()->undo(); } void DolphinMainWindow::cut() @@ -423,10 +455,6 @@ void DolphinMainWindow::paste() void DolphinMainWindow::updatePasteAction() { QAction* pasteAction = actionCollection()->action(KStandardAction::name(KStandardAction::Paste)); - if (pasteAction == 0) { - return; - } - QPair pasteInfo = m_activeViewContainer->view()->pasteInfo(); pasteAction->setEnabled(pasteInfo.first); pasteAction->setText(pasteInfo.second); @@ -458,35 +486,42 @@ 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(); + + setActiveViewContainer(m_viewTab[m_tabIndex].secondaryView); + } 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; + + setActiveViewContainer(m_viewTab[m_tabIndex].primaryView); } 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_viewTab[m_tabIndex].primaryView); } - setActiveViewContainer(m_viewContainer[PrimaryView]); updateViewActions(); } @@ -526,13 +561,6 @@ void DolphinMainWindow::editLocation() lineEdit->setSelection(0, text.length()); } -void DolphinMainWindow::adjustViewProperties() -{ - clearStatusBar(); - ViewPropertiesDialog dlg(m_activeViewContainer->view()); - dlg.exec(); -} - void DolphinMainWindow::goBack() { clearStatusBar(); @@ -570,16 +598,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 +616,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 +642,6 @@ void DolphinMainWindow::compareFiles() command.append(urlB.pathOrUrl()); command.append('\"'); KRun::runCommand(command, "Kompare", "kompare", this); - } void DolphinMainWindow::toggleShowMenuBar() @@ -629,6 +656,123 @@ 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 + m_viewTab[m_tabIndex].isPrimaryViewActive = m_viewTab[m_tabIndex].primaryView->isActive(); + QSplitter* splitter = m_viewTab[m_tabIndex].splitter; + splitter->hide(); + m_centralWidgetLayout->removeWidget(splitter); + + // show active tab content + m_tabIndex = index; + + ViewTab& viewTab = m_viewTab[index]; + m_centralWidgetLayout->addWidget(viewTab.splitter); + viewTab.primaryView->show(); + if (viewTab.secondaryView != 0) { + viewTab.secondaryView->show(); + } + viewTab.splitter->show(); + + setActiveViewContainer(viewTab.isPrimaryViewActive ? viewTab.primaryView : + viewTab.secondaryView); +} + +void DolphinMainWindow::closeTab() +{ + closeTab(m_tabBar->currentIndex()); +} + +void DolphinMainWindow::closeTab(int index) +{ + Q_ASSERT(index >= 0); + Q_ASSERT(index < m_viewTab.count()); + if (m_viewTab.count() == 1) { + // the last tab may never get closed + return; + } + + if (index == m_tabIndex) { + // The tab that should be closed is the active tab. Activate the + // previous tab before closing the tab. + setActiveTab((index > 0) ? index - 1 : 1); + } + + // delete tab + m_viewTab[index].primaryView->deleteLater(); + if (m_viewTab[index].secondaryView != 0) { + m_viewTab[index].secondaryView->deleteLater(); + } + m_viewTab[index].splitter->deleteLater(); + m_viewTab.erase(m_viewTab.begin() + index); + + m_tabBar->blockSignals(true); + m_tabBar->removeTab(index); + + if (m_tabIndex > index) { + m_tabIndex--; + Q_ASSERT(m_tabIndex >= 0); + } + + // if only one tab is left, also remove the tab entry so that + // closing the last tab is not possible + if (m_viewTab.count() == 1) { + m_tabBar->removeTab(0); + } else { + m_tabBar->blockSignals(false); + } +} + +void DolphinMainWindow::openTabContextMenu(int index, const QPoint& pos) +{ + KMenu menu(this); + + QAction* newTabAction = menu.addAction(KIcon("tab-new"), i18nc("@action:inmenu", "New Tab")); + newTabAction->setShortcut(actionCollection()->action("new_tab")->shortcut()); + + QAction* closeOtherTabsAction = menu.addAction(KIcon("tab-close-other"), i18nc("@action:inmenu", "Close Other Tabs")); + + QAction* closeTabAction = menu.addAction(KIcon("tab-close"), i18nc("@action:inmenu", "Close Tab")); + closeTabAction->setShortcut(actionCollection()->action("close_tab")->shortcut()); + + QAction* selectedAction = menu.exec(pos); + if (selectedAction == newTabAction) { + const ViewTab& tab = m_viewTab[index]; + Q_ASSERT(tab.primaryView != 0); + const KUrl url = (tab.secondaryView != 0) && tab.secondaryView->isActive() ? + tab.secondaryView->url() : tab.primaryView->url(); + openNewTab(url); + m_tabBar->setCurrentIndex(m_viewTab.count() - 1); + } else if (selectedAction == closeOtherTabsAction) { + const int count = m_tabBar->count(); + for (int i = 0; i < index; ++i) { + closeTab(0); + } + for (int i = index + 1; i < count; ++i) { + closeTab(1); + } + } else if (selectedAction == closeTabAction) { + closeTab(index); + } +} + +void DolphinMainWindow::handlePlacesClick(const KUrl& url, Qt::MouseButtons buttons) +{ + if (buttons & Qt::MidButton) { + openNewTab(url); + m_tabBar->setCurrentIndex(m_viewTab.count() - 1); + } else { + changeUrl(url); + } +} + void DolphinMainWindow::init() { DolphinSettings& settings = DolphinSettings::instance(); @@ -643,7 +787,7 @@ void DolphinMainWindow::init() setAcceptDrops(true); - m_splitter = new QSplitter(this); + m_viewTab[m_tabIndex].splitter = new QSplitter(this); setupActions(); @@ -652,18 +796,38 @@ 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->setCloseButtonEnabled(true); + connect(m_tabBar, SIGNAL(currentChanged(int)), + this, SLOT(setActiveTab(int))); + connect(m_tabBar, SIGNAL(closeRequest(int)), + this, SLOT(closeTab(int))); + connect(m_tabBar, SIGNAL(contextMenu(int, const QPoint&)), + this, SLOT(openTabContextMenu(int, const QPoint&))); + connect(m_tabBar, SIGNAL(newTabRequest()), + this, SLOT(openNewTab())); + m_tabBar->blockSignals(true); // signals get unblocked after at least 2 tabs are open + + 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,14 +858,21 @@ 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; } m_activeViewContainer->setActive(false); m_activeViewContainer = viewContainer; + + // Activating the view container might trigger a recursive setActiveViewContainer() call + // inside DolphinMainWindow::toggleActiveView() when having a split view. Temporary + // disconnect the activated() signal in this case: + disconnect(m_activeViewContainer->view(), SIGNAL(activated()), this, SLOT(toggleActiveView())); m_activeViewContainer->setActive(true); + connect(m_activeViewContainer->view(), SIGNAL(activated()), this, SLOT(toggleActiveView())); m_actionHandler->setCurrentView(viewContainer->view()); @@ -712,6 +883,9 @@ void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContain const KUrl& url = m_activeViewContainer->url(); setCaption(url.fileName()); + if (m_viewTab.count() > 1) { + m_tabBar->setTabText(m_tabIndex, tabName(url)); + } emit urlChanged(url); } @@ -732,6 +906,17 @@ 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())); + + QAction* closeTab = new QAction(KIcon("tab-close"), i18nc("@action:inmenu File", "Close Tab"), this); + closeTab->setShortcut(Qt::CTRL | Qt::Key_W); + connect(closeTab, SIGNAL(triggered()), this, SLOT(closeTab())); + actionCollection()->addAction("close_tab", closeTab); + KAction* properties = actionCollection()->addAction("properties"); properties->setText(i18nc("@action:inmenu File", "Properties")); properties->setShortcut(Qt::ALT | Qt::Key_Return); @@ -793,10 +978,6 @@ void DolphinMainWindow::setupActions() editLocation->setShortcut(Qt::Key_F6); connect(editLocation, SIGNAL(triggered()), this, SLOT(editLocation())); - KAction* adjustViewProps = actionCollection()->addAction("view_properties"); - adjustViewProps->setText(i18nc("@action:inmenu View", "Adjust View Properties...")); - connect(adjustViewProps, SIGNAL(triggered()), this, SLOT(adjustViewProperties())); - // setup 'Go' menu KAction* backAction = KStandardAction::back(this, SLOT(goBack()), actionCollection()); KShortcut backShortcut = backAction->shortcut(); @@ -865,8 +1046,8 @@ void DolphinMainWindow::setupDockWidgets() addDockWidget(Qt::LeftDockWidgetArea, treeViewDock); connect(this, SIGNAL(urlChanged(KUrl)), treeWidget, SLOT(setUrl(KUrl))); - connect(treeWidget, SIGNAL(changeUrl(KUrl)), - this, SLOT(changeUrl(KUrl))); + connect(treeWidget, SIGNAL(changeUrl(KUrl, Qt::MouseButtons)), + this, SLOT(handlePlacesClick(KUrl, Qt::MouseButtons))); connect(treeWidget, SIGNAL(changeSelection(KFileItemList)), this, SLOT(changeSelection(KFileItemList))); connect(treeWidget, SIGNAL(urlsDropped(KUrl::List, KUrl)), @@ -913,8 +1094,8 @@ void DolphinMainWindow::setupDockWidgets() actionCollection()->addAction("show_places_panel", placesDock->toggleViewAction()); addDockWidget(Qt::LeftDockWidgetArea, placesDock); - connect(placesView, SIGNAL(urlChanged(KUrl)), - this, SLOT(changeUrl(KUrl))); + connect(placesView, SIGNAL(urlChanged(KUrl, Qt::MouseButtons)), + this, SLOT(handlePlacesClick(KUrl, Qt::MouseButtons))); connect(this, SIGNAL(urlChanged(KUrl)), placesView, SLOT(setUrl(KUrl))); } @@ -927,26 +1108,11 @@ void DolphinMainWindow::updateEditActions() } else { stateChanged("has_selection"); - QAction* renameAction = actionCollection()->action("rename"); - if (renameAction != 0) { - renameAction->setEnabled(true); - } - - bool enableMoveToTrash = true; - - KFileItemList::const_iterator it = list.begin(); - const KFileItemList::const_iterator end = list.end(); - while (it != end) { - const KUrl& url = (*it).url(); - // only enable the 'Move to Trash' action for local files - if (!url.isLocalFile()) { - enableMoveToTrash = false; - } - ++it; - } - - QAction* moveToTrashAction = actionCollection()->action("move_to_trash"); - moveToTrashAction->setEnabled(enableMoveToTrash); + FileItemCapabilities capabilities(list); + actionCollection()->action("rename")->setEnabled(capabilities.supportsMoving()); + const bool enableMoveToTrash = capabilities.isLocal() && capabilities.supportsMoving(); + actionCollection()->action("move_to_trash")->setEnabled(enableMoveToTrash); + actionCollection()->action("delete")->setEnabled(capabilities.supportsDeleting()); } updatePasteAction(); } @@ -977,9 +1143,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))); @@ -990,8 +1155,10 @@ void DolphinMainWindow::connectViewSignals(int viewIndex) this, SLOT(slotRequestItemInfo(KFileItem))); connect(view, SIGNAL(activated()), this, SLOT(toggleActiveView())); - connect(view, SIGNAL(doingOperation(KonqFileUndoManager::CommandType)), - this, SLOT(slotDoingOperation(KonqFileUndoManager::CommandType))); + connect(view, SIGNAL(doingOperation(KIO::FileUndoManager::CommandType)), + this, SLOT(slotDoingOperation(KIO::FileUndoManager::CommandType))); + connect(view, SIGNAL(tabRequested(const KUrl&)), + this, SLOT(openNewTab(const KUrl&))); const KUrlNavigator* navigator = container->urlNavigator(); connect(navigator, SIGNAL(urlChanged(const KUrl&)), @@ -1005,8 +1172,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,11 +1186,23 @@ void DolphinMainWindow::updateSplitAction() } } -DolphinMainWindow::UndoUiInterface::UndoUiInterface(DolphinMainWindow* mainWin) : - KonqFileUndoManager::UiInterface(mainWin), - m_mainWin(mainWin) +QString DolphinMainWindow::tabName(const KUrl& url) const +{ + QString name; + if (url.equals(KUrl("file:///"))) { + name = "/"; + } else { + name = url.fileName(); + if (name.isEmpty()) { + name = url.protocol(); + } + } + return name; +} + +DolphinMainWindow::UndoUiInterface::UndoUiInterface() : + KIO::FileUndoManager::UiInterface() { - Q_ASSERT(m_mainWin != 0); } DolphinMainWindow::UndoUiInterface::~UndoUiInterface() @@ -1032,8 +1211,13 @@ DolphinMainWindow::UndoUiInterface::~UndoUiInterface() void DolphinMainWindow::UndoUiInterface::jobError(KIO::Job* job) { - DolphinStatusBar* statusBar = m_mainWin->activeViewContainer()->statusBar(); - statusBar->setMessage(job->errorString(), DolphinStatusBar::Error); + DolphinMainWindow* mainWin= qobject_cast(parentWidget()); + if (mainWin) { + DolphinStatusBar* statusBar = mainWin->activeViewContainer()->statusBar(); + statusBar->setMessage(job->errorString(), DolphinStatusBar::Error); + } else { + KIO::FileUndoManager::UiInterface::jobError(job); + } } #include "dolphinmainwindow.moc"