X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/df5b974b1b2bb1f2c1a4a3418486457e2633aeaa..65b5d7d8e374700ec322617016b049c58a1fcecd:/src/dolphinmainwindow.cpp diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 2b60044ce..f9c9bf0df 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2006 by Peter Penz * + * Copyright (C) 2006 by Peter Penz * * Copyright (C) 2006 by Stefan Monov * * Copyright (C) 2006 by Cvetoslav Ludmiloff * * * @@ -20,24 +20,30 @@ ***************************************************************************/ #include "dolphinmainwindow.h" -#include "dolphinviewactionhandler.h" -#include "dolphinremoteencoding.h" #include -#include "search/dolphinsearchoptionsconfigurator.h" #include "dolphinapplication.h" -#include "dolphinnewmenu.h" -#include "search/dolphinsearchbox.h" -#include "settings/dolphinsettings.h" -#include "settings/dolphinsettingsdialog.h" +#include "dolphindockwidget.h" +#include "dolphincontextmenu.h" +#include "dolphinnewfilemenu.h" #include "dolphinviewcontainer.h" +#include "mainwindowadaptor.h" +#ifdef HAVE_NEPOMUK + #include "panels/search/searchpanel.h" + #include +#endif #include "panels/folders/folderspanel.h" #include "panels/places/placespanel.h" #include "panels/information/informationpanel.h" -#include "mainwindowadaptor.h" +#include "search/dolphinsearchinformation.h" +#include "settings/dolphinsettings.h" +#include "settings/dolphinsettingsdialog.h" #include "statusbar/dolphinstatusbar.h" -#include "viewproperties.h" +#include "views/dolphinviewactionhandler.h" +#include "views/dolphinremoteencoding.h" +#include "views/draganddrophelper.h" +#include "views/viewproperties.h" #ifndef Q_OS_WIN #include "panels/terminal/terminalpanel.h" @@ -45,47 +51,47 @@ #include "dolphin_generalsettings.h" #include "dolphin_iconsmodesettings.h" -#include "draganddrophelper.h" -#include -#include -#include -#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include #include -#include +#include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include #include -#include #include /* @@ -103,20 +109,25 @@ Q_DECLARE_METATYPE(ClosedTab) DolphinMainWindow::DolphinMainWindow(int id) : KXmlGuiWindow(0), - m_newMenu(0), + m_newFileMenu(0), m_showMenuBar(0), m_tabBar(0), m_activeViewContainer(0), m_centralWidgetLayout(0), - m_searchBox(0), - m_searchOptionsConfigurator(0), m_id(id), m_tabIndex(0), m_viewTab(), m_actionHandler(0), m_remoteEncoding(0), - m_settingsDialog(0) + m_settingsDialog(0), + m_lastHandleUrlStatJob(0), + m_searchDockIsTemporaryVisible(false) { + // Workaround for a X11-issue in combination with KModifierInfo + // (see DolphinContextMenu::initializeModifierKeyInfo() for + // more information): + DolphinContextMenu::initializeModifierKeyInfo(); + setObjectName("Dolphin#"); m_viewTab.append(ViewTab()); @@ -146,19 +157,71 @@ DolphinMainWindow::~DolphinMainWindow() DolphinApplication::app()->removeMainWindow(this); } -void DolphinMainWindow::toggleViews() +void DolphinMainWindow::openDirectories(const QList& dirs) { - if (m_viewTab[m_tabIndex].primaryView == 0) { + if (dirs.isEmpty()) { + return; + } + + if (dirs.count() == 1) { + m_activeViewContainer->setUrl(dirs.first()); return; } - // move secondary view from the last position of the splitter - // to the first position - m_viewTab[m_tabIndex].splitter->insertWidget(0, m_viewTab[m_tabIndex].secondaryView); + const int oldOpenTabsCount = m_viewTab.count(); - DolphinViewContainer* container = m_viewTab[m_tabIndex].primaryView; - m_viewTab[m_tabIndex].primaryView = m_viewTab[m_tabIndex].secondaryView; - m_viewTab[m_tabIndex].secondaryView = container; + const GeneralSettings* generalSettings = DolphinSettings::instance().generalSettings(); + const bool hasSplitView = generalSettings->splitView(); + + // Open each directory inside a new tab. If the "split view" option has been enabled, + // always show two directories within one tab. + QList::const_iterator it = dirs.begin(); + while (it != dirs.end()) { + openNewTab(*it); + ++it; + + if (hasSplitView && (it != dirs.end())) { + const int tabIndex = m_viewTab.count() - 1; + m_viewTab[tabIndex].secondaryView->setUrl(*it); + ++it; + } + } + + // remove the previously opened tabs + for (int i = 0; i < oldOpenTabsCount; ++i) { + closeTab(0); + } +} + +void DolphinMainWindow::openFiles(const QList& files) +{ + if (files.isEmpty()) { + return; + } + + // Get all distinct directories from 'files' and open a tab + // for each directory. If the "split view" option is enabled, two + // directories are shown inside one tab (see openDirectories()). + QList dirs; + foreach (const KUrl& url, files) { + const KUrl dir(url.directory()); + if (!dirs.contains(dir)) { + dirs.append(dir); + } + } + + openDirectories(dirs); + + // Select the files. Although the files can be split between several + // tabs, there is no need to split 'files' accordingly, as + // the DolphinView will just ignore invalid selections. + const int tabCount = m_viewTab.count(); + for (int i = 0; i < tabCount; ++i) { + m_viewTab[i].primaryView->view()->markUrlsAsSelected(files); + if (m_viewTab[i].secondaryView) { + m_viewTab[i].secondaryView->view()->markUrlsAsSelected(files); + } + } } void DolphinMainWindow::showCommand(CommandType command) @@ -198,7 +261,7 @@ void DolphinMainWindow::showCommand(CommandType command) void DolphinMainWindow::refreshViews() { - Q_ASSERT(m_viewTab[m_tabIndex].primaryView != 0); + Q_ASSERT(m_viewTab[m_tabIndex].primaryView); // remember the current active view, as because of // the refreshing the active view might change to @@ -208,12 +271,25 @@ void DolphinMainWindow::refreshViews() const int tabCount = m_viewTab.count(); for (int i = 0; i < tabCount; ++i) { m_viewTab[i].primaryView->refresh(); - if (m_viewTab[i].secondaryView != 0) { + if (m_viewTab[i].secondaryView) { m_viewTab[i].secondaryView->refresh(); } } setActiveViewContainer(activeViewContainer); + + const GeneralSettings* generalSettings = DolphinSettings::instance().generalSettings(); + if (generalSettings->modifiedStartupSettings()) { + // The startup settings have been changed by the user (see bug #254947). + // Synchronize the split-view setting with the active view: + const bool splitView = generalSettings->splitView(); + const ViewTab& activeTab = m_viewTab[m_tabIndex]; + const bool toggle = ( splitView && !activeTab.secondaryView) + || (!splitView && activeTab.secondaryView); + if (toggle) { + toggleSplitView(); + } + } } void DolphinMainWindow::pasteIntoFolder() @@ -231,7 +307,7 @@ void DolphinMainWindow::changeUrl(const KUrl& url) } DolphinViewContainer* view = activeViewContainer(); - if (view != 0) { + if (view) { view->setUrl(url); updateEditActions(); updateViewActions(); @@ -246,11 +322,6 @@ void DolphinMainWindow::changeUrl(const KUrl& url) } } -void DolphinMainWindow::changeSelection(const KFileItemList& selection) -{ - activeViewContainer()->view()->changeSelection(selection); -} - void DolphinMainWindow::slotEditableStateChanged(bool editable) { KToggleAction* editableLocationAction = @@ -262,9 +333,9 @@ void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection) { updateEditActions(); - Q_ASSERT(m_viewTab[m_tabIndex].primaryView != 0); + Q_ASSERT(m_viewTab[m_tabIndex].primaryView); int selectedUrlsCount = m_viewTab[m_tabIndex].primaryView->view()->selectedItemsCount(); - if (m_viewTab[m_tabIndex].secondaryView != 0) { + if (m_viewTab[m_tabIndex].secondaryView) { selectedUrlsCount += m_viewTab[m_tabIndex].secondaryView->view()->selectedItemsCount(); } @@ -278,15 +349,6 @@ void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection) emit selectionChanged(selection); } -void DolphinMainWindow::slotWheelMoved(int wheelDelta) -{ - if (wheelDelta > 0) { - activatePrevTab(); - } else { - activateNextTab(); - } -} - void DolphinMainWindow::slotRequestItemInfo(const KFileItem& item) { emit requestItemInfo(item); @@ -299,13 +361,13 @@ void DolphinMainWindow::updateHistory() QAction* backAction = actionCollection()->action("go_back"); backAction->setToolTip(i18nc("@info", "Go back")); - if (backAction != 0) { + if (backAction) { backAction->setEnabled(index < urlNavigator->historySize() - 1); } QAction* forwardAction = actionCollection()->action("go_forward"); forwardAction->setToolTip(i18nc("@info", "Go forward")); - if (forwardAction != 0) { + if (forwardAction) { forwardAction->setEnabled(index > 0); } } @@ -323,12 +385,18 @@ void DolphinMainWindow::openNewMainWindow() void DolphinMainWindow::openNewTab() { + const bool isUrlEditable = m_activeViewContainer->urlNavigator()->isUrlEditable(); + openNewTab(m_activeViewContainer->url()); m_tabBar->setCurrentIndex(m_viewTab.count() - 1); + // The URL navigator of the new tab should have the same editable state + // as the current tab KUrlNavigator* navigator = m_activeViewContainer->urlNavigator(); - if (navigator->isUrlEditable()) { - // if a new tab is opened and the URL is editable, assure that + navigator->setUrlEditable(isUrlEditable); + + if (isUrlEditable) { + // If a new tab is opened and the URL is editable, assure that // the user can edit the URL without manually setting the focus navigator->setFocus(); } @@ -336,23 +404,26 @@ void DolphinMainWindow::openNewTab() void DolphinMainWindow::openNewTab(const KUrl& url) { - const KIcon icon = KIcon(KMimeType::iconNameForUrl(m_activeViewContainer->url())); + QWidget* focusWidget = QApplication::focusWidget(); + 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(icon, squeezedText(tabName(m_activeViewContainer->url()))); + const KUrl currentUrl = m_activeViewContainer->url(); + m_tabBar->addTab(KIcon(KMimeType::iconNameForUrl(currentUrl)), + squeezedText(tabName(currentUrl))); m_tabBar->blockSignals(false); } - m_tabBar->addTab(icon, squeezedText(tabName(url))); + m_tabBar->addTab(KIcon(KMimeType::iconNameForUrl(url)), + squeezedText(tabName(url))); ViewTab viewTab; viewTab.splitter = new QSplitter(this); viewTab.splitter->setChildrenCollapsible(false); - viewTab.primaryView = new DolphinViewContainer(this, viewTab.splitter, url); + viewTab.primaryView = new DolphinViewContainer(url, viewTab.splitter); viewTab.primaryView->setActive(false); connectViewSignals(viewTab.primaryView); - viewTab.primaryView->view()->reload(); m_viewTab.append(viewTab); @@ -366,6 +437,12 @@ void DolphinMainWindow::openNewTab(const KUrl& url) m_viewTab[tabIndex].secondaryView->setActive(true); m_viewTab[tabIndex].isPrimaryViewActive = false; } + + if (focusWidget) { + // The DolphinViewContainer grabbed the keyboard focus. As the tab is opened + // in background, assure that the previous focused widget gets the focus back. + focusWidget->setFocus(); + } } void DolphinMainWindow::activateNextTab() @@ -394,36 +471,54 @@ void DolphinMainWindow::activatePrevTab() void DolphinMainWindow::openInNewTab() { const KFileItemList list = m_activeViewContainer->view()->selectedItems(); - if ((list.count() == 1) && list[0].isDir()) { - openNewTab(m_activeViewContainer->view()->selectedUrls()[0]); + if (list.isEmpty()) { + openNewTab(m_activeViewContainer->url()); + } else if ((list.count() == 1) && list[0].isDir()) { + openNewTab(list[0].url()); } } void DolphinMainWindow::openInNewWindow() { + KUrl newWindowUrl; + const KFileItemList list = m_activeViewContainer->view()->selectedItems(); - if ((list.count() == 1) && list[0].isDir()) { + if (list.isEmpty()) { + newWindowUrl = m_activeViewContainer->url(); + } else if ((list.count() == 1) && list[0].isDir()) { + newWindowUrl = list[0].url(); + } + + if (!newWindowUrl.isEmpty()) { DolphinMainWindow* window = DolphinApplication::app()->createMainWindow(); - window->changeUrl(m_activeViewContainer->view()->selectedUrls()[0]); + window->changeUrl(newWindowUrl); window->show(); } } void DolphinMainWindow::toggleActiveView() { - if (m_viewTab[m_tabIndex].secondaryView == 0) { + if (!m_viewTab[m_tabIndex].secondaryView) { // only one view is available return; } - Q_ASSERT(m_activeViewContainer != 0); - Q_ASSERT(m_viewTab[m_tabIndex].primaryView != 0); + Q_ASSERT(m_activeViewContainer); + Q_ASSERT(m_viewTab[m_tabIndex].primaryView); DolphinViewContainer* left = m_viewTab[m_tabIndex].primaryView; DolphinViewContainer* right = m_viewTab[m_tabIndex].secondaryView; setActiveViewContainer(m_activeViewContainer == right ? left : right); } +void DolphinMainWindow::showEvent(QShowEvent* event) +{ + KXmlGuiWindow::showEvent(event); + if (!event->spontaneous()) { + m_activeViewContainer->view()->setFocus(); + } +} + void DolphinMainWindow::closeEvent(QCloseEvent* event) { DolphinSettings& settings = DolphinSettings::instance(); @@ -447,7 +542,6 @@ void DolphinMainWindow::closeEvent(QCloseEvent* event) dialog->setCaption(i18nc("@title:window", "Confirmation")); dialog->setButtons(KDialog::Yes | KDialog::No | KDialog::Cancel); dialog->setModal(true); - dialog->showButtonSeparator(true); dialog->setButtonGuiItem(KDialog::Yes, KStandardGuiItem::quit()); dialog->setButtonGuiItem(KDialog::No, KGuiItem(i18n("C&lose Current Tab"), KIcon("tab-close"))); dialog->setButtonGuiItem(KDialog::Cancel, KStandardGuiItem::cancel()); @@ -473,7 +567,7 @@ void DolphinMainWindow::closeEvent(QCloseEvent* event) break; case KDialog::No: // Close only the current tab - closeTab(); + closeTab(); default: event->ignore(); return; @@ -484,6 +578,14 @@ void DolphinMainWindow::closeEvent(QCloseEvent* event) settings.save(); + if (m_searchDockIsTemporaryVisible) { + QDockWidget* searchDock = findChild("searchDock"); + if (searchDock) { + searchDock->hide(); + } + m_searchDockIsTemporaryVisible = false; + } + KXmlGuiWindow::closeEvent(event); } @@ -496,12 +598,14 @@ void DolphinMainWindow::saveProperties(KConfigGroup& group) for (int i = 0; i < tabCount; ++i) { const DolphinViewContainer* cont = m_viewTab[i].primaryView; group.writeEntry(tabProperty("Primary URL", i), cont->url().url()); - group.writeEntry(tabProperty("Primary Editable", i), cont->isUrlEditable()); + group.writeEntry(tabProperty("Primary Editable", i), + cont->urlNavigator()->isUrlEditable()); cont = m_viewTab[i].secondaryView; - if (cont != 0) { + if (cont) { group.writeEntry(tabProperty("Secondary URL", i), cont->url().url()); - group.writeEntry(tabProperty("Secondary Editable", i), cont->isUrlEditable()); + group.writeEntry(tabProperty("Secondary Editable", i), + cont->urlNavigator()->isUrlEditable()); } } } @@ -519,18 +623,18 @@ void DolphinMainWindow::readProperties(const KConfigGroup& group) cont = m_viewTab[i].secondaryView; const QString secondaryUrl = group.readEntry(tabProperty("Secondary URL", i)); if (!secondaryUrl.isEmpty()) { - if (cont == 0) { + if (!cont) { // a secondary view should be shown, but no one is available // currently -> create a new view toggleSplitView(); cont = m_viewTab[i].secondaryView; - Q_ASSERT(cont != 0); + Q_ASSERT(cont); } cont->setUrl(secondaryUrl); const bool editable = group.readEntry(tabProperty("Secondary Editable", i), false); cont->urlNavigator()->setUrlEditable(editable); - } else if (cont != 0) { + } else if (cont) { // no secondary view should be shown, but the default setting shows // one already -> close the view toggleSplitView(); @@ -548,14 +652,16 @@ void DolphinMainWindow::readProperties(const KConfigGroup& group) void DolphinMainWindow::updateNewMenu() { - m_newMenu->slotCheckUpToDate(); - m_newMenu->setPopupFiles(activeViewContainer()->url()); + m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->showHiddenFiles()); + m_newFileMenu->checkUpToDate(); + m_newFileMenu->setPopupFiles(activeViewContainer()->url()); } void DolphinMainWindow::createDirectory() { - m_newMenu->setPopupFiles(activeViewContainer()->url()); - m_newMenu->createDirectory(); + m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->showHiddenFiles()); + m_newFileMenu->setPopupFiles(activeViewContainer()->url()); + m_newFileMenu->createDirectory(); } void DolphinMainWindow::quit() @@ -574,7 +680,7 @@ void DolphinMainWindow::showErrorMessage(const QString& message) void DolphinMainWindow::slotUndoAvailable(bool available) { QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo)); - if (undoAction != 0) { + if (undoAction) { undoAction->setEnabled(available); } } @@ -611,7 +717,7 @@ void DolphinMainWindow::restoreClosedTab(QAction* action) void DolphinMainWindow::slotUndoTextChanged(const QString& text) { QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo)); - if (undoAction != 0) { + if (undoAction) { undoAction->setText(text); } } @@ -638,6 +744,11 @@ void DolphinMainWindow::paste() m_activeViewContainer->view()->paste(); } +void DolphinMainWindow::find() +{ + m_activeViewContainer->setSearchModeEnabled(true); +} + void DolphinMainWindow::updatePasteAction() { QAction* pasteAction = actionCollection()->action(KStandardAction::name(KStandardAction::Paste)); @@ -672,7 +783,7 @@ void DolphinMainWindow::invertSelection() void DolphinMainWindow::toggleSplitView() { - if (m_viewTab[m_tabIndex].secondaryView == 0) { + if (!m_viewTab[m_tabIndex].secondaryView) { createSecondaryView(m_tabIndex); setActiveViewContainer(m_viewTab[m_tabIndex].secondaryView); } else if (m_activeViewContainer == m_viewTab[m_tabIndex].secondaryView) { @@ -707,11 +818,22 @@ void DolphinMainWindow::reloadView() void DolphinMainWindow::stopLoading() { + m_activeViewContainer->view()->stopLoading(); +} + +void DolphinMainWindow::enableStopAction() +{ + actionCollection()->action("stop")->setEnabled(true); } -void DolphinMainWindow::toggleFilterBarVisibility(bool show) +void DolphinMainWindow::disableStopAction() { - m_activeViewContainer->showFilterBar(show); + actionCollection()->action("stop")->setEnabled(false); +} + +void DolphinMainWindow::showFilterBar() +{ + m_activeViewContainer->setFilterBarVisible(true); } void DolphinMainWindow::toggleEditLocation() @@ -731,14 +853,36 @@ void DolphinMainWindow::replaceLocation() // select the whole text of the combo box editor QLineEdit* lineEdit = navigator->editor()->lineEdit(); // krazy:exclude=qclasses - const QString text = lineEdit->text(); - lineEdit->setSelection(0, text.length()); + lineEdit->selectAll(); +} + +void DolphinMainWindow::togglePanelLockState() +{ + GeneralSettings* generalSettings = DolphinSettings::instance().generalSettings(); + + const bool newLockState = !generalSettings->lockPanels(); + foreach (QObject* child, children()) { + DolphinDockWidget* dock = qobject_cast(child); + if (dock) { + dock->setLocked(newLockState); + } + } + + generalSettings->setLockPanels(newLockState); } void DolphinMainWindow::goBack() { clearStatusBar(); - m_activeViewContainer->urlNavigator()->goBack(); + + KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator(); + urlNavigator->goBack(); + + if (urlNavigator->locationState().isEmpty()) { + // An empty location state indicates a redirection URL, + // which must be skipped too + urlNavigator->goBack(); + } } void DolphinMainWindow::goForward() @@ -758,7 +902,8 @@ void DolphinMainWindow::goBack(Qt::MouseButtons buttons) // The default case (left button pressed) is handled in goBack(). if (buttons == Qt::MidButton) { KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator(); - openNewTab(urlNavigator->historyUrl(urlNavigator->historyIndex() + 1)); + const int index = urlNavigator->historyIndex() + 1; + openNewTab(urlNavigator->locationUrl(index)); } } @@ -767,7 +912,8 @@ void DolphinMainWindow::goForward(Qt::MouseButtons buttons) // The default case (left button pressed) is handled in goForward(). if (buttons == Qt::MidButton) { KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator(); - openNewTab(urlNavigator->historyUrl(urlNavigator->historyIndex() - 1)); + const int index = urlNavigator->historyIndex() - 1; + openNewTab(urlNavigator->locationUrl(index)); } } @@ -793,34 +939,35 @@ void DolphinMainWindow::compareFiles() // - both in the secondary view // - one in the primary view and the other in the secondary // view - Q_ASSERT(m_viewTab[m_tabIndex].primaryView != 0); + Q_ASSERT(m_viewTab[m_tabIndex].primaryView); KUrl urlA; KUrl urlB; - KUrl::List urls = m_viewTab[m_tabIndex].primaryView->view()->selectedUrls(); - switch (urls.count()) { + KFileItemList items = m_viewTab[m_tabIndex].primaryView->view()->selectedItems(); + + switch (items.count()) { case 0: { - 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]; + Q_ASSERT(m_viewTab[m_tabIndex].secondaryView); + items = m_viewTab[m_tabIndex].secondaryView->view()->selectedItems(); + Q_ASSERT(items.count() == 2); + urlA = items[0].url(); + urlB = items[1].url(); break; } case 1: { - urlA = urls[0]; - Q_ASSERT(m_viewTab[m_tabIndex].secondaryView != 0); - urls = m_viewTab[m_tabIndex].secondaryView->view()->selectedUrls(); - Q_ASSERT(urls.count() == 1); - urlB = urls[0]; + urlA = items[0].url(); + Q_ASSERT(m_viewTab[m_tabIndex].secondaryView); + items = m_viewTab[m_tabIndex].secondaryView->view()->selectedItems(); + Q_ASSERT(items.count() == 1); + urlB = items[0].url(); break; } case 2: { - urlA = urls[0]; - urlB = urls[1]; + urlA = items[0].url(); + urlB = items[1].url(); break; } @@ -863,8 +1010,8 @@ void DolphinMainWindow::openTerminal() void DolphinMainWindow::editSettings() { - if (m_settingsDialog == 0) { - const KUrl& url = activeViewContainer()->url(); + if (!m_settingsDialog) { + const KUrl url = activeViewContainer()->url(); m_settingsDialog = new DolphinSettingsDialog(url, this); m_settingsDialog->setAttribute(Qt::WA_DeleteOnClose); m_settingsDialog->show(); @@ -885,7 +1032,7 @@ void DolphinMainWindow::setActiveTab(int index) ViewTab& hiddenTab = m_viewTab[m_tabIndex]; hiddenTab.isPrimaryViewActive = hiddenTab.primaryView->isActive(); hiddenTab.primaryView->setActive(false); - if (hiddenTab.secondaryView != 0) { + if (hiddenTab.secondaryView) { hiddenTab.secondaryView->setActive(false); } QSplitter* splitter = m_viewTab[m_tabIndex].splitter; @@ -898,7 +1045,7 @@ void DolphinMainWindow::setActiveTab(int index) ViewTab& viewTab = m_viewTab[index]; m_centralWidgetLayout->addWidget(viewTab.splitter, 1); viewTab.primaryView->show(); - if (viewTab.secondaryView != 0) { + if (viewTab.secondaryView) { viewTab.secondaryView->show(); } viewTab.splitter->show(); @@ -930,7 +1077,7 @@ void DolphinMainWindow::closeTab(int index) // delete tab m_viewTab[index].primaryView->deleteLater(); - if (m_viewTab[index].secondaryView != 0) { + if (m_viewTab[index].secondaryView) { m_viewTab[index].secondaryView->deleteLater(); } m_viewTab[index].splitter->deleteLater(); @@ -961,6 +1108,8 @@ void DolphinMainWindow::openTabContextMenu(int index, const QPoint& pos) QAction* newTabAction = menu.addAction(KIcon("tab-new"), i18nc("@action:inmenu", "New Tab")); newTabAction->setShortcut(actionCollection()->action("new_tab")->shortcut()); + QAction* detachTabAction = menu.addAction(KIcon("tab-detach"), i18nc("@action:inmenu", "Detach Tab")); + 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")); @@ -968,11 +1117,32 @@ void DolphinMainWindow::openTabContextMenu(int index, const QPoint& pos) 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() ? + Q_ASSERT(tab.primaryView); + const KUrl url = tab.secondaryView && tab.secondaryView->isActive() ? tab.secondaryView->url() : tab.primaryView->url(); openNewTab(url); m_tabBar->setCurrentIndex(m_viewTab.count() - 1); + } else if (selectedAction == detachTabAction) { + const ViewTab& tab = m_viewTab[index]; + Q_ASSERT(tab.primaryView); + const KUrl primaryUrl = tab.primaryView->url(); + DolphinMainWindow* window = DolphinApplication::app()->createMainWindow(); + window->changeUrl(primaryUrl); + + if (tab.secondaryView) { + const KUrl secondaryUrl = tab.secondaryView->url(); + if (!window->m_viewTab[0].secondaryView) { + window->toggleSplitView(); + } + window->m_viewTab[0].secondaryView->setUrl(secondaryUrl); + if (tab.primaryView->isActive()) { + window->m_viewTab[0].primaryView->setActive(true); + } else { + window->m_viewTab[0].secondaryView->setActive(true); + } + } + window->show(); + closeTab(index); } else if (selectedAction == closeOtherTabsAction) { const int count = m_tabBar->count(); for (int i = 0; i < index; ++i) { @@ -986,6 +1156,12 @@ void DolphinMainWindow::openTabContextMenu(int index, const QPoint& pos) } } +void DolphinMainWindow::slotTabMoved(int from, int to) +{ + m_viewTab.move(from, to); + m_tabIndex = m_tabBar->currentIndex(); +} + void DolphinMainWindow::handlePlacesClick(const KUrl& url, Qt::MouseButtons buttons) { if (buttons & Qt::MidButton) { @@ -1001,35 +1177,109 @@ void DolphinMainWindow::slotTestCanDecode(const QDragMoveEvent* event, bool& can canDecode = KUrl::List::canDecode(event->mimeData()); } -void DolphinMainWindow::searchItems() +void DolphinMainWindow::handleUrl(const KUrl& url) { - const QString searchOptions = m_searchOptionsConfigurator->options(); + delete m_lastHandleUrlStatJob; + m_lastHandleUrlStatJob = 0; + + if (url.isLocalFile() && QFileInfo(url.toLocalFile()).isDir()) { + activeViewContainer()->setUrl(url); + } else if (KProtocolManager::supportsListing(url)) { + // stat the URL to see if it is a dir or not + m_lastHandleUrlStatJob = KIO::stat(url, KIO::HideProgressInfo); + connect(m_lastHandleUrlStatJob, SIGNAL(result(KJob*)), + this, SLOT(slotHandleUrlStatFinished(KJob*))); + + } else { + new KRun(url, this); + } +} - QString searchString = m_searchBox->text(); - if (!searchString.isEmpty() && !searchOptions.isEmpty()) { - searchString += ' ' + searchOptions; - } else if (!searchOptions.isEmpty()) { - searchString += searchOptions; +void DolphinMainWindow::slotHandleUrlStatFinished(KJob* job) +{ + m_lastHandleUrlStatJob = 0; + const KIO::UDSEntry entry = static_cast(job)->statResult(); + const KUrl url = static_cast(job)->url(); + if (entry.isDir()) { + activeViewContainer()->setUrl(url); + } else { + new KRun(url, this); } +} - if (!searchString.isEmpty()) { - m_activeViewContainer->setUrl(KUrl("nepomuksearch:/" + searchString)); +void DolphinMainWindow::tabDropEvent(int tab, QDropEvent* event) +{ + const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); + if (!urls.isEmpty() && tab != -1) { + const ViewTab& viewTab = m_viewTab[tab]; + const KUrl destPath = viewTab.isPrimaryViewActive ? viewTab.primaryView->url() : viewTab.secondaryView->url(); + DragAndDropHelper::instance().dropUrls(KFileItem(), destPath, event, m_tabBar); } } -void DolphinMainWindow::slotTabMoved(int from, int to) +void DolphinMainWindow::slotWriteStateChanged(bool isFolderWritable) { - m_viewTab.move(from, to); - m_tabIndex = m_tabBar->currentIndex(); + newFileMenu()->setEnabled(isFolderWritable); } -void DolphinMainWindow::showSearchOptions() +void DolphinMainWindow::slotSearchModeChanged(bool enabled) { #ifdef HAVE_NEPOMUK - m_searchOptionsConfigurator->show(); + const KUrl url = m_activeViewContainer->url(); + const DolphinSearchInformation& searchInfo = DolphinSearchInformation::instance(); + if (!searchInfo.isIndexingEnabled() || !searchInfo.isPathIndexed(url)) { + return; + } + + QDockWidget* searchDock = findChild("searchDock"); + if (!searchDock) { + return; + } + + if (enabled) { + if (!searchDock->isVisible()) { + m_searchDockIsTemporaryVisible = true; + } + searchDock->show(); + } else { + if (searchDock->isVisible() && m_searchDockIsTemporaryVisible) { + searchDock->hide(); + } + m_searchDockIsTemporaryVisible = false; + } +#else + Q_UNUSED(enabled); #endif } +void DolphinMainWindow::openContextMenu(const KFileItem& item, + const KUrl& url, + const QList& customActions) +{ + QPointer contextMenu = new DolphinContextMenu(this, item, url); + contextMenu->setCustomActions(customActions); + const DolphinContextMenu::Command command = contextMenu->open(); + + switch (command) { + case DolphinContextMenu::OpenParentFolderInNewWindow: { + DolphinMainWindow* window = DolphinApplication::app()->createMainWindow(); + window->changeUrl(item.url().upUrl()); + window->show(); + break; + } + + case DolphinContextMenu::OpenParentFolderInNewTab: + openNewTab(item.url().upUrl()); + break; + + case DolphinContextMenu::None: + default: + break; + } + + delete contextMenu; +} + void DolphinMainWindow::init() { DolphinSettings& settings = DolphinSettings::instance(); @@ -1049,20 +1299,18 @@ void DolphinMainWindow::init() setupActions(); - const KUrl& homeUrl = generalSettings->homeUrl(); + const KUrl homeUrl(generalSettings->homeUrl()); setUrlAsCaption(homeUrl); m_actionHandler = new DolphinViewActionHandler(actionCollection(), this); connect(m_actionHandler, SIGNAL(actionBeingHandled()), SLOT(clearStatusBar())); connect(m_actionHandler, SIGNAL(createDirectory()), SLOT(createDirectory())); ViewProperties props(homeUrl); - m_viewTab[m_tabIndex].primaryView = new DolphinViewContainer(this, - m_viewTab[m_tabIndex].splitter, - homeUrl); + m_viewTab[m_tabIndex].primaryView = new DolphinViewContainer(homeUrl, + m_viewTab[m_tabIndex].splitter); m_activeViewContainer = m_viewTab[m_tabIndex].primaryView; connectViewSignals(m_activeViewContainer); DolphinView* view = m_activeViewContainer->view(); - view->reload(); m_activeViewContainer->show(); m_actionHandler->setCurrentView(view); @@ -1070,13 +1318,6 @@ void DolphinMainWindow::init() connect(this, SIGNAL(urlChanged(const KUrl&)), m_remoteEncoding, SLOT(slotAboutToOpenUrl())); -#ifdef HAVE_NEPOMUK - m_searchOptionsConfigurator = new DolphinSearchOptionsConfigurator(this); - m_searchOptionsConfigurator->hide(); - connect(m_searchOptionsConfigurator, SIGNAL(searchOptionsChanged(QString)), - this, SLOT(searchItems())); -#endif - m_tabBar = new KTabBar(this); m_tabBar->setMovable(true); m_tabBar->setTabsClosable(true); @@ -1090,12 +1331,12 @@ void DolphinMainWindow::init() this, SLOT(openNewTab())); connect(m_tabBar, SIGNAL(testCanDecode(const QDragMoveEvent*, bool&)), this, SLOT(slotTestCanDecode(const QDragMoveEvent*, bool&))); - connect(m_tabBar, SIGNAL(wheelDelta(int)), - this, SLOT(slotWheelMoved(int))); connect(m_tabBar, SIGNAL(mouseMiddleClick(int)), this, SLOT(closeTab(int))); connect(m_tabBar, SIGNAL(tabMoved(int, int)), this, SLOT(slotTabMoved(int, int))); + connect(m_tabBar, SIGNAL(receivedDropEvent(int, QDropEvent*)), + this, SLOT(tabDropEvent(int, QDropEvent*))); m_tabBar->blockSignals(true); // signals get unblocked after at least 2 tabs are open @@ -1103,9 +1344,6 @@ void DolphinMainWindow::init() m_centralWidgetLayout = new QVBoxLayout(centralWidget); m_centralWidgetLayout->setSpacing(0); m_centralWidgetLayout->setMargin(0); -#ifdef HAVE_NEPOMUK - m_centralWidgetLayout->addWidget(m_searchOptionsConfigurator); -#endif m_centralWidgetLayout->addWidget(m_tabBar); m_centralWidgetLayout->addWidget(m_viewTab[m_tabIndex].splitter, 1); @@ -1114,24 +1352,18 @@ void DolphinMainWindow::init() emit urlChanged(homeUrl); setupGUI(Keys | Save | Create | ToolBar); - - m_searchBox->setParent(toolBar("searchToolBar")); - m_searchBox->show(); - connect(m_searchBox, SIGNAL(requestSearchOptions()), - this, SLOT(showSearchOptions())); - stateChanged("new_file"); QClipboard* clipboard = QApplication::clipboard(); connect(clipboard, SIGNAL(dataChanged()), this, SLOT(updatePasteAction())); - updatePasteAction(); - updateGoActions(); if (generalSettings->splitView()) { toggleSplitView(); } + updateEditActions(); updateViewActions(); + updateGoActions(); QAction* showFilterBarAction = actionCollection()->action("show_filter_bar"); showFilterBarAction->setChecked(generalSettings->filterBar()); @@ -1146,7 +1378,7 @@ void DolphinMainWindow::init() void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContainer) { - Q_ASSERT(viewContainer != 0); + Q_ASSERT(viewContainer); Q_ASSERT((viewContainer == m_viewTab[m_tabIndex].primaryView) || (viewContainer == m_viewTab[m_tabIndex].secondaryView)); if (m_activeViewContainer == viewContainer) { @@ -1170,9 +1402,9 @@ void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContain updateViewActions(); updateGoActions(); - const KUrl& url = m_activeViewContainer->url(); + const KUrl url = m_activeViewContainer->url(); setUrlAsCaption(url); - if (m_viewTab.count() > 1 && m_viewTab[m_tabIndex].secondaryView != 0) { + if (m_viewTab.count() > 1) { m_tabBar->setTabText(m_tabIndex, tabName(url)); m_tabBar->setTabIcon(m_tabIndex, KIcon(KMimeType::iconNameForUrl(url))); } @@ -1183,8 +1415,8 @@ void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContain void DolphinMainWindow::setupActions() { // setup 'File' menu - m_newMenu = new DolphinNewMenu(this, this); - KMenu* menu = m_newMenu->menu(); + m_newFileMenu = new DolphinNewFileMenu(this); + KMenu* menu = m_newFileMenu->menu(); menu->setTitle(i18nc("@title:menu Create new folder, file, link, etc.", "Create New")); menu->setIcon(KIcon("document-new")); connect(menu, SIGNAL(aboutToShow()), @@ -1220,7 +1452,7 @@ void DolphinMainWindow::setupActions() // doesn't work KAction* cut = KStandardAction::cut(this, SLOT(cut()), actionCollection()); KShortcut cutShortcut = cut->shortcut(); - cutShortcut.remove(Qt::SHIFT + Qt::Key_Delete, KShortcut::KeepEmpty); + cutShortcut.remove(Qt::SHIFT | Qt::Key_Delete, KShortcut::KeepEmpty); cut->setShortcut(cutShortcut); KStandardAction::copy(this, SLOT(copy()), actionCollection()); KAction* paste = KStandardAction::paste(this, SLOT(paste()), actionCollection()); @@ -1229,9 +1461,11 @@ void DolphinMainWindow::setupActions() // due to the long text, the text "Paste" is used: paste->setIconText(i18nc("@action:inmenu Edit", "Paste")); + KStandardAction::find(this, SLOT(find()), actionCollection()); + KAction* selectAll = actionCollection()->addAction("select_all"); selectAll->setText(i18nc("@action:inmenu Edit", "Select All")); - selectAll->setShortcut(Qt::CTRL + Qt::Key_A); + selectAll->setShortcut(Qt::CTRL | Qt::Key_A); connect(selectAll, SIGNAL(triggered()), this, SLOT(selectAll())); KAction* invertSelection = actionCollection()->addAction("invert_selection"); @@ -1298,16 +1532,11 @@ void DolphinMainWindow::setupActions() KStandardAction::home(this, SLOT(goHome()), actionCollection()); // setup 'Tools' menu - KToggleAction* showSearchBar = actionCollection()->add("show_search_bar"); - showSearchBar->setText(i18nc("@action:inmenu Tools", "Show Search Bar")); - showSearchBar->setShortcut(Qt::CTRL | Qt::Key_S); - connect(showSearchBar, SIGNAL(triggered(bool)), this, SLOT(toggleFilterBarVisibility(bool))); - - KToggleAction* showFilterBar = actionCollection()->add("show_filter_bar"); + KAction* showFilterBar = actionCollection()->addAction("show_filter_bar"); showFilterBar->setText(i18nc("@action:inmenu Tools", "Show Filter Bar")); showFilterBar->setIcon(KIcon("view-filter")); showFilterBar->setShortcut(Qt::CTRL | Qt::Key_I); - connect(showFilterBar, SIGNAL(triggered(bool)), this, SLOT(toggleFilterBarVisibility(bool))); + connect(showFilterBar, SIGNAL(triggered()), this, SLOT(showFilterBar())); KAction* compareFiles = actionCollection()->addAction("compare_files"); compareFiles->setText(i18nc("@action:inmenu Tools", "Compare Files")); @@ -1326,17 +1555,23 @@ void DolphinMainWindow::setupActions() KStandardAction::preferences(this, SLOT(editSettings()), actionCollection()); // not in menu actions + QList nextTabKeys; + nextTabKeys.append(KStandardShortcut::tabNext().primary()); + nextTabKeys.append(QKeySequence(Qt::CTRL | Qt::Key_Tab)); + + QList prevTabKeys; + prevTabKeys.append(KStandardShortcut::tabPrev().primary()); + prevTabKeys.append(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_Tab)); + KAction* activateNextTab = actionCollection()->addAction("activate_next_tab"); activateNextTab->setText(i18nc("@action:inmenu", "Activate Next Tab")); connect(activateNextTab, SIGNAL(triggered()), SLOT(activateNextTab())); - activateNextTab->setShortcuts(QApplication::isRightToLeft() ? KStandardShortcut::tabPrev() : - KStandardShortcut::tabNext()); + activateNextTab->setShortcuts(QApplication::isRightToLeft() ? prevTabKeys : nextTabKeys); KAction* activatePrevTab = actionCollection()->addAction("activate_prev_tab"); activatePrevTab->setText(i18nc("@action:inmenu", "Activate Previous Tab")); connect(activatePrevTab, SIGNAL(triggered()), SLOT(activatePrevTab())); - activatePrevTab->setShortcuts(QApplication::isRightToLeft() ? KStandardShortcut::tabNext() : - KStandardShortcut::tabPrev()); + activatePrevTab->setShortcuts(QApplication::isRightToLeft() ? nextTabKeys : prevTabKeys); // for context menu KAction* openInNewTab = actionCollection()->addAction("open_in_new_tab"); @@ -1348,32 +1583,34 @@ void DolphinMainWindow::setupActions() openInNewWindow->setText(i18nc("@action:inmenu", "Open in New Window")); openInNewWindow->setIcon(KIcon("window-new")); connect(openInNewWindow, SIGNAL(triggered()), this, SLOT(openInNewWindow())); - - // 'Search' toolbar - m_searchBox = new DolphinSearchBox(this); - connect(m_searchBox, SIGNAL(search(QString)), this, SLOT(searchItems())); - - KAction* search = new KAction(this); - actionCollection()->addAction("search_bar", search); - search->setText(i18nc("@action:inmenu", "Search Bar")); - search->setDefaultWidget(m_searchBox); - search->setShortcutConfigurable(false); } 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); QAction* infoAction = infoDock->toggleViewAction(); - infoAction->setText(i18nc("@title:window", "Information")); - infoAction->setShortcut(Qt::Key_F11); infoAction->setIcon(KIcon("dialog-information")); - actionCollection()->addAction("show_info_panel", infoDock->toggleViewAction()); + infoAction->setShortcut(Qt::Key_F11); + addActionCloneToCollection(infoAction, "show_information_panel"); addDockWidget(Qt::RightDockWidgetArea, infoDock); connect(this, SIGNAL(urlChanged(KUrl)), @@ -1383,76 +1620,123 @@ 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(); - foldersAction->setText(i18nc("@title:window", "Folders")); foldersAction->setShortcut(Qt::Key_F7); foldersAction->setIcon(KIcon("folder")); - actionCollection()->addAction("show_folders_panel", foldersDock->toggleViewAction()); + addActionCloneToCollection(foldersAction, "show_folders_panel"); addDockWidget(Qt::LeftDockWidgetArea, foldersDock); connect(this, SIGNAL(urlChanged(KUrl)), foldersPanel, SLOT(setUrl(KUrl))); connect(foldersPanel, SIGNAL(changeUrl(KUrl, Qt::MouseButtons)), this, SLOT(handlePlacesClick(KUrl, Qt::MouseButtons))); - connect(foldersPanel, SIGNAL(changeSelection(KFileItemList)), - this, SLOT(changeSelection(KFileItemList))); - // 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())); QAction* terminalAction = terminalDock->toggleViewAction(); - terminalAction->setText(i18nc("@title:window Shell terminal", "Terminal")); terminalAction->setShortcut(Qt::Key_F4); terminalAction->setIcon(KIcon("utilities-terminal")); - actionCollection()->addAction("show_terminal_panel", terminalDock->toggleViewAction()); + addActionCloneToCollection(terminalAction, "show_terminal_panel"); addDockWidget(Qt::BottomDockWidgetArea, terminalDock); connect(this, SIGNAL(urlChanged(KUrl)), terminalPanel, SLOT(setUrl(KUrl))); #endif + // Setup "Search" +#ifdef HAVE_NEPOMUK + DolphinDockWidget* searchDock = new DolphinDockWidget(i18nc("@title:window", "Search")); + searchDock->setLocked(lock); + searchDock->setObjectName("searchDock"); + searchDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + Panel* searchPanel = new SearchPanel(searchDock); + searchPanel->setCustomContextMenuActions(QList() << lockLayoutAction); + connect(searchPanel, SIGNAL(urlActivated(KUrl)), this, SLOT(handleUrl(KUrl))); + searchDock->setWidget(searchPanel); + + QAction* searchAction = searchDock->toggleViewAction(); + searchAction->setShortcut(Qt::Key_F12); + searchAction->setIcon(KIcon("system-search")); + addActionCloneToCollection(searchAction, "show_search_panel"); + addDockWidget(Qt::RightDockWidgetArea, searchDock); + connect(this, SIGNAL(urlChanged(KUrl)), + searchPanel, SLOT(setUrl(KUrl))); +#endif + const bool firstRun = DolphinSettings::instance().generalSettings()->firstRun(); if (firstRun) { + infoDock->hide(); foldersDock->hide(); #ifndef Q_OS_WIN terminalDock->hide(); +#endif +#ifdef HAVE_NEPOMUK + searchDock->hide(); #endif } - 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); + QAction* separator = new QAction(placesPanel); + separator->setSeparator(true); + QList placesActions; + placesActions.append(separator); + placesActions.append(lockLayoutAction); + placesPanel->addActions(placesActions); placesPanel->setModel(DolphinSettings::instance().placesModel()); placesPanel->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + placesDock->setWidget(placesPanel); QAction* placesAction = placesDock->toggleViewAction(); - placesAction->setText(i18nc("@title:window", "Places")); placesAction->setShortcut(Qt::Key_F9); placesAction->setIcon(KIcon("bookmarks")); - actionCollection()->addAction("show_places_panel", placesDock->toggleViewAction()); + addActionCloneToCollection(placesAction, "show_places_panel"); addDockWidget(Qt::LeftDockWidgetArea, placesDock); connect(placesPanel, SIGNAL(urlChanged(KUrl, Qt::MouseButtons)), this, SLOT(handlePlacesClick(KUrl, Qt::MouseButtons))); 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); + panelsMenu->addAction(placesAction); + panelsMenu->addAction(infoAction); + panelsMenu->addAction(foldersAction); +#ifndef Q_OS_WIN + panelsMenu->addAction(terminalAction); +#endif +#ifdef HAVE_NEPOMUK + panelsMenu->addAction(searchAction); +#endif + panelsMenu->addSeparator(); + panelsMenu->addAction(lockLayoutAction); } void DolphinMainWindow::updateEditActions() @@ -1499,7 +1783,7 @@ void DolphinMainWindow::updateViewActions() void DolphinMainWindow::updateGoActions() { QAction* goUpAction = actionCollection()->action(KStandardAction::name(KStandardAction::Up)); - const KUrl& currentUrl = m_activeViewContainer->url(); + const KUrl currentUrl = m_activeViewContainer->url(); goUpAction->setEnabled(currentUrl.upUrl() != currentUrl); } @@ -1515,7 +1799,7 @@ void DolphinMainWindow::rememberClosedTab(int index) ClosedTab closedTab; closedTab.primaryUrl = m_viewTab[index].primaryView->url(); - if (m_viewTab[index].secondaryView != 0) { + if (m_viewTab[index].secondaryView) { closedTab.secondaryUrl = m_viewTab[index].secondaryView->url(); closedTab.isSplit = true; } else { @@ -1550,6 +1834,10 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container) { connect(container, SIGNAL(showFilterBarChanged(bool)), this, SLOT(updateFilterBarAction(bool))); + connect(container, SIGNAL(writeStateChanged(bool)), + this, SLOT(slotWriteStateChanged(bool))); + connect(container, SIGNAL(searchModeChanged(bool)), + this, SLOT(slotSearchModeChanged(bool))); DolphinView* view = container->view(); connect(view, SIGNAL(selectionChanged(KFileItemList)), @@ -1560,6 +1848,12 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container) this, SLOT(toggleActiveView())); connect(view, SIGNAL(tabRequested(const KUrl&)), this, SLOT(openNewTab(const KUrl&))); + connect(view, SIGNAL(requestContextMenu(KFileItem, const KUrl&, const QList&)), + this, SLOT(openContextMenu(KFileItem, const KUrl&, const QList&))); + connect(view, SIGNAL(startedPathLoading(KUrl)), + this, SLOT(enableStopAction())); + connect(view, SIGNAL(finishedPathLoading(KUrl)), + this, SLOT(disableStopAction())); const KUrlNavigator* navigator = container->urlNavigator(); connect(navigator, SIGNAL(urlChanged(const KUrl&)), @@ -1568,12 +1862,14 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container) this, SLOT(updateHistory())); connect(navigator, SIGNAL(editableStateChanged(bool)), this, SLOT(slotEditableStateChanged(bool))); + connect(navigator, SIGNAL(tabRequested(const KUrl&)), + this, SLOT(openNewTab(KUrl))); } void DolphinMainWindow::updateSplitAction() { QAction* splitAction = actionCollection()->action("split_view"); - if (m_viewTab[m_tabIndex].secondaryView != 0) { + if (m_viewTab[m_tabIndex].secondaryView) { if (m_activeViewContainer == m_viewTab[m_tabIndex].secondaryView) { splitAction->setText(i18nc("@action:intoolbar Close right view", "Close")); splitAction->setToolTip(i18nc("@info", "Close right view")); @@ -1627,11 +1923,10 @@ void DolphinMainWindow::createSecondaryView(int tabIndex) const int newWidth = (m_viewTab[tabIndex].primaryView->width() - splitter->handleWidth()) / 2; const DolphinView* view = m_viewTab[tabIndex].primaryView->view(); - m_viewTab[tabIndex].secondaryView = new DolphinViewContainer(this, 0, view->rootUrl()); + m_viewTab[tabIndex].secondaryView = new DolphinViewContainer(view->rootUrl(), 0); splitter->addWidget(m_viewTab[tabIndex].secondaryView); splitter->setSizes(QList() << newWidth << newWidth); connectViewSignals(m_viewTab[tabIndex].secondaryView); - m_viewTab[tabIndex].secondaryView->view()->reload(); m_viewTab[tabIndex].secondaryView->setActive(false); m_viewTab[tabIndex].secondaryView->show(); } @@ -1644,15 +1939,16 @@ QString DolphinMainWindow::tabProperty(const QString& property, int tabIndex) co void DolphinMainWindow::setUrlAsCaption(const KUrl& url) { QString caption; - if (url.equals(KUrl("file:///"))) { - caption = '/'; - } else { - caption = url.fileName(); - if (caption.isEmpty()) { - caption = url.protocol(); - } + if (!url.isLocalFile()) { + caption.append(url.protocol() + " - "); + if (url.hasHost()) { + caption.append(url.host() + " - "); + } } - + + const QString fileName = url.fileName().isEmpty() ? "/" : url.fileName(); + caption.append(fileName); + setCaption(caption); } @@ -1662,6 +1958,14 @@ QString DolphinMainWindow::squeezedText(const QString& text) const return fm.elidedText(text, Qt::ElideMiddle, fm.maxWidth() * 10); } +void DolphinMainWindow::addActionCloneToCollection(QAction* action, const QString& actionName) +{ + KAction* actionClone = actionCollection()->addAction(actionName); + actionClone->setText(action->text()); + actionClone->setIcon(action->icon()); + connect(actionClone, SIGNAL(triggered()), action, SLOT(trigger())); +} + DolphinMainWindow::UndoUiInterface::UndoUiInterface() : KIO::FileUndoManager::UiInterface() {