diff --git a/src/panels/information/informationpanel.cpp b/src/panels/information/informationpanel.cpp index 2b6fff158..e5257bc72 100644 --- a/src/panels/information/informationpanel.cpp +++ b/src/panels/information/informationpanel.cpp @@ -1,421 +1,421 @@ /*************************************************************************** * 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 * ***************************************************************************/ #include "informationpanel.h" #include "informationpanelcontent.h" #include #include #include #include #include #include #include #include #include #include #include #include "dolphin_informationpanelsettings.h" #include "filemetadataconfigurationdialog.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_fileItem(), m_selection(), m_folderStatJob(nullptr), m_content(nullptr) { } InformationPanel::~InformationPanel() { } void InformationPanel::setSelection(const KFileItemList& selection) { m_selection = selection; m_fileItem = KFileItem(); if (!isVisible()) { return; } const int count = selection.count(); if (count == 0) { if (!isEqualToShownUrl(url())) { m_shownUrl = url(); showItemInfo(); } } else { if ((count == 1) && !selection.first().url().isEmpty()) { m_urlCandidate = selection.first().url(); } m_infoTimer->start(); } } void InformationPanel::requestDelayedItemInfo(const KFileItem& item) { if (!isVisible() || (item.isNull() && m_fileItem.isNull())) { return; } if (QApplication::mouseButtons() & Qt::LeftButton) { // Ignore the request of an item information when a rubberband // selection is ongoing. return; } cancelRequest(); if (item.isNull()) { // The cursor is above the viewport. If files are selected, // show information regarding the selection. if (!m_selection.isEmpty()) { m_fileItem = KFileItem(); m_infoTimer->start(); } } else if (item.url().isValid() && !isEqualToShownUrl(item.url())) { // The cursor is above an item that is not shown currently m_urlCandidate = item.url(); m_fileItem = item; m_infoTimer->start(); } } bool InformationPanel::urlChanged() { if (!url().isValid()) { return false; } if (!isVisible()) { return true; } cancelRequest(); m_selection.clear(); if (!isEqualToShownUrl(url())) { m_shownUrl = url(); m_fileItem = KFileItem(); // 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()) { if (!m_initialized) { // do a delayed initialization so that no performance // penalty is given when Dolphin is started with a closed // Information Panel init(); } m_shownUrl = url(); showItemInfo(); } } void InformationPanel::resizeEvent(QResizeEvent* event) { if (isVisible()) { m_urlCandidate = m_shownUrl; m_infoTimer->start(); } Panel::resizeEvent(event); } void InformationPanel::contextMenuEvent(QContextMenuEvent* event) { 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* configureAction = popup.addAction(i18nc("@action:inmenu", "Configure...")); configureAction->setIcon(QIcon::fromTheme(QStringLiteral("configure"))); 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) { - m_content->setPreviewVisible(isChecked); InformationPanelSettings::setPreviewsShown(isChecked); + m_content->refreshPreview(); } else if (action == configureAction) { FileMetaDataConfigurationDialog* dialog = new FileMetaDataConfigurationDialog(this); dialog->setDescription(i18nc("@label::textbox", "Select which data should be shown in the information panel:")); dialog->setItems(m_content->items()); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); connect(dialog, &FileMetaDataConfigurationDialog::destroyed, m_content, &InformationPanelContent::refreshMetaData); } 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()) { return; } cancelRequest(); if (m_fileItem.isNull() && (m_selection.count() > 1)) { // The information for a selection of items should be shown m_content->showItems(m_selection); } else { // The information for exactly one item should be shown KFileItem item; if (!m_fileItem.isNull()) { item = m_fileItem; } else if (!m_selection.isEmpty()) { Q_ASSERT(m_selection.count() == 1); item = m_selection.first(); } if (item.isNull()) { // No item is hovered and no selection has been done: provide // an item for the currently shown directory. m_folderStatJob = KIO::stat(url(), KIO::HideProgressInfo); if (m_folderStatJob->uiDelegate()) { KJobWidgets::setWindow(m_folderStatJob, this); } connect(m_folderStatJob, &KIO::Job::result, this, &InformationPanel::slotFolderStatFinished); } else { m_content->showItem(item); } } } 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 = 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) { if (m_shownUrl == QUrl::fromLocalFile(source)) { m_shownUrl = QUrl::fromLocalFile(dest); m_fileItem = KFileItem(m_shownUrl); if ((m_selection.count() == 1) && (m_selection[0].url() == QUrl::fromLocalFile(source))) { m_selection[0] = m_fileItem; // 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 // performance bottlenecks when renaming several hundreds of files. } showItemInfo(); } } void InformationPanel::slotFilesAdded(const QString& directory) { if (m_shownUrl == QUrl::fromLocalFile(directory)) { // If the 'trash' icon changes because the trash has been emptied or got filled, // the signal filesAdded("trash:/") will be emitted. KFileItem item(QUrl::fromLocalFile(directory)); requestDelayedItemInfo(item); } } void InformationPanel::slotFilesChanged(const QStringList& files) { for (const QString& fileName : files) { if (m_shownUrl == QUrl::fromLocalFile(fileName)) { showItemInfo(); break; } } } void InformationPanel::slotFilesRemoved(const QStringList& files) { for (const QString& fileName : files) { if (m_shownUrl == QUrl::fromLocalFile(fileName)) { // the currently shown item has been removed, show // the parent directory as fallback markUrlAsInvalid(); break; } } } void InformationPanel::slotEnteredDirectory(const QString& directory) { if (m_shownUrl == QUrl::fromLocalFile(directory)) { KFileItem item(QUrl::fromLocalFile(directory)); requestDelayedItemInfo(item); } } void InformationPanel::slotLeftDirectory(const QString& directory) { if (m_shownUrl == QUrl::fromLocalFile(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 // indicate an invalid directory. markUrlAsInvalid(); } } 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. m_invalidUrlCandidate.clear(); m_urlCandidate.clear(); } bool InformationPanel::isEqualToShownUrl(const QUrl& url) const { return m_shownUrl.matches(url, QUrl::StripTrailingSlash); } void InformationPanel::markUrlAsInvalid() { m_invalidUrlCandidate = m_shownUrl; m_resetUrlTimer->start(); } void InformationPanel::init() { m_infoTimer = new QTimer(this); m_infoTimer->setInterval(300); m_infoTimer->setSingleShot(true); connect(m_infoTimer, &QTimer::timeout, this, &InformationPanel::slotInfoTimeout); m_urlChangedTimer = new QTimer(this); m_urlChangedTimer->setInterval(200); m_urlChangedTimer->setSingleShot(true); connect(m_urlChangedTimer, &QTimer::timeout, this, &InformationPanel::showItemInfo); m_resetUrlTimer = new QTimer(this); m_resetUrlTimer->setInterval(1000); m_resetUrlTimer->setSingleShot(true); 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, &InformationPanelContent::urlActivated, this, &InformationPanel::urlActivated); QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(m_content); m_initialized = true; } diff --git a/src/panels/information/informationpanelcontent.cpp b/src/panels/information/informationpanelcontent.cpp index 4b34e55e3..e2b90dcc8 100644 --- a/src/panels/information/informationpanelcontent.cpp +++ b/src/panels/information/informationpanelcontent.cpp @@ -1,368 +1,364 @@ /*************************************************************************** * Copyright (C) 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 * ***************************************************************************/ #include "informationpanelcontent.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dolphin_informationpanelsettings.h" #include "phononwidget.h" #include "pixmapviewer.h" InformationPanelContent::InformationPanelContent(QWidget* parent) : QWidget(parent), m_item(), m_previewJob(nullptr), m_outdatedPreviewTimer(nullptr), m_preview(nullptr), m_phononWidget(nullptr), m_nameLabel(nullptr), m_metaDataWidget(nullptr), m_metaDataArea(nullptr), m_placesItemModel(nullptr) { parent->installEventFilter(this); // Initialize timer for disabling an outdated preview with a small // delay. This prevents flickering if the new preview can be generated // within a very small timeframe. m_outdatedPreviewTimer = new QTimer(this); m_outdatedPreviewTimer->setInterval(300); m_outdatedPreviewTimer->setSingleShot(true); connect(m_outdatedPreviewTimer, &QTimer::timeout, this, &InformationPanelContent::markOutdatedPreview); QVBoxLayout* layout = new QVBoxLayout(this); // preview const int minPreviewWidth = KIconLoader::SizeEnormous + KIconLoader::SizeMedium; m_preview = new PixmapViewer(parent); m_preview->setMinimumWidth(minPreviewWidth); m_preview->setMinimumHeight(KIconLoader::SizeEnormous); m_phononWidget = new PhononWidget(parent); m_phononWidget->hide(); m_phononWidget->setMinimumWidth(minPreviewWidth); connect(m_phononWidget, &PhononWidget::hasVideoChanged, this, &InformationPanelContent::slotHasVideoChanged); // name m_nameLabel = new QLabel(parent); QFont font = m_nameLabel->font(); font.setBold(true); m_nameLabel->setFont(font); m_nameLabel->setTextFormat(Qt::PlainText); m_nameLabel->setAlignment(Qt::AlignHCenter); m_nameLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); const bool previewsShown = InformationPanelSettings::previewsShown(); m_preview->setVisible(previewsShown); m_metaDataWidget = new Baloo::FileMetaDataWidget(parent); m_metaDataWidget->setDateFormat(static_cast(InformationPanelSettings::dateFormat())); connect(m_metaDataWidget, &Baloo::FileMetaDataWidget::urlActivated, this, &InformationPanelContent::urlActivated); m_metaDataWidget->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); m_metaDataWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); // Encapsulate the MetaDataWidget inside a container that has a dummy widget // at the bottom. This prevents that the meta data widget gets vertically stretched // in the case where the height of m_metaDataArea > m_metaDataWidget. QWidget* metaDataWidgetContainer = new QWidget(parent); QVBoxLayout* containerLayout = new QVBoxLayout(metaDataWidgetContainer); containerLayout->setContentsMargins(0, 0, 0, 0); containerLayout->setSpacing(0); containerLayout->addWidget(m_metaDataWidget); containerLayout->addStretch(); m_metaDataArea = new QScrollArea(parent); m_metaDataArea->setWidget(metaDataWidgetContainer); m_metaDataArea->setWidgetResizable(true); m_metaDataArea->setFrameShape(QFrame::NoFrame); QWidget* viewport = m_metaDataArea->viewport(); viewport->installEventFilter(this); layout->addWidget(m_preview); layout->addWidget(m_phononWidget); layout->addWidget(m_nameLabel); layout->addWidget(new KSeparator()); layout->addWidget(m_metaDataArea); m_placesItemModel = new PlacesItemModel(this); } InformationPanelContent::~InformationPanelContent() { InformationPanelSettings::self()->save(); } void InformationPanelContent::showItem(const KFileItem& item) { + m_item = item; + + refreshPreview(); + refreshMetaData(); +} + +void InformationPanelContent::refreshPreview() { // If there is a preview job, kill it to prevent that we have jobs for // multiple items running, and thus a race condition (bug 250787). if (m_previewJob) { m_previewJob->kill(); } - const QUrl itemUrl = item.url(); - const bool isSearchUrl = itemUrl.scheme().contains(QStringLiteral("search")) && item.localPath().isEmpty(); - setNameLabelText(item.text()); - if (isSearchUrl) { - // in the case of a search-URL the URL is not readable for humans - // (at least not useful to show in the Information Panel) - m_preview->setPixmap( - QIcon::fromTheme(QStringLiteral("nepomuk")).pixmap(KIconLoader::SizeEnormous, KIconLoader::SizeEnormous) - ); - } else { - // try to get a preview pixmap from the item... - - // Mark the currently shown preview as outdated. This is done - // with a small delay to prevent a flickering when the next preview - // can be shown within a short timeframe. This timer is not started - // for directories, as directory previews might fail and return the - // same icon. - if (!item.isDir()) { - m_outdatedPreviewTimer->start(); - } + if (InformationPanelSettings::previewsShown()) { + m_preview->show(); + + const QUrl itemUrl = m_item.url(); + const bool isSearchUrl = itemUrl.scheme().contains(QStringLiteral("search")) && m_item.localPath().isEmpty(); + setNameLabelText(m_item.text()); + if (isSearchUrl) { + // in the case of a search-URL the URL is not readable for humans + // (at least not useful to show in the Information Panel) + m_preview->setPixmap( + QIcon::fromTheme(QStringLiteral("nepomuk")).pixmap(KIconLoader::SizeEnormous, KIconLoader::SizeEnormous) + ); + } else { + // try to get a preview pixmap from the item... + + // Mark the currently shown preview as outdated. This is done + // with a small delay to prevent a flickering when the next preview + // can be shown within a short timeframe. This timer is not started + // for directories, as directory previews might fail and return the + // same icon. + if (!m_item.isDir()) { + m_outdatedPreviewTimer->start(); + } - QStringList plugins = KIO::PreviewJob::availablePlugins(); - m_previewJob = new KIO::PreviewJob(KFileItemList() << item, - QSize(m_preview->width(), m_preview->height()), - &plugins); - m_previewJob->setScaleType(KIO::PreviewJob::Unscaled); - m_previewJob->setIgnoreMaximumSize(item.isLocalFile()); - if (m_previewJob->uiDelegate()) { - KJobWidgets::setWindow(m_previewJob, this); - } + QStringList plugins = KIO::PreviewJob::availablePlugins(); + m_previewJob = new KIO::PreviewJob(KFileItemList() << m_item, + QSize(m_preview->width(), m_preview->height()), + &plugins); + m_previewJob->setScaleType(KIO::PreviewJob::Unscaled); + m_previewJob->setIgnoreMaximumSize(m_item.isLocalFile()); + if (m_previewJob->uiDelegate()) { + KJobWidgets::setWindow(m_previewJob, this); + } - connect(m_previewJob.data(), &KIO::PreviewJob::gotPreview, - this, &InformationPanelContent::showPreview); - connect(m_previewJob.data(), &KIO::PreviewJob::failed, - this, &InformationPanelContent::showIcon); - } + connect(m_previewJob.data(), &KIO::PreviewJob::gotPreview, + this, &InformationPanelContent::showPreview); + connect(m_previewJob.data(), &KIO::PreviewJob::failed, + this, &InformationPanelContent::showIcon); - if (m_metaDataWidget) { - m_metaDataWidget->setDateFormat(static_cast(InformationPanelSettings::dateFormat())); - m_metaDataWidget->show(); - m_metaDataWidget->setItems(KFileItemList() << item); - } - - if (InformationPanelSettings::previewsShown()) { - const QString mimeType = item.mimetype(); - const bool usePhonon = mimeType.startsWith(QLatin1String("audio/")) || mimeType.startsWith(QLatin1String("video/")); - if (usePhonon) { - m_phononWidget->show(); - m_phononWidget->setUrl(item.targetUrl()); - if (m_preview->isVisible()) { + const QString mimeType = m_item.mimetype(); + const bool usePhonon = mimeType.startsWith(QLatin1String("audio/")) || mimeType.startsWith(QLatin1String("video/")); + if (usePhonon) { + m_phononWidget->show(); + m_phononWidget->setUrl(m_item.targetUrl()); m_phononWidget->setVideoSize(m_preview->size()); + } else { + m_phononWidget->hide(); } - } else { - m_phononWidget->hide(); - m_preview->setVisible(true); } } else { + m_preview->hide(); m_phononWidget->hide(); } +} - m_item = item; +void InformationPanelContent::refreshMetaData() { + if (m_metaDataWidget) { + m_metaDataWidget->setDateFormat(static_cast(InformationPanelSettings::dateFormat())); + m_metaDataWidget->show(); + m_metaDataWidget->setItems(KFileItemList() << m_item); + } } void InformationPanelContent::showItems(const KFileItemList& items) { // If there is a preview job, kill it to prevent that we have jobs for // multiple items running, and thus a race condition (bug 250787). if (m_previewJob) { m_previewJob->kill(); } m_preview->setPixmap( QIcon::fromTheme(QStringLiteral("dialog-information")).pixmap(KIconLoader::SizeEnormous, KIconLoader::SizeEnormous) ); setNameLabelText(i18ncp("@label", "%1 item selected", "%1 items selected", items.count())); if (m_metaDataWidget) { m_metaDataWidget->setItems(items); } m_phononWidget->hide(); m_item = KFileItem(); } bool InformationPanelContent::eventFilter(QObject* obj, QEvent* event) { switch (event->type()) { case QEvent::Resize: { QResizeEvent* resizeEvent = static_cast(event); if (obj == m_metaDataArea->viewport()) { // The size of the meta text area has changed. Adjust the fixed // width in a way that no horizontal scrollbar needs to be shown. m_metaDataWidget->setFixedWidth(resizeEvent->size().width()); } else if (obj == parent()) { adjustWidgetSizes(resizeEvent->size().width()); } break; } case QEvent::Polish: adjustWidgetSizes(parentWidget()->width()); break; case QEvent::FontChange: m_metaDataWidget->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); break; default: break; } return QWidget::eventFilter(obj, event); } void InformationPanelContent::showIcon(const KFileItem& item) { m_outdatedPreviewTimer->stop(); QPixmap pixmap = QIcon::fromTheme(item.iconName()).pixmap(KIconLoader::SizeEnormous, KIconLoader::SizeEnormous); KIconLoader::global()->drawOverlays(item.overlays(), pixmap, KIconLoader::Desktop); m_preview->setPixmap(pixmap); } void InformationPanelContent::showPreview(const KFileItem& item, const QPixmap& pixmap) { m_outdatedPreviewTimer->stop(); Q_UNUSED(item); QPixmap p = pixmap; KIconLoader::global()->drawOverlays(item.overlays(), p, KIconLoader::Desktop); m_preview->setPixmap(p); } void InformationPanelContent::markOutdatedPreview() { KIconEffect *iconEffect = KIconLoader::global()->iconEffect(); QPixmap disabledPixmap = iconEffect->apply(m_preview->pixmap(), KIconLoader::Desktop, KIconLoader::DisabledState); m_preview->setPixmap(disabledPixmap); } -void InformationPanelContent::setPreviewVisible(bool visible) { - m_preview->setVisible(visible); -} - KFileItemList InformationPanelContent::items() { return m_metaDataWidget->items(); } void InformationPanelContent::slotHasVideoChanged(bool hasVideo) { m_preview->setVisible(InformationPanelSettings::previewsShown() && !hasVideo); } -void InformationPanelContent::refreshMetaData() -{ - if (!m_item.isNull()) { - showItem(m_item); - } -} - void InformationPanelContent::setNameLabelText(const QString& text) { QTextOption textOption; textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); const QString processedText = Qt::mightBeRichText(text) ? text : KStringHandler::preProcessWrap(text); QTextLayout textLayout(processedText); textLayout.setFont(m_nameLabel->font()); textLayout.setTextOption(textOption); QString wrappedText; wrappedText.reserve(processedText.length()); // wrap the text to fit into the width of m_nameLabel textLayout.beginLayout(); QTextLine line = textLayout.createLine(); while (line.isValid()) { line.setLineWidth(m_nameLabel->width()); wrappedText += processedText.midRef(line.textStart(), line.textLength()); line = textLayout.createLine(); if (line.isValid()) { wrappedText += QChar::LineSeparator; } } textLayout.endLayout(); m_nameLabel->setText(wrappedText); } void InformationPanelContent::adjustWidgetSizes(int width) { // If the text inside the name label or the info label cannot // get wrapped, then the maximum width of the label is increased // so that the width of the information panel gets increased. // To prevent this, the maximum width is adjusted to // the current width of the panel. const int maxWidth = width - style()->layoutSpacing(QSizePolicy::DefaultType, QSizePolicy::DefaultType, Qt::Horizontal) * 4; m_nameLabel->setMaximumWidth(maxWidth); // The metadata widget also contains a text widget which may return // a large preferred width. if (m_metaDataWidget) { m_metaDataWidget->setMaximumWidth(maxWidth); } // try to increase the preview as large as possible m_preview->setSizeHint(QSize(maxWidth, maxWidth)); if (m_phononWidget->isVisible()) { // assure that the size of the video player is the same as the preview size m_phononWidget->setVideoSize(QSize(maxWidth, maxWidth)); } } diff --git a/src/panels/information/informationpanelcontent.h b/src/panels/information/informationpanelcontent.h index a80775aaa..83fb3d80b 100644 --- a/src/panels/information/informationpanelcontent.h +++ b/src/panels/information/informationpanelcontent.h @@ -1,148 +1,151 @@ /*************************************************************************** * Copyright (C) 2009-2010 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 * ***************************************************************************/ #ifndef INFORMATIONPANELCONTENT_H #define INFORMATIONPANELCONTENT_H #include #include #include #include #include class KFileItemList; class PhononWidget; class PixmapViewer; class PlacesItemModel; class QPixmap; class QString; class QLabel; class QScrollArea; namespace KIO { class PreviewJob; } #ifndef HAVE_BALOO class KFileMetaDataWidget; #else namespace Baloo { class FileMetaDataWidget; } #endif /** * @brief Manages the widgets that display the meta information * for file items of the Information Panel. */ class InformationPanelContent : public QWidget { Q_OBJECT public: explicit InformationPanelContent(QWidget* parent = nullptr); ~InformationPanelContent() override; /** * Shows the meta information for the item \p item. * The preview of the item is generated asynchronously, * the other meta information are fetched synchronously. */ void showItem(const KFileItem& item); /** - * Shows the meta information for the items \p items. + * Shows the meta information for the items \p items and its preview */ void showItems(const KFileItemList& items); - void setPreviewVisible(bool visible); - KFileItemList items(); + /** + * Refreshes the preview display, hiding it if needed + */ + void refreshPreview(); + signals: void urlActivated( const QUrl& url ); public slots: /** * Is invoked after the file meta data configuration dialog has been - * closed and refreshes the visibility of the meta data. + * closed and refreshes the displayed meta data by the panel. */ void refreshMetaData(); protected: /** @see QObject::eventFilter() */ bool eventFilter(QObject* obj, QEvent* event) override; private slots: /** * Is invoked if no preview is available for the item. In this * case the icon will be shown. */ void showIcon(const KFileItem& item); /** * Is invoked if a preview is available for the item. The preview * \a pixmap is shown inside the info page. */ void showPreview(const KFileItem& item, const QPixmap& pixmap); /** * Marks the currently shown preview as outdated * by greying the content. */ void markOutdatedPreview(); void slotHasVideoChanged(bool hasVideo); private: /** * Sets the text for the label \a m_nameLabel and assures that the * text is split in a way that it can be wrapped within the * label width (QLabel::setWordWrap() does not work if the * text represents one extremely long word). */ void setNameLabelText(const QString& text); /** * Adjusts the sizes of the widgets dependent on the available * width given by \p width. */ void adjustWidgetSizes(int width); private: KFileItem m_item; QPointer m_previewJob; QTimer* m_outdatedPreviewTimer; PixmapViewer* m_preview; PhononWidget* m_phononWidget; QLabel* m_nameLabel; #ifndef HAVE_BALOO KFileMetaDataWidget* m_metaDataWidget; #else Baloo::FileMetaDataWidget* m_metaDataWidget; #endif QScrollArea* m_metaDataArea; PlacesItemModel* m_placesItemModel; }; #endif // INFORMATIONPANELCONTENT_H