X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/c62cb08d1400bc5a084638e8ae467303d343a92c..ed2d352c42a6d517d4f29b3582c0e00aa34fe647:/src/panels/information/informationpanel.cpp diff --git a/src/panels/information/informationpanel.cpp b/src/panels/information/informationpanel.cpp index f15cf05d5..7367f1d13 100644 --- a/src/panels/information/informationpanel.cpp +++ b/src/panels/information/informationpanel.cpp @@ -1,40 +1,41 @@ -/*************************************************************************** - * Copyright (C) 2006-2009 by Peter Penz * - * * - * 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 * - ***************************************************************************/ +/* + * SPDX-FileCopyrightText: 2006-2009 Peter Penz + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ #include "informationpanel.h" -#include + +#include "informationpanelcontent.h" + +#include +#include +#include +#include + +#include + +#include +#include #include +#include #include -#include "informationpanelcontent.h" -InformationPanel::InformationPanel(QWidget* parent) : - Panel(parent), - m_initialized(false), - m_infoTimer(0), - m_urlChangedTimer(0), - m_resetUrlTimer(0), - m_shownUrl(), - m_urlCandidate(), - m_invalidUrlCandidate(), - m_fileItem(), - m_selection(), - m_content(0) +#include "dolphin_informationpanelsettings.h" + +InformationPanel::InformationPanel(QWidget *parent) + : Panel(parent) + , m_initialized(false) + , m_infoTimer(nullptr) + , m_urlChangedTimer(nullptr) + , m_resetUrlTimer(nullptr) + , m_shownUrl() + , m_urlCandidate() + , m_invalidUrlCandidate() + , m_hoveredItem() + , m_selection() + , m_folderStatJob(nullptr) + , m_content(nullptr) { } @@ -42,88 +43,79 @@ InformationPanel::~InformationPanel() { } -QSize InformationPanel::sizeHint() const +void InformationPanel::setSelection(const KFileItemList &selection) { - QSize size = Panel::sizeHint(); - size.setWidth(minimumSizeHint().width()); - return size; -} - -void InformationPanel::setUrl(const KUrl& url) -{ - Panel::setUrl(url); - if (url.isValid() && !isEqualToShownUrl(url)) { - if (isVisible()) { - cancelRequest(); - m_shownUrl = url; - // Update the content with a delay. This gives - // the directory lister the chance to show the content - // before expensive operations are done to show - // meta information. - m_urlChangedTimer->start(); - } else { - m_shownUrl = url; - } - } -} + m_selection = selection; -void InformationPanel::setSelection(const KFileItemList& selection) -{ if (!isVisible()) { return; } - if ((selection.count() == 0) && (m_selection.count() == 0)) { - // The selection has not really changed, only the current index. - // QItemSelectionModel emits a signal in this case and it is less - // expensive doing the check this way instead of patching - // DolphinView::emitSelectionChanged(). - return; - } - - m_selection = selection; - m_fileItem = KFileItem(); - const int count = selection.count(); if (count == 0) { if (!isEqualToShownUrl(url())) { m_shownUrl = url(); showItemInfo(); } + m_infoTimer->stop(); } else { if ((count == 1) && !selection.first().url().isEmpty()) { m_urlCandidate = selection.first().url(); } - m_infoTimer->start(); + showItemInfo(); } } -void InformationPanel::requestDelayedItemInfo(const KFileItem& item) +void InformationPanel::requestDelayedItemInfo(const KFileItem &item) { - if (!isVisible()) { + if (!isVisible() || !InformationPanelSettings::showHovered()) { return; } - cancelRequest(); + if (QApplication::mouseButtons() & Qt::LeftButton) { + // Ignore the request of an item information when a rubberband + // selection is ongoing. + return; + } - m_fileItem = KFileItem(); if (item.isNull()) { - // The cursor is above the viewport. If files are selected, - // show information regarding the selection. - if (m_selection.size() > 0) { - m_infoTimer->start(); - } - } else { - const KUrl url = item.url(); - if (url.isValid() && !isEqualToShownUrl(url)) { - m_urlCandidate = item.url(); - m_fileItem = item; - m_infoTimer->start(); - } + m_hoveredItem = KFileItem(); + return; } + + cancelRequest(); + + m_hoveredItem = item; + m_infoTimer->start(); } -void InformationPanel::showEvent(QShowEvent* event) +bool InformationPanel::urlChanged() +{ + if (!url().isValid()) { + return false; + } + + if (!isVisible()) { + return true; + } + + cancelRequest(); + m_selection.clear(); + + if (!isEqualToShownUrl(url())) { + m_shownUrl = url(); + + // Update the content with a delay. This gives + // the directory lister the chance to show the content + // before expensive operations are done to show + // meta information. + m_urlChangedTimer->start(); + } + + return true; +} + +void InformationPanel::showEvent(QShowEvent *event) { Panel::showEvent(event); if (!event->spontaneous()) { @@ -133,11 +125,13 @@ void InformationPanel::showEvent(QShowEvent* event) // Information Panel init(); } + + m_shownUrl = url(); showItemInfo(); } } -void InformationPanel::resizeEvent(QResizeEvent* event) +void InformationPanel::resizeEvent(QResizeEvent *event) { if (isVisible()) { m_urlCandidate = m_shownUrl; @@ -146,12 +140,79 @@ void InformationPanel::resizeEvent(QResizeEvent* event) Panel::resizeEvent(event); } -void InformationPanel::contextMenuEvent(QContextMenuEvent* event) +void InformationPanel::contextMenuEvent(QContextMenuEvent *event) { - m_content->configureSettings(); + showContextMenu(event->globalPos()); Panel::contextMenuEvent(event); } +void InformationPanel::showContextMenu(const QPoint &pos) +{ + QMenu popup(this); + + QAction *previewAction = popup.addAction(i18nc("@action:inmenu", "Preview")); + previewAction->setIcon(QIcon::fromTheme(QStringLiteral("view-preview"))); + previewAction->setCheckable(true); + previewAction->setChecked(InformationPanelSettings::previewsShown()); + + QAction *previewAutoPlayAction = popup.addAction(i18nc("@action:inmenu", "Auto-Play media files")); + previewAutoPlayAction->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start"))); + previewAutoPlayAction->setCheckable(true); + previewAutoPlayAction->setChecked(InformationPanelSettings::previewsAutoPlay()); + + QAction *showHoveredAction = popup.addAction(i18nc("@action:inmenu", "Show item on hover")); + showHoveredAction->setIcon(QIcon::fromTheme(QStringLiteral("followmouse"))); + showHoveredAction->setCheckable(true); + showHoveredAction->setChecked(InformationPanelSettings::showHovered()); + + QAction *configureAction = popup.addAction(i18nc("@action:inmenu", "Configure…")); + configureAction->setIcon(QIcon::fromTheme(QStringLiteral("configure"))); + if (m_inConfigurationMode) { + configureAction->setEnabled(false); + } + + QAction *dateformatAction = popup.addAction(i18nc("@action:inmenu", "Condensed Date")); + dateformatAction->setIcon(QIcon::fromTheme(QStringLiteral("change-date-symbolic"))); + dateformatAction->setCheckable(true); + dateformatAction->setChecked(InformationPanelSettings::dateFormat() == static_cast(Baloo::DateFormats::ShortFormat)); + + popup.addSeparator(); + const auto actions = customContextMenuActions(); + for (QAction *action : actions) { + popup.addAction(action); + } + + // Open the popup and adjust the settings for the + // selected action. + QAction *action = popup.exec(pos); + if (!action) { + return; + } + + const bool isChecked = action->isChecked(); + if (action == previewAction) { + InformationPanelSettings::setPreviewsShown(isChecked); + m_content->refreshPreview(); + } else if (action == previewAutoPlayAction) { + InformationPanelSettings::setPreviewsAutoPlay(isChecked); + m_content->setPreviewAutoPlay(isChecked); + } else if (action == showHoveredAction) { + InformationPanelSettings::setShowHovered(isChecked); + if (!isChecked) { + m_hoveredItem = KFileItem(); + showItemInfo(); + } + } else if (action == configureAction) { + m_inConfigurationMode = true; + m_content->configureShownProperties(); + } else if (action == dateformatAction) { + int dateFormat = static_cast(isChecked ? Baloo::DateFormats::ShortFormat : Baloo::DateFormats::LongFormat); + + InformationPanelSettings::setDateFormat(dateFormat); + m_content->refreshMetaData(); + } +} + void InformationPanel::showItemInfo() { if (!isVisible()) { @@ -159,56 +220,73 @@ void InformationPanel::showItemInfo() } cancelRequest(); + //qDebug() << "showItemInfo" << m_fileItem; - if (showMultipleSelectionInfo()) { + if (m_hoveredItem.isNull() && (m_selection.count() > 1)) { + // The information for a selection of items should be shown m_content->showItems(m_selection); - m_shownUrl = KUrl(); } else { + // The information for exactly one item should be shown KFileItem item; - if (!m_fileItem.isNull()) { - item = m_fileItem; + if (!m_hoveredItem.isNull() && InformationPanelSettings::showHovered()) { + item = m_hoveredItem; } else if (!m_selection.isEmpty()) { Q_ASSERT(m_selection.count() == 1); item = m_selection.first(); - } else { - // no item is hovered and no selection has been done: provide - // an item for the directory represented by m_shownUrl - item = KFileItem(KFileItem::Unknown, KFileItem::Unknown, m_shownUrl); - item.refresh(); } - m_content->showItem(item); + if (!item.isNull()) { + m_shownUrl = item.url(); + m_content->showItem(item); + return; + } + + // No item is hovered and no selection has been done: provide + // an item for the currently shown directory. + m_shownUrl = url(); + m_folderStatJob = KIO::statDetails(m_shownUrl, KIO::StatJob::SourceSide, KIO::StatDefaultDetails | KIO::StatRecursiveSize, KIO::HideProgressInfo); + if (m_folderStatJob->uiDelegate()) { + KJobWidgets::setWindow(m_folderStatJob, this); + } + connect(m_folderStatJob, &KIO::Job::result, this, &InformationPanel::slotFolderStatFinished); } } +void InformationPanel::slotFolderStatFinished(KJob *job) +{ + m_folderStatJob = nullptr; + const KIO::UDSEntry entry = static_cast(job)->statResult(); + m_content->showItem(KFileItem(entry, m_shownUrl)); +} + void InformationPanel::slotInfoTimeout() { m_shownUrl = m_urlCandidate; + m_urlCandidate.clear(); showItemInfo(); } void InformationPanel::reset() { if (m_invalidUrlCandidate == m_shownUrl) { - m_invalidUrlCandidate = KUrl(); + m_invalidUrlCandidate = QUrl(); // The current URL is still invalid. Reset // the content to show the directory URL. m_selection.clear(); m_shownUrl = url(); - m_fileItem = KFileItem(); showItemInfo(); } } -void InformationPanel::slotFileRenamed(const QString& source, const QString& dest) +void InformationPanel::slotFileRenamed(const QString &source, const QString &dest) { - if (m_shownUrl == KUrl(source)) { - m_shownUrl = KUrl(dest); - m_fileItem = KFileItem(KFileItem::Unknown, KFileItem::Unknown, m_shownUrl); + auto sourceUrl = QUrl::fromUserInput(source); + if (m_shownUrl == sourceUrl) { + auto destUrl = QUrl::fromUserInput(dest); - if ((m_selection.count() == 1) && (m_selection[0].url() == KUrl(source))) { - m_selection[0] = m_fileItem; + if ((m_selection.count() == 1) && (m_selection[0].url() == sourceUrl)) { + m_selection[0] = KFileItem(destUrl); // Implementation note: Updating the selection is only required if exactly one // item is selected, as the name of the item is shown. If this should change // in future: Before parsing the whole selection take care to test possible @@ -219,30 +297,37 @@ void InformationPanel::slotFileRenamed(const QString& source, const QString& des } } -void InformationPanel::slotFilesAdded(const QString& directory) +void InformationPanel::slotFilesAdded(const QString &directory) { - if (m_shownUrl == KUrl(directory)) { + if (m_shownUrl == QUrl::fromUserInput(directory)) { // If the 'trash' icon changes because the trash has been emptied or got filled, // the signal filesAdded("trash:/") will be emitted. - KFileItem item(KFileItem::Unknown, KFileItem::Unknown, KUrl(directory)); - requestDelayedItemInfo(item); + requestDelayedItemInfo(KFileItem()); + } +} + +void InformationPanel::slotFilesItemChanged(const KFileItemList &changedFileItems) +{ + const auto item = changedFileItems.findByUrl(m_shownUrl); + if (!item.isNull()) { + showItemInfo(); } } -void InformationPanel::slotFilesChanged(const QStringList& files) +void InformationPanel::slotFilesChanged(const QStringList &files) { - foreach (const QString& fileName, files) { - if (m_shownUrl == KUrl(fileName)) { + for (const QString &fileName : files) { + if (m_shownUrl == QUrl::fromUserInput(fileName)) { showItemInfo(); break; } } } -void InformationPanel::slotFilesRemoved(const QStringList& files) +void InformationPanel::slotFilesRemoved(const QStringList &files) { - foreach (const QString& fileName, files) { - if (m_shownUrl == KUrl(fileName)) { + for (const QString &fileName : files) { + if (m_shownUrl == QUrl::fromUserInput(fileName)) { // the currently shown item has been removed, show // the parent directory as fallback markUrlAsInvalid(); @@ -251,17 +336,14 @@ void InformationPanel::slotFilesRemoved(const QStringList& files) } } -void InformationPanel::slotEnteredDirectory(const QString& directory) +void InformationPanel::slotEnteredDirectory(const QString &directory) { - if (m_shownUrl == KUrl(directory)) { - KFileItem item(KFileItem::Unknown, KFileItem::Unknown, KUrl(directory)); - requestDelayedItemInfo(item); - } + Q_UNUSED(directory) } -void InformationPanel::slotLeftDirectory(const QString& directory) +void InformationPanel::slotLeftDirectory(const QString &directory) { - if (m_shownUrl == KUrl(directory)) { + if (m_shownUrl == QUrl::fromUserInput(directory)) { // The signal 'leftDirectory' is also emitted when a media // has been unmounted. In this case no directory change will be // done in Dolphin, but the Information Panel must be updated to @@ -272,17 +354,22 @@ void InformationPanel::slotLeftDirectory(const QString& directory) void InformationPanel::cancelRequest() { + delete m_folderStatJob; + m_folderStatJob = nullptr; + m_infoTimer->stop(); -} + m_resetUrlTimer->stop(); + // Don't reset m_urlChangedTimer. As it is assured that the timeout of m_urlChangedTimer + // has the smallest interval (see init()), it is not possible that the exceeded timer + // would overwrite an information provided by a selection or hovering. -bool InformationPanel::showMultipleSelectionInfo() const -{ - return m_fileItem.isNull() && (m_selection.count() > 1); + m_invalidUrlCandidate.clear(); + m_urlCandidate.clear(); } -bool InformationPanel::isEqualToShownUrl(const KUrl& url) const +bool InformationPanel::isEqualToShownUrl(const QUrl &url) const { - return m_shownUrl.equals(url, KUrl::CompareWithoutTrailingSlash); + return m_shownUrl.matches(url, QUrl::StripTrailingSlash); } void InformationPanel::markUrlAsInvalid() @@ -293,42 +380,44 @@ void InformationPanel::markUrlAsInvalid() void InformationPanel::init() { - const int defaultDelay = 300; - m_infoTimer = new QTimer(this); - m_infoTimer->setInterval(defaultDelay); + m_infoTimer->setInterval(300); m_infoTimer->setSingleShot(true); - connect(m_infoTimer, SIGNAL(timeout()), - this, SLOT(slotInfoTimeout())); + connect(m_infoTimer, &QTimer::timeout, this, &InformationPanel::slotInfoTimeout); m_urlChangedTimer = new QTimer(this); - m_urlChangedTimer->setInterval(defaultDelay); + m_urlChangedTimer->setInterval(200); m_urlChangedTimer->setSingleShot(true); - connect(m_urlChangedTimer, SIGNAL(timeout()), - this, SLOT(showItemInfo())); + connect(m_urlChangedTimer, &QTimer::timeout, this, &InformationPanel::showItemInfo); m_resetUrlTimer = new QTimer(this); - m_resetUrlTimer->setInterval(defaultDelay * 3); + m_resetUrlTimer->setInterval(1000); m_resetUrlTimer->setSingleShot(true); - connect(m_resetUrlTimer, SIGNAL(timeout()), - this, SLOT(reset())); - - org::kde::KDirNotify* dirNotify = new org::kde::KDirNotify(QString(), QString(), - QDBusConnection::sessionBus(), this); - connect(dirNotify, SIGNAL(FileRenamed(QString, QString)), SLOT(slotFileRenamed(QString, QString))); - connect(dirNotify, SIGNAL(FilesAdded(QString)), SLOT(slotFilesAdded(QString))); - connect(dirNotify, SIGNAL(FilesChanged(QStringList)), SLOT(slotFilesChanged(QStringList))); - connect(dirNotify, SIGNAL(FilesRemoved(QStringList)), SLOT(slotFilesRemoved(QStringList))); - connect(dirNotify, SIGNAL(enteredDirectory(QString)), SLOT(slotEnteredDirectory(QString))); - connect(dirNotify, SIGNAL(leftDirectory(QString)), SLOT(slotLeftDirectory(QString))); + connect(m_resetUrlTimer, &QTimer::timeout, this, &InformationPanel::reset); + + Q_ASSERT(m_urlChangedTimer->interval() < m_infoTimer->interval()); + Q_ASSERT(m_urlChangedTimer->interval() < m_resetUrlTimer->interval()); + + org::kde::KDirNotify *dirNotify = new org::kde::KDirNotify(QString(), QString(), QDBusConnection::sessionBus(), this); + connect(dirNotify, &OrgKdeKDirNotifyInterface::FileRenamed, this, &InformationPanel::slotFileRenamed); + connect(dirNotify, &OrgKdeKDirNotifyInterface::FilesAdded, this, &InformationPanel::slotFilesAdded); + connect(dirNotify, &OrgKdeKDirNotifyInterface::FilesChanged, this, &InformationPanel::slotFilesChanged); + connect(dirNotify, &OrgKdeKDirNotifyInterface::FilesRemoved, this, &InformationPanel::slotFilesRemoved); + connect(dirNotify, &OrgKdeKDirNotifyInterface::enteredDirectory, this, &InformationPanel::slotEnteredDirectory); + connect(dirNotify, &OrgKdeKDirNotifyInterface::leftDirectory, this, &InformationPanel::slotLeftDirectory); m_content = new InformationPanelContent(this); - connect(m_content, SIGNAL(urlActivated(KUrl)), this, SIGNAL(urlActivated(KUrl))); - - QVBoxLayout* layout = new QVBoxLayout(this); + connect(m_content, &InformationPanelContent::urlActivated, this, &InformationPanel::urlActivated); + connect(m_content, &InformationPanelContent::configurationFinished, this, [this]() { + m_inConfigurationMode = false; + }); + connect(m_content, &InformationPanelContent::contextMenuRequested, this, &InformationPanel::showContextMenu); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(m_content); m_initialized = true; } -#include "informationpanel.moc" +#include "moc_informationpanel.cpp"