]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Allow to optionally limit the maximum number of text lines
authorPeter Penz <peter.penz19@gmail.com>
Fri, 13 Apr 2012 22:22:08 +0000 (00:22 +0200)
committerPeter Penz <peter.penz19@gmail.com>
Fri, 13 Apr 2012 22:28:24 +0000 (00:28 +0200)
Showing the whole filename unclipped seems to be a good default,
however for users with a lot of files that have extremely long names
this might get a problem especially in the icons-view.

- Allow to limit the maximum number of lines in the icons-view
- Allow to specify a maximum width in the compact-view

(No limit is required for the details-view, as the name is shortened
automatically to show other columns)

BUG: 288596
FIXED-IN: 4.9.0

src/kitemviews/kfileitemlistwidget.cpp
src/kitemviews/kitemliststyleoption.cpp
src/kitemviews/kitemliststyleoption.h
src/kitemviews/kitemlistview.cpp
src/settings/dolphin_compactmodesettings.kcfg
src/settings/dolphin_iconsmodesettings.kcfg
src/settings/viewmodes/viewsettingstab.cpp
src/settings/viewmodes/viewsettingstab.h
src/views/dolphinitemlistcontainer.cpp

index f3b4da892f6ecd633f8a84ecf4d5cb3e07ca25b8..5c5690c40f27e623a325a23ab4c22a03be4f1278 100644 (file)
@@ -279,7 +279,8 @@ QSizeF KFileItemListWidget::itemSizeHint(int index, const KItemListView* view)
     case IconsLayout: {
         const QString text = KStringHandler::preProcessWrap(values["name"].toString());
 
-        const qreal maxWidth = view->itemSize().width() - 2 * option.padding;
+        const qreal itemWidth = view->itemSize().width();
+        const qreal maxWidth = itemWidth - 2 * option.padding;
         QTextLine line;
 
         // Calculate the number of lines required for wrapping the name
@@ -298,11 +299,14 @@ QSizeF KFileItemListWidget::itemSizeHint(int index, const KItemListView* view)
         layout.endLayout();
 
         // Add one line for each additional information
-        const qreal height = textHeight +
-                             additionalRolesCount * option.fontMetrics.lineSpacing() +
-                             option.iconSize +
-                             option.padding * 3;
-        return QSizeF(view->itemSize().width(), height);
+        textHeight += additionalRolesCount * option.fontMetrics.lineSpacing();
+
+        const qreal maxTextHeight = option.maxTextSize.height();
+        if (maxTextHeight > 0 && textHeight > maxTextHeight) {
+            textHeight = maxTextHeight;
+        }
+
+        return QSizeF(itemWidth, textHeight + option.iconSize + option.padding * 3);
     }
 
     case CompactLayout: {
@@ -316,7 +320,11 @@ QSizeF KFileItemListWidget::itemSizeHint(int index, const KItemListView* view)
             maximumRequiredWidth = qMax(maximumRequiredWidth, requiredWidth);
         }
 
-        const qreal width = option.padding * 4 + option.iconSize + maximumRequiredWidth;
+        qreal width = option.padding * 4 + option.iconSize + maximumRequiredWidth;
+        const qreal maxWidth = option.maxTextSize.width();
+        if (maxWidth > 0 && width > maxWidth) {
+            width = maxWidth;
+        }
         const qreal height = option.padding * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * option.fontMetrics.lineSpacing());
         return QSizeF(width, height);
     }
@@ -756,25 +764,46 @@ void KFileItemListWidget::updateIconsLayoutTextCache()
     // Initialize properties for the "name" role. It will be used as anchor
     // for initializing the position of the other roles.
     TextInfo* nameTextInfo = m_textInfo.value("name");
-    nameTextInfo->staticText.setText(KStringHandler::preProcessWrap(values["name"].toString()));
+    const QString nameText = KStringHandler::preProcessWrap(values["name"].toString());
+    nameTextInfo->staticText.setText(nameText);
 
     // Calculate the number of lines required for the name and the required width
     qreal nameWidth = 0;
     qreal nameHeight = 0;
     QTextLine line;
 
+    const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0);
+    const int maxNameLines = (option.maxTextSize.height() / int(lineSpacing)) - additionalRolesCount;
+
     QTextLayout layout(nameTextInfo->staticText.text(), option.font);
     layout.setTextOption(nameTextInfo->staticText.textOption());
     layout.beginLayout();
+    int nameLineIndex = 0;
     while ((line = layout.createLine()).isValid()) {
         line.setLineWidth(maxWidth);
         nameWidth = qMax(nameWidth, line.naturalTextWidth());
         nameHeight += line.height();
+
+        ++nameLineIndex;
+        if (nameLineIndex == maxNameLines) {
+            // The maximum number of textlines has been reached. If this is
+            // the case provide an elided text if necessary.
+            const int textLength = line.textStart() + line.textLength();
+            if (textLength < nameText.length()) {
+                // Elide the last line of the text
+                QString lastTextLine = nameText.mid(line.textStart(), line.textLength());
+                lastTextLine = option.fontMetrics.elidedText(lastTextLine,
+                                                             Qt::ElideRight,
+                                                             line.naturalTextWidth() - 1);
+                const QString elidedText = nameText.left(line.textStart()) + lastTextLine;
+                nameTextInfo->staticText.setText(elidedText);
+            }
+            break;
+        }
     }
     layout.endLayout();
 
     // Use one line for each additional information
-    const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0);
     nameTextInfo->staticText.setTextWidth(maxWidth);
     nameTextInfo->pos = QPointF(padding, widgetHeight -
                                          nameHeight -
index c512fa43ec09f0caf3ee05243bdfceb2a937fad3..36cfeb088c58e8b103990b2bfc6307a2669b3e07 100644 (file)
@@ -30,7 +30,8 @@ KItemListStyleOption::KItemListStyleOption() :
     horizontalMargin(0),
     verticalMargin(0),
     iconSize(KIconLoader::SizeMedium),
-    extendedSelectionRegion(false)
+    extendedSelectionRegion(false),
+    maxTextSize()
 {
 }
 
@@ -43,7 +44,8 @@ KItemListStyleOption::KItemListStyleOption(const KItemListStyleOption& other) :
     horizontalMargin(other.horizontalMargin),
     verticalMargin(other.verticalMargin),
     iconSize(other.iconSize),
-    extendedSelectionRegion(other.extendedSelectionRegion)
+    extendedSelectionRegion(other.extendedSelectionRegion),
+    maxTextSize(other.maxTextSize)
 {
 }
 
index 62441ef4b059f0f98a14da4f4b5ad3694f6fca71..1a304fc28f52ab6f478a16dc4576f6f423c92a5f 100644 (file)
@@ -43,6 +43,7 @@ public:
     int verticalMargin;
     int iconSize;
     bool extendedSelectionRegion;
+    QSize maxTextSize;
 };
 #endif
 
index 732ed24e48fe3ae5de05edf611aafd24f7166350..c625234104a991acb0984aeaac2735e62f95282b 100644 (file)
@@ -148,10 +148,10 @@ Qt::Orientation KItemListView::scrollOrientation() const
     return m_layouter->scrollOrientation();
 }
 
-void KItemListView::setItemSize(const QSizeF& itemSize)
+void KItemListView::setItemSize(const QSizeF& size)
 {
     const QSizeF previousSize = m_itemSize;
-    if (itemSize == previousSize) {
+    if (size == previousSize) {
         return;
     }
 
@@ -159,14 +159,14 @@ void KItemListView::setItemSize(const QSizeF& itemSize)
     // are changed in the grid layout. Although the animation
     // engine can handle this usecase, it looks obtrusive.
     const bool animate = !changesItemGridLayout(m_layouter->size(),
-                                                itemSize,
+                                                size,
                                                 m_layouter->itemMargin());
 
     const bool alternateBackgroundsChanged = (m_visibleRoles.count() > 1) &&
-                                             (( m_itemSize.isEmpty() && !itemSize.isEmpty()) ||
-                                              (!m_itemSize.isEmpty() && itemSize.isEmpty()));
+                                             (( m_itemSize.isEmpty() && !size.isEmpty()) ||
+                                              (!m_itemSize.isEmpty() && size.isEmpty()));
 
-    m_itemSize = itemSize;
+    m_itemSize = size;
 
     if (alternateBackgroundsChanged) {
         // For an empty item size alternate backgrounds are drawn if more than
@@ -175,23 +175,23 @@ void KItemListView::setItemSize(const QSizeF& itemSize)
         updateAlternateBackgrounds();
     }
 
-    if (itemSize.isEmpty()) {
+    if (size.isEmpty()) {
         if (m_headerWidget->automaticColumnResizing()) {
             updatePreferredColumnWidths();
         } else {
             // Only apply the changed height and respect the header widths
             // set by the user
             const qreal currentWidth = m_layouter->itemSize().width();
-            const QSizeF newSize(currentWidth, itemSize.height());
+            const QSizeF newSize(currentWidth, size.height());
             m_layouter->setItemSize(newSize);
         }
     } else {
-        m_layouter->setItemSize(itemSize);
+        m_layouter->setItemSize(size);
     }
 
     m_sizeHintResolver->clearCache();
     doLayout(animate ? Animation : NoAnimation);
-    onItemSizeChanged(itemSize, previousSize);
+    onItemSizeChanged(size, previousSize);
 }
 
 QSizeF KItemListView::itemSize() const
@@ -392,6 +392,12 @@ void KItemListView::setStyleOption(const KItemListStyleOption& option)
         updateGroupHeaderHeight();
     }
 
+    if (animate && previousOption.maxTextSize != option.maxTextSize) {
+        // Animating a change of the maximum text size just results in expensive
+        // temporary eliding and clipping operations and does not look good visually.
+        animate = false;
+    }
+
     QHashIterator<int, KItemListWidget*> it(m_visibleItems);
     while (it.hasNext()) {
         it.next();
@@ -399,6 +405,7 @@ void KItemListView::setStyleOption(const KItemListStyleOption& option)
     }
 
     m_sizeHintResolver->clearCache();
+    m_layouter->markAsDirty();
     doLayout(animate ? Animation : NoAnimation);
 
     onStyleOptionChanged(option, previousOption);
index 40b9dfa320e48576d7c3d265a3ae3cfe0ff94ecd..b9000c8e21f513b21e79ec831eaf79349411834d 100644 (file)
@@ -36,5 +36,9 @@
             <label>Preview size</label>
             <default code="true">KIconLoader::SizeLarge</default>
         </entry>
+        <entry name="MaximumTextWidthIndex" type="Int">
+            <label>Maximum text width index (0 means unlimited)</label>
+            <default>0</default>
+        </entry>
     </group>
 </kcfg>
index fb01a8c6517ae6d04db05474337d2733342b25f9..52cd9a28c38e4f52dce2ee795f09c3dc60755931 100644 (file)
@@ -40,5 +40,9 @@
             <label>Text width index</label>
             <default>1</default>
         </entry>
+        <entry name="MaximumTextLines" type="Int">
+            <label>Maximum textlines (0 means unlimited)</label>
+            <default>0</default>
+        </entry>
     </group>
 </kcfg>
index 23b2999b1b5312ed5f486c752150784ed1b928a9..fe043a7884745db97b5f257c7a077f9ccc57508f 100644 (file)
@@ -41,7 +41,8 @@ ViewSettingsTab::ViewSettingsTab(Mode mode, QWidget* parent) :
     m_defaultSizeSlider(0),
     m_previewSizeSlider(0),
     m_fontRequester(0),
-    m_textWidthBox(0),
+    m_widthBox(0),
+    m_maxLinesBox(0),
     m_expandableFolders(0)
 {
     QVBoxLayout* topLayout = new QVBoxLayout(this);
@@ -83,15 +84,38 @@ ViewSettingsTab::ViewSettingsTab(Mode mode, QWidget* parent) :
 
     switch (m_mode) {
     case IconsMode: {
-        QLabel* textWidthLabel = new QLabel(i18nc("@label:listbox", "Text width:"), textGroup);
-        m_textWidthBox = new KComboBox(textGroup);
-        m_textWidthBox->addItem(i18nc("@item:inlistbox Text width", "Small"));
-        m_textWidthBox->addItem(i18nc("@item:inlistbox Text width", "Medium"));
-        m_textWidthBox->addItem(i18nc("@item:inlistbox Text width", "Large"));
-        m_textWidthBox->addItem(i18nc("@item:inlistbox Text width", "Huge"));
-
-        textGroupLayout->addWidget(textWidthLabel, 2, 0, Qt::AlignRight);
-        textGroupLayout->addWidget(m_textWidthBox, 2, 1);
+        QLabel* widthLabel = new QLabel(i18nc("@label:listbox", "Width:"), textGroup);
+        m_widthBox = new KComboBox(textGroup);
+        m_widthBox->addItem(i18nc("@item:inlistbox Text width", "Small"));
+        m_widthBox->addItem(i18nc("@item:inlistbox Text width", "Medium"));
+        m_widthBox->addItem(i18nc("@item:inlistbox Text width", "Large"));
+        m_widthBox->addItem(i18nc("@item:inlistbox Text width", "Huge"));
+
+        QLabel* maxLinesLabel = new QLabel(i18nc("@label:listbox", "Maximum lines:"), textGroup);
+        m_maxLinesBox = new KComboBox(textGroup);
+        m_maxLinesBox->addItem(i18nc("@item:inlistbox Maximum lines", "Unlimited"));
+        m_maxLinesBox->addItem(i18nc("@item:inlistbox Maximum lines", "1"));
+        m_maxLinesBox->addItem(i18nc("@item:inlistbox Maximum lines", "2"));
+        m_maxLinesBox->addItem(i18nc("@item:inlistbox Maximum lines", "3"));
+        m_maxLinesBox->addItem(i18nc("@item:inlistbox Maximum lines", "4"));
+        m_maxLinesBox->addItem(i18nc("@item:inlistbox Maximum lines", "5"));
+
+        textGroupLayout->addWidget(widthLabel, 2, 0, Qt::AlignRight);
+        textGroupLayout->addWidget(m_widthBox, 2, 1);
+        textGroupLayout->addWidget(maxLinesLabel, 3, 0, Qt::AlignRight);
+        textGroupLayout->addWidget(m_maxLinesBox, 3, 1);
+        break;
+    }
+    case CompactMode: {
+        QLabel* maxWidthLabel = new QLabel(i18nc("@label:listbox", "Maximum width:"), textGroup);
+        m_widthBox = new KComboBox(textGroup);
+        m_widthBox->addItem(i18nc("@item:inlistbox Maximum width", "Unlimited"));
+        m_widthBox->addItem(i18nc("@item:inlistbox Maximum width", "Small"));
+        m_widthBox->addItem(i18nc("@item:inlistbox Maximum width", "Medium"));
+        m_widthBox->addItem(i18nc("@item:inlistbox Maximum width", "Large"));
+
+        textGroupLayout->addWidget(maxWidthLabel, 2, 0, Qt::AlignRight);
+        textGroupLayout->addWidget(m_widthBox, 2, 1);
         break;
     }
     case DetailsMode:
@@ -114,7 +138,11 @@ ViewSettingsTab::ViewSettingsTab(Mode mode, QWidget* parent) :
 
     switch (m_mode) {
     case IconsMode:
-        connect(m_textWidthBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(changed()));
+        connect(m_widthBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(changed()));
+        connect(m_maxLinesBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(changed()));
+        break;
+    case CompactMode:
+        connect(m_widthBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(changed()));
         break;
     case DetailsMode:
         connect(m_expandableFolders, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
@@ -135,7 +163,11 @@ void ViewSettingsTab::applySettings()
 
     switch (m_mode) {
     case IconsMode:
-        IconsModeSettings::setTextWidthIndex(m_textWidthBox->currentIndex());
+        IconsModeSettings::setTextWidthIndex(m_widthBox->currentIndex());
+        IconsModeSettings::setMaximumTextLines(m_maxLinesBox->currentIndex());
+        break;
+    case CompactMode:
+        CompactModeSettings::setMaximumTextWidthIndex(m_widthBox->currentIndex());
         break;
     case DetailsMode:
         DetailsModeSettings::setExpandableFolders(m_expandableFolders->isChecked());
@@ -179,7 +211,11 @@ void ViewSettingsTab::loadSettings()
 {
     switch (m_mode) {
     case IconsMode:
-        m_textWidthBox->setCurrentIndex(IconsModeSettings::textWidthIndex());
+        m_widthBox->setCurrentIndex(IconsModeSettings::textWidthIndex());
+        m_maxLinesBox->setCurrentIndex(IconsModeSettings::maximumTextLines());
+        break;
+    case CompactMode:
+        m_widthBox->setCurrentIndex(CompactModeSettings::maximumTextWidthIndex());
         break;
     case DetailsMode:
         m_expandableFolders->setChecked(DetailsModeSettings::expandableFolders());
index b21fc102c6b473830dd6bb30a76cab3e3da02935..2115da1bc52e1e5890c08cb58ffcfdd17c9a9968 100644 (file)
@@ -63,7 +63,8 @@ private:
     QSlider* m_previewSizeSlider;
 
     DolphinFontRequester* m_fontRequester;
-    KComboBox* m_textWidthBox;
+    KComboBox* m_widthBox;
+    KComboBox* m_maxLinesBox;
     QCheckBox* m_expandableFolders;
 };
 
index e8c373492abc7bd4dd283ddf22daab124e6d27d8..88e10d8a3a9b2d9bc4861ce7adce8dbbd0aab322 100644 (file)
@@ -222,6 +222,8 @@ void DolphinItemListContainer::updateGridSize()
     // Calculate the item-width and item-height
     int itemWidth;
     int itemHeight;
+    QSize maxTextSize;
+
     switch (itemLayout()) {
     case KFileItemListView::IconsLayout: {
         const int minItemWidth = 48;
@@ -238,7 +240,15 @@ void DolphinItemListContainer::updateGridSize()
         if (itemWidth < iconSize + padding * 2) {
             itemWidth = iconSize + padding * 2;
         }
-        itemHeight = padding * 3 + iconSize + styleOption.fontMetrics.height();
+
+        itemHeight = padding * 3 + iconSize + styleOption.fontMetrics.lineSpacing();
+        if (IconsModeSettings::maximumTextLines() > 0) {
+            // A restriction is given for the maximum number of textlines (0 means
+            // having no restriction)
+            const int additionalInfoCount = m_fileItemListView->visibleRoles().count() - 1;
+            const int maxAdditionalLines = additionalInfoCount + IconsModeSettings::maximumTextLines();
+            maxTextSize.rheight() = styleOption.fontMetrics.lineSpacing() * maxAdditionalLines;
+        }
 
         horizontalMargin = 4;
         verticalMargin = 8;
@@ -247,14 +257,21 @@ void DolphinItemListContainer::updateGridSize()
     case KFileItemListView::CompactLayout: {
         itemWidth = padding * 4 + iconSize + styleOption.fontMetrics.height() * 5;
         const int textLinesCount = m_fileItemListView->visibleRoles().count();
-        itemHeight = padding * 2 + qMax(iconSize, textLinesCount * styleOption.fontMetrics.height());
+        itemHeight = padding * 2 + qMax(iconSize, textLinesCount * styleOption.fontMetrics.lineSpacing());
+
+        if (CompactModeSettings::maximumTextWidthIndex() > 0) {
+            // A restriction is given for the maximum width of the text (0 means
+            // having no restriction)
+            maxTextSize.rwidth() = styleOption.fontMetrics.height() * 10 *
+                                   CompactModeSettings::maximumTextWidthIndex();
+        }
 
         horizontalMargin = 8;
         break;
     }
     case KFileItemListView::DetailsLayout: {
         itemWidth = -1;
-        itemHeight = padding * 2 + qMax(iconSize, styleOption.fontMetrics.height());
+        itemHeight = padding * 2 + qMax(iconSize, styleOption.fontMetrics.lineSpacing());
         break;
     }
     default:
@@ -269,6 +286,7 @@ void DolphinItemListContainer::updateGridSize()
     styleOption.horizontalMargin = horizontalMargin;
     styleOption.verticalMargin = verticalMargin;
     styleOption.iconSize = iconSize;
+    styleOption.maxTextSize = maxTextSize;
     m_fileItemListView->beginTransaction();
     m_fileItemListView->setStyleOption(styleOption);
     m_fileItemListView->setItemSize(QSizeF(itemWidth, itemHeight));