-cmake_minimum_required(VERSION 2.8.12)
-
-project(Dolphin)
+cmake_minimum_required(VERSION 3.0)
# KDE Application Version, managed by release script
set (KDE_APPLICATIONS_VERSION_MAJOR "17")
-set (KDE_APPLICATIONS_VERSION_MINOR "08")
-set (KDE_APPLICATIONS_VERSION_MICRO "1")
+set (KDE_APPLICATIONS_VERSION_MINOR "11")
+set (KDE_APPLICATIONS_VERSION_MICRO "70")
set (KDE_APPLICATIONS_VERSION "${KDE_APPLICATIONS_VERSION_MAJOR}.${KDE_APPLICATIONS_VERSION_MINOR}.${KDE_APPLICATIONS_VERSION_MICRO}")
+project(Dolphin VERSION ${KDE_APPLICATIONS_VERSION})
set(QT_MIN_VERSION "5.5.0")
-set(KF5_MIN_VERSION "5.30.0")
+set(KF5_MIN_VERSION "5.37.0")
set(ECM_MIN_VERSION "1.6.0")
# ECM setup
views/viewproperties.cpp
views/zoomlevelinfo.cpp
dolphinremoveaction.cpp
+ middleclickactioneventfilter.cpp
dolphinnewfilemenu.cpp
dolphindebug.cpp
)
void DolphinContextMenu::keyPressEvent(QKeyEvent *ev)
{
if (m_removeAction && ev->key() == Qt::Key_Shift) {
- m_removeAction->update();
+ m_removeAction->update(DolphinRemoveAction::ShiftState::Pressed);
}
QMenu::keyPressEvent(ev);
}
void DolphinContextMenu::keyReleaseEvent(QKeyEvent *ev)
{
if (m_removeAction && ev->key() == Qt::Key_Shift) {
- m_removeAction->update();
+ m_removeAction->update(DolphinRemoveAction::ShiftState::Released);
}
QMenu::keyReleaseEvent(ev);
}
addSeparator();
// Insert 'Rename'
- QAction* renameAction = collection->action(QStringLiteral("rename"));
- addAction(renameAction);
+ addAction(collection->action(KStandardAction::name(KStandardAction::RenameFile)));
// Insert 'Move to Trash' and/or 'Delete'
if (properties.supportsDeleting()) {
if (showDeleteAction && showMoveToTrashAction) {
delete m_removeAction;
m_removeAction = 0;
- addAction(m_mainWindow->actionCollection()->action(QStringLiteral("move_to_trash")));
+ addAction(m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::MoveToTrash)));
addAction(m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::DeleteFile)));
} else if (showDeleteAction && !showMoveToTrashAction) {
addAction(m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::DeleteFile)));
#include "dolphintabwidget.h"
#include "dolphinviewcontainer.h"
#include "dolphintabpage.h"
+#include "middleclickactioneventfilter.h"
#include "panels/folders/folderspanel.h"
#include "panels/places/placespanel.h"
#include "panels/information/informationpanel.h"
#include <KAuthorized>
#include <KConfig>
#include <kdualaction.h>
+#include <KHelpMenu>
#include <KJobWidgets>
#include <QLineEdit>
#include <KToolBar>
#include <KProtocolInfo>
#include <QMenu>
#include <KMessageBox>
+#include <KFilePlacesModel>
#include <KFileItemListProperties>
#include <KRun>
#include <KShell>
if (!showMenu) {
createControlButton();
}
+
+ // enable middle-click on back/forward/up to open in a new tab
+ auto *middleClickEventFilter = new MiddleClickActionEventFilter(this);
+ connect(middleClickEventFilter, &MiddleClickActionEventFilter::actionMiddleClicked, this, &DolphinMainWindow::slotToolBarActionMiddleClicked);
+ toolBar()->installEventFilter(middleClickEventFilter);
}
DolphinMainWindow::~DolphinMainWindow()
updatePasteAction();
}
+void DolphinMainWindow::slotToolBarActionMiddleClicked(QAction *action)
+{
+ if (action == actionCollection()->action(QStringLiteral("go_back"))) {
+ goBackInNewTab();
+ } else if (action == actionCollection()->action(QStringLiteral("go_forward"))) {
+ goForwardInNewTab();
+ } else if (action == actionCollection()->action(QStringLiteral("go_up"))) {
+ goUpInNewTab();
+ } else if (action == actionCollection()->action(QStringLiteral("go_home"))) {
+ goHomeInNewTab();
+ }
+}
+
void DolphinMainWindow::selectAll()
{
clearStatusBar();
m_activeViewContainer->urlNavigator()->goHome();
}
-void DolphinMainWindow::goBack(Qt::MouseButtons buttons)
+void DolphinMainWindow::goBackInNewTab()
{
- // The default case (left button pressed) is handled in goBack().
- if (buttons == Qt::MiddleButton) {
- KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator();
- const int index = urlNavigator->historyIndex() + 1;
- openNewTab(urlNavigator->locationUrl(index));
- }
+ KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator();
+ const int index = urlNavigator->historyIndex() + 1;
+ openNewTab(urlNavigator->locationUrl(index));
}
-void DolphinMainWindow::goForward(Qt::MouseButtons buttons)
+void DolphinMainWindow::goForwardInNewTab()
{
- // The default case (left button pressed) is handled in goForward().
- if (buttons == Qt::MiddleButton) {
- KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator();
- const int index = urlNavigator->historyIndex() - 1;
- openNewTab(urlNavigator->locationUrl(index));
- }
+ KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator();
+ const int index = urlNavigator->historyIndex() - 1;
+ openNewTab(urlNavigator->locationUrl(index));
}
-void DolphinMainWindow::goUp(Qt::MouseButtons buttons)
+void DolphinMainWindow::goUpInNewTab()
{
- // The default case (left button pressed) is handled in goUp().
- if (buttons == Qt::MiddleButton) {
- openNewTab(KIO::upUrl(activeViewContainer()->url()));
- }
+ const QUrl currentUrl = activeViewContainer()->urlNavigator()->locationUrl();
+ openNewTab(KIO::upUrl(currentUrl));
}
-void DolphinMainWindow::goHome(Qt::MouseButtons buttons)
+void DolphinMainWindow::goHomeInNewTab()
{
- // The default case (left button pressed) is handled in goHome().
- if (buttons == Qt::MiddleButton) {
- openNewTab(Dolphin::homeUrl());
- }
+ openNewTab(Dolphin::homeUrl());
}
void DolphinMainWindow::compareFiles()
addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Preferences)), menu);
// Add "Help" menu
- QMenu* helpMenu = new QMenu(i18nc("@action:inmenu", "Help"), menu);
- helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::HelpContents)));
- helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::WhatsThis)));
- helpMenu->addSeparator();
- helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::ReportBug)));
- helpMenu->addSeparator();
- helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Donate)));
- helpMenu->addSeparator();
- helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::SwitchApplicationLanguage)));
- helpMenu->addSeparator();
- helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::AboutApp)));
- helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::AboutKDE)));
- menu->addMenu(helpMenu);
+ auto helpMenu = new KHelpMenu(menu);
+ menu->addMenu(helpMenu->menu());
menu->addSeparator();
addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ShowMenubar)), menu);
void DolphinMainWindow::setUrlAsCaption(const QUrl& url)
{
- QString caption;
+ static KFilePlacesModel s_placesModel;
+
+ QString schemePrefix;
if (!url.isLocalFile()) {
- caption.append(url.scheme() + " - ");
+ schemePrefix.append(url.scheme() + " - ");
if (!url.host().isEmpty()) {
- caption.append(url.host() + " - ");
+ schemePrefix.append(url.host() + " - ");
}
}
if (GeneralSettings::showFullPathInTitlebar()) {
const QString path = url.adjusted(QUrl::StripTrailingSlash).path();
- caption.append(path);
- } else {
- QString fileName = url.adjusted(QUrl::StripTrailingSlash).fileName();
- if (fileName.isEmpty()) {
- fileName = '/';
- }
- caption.append(fileName);
+ setWindowTitle(schemePrefix + path);
+ return;
+ }
+
+ const auto& matchedPlaces = s_placesModel.match(s_placesModel.index(0,0), KFilePlacesModel::UrlRole, url, 1, Qt::MatchExactly);
+
+ if (!matchedPlaces.isEmpty()) {
+ setWindowTitle(s_placesModel.text(matchedPlaces.first()));
+ return;
+ }
+
+ QString fileName = url.adjusted(QUrl::StripTrailingSlash).fileName();
+ if (fileName.isEmpty()) {
+ fileName = '/';
}
- setWindowTitle(caption);
+ setWindowTitle(schemePrefix + fileName);
}
void DolphinMainWindow::setupActions()
closeTab->setEnabled(false);
connect(closeTab, &QAction::triggered, m_tabWidget, static_cast<void(DolphinTabWidget::*)()>(&DolphinTabWidget::closeTab));
- KStandardAction::quit(this, SLOT(quit()), actionCollection());
+ KStandardAction::quit(this, &DolphinMainWindow::quit, actionCollection());
// setup 'Edit' menu
KStandardAction::undo(this,
- SLOT(undo()),
+ &DolphinMainWindow::undo,
actionCollection());
- KStandardAction::cut(this, SLOT(cut()), actionCollection());
- KStandardAction::copy(this, SLOT(copy()), actionCollection());
- QAction* paste = KStandardAction::paste(this, SLOT(paste()), actionCollection());
+ KStandardAction::cut(this, &DolphinMainWindow::cut, actionCollection());
+ KStandardAction::copy(this, &DolphinMainWindow::copy, actionCollection());
+ QAction* paste = KStandardAction::paste(this, &DolphinMainWindow::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:
paste->setIconText(i18nc("@action:inmenu Edit", "Paste"));
- KStandardAction::find(this, SLOT(find()), actionCollection());
+ KStandardAction::find(this, &DolphinMainWindow::find, actionCollection());
QAction* selectAll = actionCollection()->addAction(QStringLiteral("select_all"));
selectAll->setText(i18nc("@action:inmenu Edit", "Select All"));
connect(replaceLocation, &QAction::triggered, this, &DolphinMainWindow::replaceLocation);
// setup 'Go' menu
- QAction* backAction = KStandardAction::back(this, SLOT(goBack()), actionCollection());
+ QAction* backAction = KStandardAction::back(this, &DolphinMainWindow::goBack, actionCollection());
auto backShortcuts = backAction->shortcuts();
backShortcuts.append(QKeySequence(Qt::Key_Backspace));
actionCollection()->setDefaultShortcuts(backAction, backShortcuts);
auto undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo));
undoAction->setEnabled(false); // undo should be disabled by default
- KStandardAction::forward(this, SLOT(goForward()), actionCollection());
- KStandardAction::up(this, SLOT(goUp()), actionCollection());
- KStandardAction::home(this, SLOT(goHome()), actionCollection());
+ KStandardAction::forward(this, &DolphinMainWindow::goForward, actionCollection());
+ KStandardAction::up(this, &DolphinMainWindow::goUp, actionCollection());
+ KStandardAction::home(this, &DolphinMainWindow::goHome, actionCollection());
// setup 'Tools' menu
QAction* showFilterBar = actionCollection()->addAction(QStringLiteral("show_filter_bar"));
stateChanged(QStringLiteral("has_selection"));
KActionCollection* col = actionCollection();
- QAction* renameAction = col->action(QStringLiteral("rename"));
- QAction* moveToTrashAction = col->action(QStringLiteral("move_to_trash"));
+ QAction* renameAction = col->action(KStandardAction::name(KStandardAction::RenameFile));
+ QAction* moveToTrashAction = col->action(KStandardAction::name(KStandardAction::MoveToTrash));
QAction* deleteAction = col->action(KStandardAction::name(KStandardAction::DeleteFile));
QAction* cutAction = col->action(KStandardAction::name(KStandardAction::Cut));
QAction* deleteWithTrashShortcut = col->action(QStringLiteral("delete_shortcut")); // see DolphinViewActionHandler
/** Changes the location to the home URL. */
void goHome();
- /**
- * Open the previous URL in the URL history in a new tab
- * if the middle mouse button is clicked.
- */
- void goBack(Qt::MouseButtons buttons);
+ /** Open the previous URL in the URL history in a new tab. */
+ void goBackInNewTab();
- /**
- * Open the next URL in the URL history in a new tab
- * if the middle mouse button is clicked.
- */
- void goForward(Qt::MouseButtons buttons);
+ /** Open the next URL in the URL history in a new tab. */
+ void goForwardInNewTab();
- /**
- * Open the URL one hierarchy above the current URL in a new tab
- * if the middle mouse button is clicked.
- */
- void goUp(Qt::MouseButtons buttons);
+ /** Open the URL one hierarchy above the current URL in a new tab. */
+ void goUpInNewTab();
- /**
- * Open the home URL in a new tab
- */
- void goHome(Qt::MouseButtons buttons);
+ /** * Open the home URL in a new tab. */
+ void goHomeInNewTab();
/** Opens Kompare for 2 selected files. */
void compareFiles();
*/
void slotDirectoryLoadingCompleted();
+ /**
+ * Is called when the user middle clicks a toolbar button.
+ *
+ * Here middle clicking Back/Forward/Up/Home will open the resulting
+ * folder in a new tab.
+ */
+ void slotToolBarActionMiddleClicked(QAction *action);
+
private:
void setupActions();
void setupDockWidgets();
{
const bool hasSelection = !selection.isEmpty();
- QAction* renameAction = actionCollection()->action(QStringLiteral("rename"));
- QAction* moveToTrashAction = actionCollection()->action(QStringLiteral("move_to_trash"));
+ QAction* renameAction = actionCollection()->action(KStandardAction::name(KStandardAction::RenameFile));
+ QAction* moveToTrashAction = actionCollection()->action(KStandardAction::name(KStandardAction::MoveToTrash));
QAction* deleteAction = actionCollection()->action(KStandardAction::name(KStandardAction::DeleteFile));
QAction* editMimeTypeAction = actionCollection()->action(QStringLiteral("editMimeType"));
QAction* propertiesAction = actionCollection()->action(QStringLiteral("properties"));
if (showDeleteAction && showMoveToTrashAction) {
delete m_removeAction;
m_removeAction = 0;
- editActions.append(actionCollection()->action(QStringLiteral("move_to_trash")));
+ editActions.append(actionCollection()->action(KStandardAction::name(KStandardAction::MoveToTrash)));
editActions.append(actionCollection()->action(KStandardAction::name(KStandardAction::DeleteFile)));
} else if (showDeleteAction && !showMoveToTrashAction) {
editActions.append(actionCollection()->action(KStandardAction::name(KStandardAction::DeleteFile)));
}
if (supportsMoving) {
- editActions.append(actionCollection()->action(QStringLiteral("rename")));
+ editActions.append(actionCollection()->action(KStandardAction::name(KStandardAction::RenameFile)));
}
// Normally KonqPopupMenu only shows the "Create new" submenu in the current view
bool DolphinPart::eventFilter(QObject* obj, QEvent* event)
{
+ using ShiftState = DolphinRemoveAction::ShiftState;
const int type = event->type();
if ((type == QEvent::KeyPress || type == QEvent::KeyRelease) && m_removeAction) {
if (menu && menu->parent() == m_view) {
QKeyEvent* ev = static_cast<QKeyEvent*>(event);
if (ev->key() == Qt::Key_Shift) {
- m_removeAction->update();
+ m_removeAction->update(type == QEvent::KeyPress ? ShiftState::Pressed : ShiftState::Released);
}
}
}
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<kpartgui name="dolphinpart" version="12" translationDomain="dolphin">
+<kpartgui name="dolphinpart" version="14" translationDomain="dolphin">
<MenuBar>
<Menu name="edit"><text>&Edit</text>
<Action name="new_menu"/>
<Separator/>
- <Action name="rename"/>
- <Action name="move_to_trash" />
+ <Action name="renamefile"/>
+ <Action name="movetotrash" />
<Action name="deletefile"/>
<Action name="editMimeType"/>
<Action name="properties"/>
</ToolBar>
<State name="has_selection" >
<enable>
- <Action name="move_to_trash" />
+ <Action name="movetotrash" />
<Action name="deletefile" />
</enable>
</State>
<State name="has_no_selection" >
<disable>
- <Action name="rename" />
- <Action name="move_to_trash" />
+ <Action name="renamefile" />
+ <Action name="movetotrash" />
<Action name="deletefile" />
</disable>
</State>
/***************************************************************************
- * Copyright (C) 2013 by Dawit Alemayehu <adawit@kde.org *
+ * Copyright (C) 2013 by Dawit Alemayehu <adawit@kde.org> *
+ * Copyright (C) 2017 by Elvis Angelaccio <elvis.angelaccio@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
}
}
-void DolphinRemoveAction::update()
+void DolphinRemoveAction::update(ShiftState shiftState)
{
- Q_ASSERT(m_collection);
- // Using setText(action->text()) does not apply the &-shortcut.
- // This is only done until the original action has been shown at least once. To
- // bypass this issue, the text and &-shortcut is applied manually.
- if (qApp->queryKeyboardModifiers() & Qt::ShiftModifier) {
- m_action = m_collection ? m_collection->action(KStandardAction::name(KStandardAction::DeleteFile)) : 0;
- setText(i18nc("@action:inmenu", "&Delete"));
+ if (!m_collection) {
+ m_action = nullptr;
+ return;
+ }
+
+ if (shiftState == ShiftState::Unknown) {
+ shiftState = QGuiApplication::keyboardModifiers() & Qt::ShiftModifier ? ShiftState::Pressed : ShiftState::Released;
+ }
+
+ switch (shiftState) {
+ case ShiftState::Pressed: {
+ m_action = m_collection->action(KStandardAction::name(KStandardAction::DeleteFile));
// Make sure we show Shift+Del in the context menu.
auto deleteShortcuts = m_action->shortcuts();
deleteShortcuts.removeAll(Qt::SHIFT | Qt::Key_Delete);
deleteShortcuts.prepend(Qt::SHIFT | Qt::Key_Delete);
m_collection->setDefaultShortcuts(this, deleteShortcuts);
- } else {
- m_action = m_collection ? m_collection->action(QStringLiteral("move_to_trash")) : 0;
- setText(i18nc("@action:inmenu", "&Move to Trash"));
+ break;
+ }
+ case ShiftState::Released:
+ m_action = m_collection->action(KStandardAction::name(KStandardAction::MoveToTrash));
m_collection->setDefaultShortcuts(this, m_action->shortcuts());
+ break;
+ case ShiftState::Unknown:
+ Q_UNREACHABLE();
+ break;
}
if (m_action) {
+ setText(m_action->text());
setIcon(m_action->icon());
setEnabled(m_action->isEnabled());
}
/***************************************************************************
- * Copyright (C) 2013 by Dawit Alemayehu <adawit@kde.org *
+ * Copyright (C) 2013 by Dawit Alemayehu <adawit@kde.org> *
+ * Copyright (C) 2017 by Elvis Angelaccio <elvis.angelaccio@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* A QAction that manages the delete based on the current state of
* the Shift key or the parameter passed to update.
*
- * This class expects the presence of both the "move_to_trash" and
+ * This class expects the presence of both the KStandardAction::MoveToTrash and
* KStandardAction::DeleteFile actions in @ref collection.
*/
class DOLPHIN_EXPORT DolphinRemoveAction : public QAction
{
Q_OBJECT
public:
+
+ enum class ShiftState {
+ Unknown,
+ Pressed,
+ Released
+ };
+
DolphinRemoveAction(QObject* parent, KActionCollection* collection);
+
/**
- * Updates this action key based on the state of the Shift key.
+ * Updates this action key based on @p shiftState.
+ * Default value is QueryShiftState, meaning it will query QGuiApplication::modifiers().
*/
- void update();
+ void update(ShiftState shiftState = ShiftState::Unknown);
private Q_SLOTS:
void slotRemoveActionTriggered();
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<kpartgui name="dolphin" version="15">
+<kpartgui name="dolphin" version="17">
<MenuBar>
<Menu name="file">
<Action name="new_menu" />
<Action name="close_tab" />
<Action name="undo_close_tab" />
<Separator/>
- <Action name="rename" />
- <Action name="move_to_trash" />
+ <Action name="renamefile" />
+ <Action name="movetotrash" />
<Action name="deletefile" />
<Separator/>
<Action name="properties" />
<Action name="edit_redo" />
<Action name="edit_cut" />
<Action name="edit_copy" />
- <Action name="rename" />
- <Action name="move_to_trash" />
+ <Action name="renamefile" />
+ <Action name="movetotrash" />
<Action name="deletefile" />
<Action name="invert_selection" />
<Separator/>
<enable>
<Action name="edit_cut" />
<Action name="edit_copy" />
- <Action name="rename" />
- <Action name="move_to_trash" />
+ <Action name="renamefile" />
+ <Action name="movetotrash" />
<Action name="deletefile" />
<Action name="invert_selection" />
</enable>
<disable>
<Action name="edit_cut" />
<Action name="edit_copy" />
- <Action name="rename" />
- <Action name="move_to_trash" />
+ <Action name="renamefile" />
+ <Action name="movetotrash" />
<Action name="deletefile" />
<Action name="delete_shortcut" />
<Action name="invert_selection" />
#include <QTimer>
#include <QMimeData>
#include <QVBoxLayout>
+#include <QLoggingCategory>
#include <KFileItemActions>
#include <KFilePlacesModel>
#endif
#include "global.h"
+#include "dolphindebug.h"
#include "dolphin_generalsettings.h"
#include "filterbar/filterbar.h"
#include "search/dolphinsearchbox.h"
this, &DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged);
connect(m_urlNavigator, &KUrlNavigator::urlChanged,
this, &DolphinViewContainer::slotUrlNavigatorLocationChanged);
+ connect(m_urlNavigator, &KUrlNavigator::urlSelectionRequested,
+ this, &DolphinViewContainer::slotUrlSelectionRequested);
connect(m_urlNavigator, &KUrlNavigator::returnPressed,
this, &DolphinViewContainer::slotReturnPressed);
connect(m_urlNavigator, &KUrlNavigator::urlsDropped, this, [=](const QUrl &destination, QDropEvent *event) {
}
}
+void DolphinViewContainer::slotUrlSelectionRequested(const QUrl& url)
+{
+ qCDebug(DolphinDebug) << "slotUrlSelectionRequested: " << url;
+ m_view->markUrlsAsSelected({url});
+ m_view->markUrlAsCurrent(url); // makes the item scroll into view
+}
+
void DolphinViewContainer::redirect(const QUrl& oldUrl, const QUrl& newUrl)
{
Q_UNUSED(oldUrl);
*/
void slotUrlNavigatorLocationChanged(const QUrl& url);
+ /**
+ * @see KUrlNavigator::urlSelectionRequested
+ */
+ void slotUrlSelectionRequested(const QUrl& url);
+
/**
* Is invoked when a redirection is done and changes the
* URL of the URL navigator to \a newUrl without triggering
// does not care whether the parent-URL has already been
// expanded.
QUrl urlToExpand = m_dirLister->url();
- const QStringList subDirs = url.path().mid(pos).split(QDir::separator());
+
+ // first subdir can be empty, if m_dirLister->url().path() does not end with '/'
+ // this happens if baseUrl is not root but a home directory, see FoldersPanel,
+ // so using QString::SkipEmptyParts
+ const QStringList subDirs = url.path().mid(pos).split(QDir::separator(), QString::SkipEmptyParts);
for (int i = 0; i < subDirs.count() - 1; ++i) {
urlToExpand.setPath(urlToExpand.path() + '/' + subDirs.at(i));
m_urlsToExpand.insert(urlToExpand);
{ "imageSize", ImageSizeRole, I18N_NOOP2_NOSTRIP("@label", "Image Size"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
{ "orientation", OrientationRole, I18N_NOOP2_NOSTRIP("@label", "Orientation"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
{ "artist", ArtistRole, I18N_NOOP2_NOSTRIP("@label", "Artist"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "genre", GenreRole, I18N_NOOP2_NOSTRIP("@label", "Genre"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
{ "album", AlbumRole, I18N_NOOP2_NOSTRIP("@label", "Album"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
{ "duration", DurationRole, I18N_NOOP2_NOSTRIP("@label", "Duration"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "bitrate", BitrateRole, I18N_NOOP2_NOSTRIP("@label", "Bitrate"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
{ "track", TrackRole, I18N_NOOP2_NOSTRIP("@label", "Track"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "releaseYear", ReleaseYearRole, I18N_NOOP2_NOSTRIP("@label", "Release Year"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
{ "path", PathRole, I18N_NOOP2_NOSTRIP("@label", "Path"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
{ "deletiontime",DeletionTimeRole,I18N_NOOP2_NOSTRIP("@label", "Deletion Time"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
{ "destination", DestinationRole, I18N_NOOP2_NOSTRIP("@label", "Link Destination"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
GroupRole, TypeRole, DestinationRole, PathRole, DeletionTimeRole,
// User visible roles available with Baloo:
CommentRole, TagsRole, RatingRole, ImageSizeRole, OrientationRole,
- WordCountRole, TitleRole, LineCountRole, ArtistRole, AlbumRole, DurationRole, TrackRole,
- OriginUrlRole,
+ WordCountRole, TitleRole, LineCountRole, ArtistRole, GenreRole, AlbumRole, DurationRole, TrackRole, ReleaseYearRole,
+ BitrateRole, OriginUrlRole,
// Non-visible roles:
IsDirRole, IsLinkRole, IsHiddenRole, IsExpandedRole, IsExpandableRole, ExpandedParentsCountRole,
// Mandatory last entry:
#include <Baloo/File>
#include <KFileMetaData/PropertyInfo>
#include <KFileMetaData/UserMetaData>
+#include <KFormat>
#include <QTime>
#include <QMap>
} else if (role == "duration") {
const QString duration = durationFromValue(value.toInt());
values.insert(role, duration);
+ } else if (role == "bitrate") {
+ const QString bitrate = bitrateFromValue(value.toInt());
+ values.insert(role, bitrate);
} else {
values.insert(role, value.toString());
}
{ "height", "imageSize" },
{ "nexif.orientation", "orientation", },
{ "artist", "artist" },
+ { "genre", "genre" },
{ "album", "album" },
{ "duration", "duration" },
+ { "bitRate", "bitrate" },
+ { "releaseYear", "releaseYear" },
{ "trackNumber", "track" },
{ "originUrl", "originUrl" }
};
return duration.toString(QStringLiteral("hh:mm:ss"));
}
+
+QString KBalooRolesProvider::bitrateFromValue(int value) const
+{
+ KFormat form;
+ QString bitrate = i18nc("@label bitrate (per second)", "%1/s", form.formatByteSize(value, 1, KFormat::MetricBinaryDialect));
+ return bitrate;
+}
+
*/
QString durationFromValue(int value) const;
+ /**
+ * @return Bitrate in the format N kB/s for the value given
+ * in b/s.
+ */
+ QString bitrateFromValue(int value) const;
+
private:
QSet<QByteArray> m_roles;
QHash<QString, QByteArray> m_roleForProperty;
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2017 Kai Uwe Broulik <kde@privat.broulik.de> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "middleclickactioneventfilter.h"
+
+#include <QAction>
+#include <QEvent>
+#include <QMouseEvent>
+#include <QToolBar>
+
+MiddleClickActionEventFilter::MiddleClickActionEventFilter(QObject *parent) : QObject(parent)
+{
+
+}
+
+MiddleClickActionEventFilter::~MiddleClickActionEventFilter() = default;
+
+bool MiddleClickActionEventFilter::eventFilter(QObject *watched, QEvent *event)
+{
+ if (event->type() == QEvent::MouseButtonPress
+ || event->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent *me = static_cast<QMouseEvent *>(event);
+
+ if (me->button() == Qt::MiddleButton) {
+ QToolBar *toolBar = qobject_cast<QToolBar *>(watched);
+
+ QAction *action = toolBar->actionAt(me->pos());
+ if (action) {
+ if (event->type() == QEvent::MouseButtonPress) {
+ m_lastMiddlePressedAction = action;
+ } else if (event->type() == QEvent::MouseButtonRelease) {
+ if (m_lastMiddlePressedAction == action) {
+ emit actionMiddleClicked(action);
+ }
+ m_lastMiddlePressedAction = nullptr;
+ }
+ }
+ }
+ }
+
+ return QObject::eventFilter(watched, event);
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2017 Kai Uwe Broulik <kde@privat.broulik.de> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#pragma once
+
+#include "dolphin_export.h"
+
+#include <QObject>
+#include <QPointer>
+
+class QAction;
+
+/**
+ * An event filter that allows to detect a middle click
+ * to trigger e.g. opening something in a new tab.
+ */
+class DOLPHIN_EXPORT MiddleClickActionEventFilter : public QObject
+{
+ Q_OBJECT
+
+public:
+ MiddleClickActionEventFilter(QObject *parent);
+ ~MiddleClickActionEventFilter() override;
+
+signals:
+ void actionMiddleClicked(QAction *action);
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event) override;
+
+private:
+ QPointer<QAction> m_lastMiddlePressedAction;
+
+};
<li xml:lang="et">Võimalus kasutada mitut laadi vaatestiile ja -omadusi ning neid igati enda käe järgi seadistada.</li>
<li xml:lang="fi">Tukee useita erilaisia näkymätyylejä ja -ominaisuuksia, ja mahdollistaa näkymän muokkaamisen mieleisekseen.</li>
<li xml:lang="fr">Prend en charge plusieurs types de styles d'affichage et de propriété et vous permet de configurer l'affichage de la manière exacte que vous voulez.</li>
- <li xml:lang="gl">É compatíbel con varios estilos e propiedades de vista diferentes, e permítelle configurar a vista como mellor lle pareza.</li>
+ <li xml:lang="gl">É compatíbel con varios estilos e propiedades de vista distintos, e permítelle configurar a vista como mellor lle pareza.</li>
<li xml:lang="hu">Számos különféle nézetstílus fajtát és tulajdonságot támogat, valamint lehetővé teszi a nézet beállítását pontosan olyanra, ahogy azt látni szeretné.</li>
<li xml:lang="ia">Il supporta multe differente typos de stilos de vista e proprietates e il permitte te configurar le vista exactemente como tu vole.</li>
<li xml:lang="it">Supporta diversi stili di visualizzazione e proprietà e ti consente di configurare la vista come desideri.</li>
<label>Hidden files shown</label>
<default>false</default>
</entry>
+ <entry name="LimitFoldersPanelToHome" type="Bool">
+ <label>Limit folders panel to home directory if inside home</label>
+ <default>true</default>
+ </entry>
<entry name="AutoScrolling" type="Bool">
<label>Automatic scrolling</label>
<default>true</default>
#include <views/draganddrophelper.h>
#include "dolphindebug.h"
+#include "global.h"
FoldersPanel::FoldersPanel(QWidget* parent) :
Panel(parent),
return FoldersPanelSettings::hiddenFilesShown();
}
+void FoldersPanel::setLimitFoldersPanelToHome(bool enable)
+{
+ FoldersPanelSettings::setLimitFoldersPanelToHome(enable);
+ reloadTree();
+}
+
+bool FoldersPanel::limitFoldersPanelToHome() const
+{
+ return FoldersPanelSettings::limitFoldersPanelToHome();
+}
+
void FoldersPanel::setAutoScrolling(bool enable)
{
// TODO: Not supported yet in Dolphin 2.0
return true;
}
+void FoldersPanel::reloadTree()
+{
+ if (m_controller) {
+ loadTree(url());
+ }
+}
+
+
void FoldersPanel::showEvent(QShowEvent* event)
{
if (event->spontaneous()) {
QUrl baseUrl;
if (url.isLocalFile()) {
- // Use the root directory as base for local URLs (#150941)
- baseUrl = QUrl::fromLocalFile(QDir::rootPath());
+ const bool isInHomeFolder = Dolphin::homeUrl().isParentOf(url) || (Dolphin::homeUrl() == url);
+ if (FoldersPanelSettings::limitFoldersPanelToHome() && isInHomeFolder) {
+ baseUrl = Dolphin::homeUrl();
+ } else {
+ // Use the root directory as base for local URLs (#150941)
+ baseUrl = QUrl::fromLocalFile(QDir::rootPath());
+ }
} else {
// Clear the path for non-local URLs and use it as base
baseUrl = url;
const int index = m_model->index(url);
if (index >= 0) {
updateCurrentItem(index);
+ } else if (url == baseUrl) {
+ // clear the selection when visiting the base url
+ updateCurrentItem(-1);
} else {
m_updateCurrentItem = true;
m_model->expandParentDirectories(url);
+
// slotLoadingCompleted() will be invoked after the model has
// expanded the url
}
virtual ~FoldersPanel();
void setShowHiddenFiles(bool show);
+ void setLimitFoldersPanelToHome(bool enable);
bool showHiddenFiles() const;
+ bool limitFoldersPanelToHome() const;
void setAutoScrolling(bool enable);
bool autoScrolling() const;
*/
void startFadeInAnimation();
+
private:
/**
* Initializes the base URL of the tree and expands all
*/
void loadTree(const QUrl& url);
+ void reloadTree();
+
/**
* Sets the item with the index \a index as current item, selects
* the item and assures that the item will be visible.
#include <QClipboard>
#include <QMimeData>
#include <QPointer>
+#include "global.h"
TreeViewContextMenu::TreeViewContextMenu(FoldersPanel* parent,
const KFileItem& fileInfo) :
popup->addAction(showHiddenFilesAction);
connect(showHiddenFilesAction, &QAction::toggled, this, &TreeViewContextMenu::setShowHiddenFiles);
+ // insert 'Limit to Home Directory'
+ const QUrl url = m_fileItem.url();
+ const bool showLimitToHomeDirectory = url.isLocalFile() && (Dolphin::homeUrl().isParentOf(url) || (Dolphin::homeUrl() == url));
+ if (showLimitToHomeDirectory) {
+ QAction* limitFoldersPanelToHomeAction = new QAction(i18nc("@action:inmenu", "Limit to Home Directory"), this);
+ limitFoldersPanelToHomeAction->setCheckable(true);
+ limitFoldersPanelToHomeAction->setChecked(m_parent->limitFoldersPanelToHome());
+ popup->addAction(limitFoldersPanelToHomeAction);
+ connect(limitFoldersPanelToHomeAction, &QAction::toggled, this, &TreeViewContextMenu::setLimitFoldersPanelToHome);
+ }
+
// insert 'Automatic Scrolling'
QAction* autoScrollingAction = new QAction(i18nc("@action:inmenu", "Automatic Scrolling"), this);
autoScrollingAction->setCheckable(true);
m_parent->setShowHiddenFiles(show);
}
+void TreeViewContextMenu::setLimitFoldersPanelToHome(bool enable)
+{
+ m_parent->setLimitFoldersPanelToHome(enable);
+}
+
void TreeViewContextMenu::setAutoScrolling(bool enable)
{
m_parent->setAutoScrolling(enable);
*/
void setShowHiddenFiles(bool show);
+ /**
+ * Sets the 'Limit folders panel to home' setting for the
+ * folders panel to \a enable.
+ */
+ void setLimitFoldersPanelToHome(bool enable);
+
/**
* Sets the 'Automatic Scrolling' setting for the
* folders panel to \a enable.
}
} else if (role == "url") {
m_bookmark.setUrl(url());
- } else if (role == "udi)") {
+ } else if (role == "udi") {
m_bookmark.setMetaDataItem(QStringLiteral("UDI"), udi());
} else if (role == "isSystemItem") {
m_bookmark.setMetaDataItem(QStringLiteral("isSystemItem"), isSystemItem() ? QStringLiteral("true") : QStringLiteral("false"));
#include "dolphin_generalsettings.h"
+#include "global.h"
#include <KFileItem>
#include "dolphindebug.h"
#include <KDirNotify>
}
}
+ QAction* openInNewWindowAction = menu.addAction(QIcon::fromTheme("window-new"), i18nc("@item:inmenu", "Open in New Window"));
QAction* openInNewTabAction = menu.addAction(QIcon::fromTheme("tab-new"), i18nc("@item:inmenu", "Open in New Tab"));
if (!isDevice && !isTrash) {
menu.addSeparator();
} else if (action == hideAction) {
item->setHidden(hideAction->isChecked());
m_model->saveBookmarks();
+ } else if (action == openInNewWindowAction) {
+ Dolphin::openNewWindow({PlacesItemModel::convertedUrl(m_model->data(index).value("url").toUrl())}, this);
} else if (action == openInNewTabAction) {
// TriggerItem does set up the storage first and then it will
// emit the slotItemMiddleClicked signal, because of Qt::MiddleButton.
QListWidgetItem* item = new QListWidgetItem(info.translation, m_listWidget);
item->setCheckState(visibleRoles.contains(info.role) ? Qt::Checked : Qt::Unchecked);
- const bool enable = (!info.requiresBaloo && !info.requiresIndexer) ||
+ const bool enable = ((!info.requiresBaloo && !info.requiresIndexer) ||
(info.requiresBaloo) ||
- (info.requiresIndexer && indexingEnabled);
+ (info.requiresIndexer && indexingEnabled)) && info.role != "text";
if (!enable) {
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
m_remoteFileSizeBox->setSuffix(QStringLiteral(" MB"));
m_remoteFileSizeBox->setRange(0, 9999999); /* MB */
- QHBoxLayout* fileSizeBoxLayout = new QHBoxLayout(this);
+ QHBoxLayout* fileSizeBoxLayout = new QHBoxLayout();
fileSizeBoxLayout->addWidget(remoteFileSizeLabel, 0, Qt::AlignRight);
fileSizeBoxLayout->addWidget(m_remoteFileSizeBox);
topLayout->addWidget(iconSizeGroup);
topLayout->addWidget(textGroup);
- topLayout->addWidget(m_expandableFolders);
+ if (m_expandableFolders) {
+ topLayout->addWidget(m_expandableFolders);
+ }
topLayout->addStretch(1);
loadSettings();
// File menu
- QAction* rename = m_actionCollection->addAction(QStringLiteral("rename"));
- rename->setText(i18nc("@action:inmenu File", "Rename..."));
- m_actionCollection->setDefaultShortcut(rename, Qt::Key_F2);
- rename->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename")));
- connect(rename, &QAction::triggered, this, &DolphinViewActionHandler::slotRename);
-
- QAction* moveToTrash = m_actionCollection->addAction(QStringLiteral("move_to_trash"));
- moveToTrash->setText(i18nc("@action:inmenu File", "Move to Trash"));
- moveToTrash->setIcon(QIcon::fromTheme(QStringLiteral("user-trash")));
- m_actionCollection->setDefaultShortcut(moveToTrash, QKeySequence::Delete);
- connect(moveToTrash, &QAction::triggered,
- this, &DolphinViewActionHandler::slotTrashActivated);
+ KStandardAction::renameFile(this, &DolphinViewActionHandler::slotRename, m_actionCollection);
+ KStandardAction::moveToTrash(this, &DolphinViewActionHandler::slotTrashActivated, m_actionCollection);
auto deleteAction = KStandardAction::deleteFile(this, &DolphinViewActionHandler::slotDeleteItems, m_actionCollection);
auto deleteShortcuts = deleteAction->shortcuts();
if (!deleteShortcuts.contains(Qt::SHIFT | Qt::Key_Delete)) {
m_actionCollection->setDefaultShortcuts(deleteAction, deleteShortcuts);
}
- // This action is useful for being enabled when "move_to_trash" should be
+ // This action is useful for being enabled when KStandardAction::MoveToTrash should be
// disabled and KStandardAction::DeleteFile is enabled (e.g. non-local files), so that Key_Del
// can be used for deleting the file (#76016). It needs to be a separate action
// so that the Edit menu isn't affected.
connect(viewModeActions, static_cast<void(KSelectAction::*)(QAction*)>(&KSelectAction::triggered), this, &DolphinViewActionHandler::slotViewModeActionTriggered);
KStandardAction::zoomIn(this,
- SLOT(zoomIn()),
+ &DolphinViewActionHandler::zoomIn,
m_actionCollection);
KStandardAction::zoomOut(this,
- SLOT(zoomOut()),
+ &DolphinViewActionHandler::zoomOut,
m_actionCollection);
KToggleAction* showPreview = m_actionCollection->add<KToggleAction>(QStringLiteral("show_preview"));
m_contentRetrievalTimer(0),
m_transientParent(0),
m_fileMetaDataWidget(0),
- m_tooltipWidget(new KToolTipWidget()),
m_toolTipRequested(false),
m_metaDataRequested(false),
m_appliedWaitCursor(false),
m_metaDataRequested = false;
m_showToolTipTimer->stop();
m_contentRetrievalTimer->stop();
- m_tooltipWidget->hideLater();
+ if (m_tooltipWidget) {
+ m_tooltipWidget->hideLater();
+ }
}
void ToolTipManager::startContentRetrieval()
// Adjust the size to get a proper sizeHint()
m_fileMetaDataWidget->adjustSize();
+ if (!m_tooltipWidget) {
+ m_tooltipWidget.reset(new KToolTipWidget());
+ }
m_tooltipWidget->showBelow(m_itemRect, m_fileMetaDataWidget, m_transientParent);
m_toolTipRequested = false;
}