#include "views/dolphinremoteencoding.h"
#include "views/draganddrophelper.h"
#include "views/viewproperties.h"
+#include "views/dolphinnewfilemenuobserver.h"
#ifndef Q_OS_WIN
#include "panels/terminal/terminalpanel.h"
#include <kdualaction.h>
#include <KFileDialog>
#include <KGlobal>
+#include <KDialog>
+#include <KJobWidgets>
+#include <KMimeType>
#include <KLineEdit>
#include <KToolBar>
#include <KIcon>
#include <QClipboard>
#include <QToolButton>
#include <QSplitter>
+#include <QTimer>
+#include <QPushButton>
namespace {
// Used for GeneralSettings::version() to determine whether
m_updateToolBarTimer(0),
m_lastHandleUrlStatJob(0)
{
- // Workaround for a X11-issue in combination with KModifierInfo
- // (see DolphinContextMenu::initializeModifierKeyInfo() for
- // more information):
- DolphinContextMenu::initializeModifierKeyInfo();
-
setObjectName("Dolphin#");
m_viewTab.append(ViewTab());
ViewTab& viewTab = m_viewTab[m_tabIndex];
viewTab.wasActive = true; // The first opened tab is automatically active
+ connect(&DolphinNewFileMenuObserver::instance(), SIGNAL(errorMessage(QString)),
+ this, SLOT(showErrorMessage(QString)));
+
KIO::FileUndoManager* undoManager = KIO::FileUndoManager::self();
undoManager->setUiInterface(new UndoUiInterface());
// Open each directory inside a new tab. If the "split view" option has been enabled,
// always show two directories within one tab.
- QList<KUrl>::const_iterator it = dirs.begin();
- while (it != dirs.end()) {
+ QList<KUrl>::const_iterator it = dirs.constBegin();
+ while (it != dirs.constEnd()) {
openNewTab(*it);
++it;
- if (hasSplitView && (it != dirs.end())) {
+ if (hasSplitView && (it != dirs.constEnd())) {
const int tabIndex = m_viewTab.count() - 1;
m_viewTab[tabIndex].secondaryView->setUrl(*it);
++it;
void DolphinMainWindow::openInNewTab()
{
- const KFileItemList list = m_activeViewContainer->view()->selectedItems();
+ const KFileItemList& list = m_activeViewContainer->view()->selectedItems();
if (list.isEmpty()) {
openNewTab(m_activeViewContainer->url());
- } else if ((list.count() == 1) && list[0].isDir()) {
- openNewTab(list[0].url());
+ } else {
+ foreach (const KFileItem& item, list) {
+ const KUrl& url = DolphinView::openItemAsFolderUrl(item);
+ if (!url.isEmpty()) {
+ openNewTab(url);
+ }
+ }
}
}
const KFileItemList list = m_activeViewContainer->view()->selectedItems();
if (list.isEmpty()) {
newWindowUrl = m_activeViewContainer->url();
- } else if ((list.count() == 1) && list[0].isDir()) {
- newWindowUrl = list[0].url();
+ } else if (list.count() == 1) {
+ const KFileItem& item = list.first();
+ newWindowUrl = DolphinView::openItemAsFolderUrl(item);
}
if (!newWindowUrl.isEmpty()) {
- KRun::run("dolphin %u", KUrl::List() << newWindowUrl, this);
+ KRun::run("dolphin %u", QList<QUrl>() << newWindowUrl, this);
}
}
// KDialog::Yes -> Quit
// KDialog::No -> Close only the current tab
// KDialog::Cancel -> do nothing
- KDialog *dialog = new KDialog(this, Qt::Dialog);
- dialog->setCaption(i18nc("@title:window", "Confirmation"));
- dialog->setButtons(KDialog::Yes | KDialog::No | KDialog::Cancel);
+ QDialog *dialog = new QDialog(this, Qt::Dialog);
+ dialog->setWindowTitle(i18nc("@title:window", "Confirmation"));
dialog->setModal(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());
- dialog->setDefaultButton(KDialog::Yes);
+ QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Yes | QDialogButtonBox::No | QDialogButtonBox::Cancel);
+ KGuiItem::assign(buttons->button(QDialogButtonBox::Yes), KStandardGuiItem::quit());
+ KGuiItem::assign(buttons->button(QDialogButtonBox::No), KGuiItem(i18n("C&lose Current Tab"), KIcon("tab-close")));
+ KGuiItem::assign(buttons->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
+ buttons->button(QDialogButtonBox::Yes)->setDefault(true);
bool doNotAskAgainCheckboxResult = false;
const int result = KMessageBox::createKMessageBox(dialog,
+ buttons,
QMessageBox::Warning,
i18n("You have multiple tabs open in this window, are you sure you want to quit?"),
QStringList(),
Q_ASSERT(cont);
}
+ // The right view must be activated before the URL is set. Changing
+ // the URL in the right view will emit the right URL navigator's
+ // urlChanged(KUrl) signal, which is connected to the changeUrl(KUrl)
+ // slot. That slot will change the URL in the left view if it is still
+ // active. See https://bugs.kde.org/show_bug.cgi?id=330047.
+ setActiveViewContainer(cont);
+
cont->setUrl(secondaryUrl);
const bool editable = group.readEntry(tabProperty("Secondary Editable", i), false);
cont->urlNavigator()->setUrlEditable(editable);
void DolphinMainWindow::compareFiles()
{
- // The method is only invoked if exactly 2 files have
- // been selected. The selected files may be:
- // - both in the primary view
- // - both in the secondary view
- // - one in the primary view and the other in the secondary
- // view
- Q_ASSERT(m_viewTab[m_tabIndex].primaryView);
-
- KUrl urlA;
- KUrl urlB;
+ const DolphinViewContainer* primaryViewContainer = m_viewTab[m_tabIndex].primaryView;
+ Q_ASSERT(primaryViewContainer);
+ KFileItemList items = primaryViewContainer->view()->selectedItems();
- KFileItemList items = m_viewTab[m_tabIndex].primaryView->view()->selectedItems();
-
- switch (items.count()) {
- case 0: {
- 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 = 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;
+ const DolphinViewContainer* secondaryViewContainer = m_viewTab[m_tabIndex].secondaryView;
+ if (secondaryViewContainer) {
+ items.append(secondaryViewContainer->view()->selectedItems());
}
- case 2: {
- urlA = items[0].url();
- urlB = items[1].url();
- break;
+ if (items.count() != 2) {
+ // The action is disabled in this case, but it could have been triggered
+ // via D-Bus, see https://bugs.kde.org/show_bug.cgi?id=325517
+ return;
}
- default: {
- // may not happen: compareFiles may only get invoked if 2
- // files are selected
- Q_ASSERT(false);
- }
- }
+ KUrl urlA = items.at(0).url();
+ KUrl urlB = items.at(1).url();
QString command("kompare -c \"");
command.append(urlA.pathOrUrl());
// stat the URL to see if it is a dir or not
m_lastHandleUrlStatJob = KIO::stat(url, KIO::HideProgressInfo);
if (m_lastHandleUrlStatJob->ui()) {
- m_lastHandleUrlStatJob->ui()->setWindow(this);
+ KJobWidgets::setWindow(m_lastHandleUrlStatJob, this);
}
connect(m_lastHandleUrlStatJob, SIGNAL(result(KJob*)),
this, SLOT(slotHandleUrlStatFinished(KJob*)));
const ViewTab& viewTab = m_viewTab[tab];
const DolphinView* view = viewTab.isPrimaryViewActive ? viewTab.primaryView->view()
: viewTab.secondaryView->view();
- const QString error = DragAndDropHelper::dropUrls(view->rootItem(), view->url(), event);
+ QString error;
+ DragAndDropHelper::dropUrls(view->rootItem(), view->url(), event, error);
if (!error.isEmpty()) {
activeViewContainer()->showMessage(error, DolphinViewContainer::Error);
}
switch (command) {
case DolphinContextMenu::OpenParentFolderInNewWindow: {
- KRun::run("dolphin %u", KUrl::List() << item.url().upUrl(), this);
+
+ KRun::run("dolphin %u", QList<QUrl>() << KIO::upUrl(item.url()), this);
break;
}
case DolphinContextMenu::OpenParentFolderInNewTab:
- openNewTab(item.url().upUrl());
+ openNewTab(KIO::upUrl(item.url()));
break;
case DolphinContextMenu::None:
activeViewContainer()->showMessage(error, DolphinViewContainer::Error);
}
+void DolphinMainWindow::slotPlaceActivated(const KUrl& url)
+{
+ DolphinViewContainer* view = activeViewContainer();
+
+ if (view->url() == url) {
+ // We can end up here if the user clicked a device in the Places Panel
+ // which had been unmounted earlier, see https://bugs.kde.org/show_bug.cgi?id=161385.
+ reloadView();
+ } else {
+ changeUrl(url);
+ }
+}
+
void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContainer)
{
Q_ASSERT(viewContainer);
void DolphinMainWindow::setupActions()
{
// setup 'File' menu
- m_newFileMenu = new DolphinNewFileMenu(this);
- KMenu* menu = m_newFileMenu->menu();
+ m_newFileMenu = new DolphinNewFileMenu(actionCollection(), this);
+ QMenu* menu = m_newFileMenu->menu();
menu->setTitle(i18nc("@title:menu Create new folder, file, link, etc.", "Create New"));
menu->setIcon(KIcon("document-new"));
+ m_newFileMenu->setDelayed(false);
connect(menu, SIGNAL(aboutToShow()),
this, SLOT(updateNewMenu()));
- KAction* newWindow = actionCollection()->addAction("new_window");
+ QAction* newWindow = actionCollection()->addAction("new_window");
newWindow->setIcon(KIcon("window-new"));
newWindow->setText(i18nc("@action:inmenu File", "New &Window"));
newWindow->setShortcut(Qt::CTRL | Qt::Key_N);
connect(newWindow, SIGNAL(triggered()), this, SLOT(openNewMainWindow()));
- KAction* newTab = actionCollection()->addAction("new_tab");
+ QAction* newTab = actionCollection()->addAction("new_tab");
newTab->setIcon(KIcon("tab-new"));
newTab->setText(i18nc("@action:inmenu File", "New Tab"));
- newTab->setShortcut(KShortcut(Qt::CTRL | Qt::Key_T, Qt::CTRL | Qt::SHIFT | Qt::Key_N));
+ newTab->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL | Qt::Key_T) << QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_N));
connect(newTab, SIGNAL(triggered()), this, SLOT(openNewTab()));
- KAction* closeTab = actionCollection()->addAction("close_tab");
+ QAction* closeTab = actionCollection()->addAction("close_tab");
closeTab->setIcon(KIcon("tab-close"));
closeTab->setText(i18nc("@action:inmenu File", "Close Tab"));
closeTab->setShortcut(Qt::CTRL | Qt::Key_W);
// need to remove shift+del from cut action, else the shortcut for deletejob
// doesn't work
- KAction* cut = KStandardAction::cut(this, SLOT(cut()), actionCollection());
- KShortcut cutShortcut = cut->shortcut();
- cutShortcut.remove(Qt::SHIFT | Qt::Key_Delete, KShortcut::KeepEmpty);
- cut->setShortcut(cutShortcut);
+ QAction* cut = KStandardAction::cut(this, SLOT(cut()), actionCollection());
+ auto cutShortcuts = cut->shortcuts();
+ cutShortcuts.removeAll(QKeySequence(Qt::SHIFT | Qt::Key_Delete));
+ cut->setShortcuts(cutShortcuts);
KStandardAction::copy(this, SLOT(copy()), actionCollection());
- KAction* paste = KStandardAction::paste(this, SLOT(paste()), actionCollection());
+ QAction* paste = KStandardAction::paste(this, SLOT(paste()), actionCollection());
// The text of the paste-action is modified dynamically by Dolphin
// (e. g. to "Paste One Folder"). To prevent that the size of the toolbar changes
// due to the long text, the text "Paste" is used:
KStandardAction::find(this, SLOT(find()), actionCollection());
- KAction* selectAll = actionCollection()->addAction("select_all");
+ QAction* selectAll = actionCollection()->addAction("select_all");
selectAll->setText(i18nc("@action:inmenu Edit", "Select All"));
selectAll->setShortcut(Qt::CTRL | Qt::Key_A);
connect(selectAll, SIGNAL(triggered()), this, SLOT(selectAll()));
- KAction* invertSelection = actionCollection()->addAction("invert_selection");
+ QAction* invertSelection = actionCollection()->addAction("invert_selection");
invertSelection->setText(i18nc("@action:inmenu Edit", "Invert Selection"));
invertSelection->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_A);
connect(invertSelection, SIGNAL(triggered()), this, SLOT(invertSelection()));
// setup 'View' menu
// (note that most of it is set up in DolphinViewActionHandler)
- KAction* split = actionCollection()->addAction("split_view");
+ QAction* split = actionCollection()->addAction("split_view");
split->setShortcut(Qt::Key_F3);
updateSplitAction();
connect(split, SIGNAL(triggered()), this, SLOT(toggleSplitView()));
- KAction* reload = actionCollection()->addAction("reload");
+ QAction* reload = actionCollection()->addAction("reload");
reload->setText(i18nc("@action:inmenu View", "Reload"));
reload->setShortcut(Qt::Key_F5);
reload->setIcon(KIcon("view-refresh"));
connect(reload, SIGNAL(triggered()), this, SLOT(reloadView()));
- KAction* stop = actionCollection()->addAction("stop");
+ QAction* stop = actionCollection()->addAction("stop");
stop->setText(i18nc("@action:inmenu View", "Stop"));
stop->setToolTip(i18nc("@info", "Stop loading"));
stop->setIcon(KIcon("process-stop"));
editableLocation->setShortcut(Qt::Key_F6);
connect(editableLocation, SIGNAL(triggered()), this, SLOT(toggleEditLocation()));
- KAction* replaceLocation = actionCollection()->addAction("replace_location");
+ QAction* replaceLocation = actionCollection()->addAction("replace_location");
replaceLocation->setText(i18nc("@action:inmenu Navigation Bar", "Replace Location"));
replaceLocation->setShortcut(Qt::CTRL | Qt::Key_L);
connect(replaceLocation, SIGNAL(triggered()), this, SLOT(replaceLocation()));
// setup 'Go' menu
- KAction* backAction = KStandardAction::back(this, SLOT(goBack()), actionCollection());
+ QAction* backAction = KStandardAction::back(this, SLOT(goBack()), actionCollection());
connect(backAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(goBack(Qt::MouseButtons)));
- KShortcut backShortcut = backAction->shortcut();
- backShortcut.setAlternate(Qt::Key_Backspace);
- backAction->setShortcut(backShortcut);
+ auto backShortcuts = backAction->shortcuts();
+ backShortcuts.append(QKeySequence(Qt::Key_Backspace));
+ backAction->setShortcuts(backShortcuts);
m_recentTabsMenu = new KActionMenu(i18n("Recently Closed Tabs"), this);
m_recentTabsMenu->setIcon(KIcon("edit-undo"));
+ m_recentTabsMenu->setDelayed(false);
actionCollection()->addAction("closed_tabs", m_recentTabsMenu);
connect(m_recentTabsMenu->menu(), SIGNAL(triggered(QAction*)),
this, SLOT(restoreClosedTab(QAction*)));
m_recentTabsMenu->addSeparator();
m_recentTabsMenu->setEnabled(false);
- KAction* forwardAction = KStandardAction::forward(this, SLOT(goForward()), actionCollection());
+ QAction* forwardAction = KStandardAction::forward(this, SLOT(goForward()), actionCollection());
connect(forwardAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(goForward(Qt::MouseButtons)));
- KAction* upAction = KStandardAction::up(this, SLOT(goUp()), actionCollection());
+ QAction* upAction = KStandardAction::up(this, SLOT(goUp()), actionCollection());
connect(upAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(goUp(Qt::MouseButtons)));
- KAction* homeAction = KStandardAction::home(this, SLOT(goHome()), actionCollection());
+ QAction* homeAction = KStandardAction::home(this, SLOT(goHome()), actionCollection());
connect(homeAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(goHome(Qt::MouseButtons)));
// setup 'Tools' menu
- KAction* showFilterBar = actionCollection()->addAction("show_filter_bar");
+ QAction* 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()), this, SLOT(showFilterBar()));
- KAction* compareFiles = actionCollection()->addAction("compare_files");
+ QAction* compareFiles = actionCollection()->addAction("compare_files");
compareFiles->setText(i18nc("@action:inmenu Tools", "Compare Files"));
compareFiles->setIcon(KIcon("kompare"));
compareFiles->setEnabled(false);
connect(compareFiles, SIGNAL(triggered()), this, SLOT(compareFiles()));
- KAction* openTerminal = actionCollection()->addAction("open_terminal");
+ QAction* openTerminal = actionCollection()->addAction("open_terminal");
openTerminal->setText(i18nc("@action:inmenu Tools", "Open Terminal"));
openTerminal->setIcon(KIcon("utilities-terminal"));
openTerminal->setShortcut(Qt::SHIFT | Qt::Key_F4);
// not in menu actions
QList<QKeySequence> nextTabKeys;
- nextTabKeys.append(KStandardShortcut::tabNext().primary());
+ nextTabKeys.append(KStandardShortcut::tabNext().first()); //TODO: is this correct
nextTabKeys.append(QKeySequence(Qt::CTRL | Qt::Key_Tab));
QList<QKeySequence> prevTabKeys;
- prevTabKeys.append(KStandardShortcut::tabPrev().primary());
+ prevTabKeys.append(KStandardShortcut::tabPrev().first()); //TODO: is this correct
prevTabKeys.append(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_Tab));
- KAction* activateNextTab = actionCollection()->addAction("activate_next_tab");
+ QAction* activateNextTab = actionCollection()->addAction("activate_next_tab");
activateNextTab->setText(i18nc("@action:inmenu", "Activate Next Tab"));
connect(activateNextTab, SIGNAL(triggered()), SLOT(activateNextTab()));
activateNextTab->setShortcuts(QApplication::isRightToLeft() ? prevTabKeys : nextTabKeys);
- KAction* activatePrevTab = actionCollection()->addAction("activate_prev_tab");
+ QAction* activatePrevTab = actionCollection()->addAction("activate_prev_tab");
activatePrevTab->setText(i18nc("@action:inmenu", "Activate Previous Tab"));
connect(activatePrevTab, SIGNAL(triggered()), SLOT(activatePrevTab()));
activatePrevTab->setShortcuts(QApplication::isRightToLeft() ? nextTabKeys : prevTabKeys);
// for context menu
- KAction* openInNewTab = actionCollection()->addAction("open_in_new_tab");
+ QAction* openInNewTab = actionCollection()->addAction("open_in_new_tab");
openInNewTab->setText(i18nc("@action:inmenu", "Open in New Tab"));
openInNewTab->setIcon(KIcon("tab-new"));
connect(openInNewTab, SIGNAL(triggered()), this, SLOT(openInNewTab()));
- KAction* openInNewWindow = actionCollection()->addAction("open_in_new_window");
+ QAction* openInNewTabs = actionCollection()->addAction("open_in_new_tabs");
+ openInNewTabs->setText(i18nc("@action:inmenu", "Open in New Tabs"));
+ openInNewTabs->setIcon(KIcon("tab-new"));
+ connect(openInNewTabs, SIGNAL(triggered()), this, SLOT(openInNewTab()));
+
+ QAction* openInNewWindow = actionCollection()->addAction("open_in_new_window");
openInNewWindow->setText(i18nc("@action:inmenu", "Open in New Window"));
openInNewWindow->setIcon(KIcon("window-new"));
connect(openInNewWindow, SIGNAL(triggered()), this, SLOT(openInNewWindow()));
addDockWidget(Qt::LeftDockWidgetArea, placesDock);
connect(placesPanel, SIGNAL(placeActivated(KUrl)),
- this, SLOT(changeUrl(KUrl)));
+ this, SLOT(slotPlaceActivated(KUrl)));
connect(placesPanel, SIGNAL(placeMiddleClicked(KUrl)),
this, SLOT(openNewTab(KUrl)));
connect(placesPanel, SIGNAL(errorMessage(QString)),
void DolphinMainWindow::rememberClosedTab(int index)
{
- KMenu* tabsMenu = m_recentTabsMenu->menu();
+ QMenu* tabsMenu = m_recentTabsMenu->menu();
const QString primaryPath = m_viewTab[index].primaryView->url().path();
const QString iconName = KMimeType::iconNameForUrl(primaryPath);
QAction* dockAction,
const QString& actionName)
{
- KAction* panelAction = actionCollection()->addAction(actionName);
+ QAction* panelAction = actionCollection()->addAction(actionName);
panelAction->setCheckable(true);
panelAction->setChecked(dockAction->isChecked());
panelAction->setText(dockAction->text());