X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/3e14a97a0f139a07e7fe3f6dcdb3b6ee689aa214..f3a86bf29e9165bbe2861c0af5e537d6d6f80854:/src/dolphinviewcontainer.cpp diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp index f64689d01..e21262977 100644 --- a/src/dolphinviewcontainer.cpp +++ b/src/dolphinviewcontainer.cpp @@ -18,64 +18,70 @@ ***************************************************************************/ #include "dolphinviewcontainer.h" -#include -#include -#include -#include -#include +#include "dolphin_generalsettings.h" +#include "dolphinplacesmodelsingleton.h" +#include "dolphindebug.h" +#include "filterbar/filterbar.h" +#include "global.h" +#include "search/dolphinsearchbox.h" +#include "statusbar/dolphinstatusbar.h" +#include "trash/dolphintrash.h" +#include "views/viewmodecontroller.h" +#include "views/viewproperties.h" +#ifdef HAVE_KACTIVITIES +#include +#endif #include #include -#include -#include #include +#include #include -#include +#include +#include #include -#include #include #include -#include -#ifdef KActivities_FOUND -#endif - -#include "dolphin_generalsettings.h" -#include "filterbar/filterbar.h" -#include "search/dolphinsearchbox.h" -#include "statusbar/dolphinstatusbar.h" -#include "views/draganddrophelper.h" -#include "views/viewmodecontroller.h" -#include "views/viewproperties.h" +#include +#include +#include +#include +#include +#include DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) : QWidget(parent), - m_topLayout(0), - m_urlNavigator(0), - m_searchBox(0), - m_messageWidget(0), - m_view(0), - m_filterBar(0), - m_statusBar(0), - m_statusBarTimer(0), + m_topLayout(nullptr), + m_navigatorWidget(nullptr), + m_urlNavigator(nullptr), + m_emptyTrashButton(nullptr), + m_searchBox(nullptr), + m_searchModeEnabled(false), + m_messageWidget(nullptr), + m_view(nullptr), + m_filterBar(nullptr), + m_statusBar(nullptr), + m_statusBarTimer(nullptr), m_statusBarTimestamp(), - m_autoGrabFocus(true), - m_dropDestination(), - m_dropEvent(0) -#ifdef KActivities_FOUND - , m_activityResourceInstance(0) + m_autoGrabFocus(true) +#ifdef HAVE_KACTIVITIES + , m_activityResourceInstance(nullptr) #endif { hide(); m_topLayout = new QVBoxLayout(this); m_topLayout->setSpacing(0); - m_topLayout->setMargin(0); + m_topLayout->setContentsMargins(0, 0, 0, 0); + + m_navigatorWidget = new QWidget(this); + QHBoxLayout* navigatorLayout = new QHBoxLayout(m_navigatorWidget); + navigatorLayout->setSpacing(0); + navigatorLayout->setContentsMargins(0, 0, 0, 0); - m_urlNavigator = new KUrlNavigator(new KFilePlacesModel(this), url, this); - connect(m_urlNavigator, &KUrlNavigator::urlsDropped, - this, &DolphinViewContainer::dropUrls); + m_urlNavigator = new KUrlNavigator(DolphinPlacesModelSingleton::instance().placesModel(), url, this); connect(m_urlNavigator, &KUrlNavigator::activated, this, &DolphinViewContainer::activate); connect(m_urlNavigator->editor(), &KUrlComboBox::completionModeChanged, @@ -84,10 +90,17 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) : const GeneralSettings* settings = GeneralSettings::self(); m_urlNavigator->setUrlEditable(settings->editableUrl()); m_urlNavigator->setShowFullPath(settings->showFullPath()); - m_urlNavigator->setHomeUrl(QUrl::fromLocalFile(settings->homeUrl())); + m_urlNavigator->setHomeUrl(Dolphin::homeUrl()); KUrlComboBox* editor = m_urlNavigator->editor(); editor->setCompletionMode(KCompletion::CompletionMode(settings->urlCompletionMode())); + m_emptyTrashButton = new QPushButton(QIcon::fromTheme(QStringLiteral("user-trash")), i18nc("@action:button", "Empty Trash"), this); + m_emptyTrashButton->setFlat(true); + connect(m_emptyTrashButton, &QPushButton::clicked, this, [this]() { Trash::empty(this); }); + connect(&Trash::instance(), &Trash::emptinessChanged, m_emptyTrashButton, &QPushButton::setDisabled); + m_emptyTrashButton->setDisabled(Trash::isEmpty()); + m_emptyTrashButton->hide(); + m_searchBox = new DolphinSearchBox(this); m_searchBox->hide(); connect(m_searchBox, &DolphinSearchBox::activated, this, &DolphinViewContainer::activate); @@ -99,13 +112,19 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) : m_messageWidget->setCloseButtonVisible(true); m_messageWidget->hide(); +#ifndef Q_OS_WIN + if (getuid() == 0) { + + // We must be logged in as the root user; show a big scary warning + showMessage(i18n("Running Dolphin as root can be dangerous. Please be careful."), Warning); + } +#endif + m_view = new DolphinView(url, this); connect(m_view, &DolphinView::urlChanged, - m_urlNavigator, &KUrlNavigator::setUrl); + m_urlNavigator, &KUrlNavigator::setLocationUrl); connect(m_view, &DolphinView::urlChanged, m_messageWidget, &KMessageWidget::hide); - connect(m_view, &DolphinView::directoryLoadingCompleted, - m_messageWidget, &KMessageWidget::hide); connect(m_view, &DolphinView::writeStateChanged, this, &DolphinViewContainer::writeStateChanged); connect(m_view, &DolphinView::requestItemInfo, @@ -130,8 +149,6 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) : this, &DolphinViewContainer::updateDirectorySortingProgress); connect(m_view, &DolphinView::selectionChanged, this, &DolphinViewContainer::delayedStatusBarUpdate); - connect(m_view, &DolphinView::urlAboutToBeChanged, - this, &DolphinViewContainer::slotViewUrlAboutToBeChanged); connect(m_view, &DolphinView::errorMessage, this, &DolphinViewContainer::showErrorMessage); connect(m_view, &DolphinView::urlIsFileError, @@ -143,10 +160,17 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) : this, &DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged); connect(m_urlNavigator, &KUrlNavigator::urlChanged, this, &DolphinViewContainer::slotUrlNavigatorLocationChanged); - connect(m_urlNavigator, &KUrlNavigator::historyChanged, - this, &DolphinViewContainer::slotHistoryChanged); + 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) { + m_view->dropUrls(destination, event, m_urlNavigator->dropWidget()); + }); + + connect(m_view, &DolphinView::directoryLoadingCompleted, this, [this]() { + m_emptyTrashButton->setVisible(m_view->url().scheme() == QLatin1String("trash")); + }); // Initialize status bar m_statusBar = new DolphinStatusBar(this); @@ -186,7 +210,10 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) : connect(m_view, &DolphinView::urlChanged, m_filterBar, &FilterBar::slotUrlChanged); - m_topLayout->addWidget(m_urlNavigator); + navigatorLayout->addWidget(m_urlNavigator); + navigatorLayout->addWidget(m_emptyTrashButton); + + m_topLayout->addWidget(m_navigatorWidget); m_topLayout->addWidget(m_searchBox); m_topLayout->addWidget(m_messageWidget); m_topLayout->addWidget(m_view); @@ -197,11 +224,10 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) : // Initialize kactivities resource instance - #ifdef KActivities_FOUND - m_activityResourceInstance = new KActivities::ResourceInstance( - window()->winId(), url); +#ifdef HAVE_KACTIVITIES + m_activityResourceInstance = new KActivities::ResourceInstance(window()->winId(), url); m_activityResourceInstance->setParent(this); - #endif +#endif } DolphinViewContainer::~DolphinViewContainer() @@ -219,13 +245,13 @@ void DolphinViewContainer::setActive(bool active) m_urlNavigator->setActive(active); m_view->setActive(active); - #ifdef KActivities_FOUND +#ifdef HAVE_KACTIVITIES if (active) { m_activityResourceInstance->notifyFocusedIn(); } else { m_activityResourceInstance->notifyFocusedOut(); } - #endif +#endif } bool DolphinViewContainer::isActive() const @@ -244,6 +270,11 @@ bool DolphinViewContainer::autoGrabFocus() const return m_autoGrabFocus; } +QString DolphinViewContainer::currentSearchText() const +{ + return m_searchBox->text(); +} + const DolphinStatusBar* DolphinViewContainer::statusBar() const { return m_statusBar; @@ -282,6 +313,10 @@ void DolphinViewContainer::showMessage(const QString& msg, MessageType type) m_messageWidget->setText(msg); + // TODO: wrap at arbitrary character positions once QLabel can do this + // https://bugreports.qt.io/browse/QTBUG-1276 + m_messageWidget->setWordWrap(true); + switch (type) { case Information: m_messageWidget->setMessageType(KMessageWidget::Information); break; case Warning: m_messageWidget->setMessageType(KMessageWidget::Warning); break; @@ -309,7 +344,7 @@ void DolphinViewContainer::readSettings() // settings of the URL navigator and the filterbar. m_urlNavigator->setUrlEditable(GeneralSettings::editableUrl()); m_urlNavigator->setShowFullPath(GeneralSettings::showFullPath()); - m_urlNavigator->setHomeUrl(QUrl::fromLocalFile(GeneralSettings::homeUrl())); + m_urlNavigator->setHomeUrl(Dolphin::homeUrl()); setFilterBarVisible(GeneralSettings::filterBar()); } @@ -333,7 +368,7 @@ void DolphinViewContainer::setSearchModeEnabled(bool enabled) } m_searchBox->setVisible(enabled); - m_urlNavigator->setVisible(!enabled); + m_navigatorWidget->setVisible(!enabled); if (enabled) { const QUrl& locationUrl = m_urlNavigator->locationUrl(); @@ -345,15 +380,17 @@ void DolphinViewContainer::setSearchModeEnabled(bool enabled) // started with a search-URL, the home URL is used as fallback. QUrl url = m_searchBox->searchPath(); if (url.isEmpty() || !url.isValid() || isSearchUrl(url)) { - url = QUrl::fromLocalFile(GeneralSettings::self()->homeUrl()); + url = Dolphin::homeUrl(); } m_urlNavigator->setLocationUrl(url); } + + m_searchModeEnabled = enabled; } bool DolphinViewContainer::isSearchModeEnabled() const { - return m_searchBox->isVisible(); + return m_searchModeEnabled; } QString DolphinViewContainer::placesText() const @@ -361,26 +398,82 @@ QString DolphinViewContainer::placesText() const QString text; if (isSearchModeEnabled()) { - text = m_searchBox->searchPath().fileName() + QLatin1String(": ") + m_searchBox->text(); + text = i18n("Search for %1 in %2", m_searchBox->text(), m_searchBox->searchPath().fileName()); } else { text = url().fileName(); if (text.isEmpty()) { text = url().host(); } + if (text.isEmpty()) { + text = url().scheme(); + } } return text; } +void DolphinViewContainer::reload() +{ + view()->reload(); + m_messageWidget->hide(); +} + +QString DolphinViewContainer::caption() const +{ + if (GeneralSettings::showFullPathInTitlebar()) { + if (!url().isLocalFile()) { + return url().adjusted(QUrl::StripTrailingSlash).toString(); + } + return url().adjusted(QUrl::StripTrailingSlash).path(); + } + + KFilePlacesModel *placesModel = DolphinPlacesModelSingleton::instance().placesModel(); + const auto& matchedPlaces = placesModel->match(placesModel->index(0,0), KFilePlacesModel::UrlRole, url(), 1, Qt::MatchExactly); + + if (!matchedPlaces.isEmpty()) { + return placesModel->text(matchedPlaces.first()); + } + + if (isSearchModeEnabled()) { + if (currentSearchText().isEmpty()){ + return i18n("Search"); + } else { + return i18n("Search for %1", currentSearchText()); + } + } + + if (!url().isLocalFile()) { + QUrl adjustedUrl = url().adjusted(QUrl::StripTrailingSlash); + QString caption; + if (!adjustedUrl.fileName().isEmpty()) { + caption = adjustedUrl.fileName(); + } else if (!adjustedUrl.path().isEmpty() && adjustedUrl.path() != "/") { + caption = adjustedUrl.path(); + } else if (!adjustedUrl.host().isEmpty()) { + caption = adjustedUrl.host(); + } else { + caption = adjustedUrl.toString(); + } + return caption; + } + + QString fileName = url().adjusted(QUrl::StripTrailingSlash).fileName(); + if (fileName.isEmpty()) { + fileName = '/'; + } + + return fileName; +} + void DolphinViewContainer::setUrl(const QUrl& newUrl) { if (newUrl != m_urlNavigator->locationUrl()) { m_urlNavigator->setLocationUrl(newUrl); } - #ifdef KActivities_FOUND +#ifdef HAVE_KACTIVITIES m_activityResourceInstance->setUri(newUrl); - #endif +#endif } void DolphinViewContainer::setFilterBarVisible(bool visible) @@ -479,14 +572,14 @@ void DolphinViewContainer::slotDirectoryLoadingCanceled() void DolphinViewContainer::slotUrlIsFileError(const QUrl& url) { - const KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url); + const KFileItem item(url); // Find out if the file can be opened in the view (for example, this is the // case if the file is an archive). The mime type must be known for that. item.determineMimeType(); const QUrl& folderUrl = DolphinView::openItemAsFolderUrl(item, true); if (!folderUrl.isEmpty()) { - m_view->setUrl(folderUrl); + setUrl(folderUrl); } else { slotItemActivated(item); } @@ -501,7 +594,7 @@ void DolphinViewContainer::slotItemActivated(const KFileItem& item) const QUrl& url = DolphinView::openItemAsFolderUrl(item, GeneralSettings::browseThroughArchives()); if (!url.isEmpty()) { - m_view->setUrl(url); + setUrl(url); return; } @@ -544,28 +637,9 @@ void DolphinViewContainer::activate() setActive(true); } -void DolphinViewContainer::slotViewUrlAboutToBeChanged(const QUrl& url) +void DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged(const QUrl&) { - // URL changes of the view can happen in two ways: - // 1. The URL navigator gets changed and will trigger the view to update its URL - // 2. The URL of the view gets changed and will trigger the URL navigator to update - // its URL (e.g. by clicking on an item) - // In this scope the view-state may only get saved in case 2: - if (url != m_urlNavigator->locationUrl()) { - saveViewState(); - } -} - -void DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged(const QUrl& url) -{ - // URL changes of the view can happen in two ways: - // 1. The URL navigator gets changed and will trigger the view to update its URL - // 2. The URL of the view gets changed and will trigger the URL navigator to update - // its URL (e.g. by clicking on an item) - // In this scope the view-state may only get saved in case 1: - if (url != m_view->url()) { - saveViewState(); - } + saveViewState(); } void DolphinViewContainer::slotUrlNavigatorLocationChanged(const QUrl& url) @@ -575,21 +649,22 @@ void DolphinViewContainer::slotUrlNavigatorLocationChanged(const QUrl& url) if (KProtocolManager::supportsListing(url)) { setSearchModeEnabled(isSearchUrl(url)); m_view->setUrl(url); + tryRestoreViewState(); if (m_autoGrabFocus && isActive() && !isSearchUrl(url)) { // When an URL has been entered, the view should get the focus. // The focus must be requested asynchronously, as changing the URL might create // a new view widget. - QTimer::singleShot(0, this, SLOT(requestFocus())); + QTimer::singleShot(0, this, &DolphinViewContainer::requestFocus); } } else if (KProtocolManager::isSourceProtocol(url)) { - QString app = "konqueror"; + QString app = QStringLiteral("konqueror"); if (url.scheme().startsWith(QLatin1String("http"))) { showMessage(i18nc("@info:status", // krazy:exclude=qmethods "Dolphin does not support web pages, the web browser has been launched"), Information); - const KConfigGroup config(KSharedConfig::openConfig("kdeglobals"), "General"); + const KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kdeglobals")), "General"); const QString browser = config.readEntry("BrowserApplication"); if (!browser.isEmpty()) { app = browser; @@ -612,39 +687,10 @@ void DolphinViewContainer::slotUrlNavigatorLocationChanged(const QUrl& url) } } -void DolphinViewContainer::dropUrls(const QUrl& destination, QDropEvent* event) -{ - m_dropDestination = destination; - - const QMimeData* mimeData = event->mimeData(); - QMimeData* mimeDataCopy = new QMimeData; - foreach (const QString& format, mimeData->formats()) { - mimeDataCopy->setData(format, mimeData->data(format)); - } - - m_dropEvent.reset(new QDropEvent(event->pos(), - event->possibleActions(), - mimeDataCopy, - event->mouseButtons(), - event->keyboardModifiers())); - - QTimer::singleShot(0, this, SLOT(dropUrlsDelayed())); -} - -void DolphinViewContainer::dropUrlsDelayed() +void DolphinViewContainer::slotUrlSelectionRequested(const QUrl& url) { - if (m_dropEvent.isNull()) { - return; - } - - QString error; - DragAndDropHelper::dropUrls(KFileItem(), m_dropDestination, m_dropEvent.data(), error); - if (!error.isEmpty()) { - showMessage(error, Error); - } - - delete m_dropEvent->mimeData(); - m_dropEvent.reset(); + m_view->markUrlsAsSelected({url}); + m_view->markUrlAsCurrent(url); // makes the item scroll into view } void DolphinViewContainer::redirect(const QUrl& oldUrl, const QUrl& newUrl) @@ -673,15 +719,6 @@ void DolphinViewContainer::saveUrlCompletionMode(KCompletion::CompletionMode com GeneralSettings::setUrlCompletionMode(completion); } -void DolphinViewContainer::slotHistoryChanged() -{ - QByteArray locationState = m_urlNavigator->locationState(); - if (!locationState.isEmpty()) { - QDataStream stream(&locationState, QIODevice::ReadOnly); - m_view->restoreState(stream); - } -} - void DolphinViewContainer::slotReturnPressed() { if (!GeneralSettings::editableUrl()) { @@ -693,7 +730,7 @@ void DolphinViewContainer::startSearching() { const QUrl url = m_searchBox->urlForSearching(); if (url.isValid() && !url.isEmpty()) { - m_view->setViewPropertiesContext("search"); + m_view->setViewPropertiesContext(QStringLiteral("search")); m_urlNavigator->setLocationUrl(url); } } @@ -721,7 +758,7 @@ void DolphinViewContainer::showErrorMessage(const QString& msg) bool DolphinViewContainer::isSearchUrl(const QUrl& url) const { - return url.scheme().contains("search"); + return url.scheme().contains(QStringLiteral("search")); } void DolphinViewContainer::saveViewState() @@ -731,3 +768,12 @@ void DolphinViewContainer::saveViewState() m_view->saveState(stream); m_urlNavigator->saveLocationState(locationState); } + +void DolphinViewContainer::tryRestoreViewState() +{ + QByteArray locationState = m_urlNavigator->locationState(); + if (!locationState.isEmpty()) { + QDataStream stream(&locationState, QIODevice::ReadOnly); + m_view->restoreState(stream); + } +}