The complexity of the class InformationPanel has grown a lot from KDE 4.0 to KDE 4.3. One main reason is that a lot of things are done now asynchronously with timers to prevent a blocking UI and unnecessary expensive operations.

To keep the Information Panel maintainable and prepared for future features a cleanup has been done. The whole user interface handling has been moved into the class InformationPanelContent that offers a straight forward interface: showItem(const KFileItem& item) and showItems(const KFileItemList& items).

The class InformationPanel is responsible for calling those methods in a way that hovering items, changing directories, doing selections, rename and delete operations, ... don't result in calling showItem() 10 times per second.

This cleanup won't be backported to KDE 4.3.x

svn path=/trunk/KDE/kdebase/apps/; revision=991902
This commit is contained in:
Peter Penz 2009-07-05 22:54:37 +00:00
parent b4aacaf4d2
commit dc29afa688
5 changed files with 766 additions and 690 deletions

View file

@ -105,6 +105,7 @@ set(dolphin_SRCS
pixmapviewer.cpp
panels/information/commentwidget.cpp
panels/information/informationpanel.cpp
panels/information/informationpanelcontent.cpp
panels/information/metadatawidget.cpp
panels/information/metatextlabel.cpp
panels/information/phononwidget.cpp

View file

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at> *
* Copyright (C) 2006-2009 by Peter Penz <peter.penz@gmx.at> *
* *
* 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 *
@ -18,71 +18,14 @@
***************************************************************************/
#include "informationpanel.h"
#include <config-nepomuk.h>
#include <kdialog.h>
#include <kdirnotify.h>
#include <kfileitem.h>
#include <kfilemetainfo.h>
#include <kfileplacesmodel.h>
#include <kglobalsettings.h>
#include <kio/previewjob.h>
#include <kiconeffect.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmenu.h>
#include <kseparator.h>
#ifdef HAVE_NEPOMUK
#define DISABLE_NEPOMUK_LEGACY
#include <Nepomuk/Resource>
#include <Nepomuk/Types/Property>
#include <Nepomuk/Variant>
#endif
#include <Phonon/BackendCapabilities>
#include <Phonon/MediaObject>
#include <Phonon/SeekSlider>
#include <QEvent>
#include <QInputDialog>
#include <QLabel>
#include <QPainter>
#include <QPixmap>
#include <QResizeEvent>
#include <QScrollArea>
#include <QTextLayout>
#include <QTextLine>
#include <QTimer>
#include <QScrollBar>
#include <QVBoxLayout>
#include "dolphin_informationpanelsettings.h"
#include "settings/dolphinsettings.h"
#include "metadatawidget.h"
#include "metatextlabel.h"
#include "phononwidget.h"
#include "pixmapviewer.h"
/**
* Helper function for sorting items with qSort() in
* InformationPanel::contextMenu().
*/
bool lessThan(const QAction* action1, const QAction* action2)
{
return action1->text() < action2->text();
}
#include <QShowEvent>
#include "informationpanelcontent.h"
InformationPanel::InformationPanel(QWidget* parent) :
Panel(parent),
m_initialized(false),
m_pendingPreview(false),
m_infoTimer(0),
m_outdatedPreviewTimer(0),
m_urlChangedTimer(0),
m_resetUrlTimer(0),
m_shownUrl(),
@ -90,20 +33,12 @@ InformationPanel::InformationPanel(QWidget* parent) :
m_invalidUrlCandidate(),
m_fileItem(),
m_selection(),
m_nameLabel(0),
m_preview(0),
m_previewSeparator(0),
m_phononWidget(0),
m_metaDataWidget(0),
m_metaDataSeparator(0),
m_metaTextArea(0),
m_metaTextLabel(0)
m_content(0)
{
}
InformationPanel::~InformationPanel()
{
InformationPanelSettings::self()->writeConfig();
}
QSize InformationPanel::sizeHint() const
@ -174,7 +109,6 @@ void InformationPanel::requestDelayedItemInfo(const KFileItem& item)
// The cursor is above the viewport. If files are selected,
// show information regarding the selection.
if (m_selection.size() > 0) {
m_pendingPreview = false;
m_infoTimer->start();
}
} else {
@ -204,170 +138,16 @@ void InformationPanel::showEvent(QShowEvent* event)
void InformationPanel::resizeEvent(QResizeEvent* event)
{
if (isVisible()) {
// 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 = event->size().width() - KDialog::spacingHint() * 4;
m_nameLabel->setMaximumWidth(maxWidth);
// The metadata widget also contains a text widget which may return
// a large preferred width.
if (m_metaDataWidget != 0) {
m_metaDataWidget->setMaximumWidth(maxWidth);
}
// try to increase the preview as large as possible
m_preview->setSizeHint(QSize(maxWidth, maxWidth));
m_urlCandidate = m_shownUrl; // reset the URL candidate if a resizing is done
m_urlCandidate = m_shownUrl;
m_infoTimer->start();
if (m_phononWidget->isVisible() && (m_phononWidget->mode() == PhononWidget::Video)) {
// assure that the size of the video player is the same as the preview size
m_phononWidget->setVideoSize(QSize(maxWidth, maxWidth));
}
}
Panel::resizeEvent(event);
}
bool InformationPanel::eventFilter(QObject* obj, QEvent* event)
{
// Check whether the size of the meta text area has changed and adjust
// the fixed width in a way that no horizontal scrollbar needs to be shown.
if ((obj == m_metaTextArea->viewport()) && (event->type() == QEvent::Resize)) {
QResizeEvent* resizeEvent = static_cast<QResizeEvent*>(event);
m_metaTextLabel->setFixedWidth(resizeEvent->size().width());
}
return Panel::eventFilter(obj, event);
}
void InformationPanel::contextMenuEvent(QContextMenuEvent* event)
{
m_content->configureSettings();
Panel::contextMenuEvent(event);
#ifdef HAVE_NEPOMUK
if (showMultipleSelectionInfo()) {
return;
}
KMenu popup(this);
QAction* previewAction = popup.addAction(i18nc("@action:inmenu", "Preview"));
previewAction->setIcon(KIcon("view-preview"));
previewAction->setCheckable(true);
previewAction->setChecked(InformationPanelSettings::showPreview());
const bool metaDataAvailable = MetaDataWidget::metaDataAvailable();
QAction* ratingAction = popup.addAction(i18nc("@action:inmenu", "Rating"));
ratingAction->setIcon(KIcon("rating"));
ratingAction->setCheckable(true);
ratingAction->setChecked(InformationPanelSettings::showRating());
ratingAction->setEnabled(metaDataAvailable);
QAction* commentAction = popup.addAction(i18nc("@action:inmenu", "Comment"));
commentAction->setIcon(KIcon("text-plain"));
commentAction->setCheckable(true);
commentAction->setChecked(InformationPanelSettings::showComment());
commentAction->setEnabled(metaDataAvailable);
QAction* tagsAction = popup.addAction(i18nc("@action:inmenu", "Tags"));
tagsAction->setCheckable(true);
tagsAction->setChecked(InformationPanelSettings::showTags());
tagsAction->setEnabled(metaDataAvailable);
KConfig config("kmetainformationrc", KConfig::NoGlobals);
KConfigGroup settings = config.group("Show");
initMetaInfoSettings(settings);
QList<QAction*> actions;
// Get all meta information labels that are available for
// the currently shown file item and add them to the popup.
Nepomuk::Resource res(updateFileItem().url());
QHash<QUrl, Nepomuk::Variant> properties = res.properties();
QHash<QUrl, Nepomuk::Variant>::const_iterator it = properties.constBegin();
while (it != properties.constEnd()) {
Nepomuk::Types::Property prop(it.key());
const QString key = prop.name();
// Meta information provided by Nepomuk that is already
// available from KFileItem should not be configurable.
bool skip = (key == "fileExtension") ||
(key == "name") ||
(key == "sourceModified") ||
(key == "size") ||
(key == "mime type");
if (!skip) {
// Check whether there is already a meta information
// having the same label. In this case don't show it
// twice in the menu.
foreach (const QAction* action, actions) {
if (action->data().toString() == key) {
skip = true;
break;
}
}
}
if (!skip) {
const QString label = tunedLabel(prop.label());
QAction* action = new QAction(label, &popup);
action->setCheckable(true);
action->setChecked(settings.readEntry(key, true));
action->setData(key);
actions.append(action);
}
++it;
}
if (actions.count() > 0) {
popup.addSeparator();
// add all items alphabetically sorted to the popup
qSort(actions.begin(), actions.end(), lessThan);
foreach (QAction* action, actions) {
popup.addAction(action);
}
}
// Open the popup and adjust the settings for the
// selected action.
QAction* action = popup.exec(QCursor::pos());
if (action == 0) {
return;
}
const bool isChecked = action->isChecked();
if (action == previewAction) {
m_preview->setVisible(isChecked);
m_previewSeparator->setVisible(isChecked);
InformationPanelSettings::setShowPreview(isChecked);
updatePhononWidget();
} else if (action == ratingAction) {
m_metaDataWidget->setRatingVisible(isChecked);
InformationPanelSettings::setShowRating(isChecked);
} else if (action == commentAction) {
m_metaDataWidget->setCommentVisible(isChecked);
InformationPanelSettings::setShowComment(isChecked);
} else if (action == tagsAction) {
m_metaDataWidget->setTagsVisible(isChecked);
InformationPanelSettings::setShowTags(isChecked);
} else {
settings.writeEntry(action->data().toString(), action->isChecked());
settings.sync();
showMetaInfo();
}
if (m_metaDataWidget != 0) {
const bool visible = m_metaDataWidget->isRatingVisible() ||
m_metaDataWidget->isCommentVisible() ||
m_metaDataWidget->areTagsVisible();
m_metaDataSeparator->setVisible(visible);
}
#endif
}
void InformationPanel::showItemInfo()
@ -379,47 +159,25 @@ void InformationPanel::showItemInfo()
cancelRequest();
if (showMultipleSelectionInfo()) {
KIconLoader iconLoader;
QPixmap icon = iconLoader.loadIcon("dialog-information",
KIconLoader::NoGroup,
KIconLoader::SizeEnormous);
m_preview->setPixmap(icon);
setNameLabelText(i18ncp("@info", "%1 item selected", "%1 items selected", m_selection.count()));
m_content->showItems(m_selection);
m_shownUrl = KUrl();
} else {
const KFileItem item = updateFileItem();
const KUrl itemUrl = item.url();
if (!applyPlace(itemUrl)) {
// try to get a preview pixmap from the item...
m_pendingPreview = true;
// 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();
}
KIO::PreviewJob* job = KIO::filePreview(KFileItemList() << item,
m_preview->width(),
m_preview->height(),
0,
0,
false,
true);
connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)),
this, SLOT(showPreview(const KFileItem&, const QPixmap&)));
connect(job, SIGNAL(failed(const KFileItem&)),
this, SLOT(showIcon(const KFileItem&)));
setNameLabelText(itemUrl.fileName());
KFileItem item;
if (!m_fileItem.isNull()) {
item = m_fileItem;
} 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
m_fileItem = KFileItem(KFileItem::Unknown, KFileItem::Unknown, m_shownUrl);
m_fileItem.refresh();
item = m_fileItem;
}
}
showMetaInfo();
m_content->showItem(item);
}
}
void InformationPanel::slotInfoTimeout()
@ -428,36 +186,6 @@ void InformationPanel::slotInfoTimeout()
showItemInfo();
}
void InformationPanel::markOutdatedPreview()
{
KIconEffect iconEffect;
QPixmap disabledPixmap = iconEffect.apply(m_preview->pixmap(),
KIconLoader::Desktop,
KIconLoader::DisabledState);
m_preview->setPixmap(disabledPixmap);
}
void InformationPanel::showIcon(const KFileItem& item)
{
m_outdatedPreviewTimer->stop();
m_pendingPreview = false;
if (!applyPlace(item.url())) {
m_preview->setPixmap(item.pixmap(KIconLoader::SizeEnormous));
}
}
void InformationPanel::showPreview(const KFileItem& item,
const QPixmap& pixmap)
{
m_outdatedPreviewTimer->stop();
Q_UNUSED(item);
if (m_pendingPreview) {
m_preview->setPixmap(pixmap);
m_pendingPreview = false;
}
}
void InformationPanel::reset()
{
if (m_invalidUrlCandidate == m_shownUrl) {
@ -532,121 +260,11 @@ void InformationPanel::slotLeftDirectory(const QString& directory)
}
}
void InformationPanel::slotPlayingStarted()
{
m_preview->setVisible(m_phononWidget->mode() != PhononWidget::Video);
}
void InformationPanel::slotPlayingStopped()
{
m_preview->setVisible(true);
}
bool InformationPanel::applyPlace(const KUrl& url)
{
KFilePlacesModel* placesModel = DolphinSettings::instance().placesModel();
int count = placesModel->rowCount();
for (int i = 0; i < count; ++i) {
QModelIndex index = placesModel->index(i, 0);
if (url.equals(placesModel->url(index), KUrl::CompareWithoutTrailingSlash)) {
setNameLabelText(placesModel->text(index));
m_preview->setPixmap(placesModel->icon(index).pixmap(128, 128));
return true;
}
}
return false;
}
void InformationPanel::cancelRequest()
{
m_infoTimer->stop();
}
void InformationPanel::showMetaInfo()
{
m_metaTextLabel->clear();
if (showMultipleSelectionInfo()) {
if (m_metaDataWidget != 0) {
KUrl::List urls;
foreach (const KFileItem& item, m_selection) {
urls.append(item.targetUrl());
}
m_metaDataWidget->setFiles(urls);
}
quint64 totalSize = 0;
foreach (const KFileItem& item, m_selection) {
// Only count the size of files, not dirs to match what
// DolphinViewContainer::selectionStatusBarText() does.
if (!item.isDir() && !item.isLink()) {
totalSize += item.size();
}
}
m_metaTextLabel->add(i18nc("@label", "Total size:"), KIO::convertSize(totalSize));
} else {
const KFileItem item = updateFileItem();
if (item.isDir()) {
m_metaTextLabel->add(i18nc("@label", "Type:"), i18nc("@label", "Folder"));
m_metaTextLabel->add(i18nc("@label", "Modified:"), item.timeString());
} else {
m_metaTextLabel->add(i18nc("@label", "Type:"), item.mimeComment());
m_metaTextLabel->add(i18nc("@label", "Size:"), KIO::convertSize(item.size()));
m_metaTextLabel->add(i18nc("@label", "Modified:"), item.timeString());
#ifdef HAVE_NEPOMUK
KConfig config("kmetainformationrc", KConfig::NoGlobals);
KConfigGroup settings = config.group("Show");
initMetaInfoSettings(settings);
Nepomuk::Resource res(item.url());
QHash<QUrl, Nepomuk::Variant> properties = res.properties();
QHash<QUrl, Nepomuk::Variant>::const_iterator it = properties.constBegin();
while (it != properties.constEnd()) {
Nepomuk::Types::Property prop(it.key());
if (settings.readEntry(prop.name(), true)) {
// TODO #1: use Nepomuk::formatValue(res, prop) if available
// instead of it.value().toString()
// TODO #2: using tunedLabel() is a workaround for KDE 4.3 until
// we get translated labels
m_metaTextLabel->add(tunedLabel(prop.label()) + ':', it.value().toString());
}
++it;
}
#endif
}
if (m_metaDataWidget != 0) {
m_metaDataWidget->setFile(item.targetUrl());
}
}
updatePhononWidget();
}
KFileItem InformationPanel::updateFileItem()
{
if (!m_fileItem.isNull()) {
return m_fileItem;
}
if (!m_selection.isEmpty()) {
Q_ASSERT(m_selection.count() == 1);
return m_selection.first();
}
// no item is hovered and no selection has been done: provide
// an item for the directory represented by m_shownUrl
m_fileItem = KFileItem(KFileItem::Unknown, KFileItem::Unknown, m_shownUrl);
m_fileItem.refresh();
return m_fileItem;
}
bool InformationPanel::showMultipleSelectionInfo() const
{
return m_fileItem.isNull() && (m_selection.count() > 1);
@ -657,115 +275,12 @@ bool InformationPanel::isEqualToShownUrl(const KUrl& url) const
return m_shownUrl.equals(url, KUrl::CompareWithoutTrailingSlash);
}
void InformationPanel::setNameLabelText(const QString& text)
{
QTextOption textOption;
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
QTextLayout textLayout(text);
textLayout.setFont(m_nameLabel->font());
textLayout.setTextOption(textOption);
QString wrappedText;
wrappedText.reserve(text.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 += text.mid(line.textStart(), line.textLength());
line = textLayout.createLine();
if (line.isValid()) {
wrappedText += QChar::LineSeparator;
}
}
textLayout.endLayout();
m_nameLabel->setText(wrappedText);
}
void InformationPanel::markUrlAsInvalid()
{
m_invalidUrlCandidate = m_shownUrl;
m_resetUrlTimer->start();
}
void InformationPanel::initMetaInfoSettings(KConfigGroup& group)
{
if (!group.readEntry("initialized", false)) {
// The resource file is read the first time. Assure
// that some meta information is disabled per default.
static const char* disabledProperties[] = {
"asText", "contentSize", "depth", "fileExtension",
"fileName", "fileSize", "isPartOf", "mimetype", "name",
"parentUrl", "plainTextContent", "sourceModified",
"size", "url",
0 // mandatory last entry
};
int i = 0;
while (disabledProperties[i] != 0) {
group.writeEntry(disabledProperties[i], false);
++i;
}
// mark the group as initialized
group.writeEntry("initialized", true);
}
}
void InformationPanel::updatePhononWidget()
{
const bool multipleSelections = showMultipleSelectionInfo();
const bool showPreview = InformationPanelSettings::showPreview();
if (multipleSelections || !showPreview) {
m_phononWidget->hide();
} else if (!multipleSelections && showPreview) {
const KFileItem item = updateFileItem();
const QString mimeType = item.mimetype();
const bool usePhonon = Phonon::BackendCapabilities::isMimeTypeAvailable(mimeType) &&
(mimeType != "image/png"); // TODO: workaround, as Phonon
// thinks it supports PNG images
if (usePhonon) {
m_phononWidget->show();
PhononWidget::Mode mode = mimeType.startsWith(QLatin1String("video"))
? PhononWidget::Video
: PhononWidget::Audio;
m_phononWidget->setMode(mode);
m_phononWidget->setUrl(item.url());
if ((mode == PhononWidget::Video) && m_preview->isVisible()) {
m_phononWidget->setVideoSize(m_preview->size());
}
} else {
m_phononWidget->hide();
m_preview->setVisible(true);
}
}
}
QString InformationPanel::tunedLabel(const QString& label) const
{
QString tunedLabel;
const int labelLength = label.length();
if (labelLength > 0) {
tunedLabel.reserve(labelLength);
tunedLabel = label[0].toUpper();
for (int i = 1; i < labelLength; ++i) {
if (label[i].isUpper() && !label[i - 1].isSpace() && !label[i - 1].isUpper()) {
tunedLabel += ' ';
tunedLabel += label[i].toLower();
} else {
tunedLabel += label[i];
}
}
}
return tunedLabel;
}
void InformationPanel::init()
{
const int defaultDelay = 300;
@ -776,15 +291,6 @@ void InformationPanel::init()
connect(m_infoTimer, SIGNAL(timeout()),
this, SLOT(slotInfoTimeout()));
// 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(defaultDelay);
m_outdatedPreviewTimer->setSingleShot(true);
connect(m_outdatedPreviewTimer, SIGNAL(timeout()),
this, SLOT(markOutdatedPreview()));
m_urlChangedTimer = new QTimer(this);
m_urlChangedTimer->setInterval(defaultDelay);
m_urlChangedTimer->setSingleShot(true);
@ -797,84 +303,6 @@ void InformationPanel::init()
connect(m_resetUrlTimer, SIGNAL(timeout()),
this, SLOT(reset()));
QVBoxLayout* layout = new QVBoxLayout;
layout->setSpacing(KDialog::spacingHint());
// name
m_nameLabel = new QLabel(this);
QFont font = m_nameLabel->font();
font.setBold(true);
m_nameLabel->setFont(font);
m_nameLabel->setAlignment(Qt::AlignHCenter);
m_nameLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
m_nameLabel->setMaximumWidth(KIconLoader::SizeEnormous);
// preview
const int minPreviewWidth = KIconLoader::SizeEnormous + KIconLoader::SizeMedium;
m_preview = new PixmapViewer(this);
m_preview->setMinimumWidth(minPreviewWidth);
m_preview->setMinimumHeight(KIconLoader::SizeEnormous);
m_phononWidget = new PhononWidget(this);
m_phononWidget->setMinimumWidth(minPreviewWidth);
connect(m_phononWidget, SIGNAL(playingStarted()),
this, SLOT(slotPlayingStarted()));
connect(m_phononWidget, SIGNAL(playingStopped()),
this, SLOT(slotPlayingStopped()));
m_previewSeparator = new KSeparator(this);
const bool showPreview = InformationPanelSettings::showPreview();
m_preview->setVisible(showPreview);
m_previewSeparator->setVisible(showPreview);
if (MetaDataWidget::metaDataAvailable()) {
// rating, comment and tags
m_metaDataWidget = new MetaDataWidget(this);
m_metaDataWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
m_metaDataWidget->setMaximumWidth(KIconLoader::SizeEnormous);
const bool showRating = InformationPanelSettings::showRating();
const bool showComment = InformationPanelSettings::showComment();
const bool showTags = InformationPanelSettings::showTags();
m_metaDataWidget->setRatingVisible(showRating);
m_metaDataWidget->setCommentVisible(showComment);
m_metaDataWidget->setTagsVisible(showTags);
m_metaDataSeparator = new KSeparator(this);
m_metaDataSeparator->setVisible(showRating || showComment || showTags);
}
// general meta text information
m_metaTextLabel = new MetaTextLabel(this);
m_metaTextLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
m_metaTextArea = new QScrollArea(this);
m_metaTextArea->setWidget(m_metaTextLabel);
m_metaTextArea->setWidgetResizable(true);
m_metaTextArea->setFrameShape(QFrame::NoFrame);
QWidget* viewport = m_metaTextArea->viewport();
viewport->installEventFilter(this);
QPalette palette = viewport->palette();
palette.setColor(viewport->backgroundRole(), QColor(Qt::transparent));
viewport->setPalette(palette);
layout->addWidget(m_nameLabel);
layout->addWidget(new KSeparator(this));
layout->addWidget(m_preview);
layout->addWidget(m_phononWidget);
layout->addWidget(m_previewSeparator);
if (m_metaDataWidget != 0) {
layout->addWidget(m_metaDataWidget);
layout->addWidget(m_metaDataSeparator);
}
layout->addWidget(m_metaTextArea);
setLayout(layout);
org::kde::KDirNotify* dirNotify = new org::kde::KDirNotify(QString(), QString(),
QDBusConnection::sessionBus(), this);
connect(dirNotify, SIGNAL(FileRenamed(QString, QString)), SLOT(slotFileRenamed(QString, QString)));
@ -884,6 +312,8 @@ void InformationPanel::init()
connect(dirNotify, SIGNAL(enteredDirectory(QString)), SLOT(slotEnteredDirectory(QString)));
connect(dirNotify, SIGNAL(leftDirectory(QString)), SLOT(slotLeftDirectory(QString)));
m_content = new InformationPanelContent(this);
m_initialized = true;
}

View file

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at> *
* Copyright (C) 2006-2009 by Peter Penz <peter.penz@gmx.at> *
* *
* 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 *
@ -22,29 +22,7 @@
#include <panels/panel.h>
#include <QPushButton>
#include <QPixmap>
#include <QEvent>
#include <QLabel>
#include <QList>
#include <kconfig.h>
#include <kurl.h>
#include <kmimetype.h>
#include <kdesktopfileactions.h>
#include <kvbox.h>
class InformationPanelDialog;
class PhononWidget;
class PixmapViewer;
class MetaDataWidget;
class MetaTextLabel;
class QPixmap;
class QString;
class KFileItem;
class KSeparator;
class QLabel;
class QScrollArea;
class InformationPanelContent;
/**
* @brief Panel for showing meta information of one ore more selected items.
@ -85,9 +63,6 @@ protected:
/** @see QWidget::resizeEvent() */
virtual void resizeEvent(QResizeEvent* event);
/** @see QObject::eventFilter() */
virtual bool eventFilter(QObject* obj, QEvent* event);
/** @see QWidget::contextMenuEvent() */
virtual void contextMenuEvent(QContextMenuEvent* event);
@ -104,24 +79,6 @@ private slots:
*/
void slotInfoTimeout();
/**
* Marks the currently shown preview as outdated
* by greying the content.
*/
void markOutdatedPreview();
/**
* 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);
/**
* Resets the information panel to show the current
* URL (InformationPanel::url()). Is called by
@ -136,18 +93,7 @@ private slots:
void slotEnteredDirectory(const QString& directory);
void slotLeftDirectory(const QString& directory);
void slotPlayingStarted();
void slotPlayingStopped();
private:
/**
* Checks whether the an URL is repesented by a place. If yes,
* then the place icon and name are shown instead of a preview.
* @return True, if the URL represents exactly a place.
* @param url The url to check.
*/
bool applyPlace(const KUrl& url);
/** Assures that any pending item information request is cancelled. */
void cancelRequest();
@ -157,14 +103,6 @@ private:
*/
void showMetaInfo();
/**
* Updates the file item m_fileItem if necessary and returns
* the file item which should be used to show the meta information.
* The returned item is different from m_fileItem if a selection
* is given.
*/
KFileItem updateFileItem();
/**
* Returns true, if the meta information should be shown for
* the multiple selected items that are stored in
@ -180,14 +118,6 @@ private:
*/
bool isEqualToShownUrl(const KUrl& url) const;
/**
* 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);
/**
* Marks the URL as invalid and will reset the Information Panel
* after a short delay. The reset is not done synchronously to
@ -196,28 +126,12 @@ private:
*/
void markUrlAsInvalid();
/**
* Assures that the settings for the meta information
* are initialized with proper default values.
*/
void initMetaInfoSettings(KConfigGroup& group);
void updatePhononWidget();
/**
* Temporary helper method for KDE 4.3 as we currently don't get
* translated labels for Nepmok literals: Replaces camelcase labels
* like "fileLocation" by "File Location:".
*/
QString tunedLabel(const QString& label) const;
void init();
private:
bool m_initialized;
bool m_pendingPreview;
QTimer* m_infoTimer;
QTimer* m_outdatedPreviewTimer;
QTimer* m_urlChangedTimer;
QTimer* m_resetUrlTimer;
@ -237,15 +151,7 @@ private:
KFileItem m_fileItem; // file item for m_shownUrl if available (otherwise null)
KFileItemList m_selection;
QLabel* m_nameLabel;
PixmapViewer* m_preview;
KSeparator* m_previewSeparator;
PhononWidget* m_phononWidget;
MetaDataWidget* m_metaDataWidget;
KSeparator* m_metaDataSeparator;
QScrollArea* m_metaTextArea;
MetaTextLabel* m_metaTextLabel;
InformationPanelContent* m_content;
};
#endif // INFORMATIONPANEL_H

View file

@ -0,0 +1,600 @@
/***************************************************************************
* Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> *
* *
* 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 <config-nepomuk.h>
#include <kdialog.h>
#include <kfileitem.h>
#include <kfileplacesmodel.h>
#include <kio/previewjob.h>
#include <kiconeffect.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmenu.h>
#include <kseparator.h>
#include <Phonon/BackendCapabilities>
#include <Phonon/MediaObject>
#include <Phonon/SeekSlider>
#include <QEvent>
#include <QLabel>
#include <QPixmap>
#include <QResizeEvent>
#include <QScrollArea>
#include <QTextLayout>
#include <QTextLine>
#include <QTimer>
#include <QVBoxLayout>
#include "dolphin_informationpanelsettings.h"
#include "settings/dolphinsettings.h"
#include "metadatawidget.h"
#include "metatextlabel.h"
#include "phononwidget.h"
#include "pixmapviewer.h"
#ifdef HAVE_NEPOMUK
#define DISABLE_NEPOMUK_LEGACY
#include <Nepomuk/Resource>
#include <Nepomuk/Types/Property>
#include <Nepomuk/Variant>
#endif
/**
* Helper function for sorting items with qSort() in
* InformationPanelContent::contextMenu().
*/
bool lessThan(const QAction* action1, const QAction* action2)
{
return action1->text() < action2->text();
}
InformationPanelContent::InformationPanelContent(QWidget* parent) :
Panel(parent),
m_item(),
m_pendingPreview(false),
m_outdatedPreviewTimer(0),
m_nameLabel(0),
m_preview(0),
m_previewSeparator(0),
m_phononWidget(0),
m_metaDataWidget(0),
m_metaDataSeparator(0),
m_metaTextArea(0),
m_metaTextLabel(0)
{
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, SIGNAL(timeout()),
this, SLOT(markOutdatedPreview()));
QVBoxLayout* layout = new QVBoxLayout;
layout->setSpacing(KDialog::spacingHint());
// name
m_nameLabel = new QLabel(parent);
QFont font = m_nameLabel->font();
font.setBold(true);
m_nameLabel->setFont(font);
m_nameLabel->setAlignment(Qt::AlignHCenter);
m_nameLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
m_nameLabel->setMaximumWidth(KIconLoader::SizeEnormous);
// 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->setMinimumWidth(minPreviewWidth);
connect(m_phononWidget, SIGNAL(playingStarted()),
this, SLOT(slotPlayingStarted()));
connect(m_phononWidget, SIGNAL(playingStopped()),
this, SLOT(slotPlayingStopped()));
m_previewSeparator = new KSeparator(parent);
const bool showPreview = InformationPanelSettings::showPreview();
m_preview->setVisible(showPreview);
m_previewSeparator->setVisible(showPreview);
if (MetaDataWidget::metaDataAvailable()) {
// rating, comment and tags
m_metaDataWidget = new MetaDataWidget(parent);
m_metaDataWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
m_metaDataWidget->setMaximumWidth(KIconLoader::SizeEnormous);
const bool showRating = InformationPanelSettings::showRating();
const bool showComment = InformationPanelSettings::showComment();
const bool showTags = InformationPanelSettings::showTags();
m_metaDataWidget->setRatingVisible(showRating);
m_metaDataWidget->setCommentVisible(showComment);
m_metaDataWidget->setTagsVisible(showTags);
m_metaDataSeparator = new KSeparator(this);
m_metaDataSeparator->setVisible(showRating || showComment || showTags);
}
// general meta text information
m_metaTextLabel = new MetaTextLabel(parent);
m_metaTextLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
m_metaTextArea = new QScrollArea(parent);
m_metaTextArea->setWidget(m_metaTextLabel);
m_metaTextArea->setWidgetResizable(true);
m_metaTextArea->setFrameShape(QFrame::NoFrame);
QWidget* viewport = m_metaTextArea->viewport();
viewport->installEventFilter(this);
QPalette palette = viewport->palette();
palette.setColor(viewport->backgroundRole(), QColor(Qt::transparent));
viewport->setPalette(palette);
layout->addWidget(m_nameLabel);
layout->addWidget(new KSeparator(this));
layout->addWidget(m_preview);
layout->addWidget(m_phononWidget);
layout->addWidget(m_previewSeparator);
if (m_metaDataWidget != 0) {
layout->addWidget(m_metaDataWidget);
layout->addWidget(m_metaDataSeparator);
}
layout->addWidget(m_metaTextArea);
parent->setLayout(layout);
}
InformationPanelContent::~InformationPanelContent()
{
InformationPanelSettings::self()->writeConfig();
}
void InformationPanelContent::showItem(const KFileItem& item)
{
m_pendingPreview = false;
const KUrl itemUrl = item.url();
if (!applyPlace(itemUrl)) {
// try to get a preview pixmap from the item...
m_pendingPreview = true;
// 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();
}
KIO::PreviewJob* job = KIO::filePreview(KFileItemList() << item,
m_preview->width(),
m_preview->height(),
0,
0,
false,
true);
connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)),
this, SLOT(showPreview(const KFileItem&, const QPixmap&)));
connect(job, SIGNAL(failed(const KFileItem&)),
this, SLOT(showIcon(const KFileItem&)));
setNameLabelText(itemUrl.fileName());
}
m_metaTextLabel->clear();
if (item.isDir()) {
m_metaTextLabel->add(i18nc("@label", "Type:"), i18nc("@label", "Folder"));
m_metaTextLabel->add(i18nc("@label", "Modified:"), item.timeString());
} else {
m_metaTextLabel->add(i18nc("@label", "Type:"), item.mimeComment());
m_metaTextLabel->add(i18nc("@label", "Size:"), KIO::convertSize(item.size()));
m_metaTextLabel->add(i18nc("@label", "Modified:"), item.timeString());
#ifdef HAVE_NEPOMUK
KConfig config("kmetainformationrc", KConfig::NoGlobals);
KConfigGroup settings = config.group("Show");
initMetaInfoSettings(settings);
Nepomuk::Resource res(item.url());
QHash<QUrl, Nepomuk::Variant> properties = res.properties();
QHash<QUrl, Nepomuk::Variant>::const_iterator it = properties.constBegin();
while (it != properties.constEnd()) {
Nepomuk::Types::Property prop(it.key());
if (settings.readEntry(prop.name(), true)) {
// TODO #1: use Nepomuk::formatValue(res, prop) if available
// instead of it.value().toString()
// TODO #2: using tunedLabel() is a workaround for KDE 4.3 until
// we get translated labels
m_metaTextLabel->add(tunedLabel(prop.label()) + ':', it.value().toString());
}
++it;
}
#endif
}
if (m_metaDataWidget != 0) {
m_metaDataWidget->setFile(item.targetUrl());
}
if (InformationPanelSettings::showPreview()) {
const QString mimeType = item.mimetype();
const bool usePhonon = Phonon::BackendCapabilities::isMimeTypeAvailable(mimeType) &&
(mimeType != "image/png"); // TODO: workaround, as Phonon
// thinks it supports PNG images
if (usePhonon) {
m_phononWidget->show();
PhononWidget::Mode mode = mimeType.startsWith(QLatin1String("video"))
? PhononWidget::Video
: PhononWidget::Audio;
m_phononWidget->setMode(mode);
m_phononWidget->setUrl(item.url());
if ((mode == PhononWidget::Video) && m_preview->isVisible()) {
m_phononWidget->setVideoSize(m_preview->size());
}
} else {
m_phononWidget->hide();
m_preview->setVisible(true);
}
} else {
m_phononWidget->hide();
}
m_item = item;
}
void InformationPanelContent::showItems(const KFileItemList& items)
{
m_pendingPreview = false;
KIconLoader iconLoader;
QPixmap icon = iconLoader.loadIcon("dialog-information",
KIconLoader::NoGroup,
KIconLoader::SizeEnormous);
m_preview->setPixmap(icon);
setNameLabelText(i18ncp("@info", "%1 item selected", "%1 items selected", items.count()));
if (m_metaDataWidget != 0) {
KUrl::List urls;
foreach (const KFileItem& item, items) {
urls.append(item.targetUrl());
}
m_metaDataWidget->setFiles(urls);
}
quint64 totalSize = 0;
foreach (const KFileItem& item, items) {
// Only count the size of files, not dirs to match what
// DolphinViewContainer::selectionStatusBarText() does.
if (!item.isDir() && !item.isLink()) {
totalSize += item.size();
}
}
m_metaTextLabel->clear();
m_metaTextLabel->add(i18nc("@label", "Total size:"), KIO::convertSize(totalSize));
m_phononWidget->hide();
m_item = KFileItem();
}
bool InformationPanelContent::eventFilter(QObject* obj, QEvent* event)
{
if (event->type() == QEvent::Resize) {
QResizeEvent* resizeEvent = static_cast<QResizeEvent*>(event);
if (obj == m_metaTextArea->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_metaTextLabel->setFixedWidth(resizeEvent->size().width());
} else if (obj == parent()) {
// 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 = resizeEvent->size().width() - KDialog::spacingHint() * 4;
m_nameLabel->setMaximumWidth(maxWidth);
// The metadata widget also contains a text widget which may return
// a large preferred width.
if (m_metaDataWidget != 0) {
m_metaDataWidget->setMaximumWidth(maxWidth);
}
// try to increase the preview as large as possible
m_preview->setSizeHint(QSize(maxWidth, maxWidth));
if (m_phononWidget->isVisible() && (m_phononWidget->mode() == PhononWidget::Video)) {
// assure that the size of the video player is the same as the preview size
m_phononWidget->setVideoSize(QSize(maxWidth, maxWidth));
}
}
}
return Panel::eventFilter(obj, event);
}
void InformationPanelContent::configureSettings()
{
#ifdef HAVE_NEPOMUK
if (m_item.isNull()) {
return;
}
KMenu popup(this);
QAction* previewAction = popup.addAction(i18nc("@action:inmenu", "Preview"));
previewAction->setIcon(KIcon("view-preview"));
previewAction->setCheckable(true);
previewAction->setChecked(InformationPanelSettings::showPreview());
const bool metaDataAvailable = MetaDataWidget::metaDataAvailable();
QAction* ratingAction = popup.addAction(i18nc("@action:inmenu", "Rating"));
ratingAction->setIcon(KIcon("rating"));
ratingAction->setCheckable(true);
ratingAction->setChecked(InformationPanelSettings::showRating());
ratingAction->setEnabled(metaDataAvailable);
QAction* commentAction = popup.addAction(i18nc("@action:inmenu", "Comment"));
commentAction->setIcon(KIcon("text-plain"));
commentAction->setCheckable(true);
commentAction->setChecked(InformationPanelSettings::showComment());
commentAction->setEnabled(metaDataAvailable);
QAction* tagsAction = popup.addAction(i18nc("@action:inmenu", "Tags"));
tagsAction->setCheckable(true);
tagsAction->setChecked(InformationPanelSettings::showTags());
tagsAction->setEnabled(metaDataAvailable);
KConfig config("kmetainformationrc", KConfig::NoGlobals);
KConfigGroup settings = config.group("Show");
initMetaInfoSettings(settings);
QList<QAction*> actions;
// Get all meta information labels that are available for
// the currently shown file item and add them to the popup.
Nepomuk::Resource res(m_item.url());
QHash<QUrl, Nepomuk::Variant> properties = res.properties();
QHash<QUrl, Nepomuk::Variant>::const_iterator it = properties.constBegin();
while (it != properties.constEnd()) {
Nepomuk::Types::Property prop(it.key());
const QString key = prop.name();
// Meta information provided by Nepomuk that is already
// available from KFileItem should not be configurable.
bool skip = (key == "fileExtension") ||
(key == "name") ||
(key == "sourceModified") ||
(key == "size") ||
(key == "mime type");
if (!skip) {
// Check whether there is already a meta information
// having the same label. In this case don't show it
// twice in the menu.
foreach (const QAction* action, actions) {
if (action->data().toString() == key) {
skip = true;
break;
}
}
}
if (!skip) {
const QString label = tunedLabel(prop.label());
QAction* action = new QAction(label, &popup);
action->setCheckable(true);
action->setChecked(settings.readEntry(key, true));
action->setData(key);
actions.append(action);
}
++it;
}
if (actions.count() > 0) {
popup.addSeparator();
// add all items alphabetically sorted to the popup
qSort(actions.begin(), actions.end(), lessThan);
foreach (QAction* action, actions) {
popup.addAction(action);
}
}
// Open the popup and adjust the settings for the
// selected action.
QAction* action = popup.exec(QCursor::pos());
if (action == 0) {
return;
}
const bool isChecked = action->isChecked();
if (action == previewAction) {
m_preview->setVisible(isChecked);
m_previewSeparator->setVisible(isChecked);
InformationPanelSettings::setShowPreview(isChecked);
} else if (action == ratingAction) {
m_metaDataWidget->setRatingVisible(isChecked);
InformationPanelSettings::setShowRating(isChecked);
} else if (action == commentAction) {
m_metaDataWidget->setCommentVisible(isChecked);
InformationPanelSettings::setShowComment(isChecked);
} else if (action == tagsAction) {
m_metaDataWidget->setTagsVisible(isChecked);
InformationPanelSettings::setShowTags(isChecked);
} else {
settings.writeEntry(action->data().toString(), action->isChecked());
settings.sync();
}
if (m_metaDataWidget != 0) {
const bool visible = m_metaDataWidget->isRatingVisible() ||
m_metaDataWidget->isCommentVisible() ||
m_metaDataWidget->areTagsVisible();
m_metaDataSeparator->setVisible(visible);
}
showItem(m_item);
#endif
}
void InformationPanelContent::showIcon(const KFileItem& item)
{
m_outdatedPreviewTimer->stop();
m_pendingPreview = false;
if (!applyPlace(item.url())) {
m_preview->setPixmap(item.pixmap(KIconLoader::SizeEnormous));
}
}
void InformationPanelContent::showPreview(const KFileItem& item,
const QPixmap& pixmap)
{
m_outdatedPreviewTimer->stop();
Q_UNUSED(item);
if (m_pendingPreview) {
m_preview->setPixmap(pixmap);
m_pendingPreview = false;
}
}
void InformationPanelContent::slotPlayingStarted()
{
m_preview->setVisible(m_phononWidget->mode() != PhononWidget::Video);
}
void InformationPanelContent::slotPlayingStopped()
{
m_preview->setVisible(true);
}
bool InformationPanelContent::applyPlace(const KUrl& url)
{
KFilePlacesModel* placesModel = DolphinSettings::instance().placesModel();
int count = placesModel->rowCount();
for (int i = 0; i < count; ++i) {
QModelIndex index = placesModel->index(i, 0);
if (url.equals(placesModel->url(index), KUrl::CompareWithoutTrailingSlash)) {
setNameLabelText(placesModel->text(index));
m_preview->setPixmap(placesModel->icon(index).pixmap(128, 128));
return true;
}
}
return false;
}
void InformationPanelContent::setNameLabelText(const QString& text)
{
QTextOption textOption;
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
QTextLayout textLayout(text);
textLayout.setFont(m_nameLabel->font());
textLayout.setTextOption(textOption);
QString wrappedText;
wrappedText.reserve(text.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 += text.mid(line.textStart(), line.textLength());
line = textLayout.createLine();
if (line.isValid()) {
wrappedText += QChar::LineSeparator;
}
}
textLayout.endLayout();
m_nameLabel->setText(wrappedText);
}
void InformationPanelContent::initMetaInfoSettings(KConfigGroup& group)
{
if (!group.readEntry("initialized", false)) {
// The resource file is read the first time. Assure
// that some meta information is disabled per default.
static const char* disabledProperties[] = {
"asText", "contentSize", "depth", "fileExtension",
"fileName", "fileSize", "isPartOf", "mimetype", "name",
"parentUrl", "plainTextContent", "sourceModified",
"size", "url",
0 // mandatory last entry
};
int i = 0;
while (disabledProperties[i] != 0) {
group.writeEntry(disabledProperties[i], false);
++i;
}
// mark the group as initialized
group.writeEntry("initialized", true);
}
}
QString InformationPanelContent::tunedLabel(const QString& label) const
{
QString tunedLabel;
const int labelLength = label.length();
if (labelLength > 0) {
tunedLabel.reserve(labelLength);
tunedLabel = label[0].toUpper();
for (int i = 1; i < labelLength; ++i) {
if (label[i].isUpper() && !label[i - 1].isSpace() && !label[i - 1].isUpper()) {
tunedLabel += ' ';
tunedLabel += label[i].toLower();
} else {
tunedLabel += label[i];
}
}
}
return tunedLabel;
}
void InformationPanelContent::init()
{
}
#include "informationpanelcontent.moc"

View file

@ -0,0 +1,139 @@
/***************************************************************************
* Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> *
* *
* 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 <panels/panel.h>
#include <kconfig.h>
#include <kurl.h>
#include <kvbox.h>
class PhononWidget;
class PixmapViewer;
class MetaDataWidget;
class MetaTextLabel;
class QPixmap;
class QString;
class KFileItem;
class KSeparator;
class QLabel;
class QScrollArea;
/**
* @brief Manages the widgets that display the meta information
* for file items of the Information Panel.
*/
class InformationPanelContent : public Panel
{
Q_OBJECT
public:
explicit InformationPanelContent(QWidget* parent = 0);
virtual ~InformationPanelContent();
/**
* Shows the meta information for the item \p item.
* The preview of the item is generated asynchronously,
* the other meta informations are fetched synchronously.
*/
void showItem(const KFileItem& item);
/**
* Shows the meta information for the items \p items.
*/
void showItems(const KFileItemList& items);
/**
* Opens a menu which allows to configure which meta information
* should be shown.
*/
void configureSettings();
protected:
/** @see QObject::eventFilter() */
virtual bool eventFilter(QObject* obj, QEvent* event);
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);
void slotPlayingStarted();
void slotPlayingStopped();
private:
/**
* Checks whether the an URL is repesented by a place. If yes,
* then the place icon and name are shown instead of a preview.
* @return True, if the URL represents exactly a place.
* @param url The url to check.
*/
bool applyPlace(const KUrl& url);
/**
* 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);
/**
* Assures that the settings for the meta information
* are initialized with proper default values.
*/
void initMetaInfoSettings(KConfigGroup& group);
/**
* Temporary helper method for KDE 4.3 as we currently don't get
* translated labels for Nepmok literals: Replaces camelcase labels
* like "fileLocation" by "File Location:".
*/
QString tunedLabel(const QString& label) const;
void init();
private:
KFileItem m_item;
bool m_pendingPreview;
QTimer* m_outdatedPreviewTimer;
QLabel* m_nameLabel;
PixmapViewer* m_preview;
KSeparator* m_previewSeparator;
PhononWidget* m_phononWidget;
MetaDataWidget* m_metaDataWidget;
KSeparator* m_metaDataSeparator;
QScrollArea* m_metaTextArea;
MetaTextLabel* m_metaTextLabel;
};
#endif // INFORMATIONPANELCONTENT_H