From b892058730544d53e0c08e32dc297f2f1256f9ae Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Wed, 5 Mar 2014 10:48:33 +0100 Subject: [PATCH 1/2] Fix Bug 326210 - Dolphin unnecessarily truncates names of soft links in compact mode FIXED-IN: 4.13.0 BUG: 326210 BUG: 310592 REVIEW: 116121 --- .../src/kitemviews/kfileitemlistwidget.cpp | 18 ++++++++++ dolphin/src/kitemviews/kfileitemlistwidget.h | 2 ++ .../kitemviews/kstandarditemlistwidget.cpp | 36 ++++++++++++++++--- .../src/kitemviews/kstandarditemlistwidget.h | 12 +++++++ 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/dolphin/src/kitemviews/kfileitemlistwidget.cpp b/dolphin/src/kitemviews/kfileitemlistwidget.cpp index 688a4da083..fe8c7e9976 100644 --- a/dolphin/src/kitemviews/kfileitemlistwidget.cpp +++ b/dolphin/src/kitemviews/kfileitemlistwidget.cpp @@ -46,6 +46,15 @@ QString KFileItemListWidgetInformant::itemText(int index, const KItemListView* v return item.text(); } +bool KFileItemListWidgetInformant::itemIsLink(int index, const KItemListView* view) const +{ + Q_ASSERT(qobject_cast(view->model())); + KFileItemModel* fileItemModel = static_cast(view->model()); + + const KFileItem item = fileItemModel->fileItem(index); + return item.isLink(); +} + QString KFileItemListWidgetInformant::roleText(const QByteArray& role, const QHash& values) const { @@ -81,6 +90,15 @@ QString KFileItemListWidgetInformant::roleText(const QByteArray& role, return text; } +QFont KFileItemListWidgetInformant::customizedFontForLinks(const QFont& baseFont) const +{ + // The customized font should be italic if the file is a symbolic link. + QFont font(baseFont); + font.setItalic(true); + return font; +} + + KFileItemListWidget::KFileItemListWidget(KItemListWidgetInformant* informant, QGraphicsItem* parent) : KStandardItemListWidget(informant, parent) { diff --git a/dolphin/src/kitemviews/kfileitemlistwidget.h b/dolphin/src/kitemviews/kfileitemlistwidget.h index 1d7bc7f012..8e8958b160 100644 --- a/dolphin/src/kitemviews/kfileitemlistwidget.h +++ b/dolphin/src/kitemviews/kfileitemlistwidget.h @@ -32,7 +32,9 @@ public: protected: virtual QString itemText(int index, const KItemListView* view) const; + virtual bool itemIsLink(int index, const KItemListView* view) const; virtual QString roleText(const QByteArray& role, const QHash& values) const; + virtual QFont customizedFontForLinks(const QFont& baseFont) const; }; class LIBDOLPHINPRIVATE_EXPORT KFileItemListWidget : public KStandardItemListWidget diff --git a/dolphin/src/kitemviews/kstandarditemlistwidget.cpp b/dolphin/src/kitemviews/kstandarditemlistwidget.cpp index 9f7b26959f..d8b5ad9083 100644 --- a/dolphin/src/kitemviews/kstandarditemlistwidget.cpp +++ b/dolphin/src/kitemviews/kstandarditemlistwidget.cpp @@ -86,16 +86,22 @@ qreal KStandardItemListWidgetInformant::preferredRoleColumnWidth(const QByteArra const QString text = roleText(role, values); qreal width = KStandardItemListWidget::columnPadding(option); + const QFontMetrics& normalFontMetrics = option.fontMetrics; + const QFontMetrics linkFontMetrics(customizedFontForLinks(option.font)); + if (role == "rating") { width += KStandardItemListWidget::preferredRatingSize(option).width(); } else { - width += option.fontMetrics.width(text); + // If current item is a link, we use the customized link font metrics instead of the normal font metrics. + const QFontMetrics& fontMetrics = itemIsLink(index, view) ? linkFontMetrics : normalFontMetrics; + + width += fontMetrics.width(text); if (role == "text") { if (view->supportsItemExpanding()) { // Increase the width by the expansion-toggle and the current expansion level const int expandedParentsCount = values.value("expandedParentsCount", 0).toInt(); - const qreal height = option.padding * 2 + qMax(option.iconSize, option.fontMetrics.height()); + const qreal height = option.padding * 2 + qMax(option.iconSize, fontMetrics.height()); width += (expandedParentsCount + 1) * height; } @@ -112,6 +118,11 @@ QString KStandardItemListWidgetInformant::itemText(int index, const KItemListVie return view->model()->data(index).value("text").toString(); } +bool KStandardItemListWidgetInformant::itemIsLink(int index, const KItemListView* view) const +{ + return false; +} + QString KStandardItemListWidgetInformant::roleText(const QByteArray& role, const QHash& values) const { @@ -122,10 +133,15 @@ QString KStandardItemListWidgetInformant::roleText(const QByteArray& role, return values.value(role).toString(); } +QFont KStandardItemListWidgetInformant::customizedFontForLinks(const QFont& baseFont) const +{ + return baseFont; +} + void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector& sizeHints, const KItemListView* view) const { const KItemListStyleOption& option = view->styleOption(); - const QFont& font = option.font; + const QFont& normalFont = option.font; const int additionalRolesCount = qMax(view->visibleRoles().count() - 1, 0); const qreal itemWidth = view->itemSize().width(); @@ -133,6 +149,8 @@ void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector const qreal additionalRolesSpacing = additionalRolesCount * option.fontMetrics.lineSpacing(); const qreal spacingAndIconHeight = option.iconSize + option.padding * 3; + const QFont linkFont = customizedFontForLinks(normalFont); + QTextOption textOption(Qt::AlignHCenter); textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); @@ -141,6 +159,9 @@ void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector continue; } + // If the current item is a link, we use the customized link font instead of the normal font. + const QFont& font = itemIsLink(index, view) ? linkFont : normalFont; + const QString& text = KStringHandler::preProcessWrap(itemText(index, view)); // Calculate the number of lines required for wrapping the name @@ -172,20 +193,25 @@ void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector void KStandardItemListWidgetInformant::calculateCompactLayoutItemSizeHints(QVector& sizeHints, const KItemListView* view) const { const KItemListStyleOption& option = view->styleOption(); - const QFontMetrics& fontMetrics = option.fontMetrics; + const QFontMetrics& normalFontMetrics = option.fontMetrics; const int additionalRolesCount = qMax(view->visibleRoles().count() - 1, 0); const QList& visibleRoles = view->visibleRoles(); const bool showOnlyTextRole = (visibleRoles.count() == 1) && (visibleRoles.first() == "text"); const qreal maxWidth = option.maxTextWidth; const qreal paddingAndIconWidth = option.padding * 4 + option.iconSize; - const qreal height = option.padding * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * option.fontMetrics.lineSpacing()); + const qreal height = option.padding * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * normalFontMetrics.lineSpacing()); + + const QFontMetrics linkFontMetrics(customizedFontForLinks(option.font)); for (int index = 0; index < sizeHints.count(); ++index) { if (!sizeHints.at(index).isEmpty()) { continue; } + // If the current item is a link, we use the customized link font metrics instead of the normal font metrics. + const QFontMetrics& fontMetrics = itemIsLink(index, view) ? linkFontMetrics : normalFontMetrics; + // For each row exactly one role is shown. Calculate the maximum required width that is necessary // to show all roles without horizontal clipping. qreal maximumRequiredWidth = 0.0; diff --git a/dolphin/src/kitemviews/kstandarditemlistwidget.h b/dolphin/src/kitemviews/kstandarditemlistwidget.h index ca198c36b5..ba426d0540 100644 --- a/dolphin/src/kitemviews/kstandarditemlistwidget.h +++ b/dolphin/src/kitemviews/kstandarditemlistwidget.h @@ -53,6 +53,13 @@ protected: */ virtual QString itemText(int index, const KItemListView* view) const; + /** + * @return The value of the "isLink" role. The default implementation returns false. + * The derived class should reimplement this function, when information about + * links is available and in usage. + */ + virtual bool itemIsLink(int index, const KItemListView* view) const; + /** * @return String representation of the role \a role. The representation of * a role might depend on other roles, so the values of all roles @@ -61,6 +68,11 @@ protected: virtual QString roleText(const QByteArray& role, const QHash& values) const; + /** + * @return A font based on baseFont which is customized for symlinks. + */ + virtual QFont customizedFontForLinks(const QFont& baseFont) const; + void calculateIconsLayoutItemSizeHints(QVector& sizeHints, const KItemListView* view) const; void calculateCompactLayoutItemSizeHints(QVector& sizeHints, const KItemListView* view) const; void calculateDetailsLayoutItemSizeHints(QVector& sizeHints, const KItemListView* view) const; From 1cbb06f593879ecf2c715d53153ae8bda8e01f93 Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Tue, 11 Mar 2014 09:07:23 +0100 Subject: [PATCH 2/2] Use QMutableHashIterator for deleting items from a QHash KItemListViewAnimation::slotFinished() used a QHashIterator to iterate over a QHash, and then removes an item from the hash using QHash::remove() inside the loop. This is quite unusual - the recommended way is to use a QMutableHashIterator (or std-style iterators and then QHash::erase(it)). This might be related to the cause of a crash in this function. BUG: 331876 REVIEW: 116666 FIXED-IN: 4.13.0 --- dolphin/src/kitemviews/private/kitemlistviewanimation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dolphin/src/kitemviews/private/kitemlistviewanimation.cpp b/dolphin/src/kitemviews/private/kitemlistviewanimation.cpp index e347c5bb11..5a00c8c3a6 100644 --- a/dolphin/src/kitemviews/private/kitemlistviewanimation.cpp +++ b/dolphin/src/kitemviews/private/kitemlistviewanimation.cpp @@ -225,13 +225,13 @@ void KItemListViewAnimation::slotFinished() { QPropertyAnimation* finishedAnim = qobject_cast(sender()); for (int type = 0; type < AnimationTypeCount; ++type) { - QHashIterator it(m_animation[type]); + QMutableHashIterator it(m_animation[type]); while (it.hasNext()) { it.next(); QPropertyAnimation* propertyAnim = it.value(); if (propertyAnim == finishedAnim) { QGraphicsWidget* widget = it.key(); - m_animation[type].remove(widget); + it.remove(); finishedAnim->deleteLater(); emit finished(widget, static_cast(type));