From 0d37038b407944a9b7ec05127b5b6d41dc1a496f Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Mon, 24 Feb 2014 14:17:03 +0100 Subject: [PATCH 01/29] Handle font and palette changes in Dolphin list views. Also update the font of the meta data widget in InformationPanelContent (smallest readable font). BUG: 329186 BUG: 315061 FIXED-IN: 4.13 REVIEW: 115958 --- src/kitemviews/kitemlistview.cpp | 41 +++++++++++++++++-- src/kitemviews/kitemlistview.h | 3 ++ .../information/informationpanelcontent.cpp | 4 ++ src/views/dolphinitemlistview.cpp | 37 +++++++++-------- src/views/dolphinitemlistview.h | 3 +- 5 files changed, 66 insertions(+), 22 deletions(-) diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index 82f8a2053..ab420cab1 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -893,11 +893,23 @@ void KItemListView::onTransactionEnd() bool KItemListView::event(QEvent* event) { - // Forward all events to the controller and handle them there - if (!m_editingRole && m_controller && m_controller->processEvent(event, transform())) { - event->accept(); - return true; + switch (event->type()) { + case QEvent::PaletteChange: + updatePalette(); + break; + + case QEvent::FontChange: + updateFont(); + break; + + default: + // Forward all other events to the controller and handle them there + if (!m_editingRole && m_controller && m_controller->processEvent(event, transform())) { + event->accept(); + return true; + } } + return QGraphicsWidget::event(event); } @@ -950,6 +962,27 @@ QList KItemListView::visibleItemListWidgets() const return m_visibleItems.values(); } +void KItemListView::updateFont() +{ + if (scene() && !scene()->views().isEmpty()) { + KItemListStyleOption option = styleOption(); + option.font = scene()->views().first()->font(); + option.fontMetrics = QFontMetrics(option.font); + + setStyleOption(option); + } +} + +void KItemListView::updatePalette() +{ + if (scene() && !scene()->views().isEmpty()) { + KItemListStyleOption option = styleOption(); + option.palette = scene()->views().first()->palette(); + + setStyleOption(option); + } +} + void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges) { if (m_itemSize.isEmpty()) { diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index f39e73a97..8a522a686 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -388,6 +388,9 @@ protected: QList visibleItemListWidgets() const; + virtual void updateFont(); + virtual void updatePalette(); + protected slots: virtual void slotItemsInserted(const KItemRangeList& itemRanges); virtual void slotItemsRemoved(const KItemRangeList& itemRanges); diff --git a/src/panels/information/informationpanelcontent.cpp b/src/panels/information/informationpanelcontent.cpp index b2dd1582e..4fb0d9442 100644 --- a/src/panels/information/informationpanelcontent.cpp +++ b/src/panels/information/informationpanelcontent.cpp @@ -271,6 +271,10 @@ bool InformationPanelContent::eventFilter(QObject* obj, QEvent* event) adjustWidgetSizes(parentWidget()->width()); break; + case QEvent::FontChange: + m_metaDataWidget->setFont(KGlobalSettings::smallestReadableFont()); + break; + default: break; } diff --git a/src/views/dolphinitemlistview.cpp b/src/views/dolphinitemlistview.cpp index 4799d7679..eb61ccb21 100644 --- a/src/views/dolphinitemlistview.cpp +++ b/src/views/dolphinitemlistview.cpp @@ -144,6 +144,26 @@ void DolphinItemListView::onVisibleRolesChanged(const QList& current updateGridSize(); } +void DolphinItemListView::updateFont() +{ + const ViewModeSettings settings(viewMode()); + + if (settings.useSystemFont()) { + KItemListView::updateFont(); + } else { + QFont font(settings.fontFamily(), qRound(settings.fontSize())); + font.setItalic(settings.italicFont()); + font.setWeight(settings.fontWeight()); + font.setPointSizeF(settings.fontSize()); + + KItemListStyleOption option = styleOption(); + option.font = font; + option.fontMetrics = QFontMetrics(font); + + setStyleOption(option); + } +} + void DolphinItemListView::updateGridSize() { const ViewModeSettings settings(viewMode()); @@ -231,23 +251,6 @@ void DolphinItemListView::updateGridSize() endTransaction(); } -void DolphinItemListView::updateFont() -{ - KItemListStyleOption option = styleOption(); - - const ViewModeSettings settings(viewMode()); - - QFont font(settings.fontFamily(), qRound(settings.fontSize())); - font.setItalic(settings.italicFont()); - font.setWeight(settings.fontWeight()); - font.setPointSizeF(settings.fontSize()); - - option.font = font; - option.fontMetrics = QFontMetrics(font); - - setStyleOption(option); -} - ViewModeSettings::ViewMode DolphinItemListView::viewMode() const { ViewModeSettings::ViewMode mode; diff --git a/src/views/dolphinitemlistview.h b/src/views/dolphinitemlistview.h index 18bb284ac..67302e44d 100644 --- a/src/views/dolphinitemlistview.h +++ b/src/views/dolphinitemlistview.h @@ -56,9 +56,10 @@ protected: virtual void onVisibleRolesChanged(const QList& current, const QList& previous); + virtual void updateFont(); + private: void updateGridSize(); - void updateFont(); ViewModeSettings::ViewMode viewMode() const; From 342822e83de4508a7e32bf9c23ee074c2d584d48 Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Mon, 24 Feb 2014 21:05:09 +0100 Subject: [PATCH 02/29] Make the handling of the "maximum text lines" setting more robust If the user sets a maximum number of text lines in the settings, this number was translated into a maximum height in pixels using QFontMetrics::lineSpacing() before this commit. In KStandardItemListWidgetInformant::itemSizeHint(), this maximum height limited the size that is reserved for the item. However, in KStandardItemListWidget::updateIconsLayoutTextCache(), the maximum height was translated back into a maximum number of lines, which limits the number of lines that are created using the QTextLayout. This approach could lead to problems if the real height of the layouted text is 1 pixel more or less than QFontMetrics::lineSpacing() times "number of lines". Now we do not store a "maximum height" inside the "maximum size" explicitly, but store a maximum number of lines and a maximum with (for Compact View) separately, and then use the number of lines also to calculate the required size in KStandardItemListWidgetInformant::itemSizeHint(). This should make sure that the correct height is reserved for each item. Thanks to Christoph Feck and Emmanuel Pescosta for helping to debug this problem and testing the patch. BUG: 323841 FIXED-IN: 4.13 REVIEW: 113871 --- src/kitemviews/kitemliststyleoption.cpp | 6 ++++-- src/kitemviews/kitemliststyleoption.h | 3 ++- src/kitemviews/kitemlistview.cpp | 3 ++- src/kitemviews/kstandarditemlistwidget.cpp | 19 +++++++++---------- src/views/dolphinitemlistview.cpp | 17 ++++++----------- 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/kitemviews/kitemliststyleoption.cpp b/src/kitemviews/kitemliststyleoption.cpp index ac2587962..edd6363c8 100644 --- a/src/kitemviews/kitemliststyleoption.cpp +++ b/src/kitemviews/kitemliststyleoption.cpp @@ -31,7 +31,8 @@ KItemListStyleOption::KItemListStyleOption() : verticalMargin(-1), iconSize(-1), extendedSelectionRegion(false), - maxTextSize() + maxTextLines(0), + maxTextWidth(0) { } @@ -45,7 +46,8 @@ KItemListStyleOption::KItemListStyleOption(const KItemListStyleOption& other) : verticalMargin(other.verticalMargin), iconSize(other.iconSize), extendedSelectionRegion(other.extendedSelectionRegion), - maxTextSize(other.maxTextSize) + maxTextLines(other.maxTextLines), + maxTextWidth(other.maxTextWidth) { } diff --git a/src/kitemviews/kitemliststyleoption.h b/src/kitemviews/kitemliststyleoption.h index 1a304fc28..782dd0ec2 100644 --- a/src/kitemviews/kitemliststyleoption.h +++ b/src/kitemviews/kitemliststyleoption.h @@ -43,7 +43,8 @@ public: int verticalMargin; int iconSize; bool extendedSelectionRegion; - QSize maxTextSize; + int maxTextLines; + int maxTextWidth; }; #endif diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index ab420cab1..f1b35fa53 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -760,7 +760,8 @@ void KItemListView::setStyleOption(const KItemListStyleOption& option) updateGroupHeaderHeight(); } - if (animate && previousOption.maxTextSize != option.maxTextSize) { + if (animate && + (previousOption.maxTextLines != option.maxTextLines || previousOption.maxTextWidth != option.maxTextWidth)) { // 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; diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index 9a9a734ed..9f7b26959 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -130,7 +130,6 @@ void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector const qreal itemWidth = view->itemSize().width(); const qreal maxWidth = itemWidth - 2 * option.padding; - const qreal maxTextHeight = option.maxTextSize.height(); const qreal additionalRolesSpacing = additionalRolesCount * option.fontMetrics.lineSpacing(); const qreal spacingAndIconHeight = option.iconSize + option.padding * 3; @@ -150,20 +149,22 @@ void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector layout.setTextOption(textOption); layout.beginLayout(); QTextLine line; + int lineCount = 0; while ((line = layout.createLine()).isValid()) { line.setLineWidth(maxWidth); line.naturalTextWidth(); textHeight += line.height(); + + ++lineCount; + if (lineCount == option.maxTextLines) { + break; + } } layout.endLayout(); // Add one line for each additional information textHeight += additionalRolesSpacing; - if (maxTextHeight > 0 && textHeight > maxTextHeight) { - textHeight = maxTextHeight; - } - sizeHints[index] = QSizeF(itemWidth, textHeight + spacingAndIconHeight); } } @@ -176,7 +177,7 @@ void KStandardItemListWidgetInformant::calculateCompactLayoutItemSizeHints(QVect const QList& visibleRoles = view->visibleRoles(); const bool showOnlyTextRole = (visibleRoles.count() == 1) && (visibleRoles.first() == "text"); - const qreal maxWidth = option.maxTextSize.width(); + 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()); @@ -1066,9 +1067,6 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() 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(), m_customizedFont); layout.setTextOption(nameTextInfo->staticText.textOption()); layout.beginLayout(); @@ -1079,7 +1077,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() nameHeight += line.height(); ++nameLineIndex; - if (nameLineIndex == maxNameLines) { + if (nameLineIndex == option.maxTextLines) { // 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(); @@ -1101,6 +1099,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() 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 - diff --git a/src/views/dolphinitemlistview.cpp b/src/views/dolphinitemlistview.cpp index eb61ccb21..db4dadf2f 100644 --- a/src/views/dolphinitemlistview.cpp +++ b/src/views/dolphinitemlistview.cpp @@ -180,7 +180,8 @@ void DolphinItemListView::updateGridSize() // Calculate the item-width and item-height int itemWidth; int itemHeight; - QSize maxTextSize; + int maxTextLines = 0; + int maxTextWidth = 0; switch (itemLayout()) { case KFileItemListView::IconsLayout: { @@ -200,16 +201,10 @@ void DolphinItemListView::updateGridSize() } itemHeight = padding * 3 + iconSize + option.fontMetrics.lineSpacing(); - if (IconsModeSettings::maximumTextLines() > 0) { - // A restriction is given for the maximum number of textlines (0 means - // having no restriction) - const int additionalInfoCount = visibleRoles().count() - 1; - const int maxAdditionalLines = additionalInfoCount + IconsModeSettings::maximumTextLines(); - maxTextSize.rheight() = option.fontMetrics.lineSpacing() * maxAdditionalLines; - } horizontalMargin = 4; verticalMargin = 8; + maxTextLines = IconsModeSettings::maximumTextLines(); break; } case KFileItemListView::CompactLayout: { @@ -220,8 +215,7 @@ void DolphinItemListView::updateGridSize() if (CompactModeSettings::maximumTextWidthIndex() > 0) { // A restriction is given for the maximum width of the text (0 means // having no restriction) - maxTextSize.rwidth() = option.fontMetrics.height() * 10 * - CompactModeSettings::maximumTextWidthIndex(); + maxTextWidth = option.fontMetrics.height() * 10 * CompactModeSettings::maximumTextWidthIndex(); } horizontalMargin = 8; @@ -244,7 +238,8 @@ void DolphinItemListView::updateGridSize() option.horizontalMargin = horizontalMargin; option.verticalMargin = verticalMargin; option.iconSize = iconSize; - option.maxTextSize = maxTextSize; + option.maxTextLines = maxTextLines; + option.maxTextWidth = maxTextWidth; beginTransaction(); setStyleOption(option); setItemSize(QSizeF(itemWidth, itemHeight)); From 9a9ab6e50cbfaee56a3d3b84ed7bea2f987985df Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Tue, 25 Feb 2014 19:38:57 +0100 Subject: [PATCH 03/29] Fix Bug 330605 - Dropbox plugin prevents git plugin from working Use scoring to find the best matching plugin for the given directory. Thanks to Phil Schaf for testing this patch! BUG: 330605 FIXED-IN: 4.12.3 REVIEW: 116019 --- .../versioncontrol/versioncontrolobserver.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/views/versioncontrol/versioncontrolobserver.cpp b/src/views/versioncontrol/versioncontrolobserver.cpp index 4d939ee0d..769c290f9 100644 --- a/src/views/versioncontrol/versioncontrolobserver.cpp +++ b/src/views/versioncontrol/versioncontrolobserver.cpp @@ -322,11 +322,18 @@ KVersionControlPlugin* VersionControlObserver::searchPlugin(const KUrl& director } } + // We use the number of upUrl() calls to find the best matching plugin + // for the given directory. The smaller value, the better it is (0 is best). + KVersionControlPlugin* bestPlugin = 0; + int bestScore = INT_MAX; + // Verify whether the current directory contains revision information // like .svn, .git, ... foreach (KVersionControlPlugin* plugin, plugins) { const QString fileName = directory.path(KUrl::AddTrailingSlash) + plugin->fileName(); if (QFile::exists(fileName)) { + // The score of this plugin is 0 (best), so we can just return this plugin, + // instead of going through the plugin scoring procedure, we can't find a better one ;) return plugin; } @@ -339,18 +346,24 @@ KVersionControlPlugin* VersionControlObserver::searchPlugin(const KUrl& director if (m_versionedDirectory) { KUrl dirUrl(directory); KUrl upUrl = dirUrl.upUrl(); - while (upUrl != dirUrl) { + int upUrlCounter = 1; + while ((upUrlCounter < bestScore) && (upUrl != dirUrl)) { const QString fileName = dirUrl.path(KUrl::AddTrailingSlash) + plugin->fileName(); if (QFile::exists(fileName)) { - return plugin; + if (upUrlCounter < bestScore) { + bestPlugin = plugin; + bestScore = upUrlCounter; + } + break; } dirUrl = upUrl; upUrl = dirUrl.upUrl(); + ++upUrlCounter; } } } - return 0; + return bestPlugin; } bool VersionControlObserver::isVersioned() const From c5d9791ad392efffa19108c3ce7a4e6a67453a09 Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Tue, 25 Feb 2014 19:41:45 +0100 Subject: [PATCH 04/29] Show the correct icon size in the zoom slider tooltip. BUG: 305694 FIXED-IN: 4.12.3 REVIEW: 111197 --- src/statusbar/dolphinstatusbar.cpp | 14 +++++++------- src/statusbar/dolphinstatusbar.h | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/statusbar/dolphinstatusbar.cpp b/src/statusbar/dolphinstatusbar.cpp index 671ef4f96..169395e63 100644 --- a/src/statusbar/dolphinstatusbar.cpp +++ b/src/statusbar/dolphinstatusbar.cpp @@ -73,6 +73,7 @@ DolphinStatusBar::DolphinStatusBar(QWidget* parent) : m_zoomSlider->setRange(ZoomLevelInfo::minimumLevel(), ZoomLevelInfo::maximumLevel()); connect(m_zoomSlider, SIGNAL(valueChanged(int)), this, SIGNAL(zoomLevelChanged(int))); + connect(m_zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(updateZoomSliderToolTip(int))); connect(m_zoomSlider, SIGNAL(sliderMoved(int)), this, SLOT(showZoomSliderToolTip(int))); // Initialize space information @@ -240,7 +241,6 @@ void DolphinStatusBar::setZoomLevel(int zoomLevel) { if (zoomLevel != m_zoomSlider->value()) { m_zoomSlider->setValue(zoomLevel); - updateZoomSliderToolTip(zoomLevel); } } @@ -338,6 +338,12 @@ void DolphinStatusBar::slotResetToDefaultText() updateLabelText(); } +void DolphinStatusBar::updateZoomSliderToolTip(int zoomLevel) +{ + const int size = ZoomLevelInfo::iconSizeForZoomLevel(zoomLevel); + m_zoomSlider->setToolTip(i18ncp("@info:tooltip", "Size: 1 pixel", "Size: %1 pixels", size)); +} + void DolphinStatusBar::setExtensionsVisible(bool visible) { bool showSpaceInfo = visible; @@ -350,10 +356,4 @@ void DolphinStatusBar::setExtensionsVisible(bool visible) m_zoomSlider->setVisible(showZoomSlider); } -void DolphinStatusBar::updateZoomSliderToolTip(int zoomLevel) -{ - const int size = ZoomLevelInfo::iconSizeForZoomLevel(zoomLevel); - m_zoomSlider->setToolTip(i18ncp("@info:tooltip", "Size: 1 pixel", "Size: %1 pixels", size)); -} - #include "dolphinstatusbar.moc" diff --git a/src/statusbar/dolphinstatusbar.h b/src/statusbar/dolphinstatusbar.h index b2afe2eb9..4d6dbb20f 100644 --- a/src/statusbar/dolphinstatusbar.h +++ b/src/statusbar/dolphinstatusbar.h @@ -122,6 +122,12 @@ private slots: */ void slotResetToDefaultText(); + /** + * Updates the text of the zoom slider tooltip to show + * the currently used size. + */ + void updateZoomSliderToolTip(int zoomLevel); + private: /** * Makes the space information widget and zoom slider widget @@ -131,12 +137,6 @@ private: */ void setExtensionsVisible(bool visible); - /** - * Updates the text of the zoom slider tooltip to show - * the currently used size. - */ - void updateZoomSliderToolTip(int zoomLevel); - private: QString m_text; QString m_defaultText; From 1eadb296e55b3f3cb455921920e990bd9836549d Mon Sep 17 00:00:00 2001 From: l10n daemon script Date: Thu, 27 Feb 2014 04:42:34 +0000 Subject: [PATCH 05/29] SVN_SILENT made messages (.desktop file) --- src/dolphinpart.desktop | 1 + src/settings/kcm/kcmdolphingeneral.desktop | 1 + src/settings/kcm/kcmdolphinnavigation.desktop | 1 + src/settings/kcm/kcmdolphinservices.desktop | 1 + src/settings/kcm/kcmdolphinviewmodes.desktop | 1 + 5 files changed, 5 insertions(+) diff --git a/src/dolphinpart.desktop b/src/dolphinpart.desktop index 10339e4bc..bdc3b929d 100644 --- a/src/dolphinpart.desktop +++ b/src/dolphinpart.desktop @@ -213,6 +213,7 @@ Name[gl]=Compacto Name[he]=מרוכז Name[hu]=Kompakt Name[ia]=Compacte +Name[is]=Þjappað Name[it]=Compatta Name[kk]=Ықшамды Name[km]=តូច​ល្មម diff --git a/src/settings/kcm/kcmdolphingeneral.desktop b/src/settings/kcm/kcmdolphingeneral.desktop index 5a79ad619..b0620ac74 100644 --- a/src/settings/kcm/kcmdolphingeneral.desktop +++ b/src/settings/kcm/kcmdolphingeneral.desktop @@ -314,6 +314,7 @@ X-KDE-Keywords[gl]=xestor de ficheiros X-KDE-Keywords[he]=מנהל קבצים X-KDE-Keywords[hu]=fájlkezelő X-KDE-Keywords[ia]=gerente de file +X-KDE-Keywords[is]=skráastjóri X-KDE-Keywords[it]=gestore dei file X-KDE-Keywords[kk]=file manager X-KDE-Keywords[km]=កម្មវិធី​គ្រប់គ្រង​ឯកសារ diff --git a/src/settings/kcm/kcmdolphinnavigation.desktop b/src/settings/kcm/kcmdolphinnavigation.desktop index 4cf793a35..8636058cd 100644 --- a/src/settings/kcm/kcmdolphinnavigation.desktop +++ b/src/settings/kcm/kcmdolphinnavigation.desktop @@ -314,6 +314,7 @@ X-KDE-Keywords[gl]=xestor de ficheiros X-KDE-Keywords[he]=מנהל קבצים X-KDE-Keywords[hu]=fájlkezelő X-KDE-Keywords[ia]=gerente de file +X-KDE-Keywords[is]=skráastjóri X-KDE-Keywords[it]=gestore dei file X-KDE-Keywords[kk]=file manager X-KDE-Keywords[km]=កម្មវិធី​គ្រប់គ្រង​ឯកសារ diff --git a/src/settings/kcm/kcmdolphinservices.desktop b/src/settings/kcm/kcmdolphinservices.desktop index aa93e6d28..34867305a 100644 --- a/src/settings/kcm/kcmdolphinservices.desktop +++ b/src/settings/kcm/kcmdolphinservices.desktop @@ -263,6 +263,7 @@ X-KDE-Keywords[gl]=xestor de ficheiros X-KDE-Keywords[he]=מנהל קבצים X-KDE-Keywords[hu]=fájlkezelő X-KDE-Keywords[ia]=gerente de file +X-KDE-Keywords[is]=skráastjóri X-KDE-Keywords[it]=gestore dei file X-KDE-Keywords[kk]=file manager X-KDE-Keywords[km]=កម្មវិធី​គ្រប់គ្រង​ឯកសារ diff --git a/src/settings/kcm/kcmdolphinviewmodes.desktop b/src/settings/kcm/kcmdolphinviewmodes.desktop index ce8401228..a4b4e058b 100644 --- a/src/settings/kcm/kcmdolphinviewmodes.desktop +++ b/src/settings/kcm/kcmdolphinviewmodes.desktop @@ -312,6 +312,7 @@ X-KDE-Keywords[gl]=xestor de ficheiros X-KDE-Keywords[he]=מנהל קבצים X-KDE-Keywords[hu]=fájlkezelő X-KDE-Keywords[ia]=gerente de file +X-KDE-Keywords[is]=skráastjóri X-KDE-Keywords[it]=gestore dei file X-KDE-Keywords[kk]=file manager X-KDE-Keywords[km]=កម្មវិធី​គ្រប់គ្រង​ឯកសារ From b7404044470bb3ef241dced31839a1d18e70e3b0 Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Thu, 27 Feb 2014 12:17:48 +0100 Subject: [PATCH 06/29] Scroll to newly dropped files. If multiple files are dropped, scroll to the first dropped file. BUG: 315722 FIXED-IN: 4.13 REVIEW: 116020 --- src/views/dolphinview.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index 9f5f48a86..b68e8aa6a 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -1046,6 +1046,7 @@ void DolphinView::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* even if (op && destUrl == url()) { // Mark the dropped urls as selected. m_clearSelectionBeforeSelectingNewItems = true; + m_markFirstNewlySelectedItemAsCurrent = true; connect(op, SIGNAL(aboutToCreate(KUrl::List)), this, SLOT(slotAboutToCreate(KUrl::List))); } From eab1b76b76d3492c9787cc11a8e8460c69924dc7 Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Sat, 1 Mar 2014 12:14:47 +0100 Subject: [PATCH 07/29] Always go back/forward in history when pressing the respective buttons Before this patch, pressing one of these buttons while an item is hovered selected this item. The motivation for this behavior was to provide a fast way to select items. However, this was counter-intuitive and confusing for many users. BUG: 310288 FIXED-IN: 4.13.0 REVIEW: 116469 --- src/kitemviews/kitemlistcontroller.cpp | 9 ++++----- src/views/dolphinview.cpp | 16 +++++++--------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index 7344b9960..61337d166 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -538,11 +538,10 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const m_pressedIndex = m_view->itemAt(m_pressedMousePos); emit mouseButtonPressed(m_pressedIndex, event->buttons()); - if ((event->buttons() & (Qt::XButton1 | Qt::XButton2)) && m_pressedIndex < 0) { - // Do not select items when clicking the empty part of the view with - // the back/forward buttons, see https://bugs.kde.org/show_bug.cgi?id=327412. - // Note that clicking an item with these buttons selects it, see comment in - // DolphinView::slotMouseButtonPressed(int, Qt::MouseButtons). + // TODO: Qt5: Replace Qt::XButton1 by Qt::BackButton and Qt::XButton2 by Qt::ForwardButton + if (event->buttons() & (Qt::XButton1 | Qt::XButton2)) { + // Do not select items when clicking the back/forward buttons, see + // https://bugs.kde.org/show_bug.cgi?id=327412. return true; } diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index b68e8aa6a..2769d670d 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -1071,17 +1071,15 @@ void DolphinView::slotModelChanged(KItemModelBase* current, KItemModelBase* prev void DolphinView::slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons) { + Q_UNUSED(itemIndex); + hideToolTip(); - if (itemIndex < 0) { - // Trigger the history navigation only when clicking on the viewport: - // Above an item the XButtons provide a simple way to select items in - // the singleClick mode. - if (buttons & Qt::XButton1) { - emit goBackRequested(); - } else if (buttons & Qt::XButton2) { - emit goForwardRequested(); - } + // TODO: Qt5: Replace Qt::XButton1 by Qt::BackButton and Qt::XButton2 by Qt::ForwardButton + if (buttons & Qt::XButton1) { + emit goBackRequested(); + } else if (buttons & Qt::XButton2) { + emit goForwardRequested(); } } From d980dccb126a298b6519bef8a6657324347a38b4 Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Mon, 3 Mar 2014 22:06:56 +0100 Subject: [PATCH 08/29] Add a hover effect for the selection toggle. FIXED-IN: 4.13.0 REVIEW: 116028 BUG: 299328 --- src/kitemviews/kitemlistcontroller.cpp | 5 +++ src/kitemviews/kitemlistwidget.cpp | 7 ++++ src/kitemviews/kitemlistwidget.h | 2 ++ .../private/kitemlistselectiontoggle.cpp | 33 +++++++------------ .../private/kitemlistselectiontoggle.h | 4 +-- 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index 61337d166..8e2ef5ef3 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -951,8 +951,13 @@ bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent* event, const if (newHoveredWidget) { newHoveredWidget->setHovered(true); + const QPointF mappedPos = newHoveredWidget->mapFromItem(m_view, pos); + newHoveredWidget->setHoverPosition(mappedPos); emit itemHovered(newHoveredWidget->index()); } + } else if (oldHoveredWidget) { + const QPointF mappedPos = oldHoveredWidget->mapFromItem(m_view, pos); + oldHoveredWidget->setHoverPosition(mappedPos); } return false; diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp index 85cd70c43..44754a694 100644 --- a/src/kitemviews/kitemlistwidget.cpp +++ b/src/kitemviews/kitemlistwidget.cpp @@ -279,6 +279,13 @@ bool KItemListWidget::isHovered() const return m_hovered; } +void KItemListWidget::setHoverPosition(const QPointF& pos) +{ + if (m_selectionToggle) { + m_selectionToggle->setHovered(m_selectionToggle->contains(pos)); + } +} + void KItemListWidget::setAlternateBackground(bool enable) { if (m_alternateBackground != enable) { diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h index 954629ddd..cfb9155eb 100644 --- a/src/kitemviews/kitemlistwidget.h +++ b/src/kitemviews/kitemlistwidget.h @@ -108,6 +108,8 @@ public: void setHovered(bool hovered); bool isHovered() const; + void setHoverPosition(const QPointF& pos); + void setAlternateBackground(bool enable); bool alternateBackground() const; diff --git a/src/kitemviews/private/kitemlistselectiontoggle.cpp b/src/kitemviews/private/kitemlistselectiontoggle.cpp index 6bbf3c2ec..accbe5181 100644 --- a/src/kitemviews/private/kitemlistselectiontoggle.cpp +++ b/src/kitemviews/private/kitemlistselectiontoggle.cpp @@ -30,7 +30,6 @@ KItemListSelectionToggle::KItemListSelectionToggle(QGraphicsItem* parent) : m_checked(false), m_hovered(false) { - setAcceptHoverEvents(true); } KItemListSelectionToggle::~KItemListSelectionToggle() @@ -51,6 +50,15 @@ bool KItemListSelectionToggle::isChecked() const return m_checked; } +void KItemListSelectionToggle::setHovered(bool hovered) +{ + if (m_hovered != hovered) { + m_hovered = hovered; + m_pixmap = QPixmap(); + update(); + } +} + void KItemListSelectionToggle::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(option); @@ -65,20 +73,6 @@ void KItemListSelectionToggle::paint(QPainter* painter, const QStyleOptionGraphi painter->drawPixmap(x, y, m_pixmap); } -void KItemListSelectionToggle::hoverEnterEvent(QGraphicsSceneHoverEvent* event) -{ - QGraphicsWidget::hoverEnterEvent(event); - m_hovered = true; - m_pixmap = QPixmap(); -} - -void KItemListSelectionToggle::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) -{ - QGraphicsWidget::hoverLeaveEvent(event); - m_hovered = false; - m_pixmap = QPixmap(); -} - void KItemListSelectionToggle::resizeEvent(QGraphicsSceneResizeEvent* event) { QGraphicsWidget::resizeEvent(event); @@ -97,12 +91,9 @@ void KItemListSelectionToggle::resizeEvent(QGraphicsSceneResizeEvent* event) void KItemListSelectionToggle::updatePixmap() { - const char* icon = m_checked ? "list-remove" : "list-add"; - m_pixmap = KIconLoader::global()->loadIcon(QLatin1String(icon), KIconLoader::NoGroup, iconSize()); - - if (m_hovered) { - KIconLoader::global()->iconEffect()->apply(m_pixmap, KIconLoader::Desktop, KIconLoader::ActiveState); - } + const QString icon = m_checked ? "list-remove" : "list-add"; + const KIconLoader::States state = m_hovered ? KIconLoader::ActiveState : KIconLoader::DisabledState; + m_pixmap = KIconLoader::global()->loadIcon(icon, KIconLoader::Desktop, iconSize(), state); } int KItemListSelectionToggle::iconSize() const diff --git a/src/kitemviews/private/kitemlistselectiontoggle.h b/src/kitemviews/private/kitemlistselectiontoggle.h index ba29293f6..758dc63bb 100644 --- a/src/kitemviews/private/kitemlistselectiontoggle.h +++ b/src/kitemviews/private/kitemlistselectiontoggle.h @@ -41,11 +41,11 @@ public: void setChecked(bool checked); bool isChecked() const; + void setHovered(bool hovered); + virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0); protected: - virtual void hoverEnterEvent(QGraphicsSceneHoverEvent* event); - virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event); virtual void resizeEvent(QGraphicsSceneResizeEvent* event); private: From 8b556c8279a7606d21cf74804cfb937b21e561cb Mon Sep 17 00:00:00 2001 From: l10n daemon script Date: Tue, 4 Mar 2014 05:44:46 +0000 Subject: [PATCH 09/29] SVN_SILENT made messages (.desktop file) --- src/dolphinpart.desktop | 1 + src/settings/kcm/kcmdolphingeneral.desktop | 1 + src/settings/kcm/kcmdolphinnavigation.desktop | 1 + src/settings/kcm/kcmdolphinservices.desktop | 1 + src/settings/kcm/kcmdolphinviewmodes.desktop | 1 + 5 files changed, 5 insertions(+) diff --git a/src/dolphinpart.desktop b/src/dolphinpart.desktop index 10339e4bc..bdc3b929d 100644 --- a/src/dolphinpart.desktop +++ b/src/dolphinpart.desktop @@ -213,6 +213,7 @@ Name[gl]=Compacto Name[he]=מרוכז Name[hu]=Kompakt Name[ia]=Compacte +Name[is]=Þjappað Name[it]=Compatta Name[kk]=Ықшамды Name[km]=តូច​ល្មម diff --git a/src/settings/kcm/kcmdolphingeneral.desktop b/src/settings/kcm/kcmdolphingeneral.desktop index 5a79ad619..b0620ac74 100644 --- a/src/settings/kcm/kcmdolphingeneral.desktop +++ b/src/settings/kcm/kcmdolphingeneral.desktop @@ -314,6 +314,7 @@ X-KDE-Keywords[gl]=xestor de ficheiros X-KDE-Keywords[he]=מנהל קבצים X-KDE-Keywords[hu]=fájlkezelő X-KDE-Keywords[ia]=gerente de file +X-KDE-Keywords[is]=skráastjóri X-KDE-Keywords[it]=gestore dei file X-KDE-Keywords[kk]=file manager X-KDE-Keywords[km]=កម្មវិធី​គ្រប់គ្រង​ឯកសារ diff --git a/src/settings/kcm/kcmdolphinnavigation.desktop b/src/settings/kcm/kcmdolphinnavigation.desktop index 4cf793a35..8636058cd 100644 --- a/src/settings/kcm/kcmdolphinnavigation.desktop +++ b/src/settings/kcm/kcmdolphinnavigation.desktop @@ -314,6 +314,7 @@ X-KDE-Keywords[gl]=xestor de ficheiros X-KDE-Keywords[he]=מנהל קבצים X-KDE-Keywords[hu]=fájlkezelő X-KDE-Keywords[ia]=gerente de file +X-KDE-Keywords[is]=skráastjóri X-KDE-Keywords[it]=gestore dei file X-KDE-Keywords[kk]=file manager X-KDE-Keywords[km]=កម្មវិធី​គ្រប់គ្រង​ឯកសារ diff --git a/src/settings/kcm/kcmdolphinservices.desktop b/src/settings/kcm/kcmdolphinservices.desktop index aa93e6d28..34867305a 100644 --- a/src/settings/kcm/kcmdolphinservices.desktop +++ b/src/settings/kcm/kcmdolphinservices.desktop @@ -263,6 +263,7 @@ X-KDE-Keywords[gl]=xestor de ficheiros X-KDE-Keywords[he]=מנהל קבצים X-KDE-Keywords[hu]=fájlkezelő X-KDE-Keywords[ia]=gerente de file +X-KDE-Keywords[is]=skráastjóri X-KDE-Keywords[it]=gestore dei file X-KDE-Keywords[kk]=file manager X-KDE-Keywords[km]=កម្មវិធី​គ្រប់គ្រង​ឯកសារ diff --git a/src/settings/kcm/kcmdolphinviewmodes.desktop b/src/settings/kcm/kcmdolphinviewmodes.desktop index ce8401228..a4b4e058b 100644 --- a/src/settings/kcm/kcmdolphinviewmodes.desktop +++ b/src/settings/kcm/kcmdolphinviewmodes.desktop @@ -312,6 +312,7 @@ X-KDE-Keywords[gl]=xestor de ficheiros X-KDE-Keywords[he]=מנהל קבצים X-KDE-Keywords[hu]=fájlkezelő X-KDE-Keywords[ia]=gerente de file +X-KDE-Keywords[is]=skráastjóri X-KDE-Keywords[it]=gestore dei file X-KDE-Keywords[kk]=file manager X-KDE-Keywords[km]=កម្មវិធី​គ្រប់គ្រង​ឯកសារ From 08b8d28154df302a1ed0e5b3abd54e823441b72c Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Wed, 5 Mar 2014 08:43:58 +0100 Subject: [PATCH 10/29] Remove some unused functions REVIEW: 116562 --- src/views/dolphinview.cpp | 10 ---------- src/views/dolphinview.h | 14 -------------- src/views/renamedialog.cpp | 9 --------- 3 files changed, 33 deletions(-) diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index 9f5f48a86..21235e5e7 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -1354,16 +1354,6 @@ void DolphinView::calculateItemCount(int& fileCount, } } -void DolphinView::showHoverInformation(const KFileItem& item) -{ - emit requestItemInfo(item); -} - -void DolphinView::clearHoverInformation() -{ - emit requestItemInfo(KFileItem()); -} - void DolphinView::slotDeleteFileFinished(KJob* job) { if (job->error() == 0) { diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h index 3731464a3..06c09edc3 100644 --- a/src/views/dolphinview.h +++ b/src/views/dolphinview.h @@ -613,20 +613,6 @@ private slots: */ void updateSortFoldersFirst(bool foldersFirst); - /** - * Updates the status bar to show hover information for the - * item \a item. If currently other items are selected, - * no hover information is shown. - * @see DolphinView::clearHoverInformation() - */ - void showHoverInformation(const KFileItem& item); - - /** - * Clears the hover information shown in the status bar. - * @see DolphinView::showHoverInformation(). - */ - void clearHoverInformation(); - /** * Indicates in the status bar that the delete operation * of the job \a job has been finished. diff --git a/src/views/renamedialog.cpp b/src/views/renamedialog.cpp index d8dbd7749..5c0ae6126 100644 --- a/src/views/renamedialog.cpp +++ b/src/views/renamedialog.cpp @@ -30,15 +30,6 @@ #include #include -/** - * Helper function for sorting items with qSort() in - * DolphinView::renameSelectedItems(). - */ -bool lessThan(const KFileItem& item1, const KFileItem& item2) -{ - return KStringHandler::naturalCompare(item1.name(), item2.name()) < 0; -} - RenameDialog::RenameDialog(QWidget *parent, const KFileItemList& items) : KDialog(parent), m_renameOneItem(false), From 6747241934218c6e7529e94598d1f16cb87951ff Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Wed, 5 Mar 2014 10:48:33 +0100 Subject: [PATCH 11/29] 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 +++++++++++ src/kitemviews/kfileitemlistwidget.h | 2 ++ src/kitemviews/kstandarditemlistwidget.cpp | 36 +++++++++++++++++++--- src/kitemviews/kstandarditemlistwidget.h | 12 ++++++++ 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp index 688a4da08..fe8c7e997 100644 --- a/src/kitemviews/kfileitemlistwidget.cpp +++ b/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/src/kitemviews/kfileitemlistwidget.h b/src/kitemviews/kfileitemlistwidget.h index 1d7bc7f01..8e8958b16 100644 --- a/src/kitemviews/kfileitemlistwidget.h +++ b/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/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index 9f7b26959..d8b5ad908 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/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/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h index ca198c36b..ba426d054 100644 --- a/src/kitemviews/kstandarditemlistwidget.h +++ b/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 773d505493773575df933babbf46eacc8f85316f Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Tue, 11 Mar 2014 09:07:23 +0100 Subject: [PATCH 12/29] 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 --- src/kitemviews/private/kitemlistviewanimation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kitemviews/private/kitemlistviewanimation.cpp b/src/kitemviews/private/kitemlistviewanimation.cpp index e347c5bb1..5a00c8c3a 100644 --- a/src/kitemviews/private/kitemlistviewanimation.cpp +++ b/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)); From d803ecec242cc4b84f89b396f216d2d33439f810 Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Sun, 16 Mar 2014 18:02:43 +0100 Subject: [PATCH 13/29] Use MIME type inheritance to find out if a file contains text Before this commit, filenamesearch checked if a file's MIME type begins with "text/" to determine if its content can be searched. This prevented that text inside shell scripts is found. BUG: 332143 REVIEW: 116805 FIXED-IN: 4.12.4 --- src/search/filenamesearchprotocol.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/search/filenamesearchprotocol.cpp b/src/search/filenamesearchprotocol.cpp index 4d6f59fa4..fd7f09a88 100644 --- a/src/search/filenamesearchprotocol.cpp +++ b/src/search/filenamesearchprotocol.cpp @@ -91,8 +91,11 @@ void FileNameSearchProtocol::searchDirectory(const KUrl& directory) bool addItem = false; if (!m_regExp || item.name().contains(*m_regExp)) { addItem = true; - } else if (m_checkContent && item.mimetype().startsWith(QLatin1String("text/"))) { + } else if (m_checkContent && item.determineMimeType()->is(QLatin1String("text/plain"))) { + qDebug() << "### Checking" << item; addItem = contentContainsPattern(item.url()); + } else { + qDebug() << "### NOT Checking" << item; } if (addItem) { From 53c48af2360f48bb06a8ac8c49f20de8b00ae568 Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Mon, 17 Mar 2014 19:49:32 +0100 Subject: [PATCH 14/29] Add the Baloo::Term to the Baloo:Query in DolphinSearchBox::balooUrlForSearching(). REVIEW: 116837 FIXED-IN: 4.13.0 --- src/search/dolphinsearchbox.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp index c178c43c7..c78ab78dc 100644 --- a/src/search/dolphinsearchbox.cpp +++ b/src/search/dolphinsearchbox.cpp @@ -455,6 +455,8 @@ KUrl DolphinSearchBox::balooUrlForSearching() const query.addCustomOption("includeFolder", m_searchPath.toLocalFile()); } + query.setTerm(term); + return query.toSearchUrl(i18nc("@title UDS_DISPLAY_NAME for a KIO directory listing. %1 is the query the user entered.", "Query Results from '%1'", text)); #else From 466868efa81ea7597f96d06ff1e2015f4ff8169a Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Wed, 19 Mar 2014 15:44:35 +0100 Subject: [PATCH 15/29] Dolphin Facet Widgets: Implement date based filtering This required changes in Baloo which require reindexing. Since the storage location has changed for Beta 3 everyone should be re-indexing everything, so it won't be a problem. --- src/search/dolphinfacetswidget.cpp | 31 ++++++++++++++++++------------ src/search/dolphinsearchbox.cpp | 2 +- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/search/dolphinfacetswidget.cpp b/src/search/dolphinfacetswidget.cpp index b7315a01c..aec84d321 100644 --- a/src/search/dolphinfacetswidget.cpp +++ b/src/search/dolphinfacetswidget.cpp @@ -111,6 +111,9 @@ DolphinFacetsWidget::~DolphinFacetsWidget() #ifdef HAVE_BALOO Baloo::Term DolphinFacetsWidget::ratingTerm() const { + Baloo::Term ratingTerm; + Baloo::Term modifiedTerm; + if (!m_anyRating->isChecked()) { int stars = 1; // represents m_oneOrMore if (m_twoOrMore->isChecked()) { @@ -124,15 +127,9 @@ Baloo::Term DolphinFacetsWidget::ratingTerm() const } const int rating = stars * 2; - - Baloo::Term term("rating", rating, Baloo::Term::GreaterEqual); - return term; + ratingTerm = Baloo::Term("rating", rating, Baloo::Term::GreaterEqual); } - return Baloo::Term(); - - /* - // FIXME: Handle date time filters if (!m_anytime->isChecked()) { QDate date = QDate::currentDate(); // represents m_today if (m_yesterday->isChecked()) { @@ -145,12 +142,22 @@ Baloo::Term DolphinFacetsWidget::ratingTerm() const date = date.addDays(1 - date.dayOfYear()); } - Nepomuk2::Query::ComparisonTerm term(Nepomuk2::Vocabulary::NIE::lastModified(), - Nepomuk2::Query::LiteralTerm(QDateTime(date)), - Nepomuk2::Query::ComparisonTerm::GreaterOrEqual); - andTerm.addSubTerm(term); + modifiedTerm = Baloo::Term("modified", date, Baloo::Term::GreaterEqual); } - */ + + if (ratingTerm.isValid() && modifiedTerm.isValid()) { + Baloo::Term term(Baloo::Term::And); + term.addSubTerm(ratingTerm); + term.addSubTerm(modifiedTerm); + + return term; + } else if (modifiedTerm.isValid()) { + return modifiedTerm; + } else if (ratingTerm.isValid()) { + return ratingTerm; + } + + return Baloo::Term(); } QStringList DolphinFacetsWidget::facetTypes() const diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp index c78ab78dc..e6b738a93 100644 --- a/src/search/dolphinsearchbox.cpp +++ b/src/search/dolphinsearchbox.cpp @@ -448,7 +448,7 @@ KUrl DolphinSearchBox::balooUrlForSearching() const if (m_contentButton->isChecked()) { query.setSearchString(text); } else { - term.addSubTerm(Baloo::Term("filename", text)); + term.addSubTerm(Baloo::Term(QLatin1String("filename"), text)); } if (m_fromHereButton->isChecked()) { From 3e576a16597b154a137604efd16323e1a1338f60 Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Mon, 24 Mar 2014 10:37:15 +0100 Subject: [PATCH 16/29] DolphinSearchBox: Only search through filename is search text is not empty --- src/search/dolphinsearchbox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp index e6b738a93..9aba4c954 100644 --- a/src/search/dolphinsearchbox.cpp +++ b/src/search/dolphinsearchbox.cpp @@ -447,7 +447,7 @@ KUrl DolphinSearchBox::balooUrlForSearching() const if (m_contentButton->isChecked()) { query.setSearchString(text); - } else { + } else if (!text.isEmpty()) { term.addSubTerm(Baloo::Term(QLatin1String("filename"), text)); } From 76e5fd48349bb521e5403d694f1dc45f2d22d1ae Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Mon, 24 Mar 2014 10:48:53 +0100 Subject: [PATCH 17/29] Dolphin Facet Widget: Convert type selection into radio buttons They were previously checkboxes. Most files cannot have more than 1 type considering that the exposed types were "Document", "Image", "Video" and "Audio". Also, it is not very simple in baloo to search through ORs for types. Not through the exposed API anyway. REVIEW: 117015 --- src/search/dolphinfacetswidget.cpp | 43 +++++++++++------------------- src/search/dolphinfacetswidget.h | 18 +++++-------- src/search/dolphinsearchbox.cpp | 2 +- 3 files changed, 23 insertions(+), 40 deletions(-) diff --git a/src/search/dolphinfacetswidget.cpp b/src/search/dolphinfacetswidget.cpp index aec84d321..3824eb94c 100644 --- a/src/search/dolphinfacetswidget.cpp +++ b/src/search/dolphinfacetswidget.cpp @@ -46,13 +46,16 @@ DolphinFacetsWidget::DolphinFacetsWidget(QWidget* parent) : m_fourOrMore(0), m_maxRating(0) { - m_documents = createCheckBox(i18nc("@option:check", "Documents")); - m_images = createCheckBox(i18nc("@option:check", "Images")); - m_audio = createCheckBox(i18nc("@option:check", "Audio Files")); - m_videos = createCheckBox(i18nc("@option:check", "Videos")); + QButtonGroup* filetypeGroup = new QButtonGroup(this); + m_anyType = createRadioButton(i18nc("@option:check", "Any"), filetypeGroup); + m_documents = createRadioButton(i18nc("@option:check", "Documents"), filetypeGroup); + m_images = createRadioButton(i18nc("@option:check", "Images"), filetypeGroup); + m_audio = createRadioButton(i18nc("@option:check", "Audio Files"), filetypeGroup); + m_videos = createRadioButton(i18nc("@option:check", "Videos"), filetypeGroup); QVBoxLayout* typeLayout = new QVBoxLayout(); typeLayout->setSpacing(0); + typeLayout->addWidget(m_anyType); typeLayout->addWidget(m_documents); typeLayout->addWidget(m_images); typeLayout->addWidget(m_audio); @@ -160,38 +163,24 @@ Baloo::Term DolphinFacetsWidget::ratingTerm() const return Baloo::Term(); } -QStringList DolphinFacetsWidget::facetTypes() const +QString DolphinFacetsWidget::facetType() const { - QStringList types; if (m_documents->isChecked()) { - types << "Document"; + return QLatin1String("Document"); + } else if (m_images->isChecked()) { + return QLatin1String("Image"); + } else if (m_audio->isChecked()) { + return QLatin1String("Audio"); + } else if (m_videos->isChecked()) { + return QLatin1String("Video"); } - if (m_images->isChecked()) { - types << "Image"; - } - - if (m_audio->isChecked()) { - types << "Audio"; - } - - if (m_videos->isChecked()) { - types << "Video"; - } - - return types; + return QString(); } #endif -QCheckBox* DolphinFacetsWidget::createCheckBox(const QString& text) -{ - QCheckBox* checkBox = new QCheckBox(text); - connect(checkBox, SIGNAL(clicked()), this, SIGNAL(facetChanged())); - return checkBox; -} - QRadioButton* DolphinFacetsWidget::createRadioButton(const QString& text, QButtonGroup* group) { diff --git a/src/search/dolphinfacetswidget.h b/src/search/dolphinfacetswidget.h index 526fe1c79..1fd1683da 100644 --- a/src/search/dolphinfacetswidget.h +++ b/src/search/dolphinfacetswidget.h @@ -57,20 +57,13 @@ public: #ifdef HAVE_BALOO Baloo::Term ratingTerm() const; - QStringList facetTypes() const; + QString facetType() const; #endif signals: void facetChanged(); private: - /** - * @return New checkbox which is connected to the - * slotFacedChanged() slot whenever it has - * been toggled. - */ - QCheckBox* createCheckBox(const QString& text); - /** * @return New radiobutton which is connected to the * slotFacedChanged() slot whenever it has @@ -80,10 +73,11 @@ private: QButtonGroup* group); private: - QCheckBox* m_documents; - QCheckBox* m_images; - QCheckBox* m_audio; - QCheckBox* m_videos; + QRadioButton* m_anyType; + QRadioButton* m_documents; + QRadioButton* m_images; + QRadioButton* m_audio; + QRadioButton* m_videos; QRadioButton* m_anytime; QRadioButton* m_today; diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp index 9aba4c954..0a7056682 100644 --- a/src/search/dolphinsearchbox.cpp +++ b/src/search/dolphinsearchbox.cpp @@ -436,7 +436,7 @@ KUrl DolphinSearchBox::balooUrlForSearching() const Baloo::Query query; query.addType("File"); - query.addTypes(m_facetsWidget->facetTypes()); + query.addType(m_facetsWidget->facetType()); Baloo::Term term(Baloo::Term::And); From 5c2f52e62a7cfef961c2f67585c84c04b4193370 Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Tue, 25 Mar 2014 23:39:47 +0100 Subject: [PATCH 18/29] Set m_anyType as checked by default. CCMAIL: me@vhanda.in --- src/search/dolphinfacetswidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/search/dolphinfacetswidget.cpp b/src/search/dolphinfacetswidget.cpp index 3824eb94c..efbefc1f6 100644 --- a/src/search/dolphinfacetswidget.cpp +++ b/src/search/dolphinfacetswidget.cpp @@ -103,6 +103,7 @@ DolphinFacetsWidget::DolphinFacetsWidget(QWidget* parent) : topLayout->addLayout(ratingLayout); topLayout->addStretch(); + m_anyType->setChecked(true); m_anytime->setChecked(true); m_anyRating->setChecked(true); } From 5d63b9a111e6ae76ff7b9f5ba9cd26be873aa115 Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Fri, 28 Mar 2014 18:48:48 +0100 Subject: [PATCH 19/29] When you open a new tab while the search mode is enabled, the newly opened tab also starts the same search (Because new tab is opened with the current view url), but the search box is in read-only mode. So you cannot close the search bar nor edit the search text. This patch fixes this by parsing the search url. The value of the "search" parameter is used as search text and the value of the "url" parameter is used for the search path ("root" folder for the search when "Search from here" mode is enabled). In case of Baloo search urls, we use Baloo::Query::fromSearchUrl. Removed everything related to read only mode in DolphinSearchBox, not needed anymore. REVIEW: 111968 BUG: 311950 FIXED-IN: 4.13.0 --- src/dolphinviewcontainer.cpp | 30 ++------ src/search/dolphinfacetswidget.cpp | 109 +++++++++++++++++++++++++++++ src/search/dolphinfacetswidget.h | 8 +++ src/search/dolphinsearchbox.cpp | 82 +++++++++++++--------- src/search/dolphinsearchbox.h | 25 +++---- 5 files changed, 184 insertions(+), 70 deletions(-) diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp index 768fd5ef9..57452b9e4 100644 --- a/src/dolphinviewcontainer.cpp +++ b/src/dolphinviewcontainer.cpp @@ -314,36 +314,18 @@ void DolphinViewContainer::setSearchModeEnabled(bool enabled) m_urlNavigator->setVisible(!enabled); if (enabled) { - KUrl url = m_urlNavigator->locationUrl(); - m_searchBox->setText(QString()); - m_searchBox->setReadOnly(isSearchUrl(url), url); - - // Remember the most recent non-search URL as search path - // of the search-box, so that it can be restored - // when switching back to the URL navigator. - int index = m_urlNavigator->historyIndex(); - const int historySize = m_urlNavigator->historySize(); - while (isSearchUrl(url) && (index < historySize)) { - ++index; - url = m_urlNavigator->locationUrl(index); - } - - if (!isSearchUrl(url)) { - m_searchBox->setSearchPath(url); - } + const KUrl& locationUrl = m_urlNavigator->locationUrl(); + m_searchBox->fromSearchUrl(locationUrl); } else { m_view->setViewPropertiesContext(QString()); // Restore the URL for the URL navigator. If Dolphin has been // started with a search-URL, the home URL is used as fallback. - const KUrl url = m_searchBox->searchPath(); - if (url.isValid() && !url.isEmpty()) { - if (isSearchUrl(url)) { - m_urlNavigator->goHome(); - } else { - m_urlNavigator->setLocationUrl(url); - } + KUrl url = m_searchBox->searchPath(); + if (url.isEmpty() || !url.isValid() || isSearchUrl(url)) { + url = GeneralSettings::self()->homeUrl(); } + m_urlNavigator->setLocationUrl(url); } } diff --git a/src/search/dolphinfacetswidget.cpp b/src/search/dolphinfacetswidget.cpp index efbefc1f6..f20ae68d5 100644 --- a/src/search/dolphinfacetswidget.cpp +++ b/src/search/dolphinfacetswidget.cpp @@ -179,8 +179,117 @@ QString DolphinFacetsWidget::facetType() const return QString(); } +bool DolphinFacetsWidget::isRatingTerm(const Baloo::Term& term) const +{ + const QList subTerms = term.subTerms(); + if (subTerms.isEmpty()) { + // If term has no sub terms, then the term itself is either a "rating" term + // or a "modified" term. + return term.property() == QLatin1String("modified") || + term.property() == QLatin1String("rating"); + + } else if (subTerms.size() == 2) { + // If term has sub terms, then the sub terms are always "rating" and "modified" terms. + + QStringList properties; + foreach (const Baloo::Term& subTerm, subTerms) { + properties << subTerm.property(); + } + + return properties.contains(QLatin1String("modified")) && + properties.contains(QLatin1String("rating")); + } + + return false; +} + +void DolphinFacetsWidget::setRatingTerm(const Baloo::Term& term) +{ + // If term has sub terms, then the sub terms are always "rating" and "modified" terms. + // If term has no sub terms, then the term itself is either a "rating" term or a "modified" + // term. To avoid code duplication we add term to subTerms list, if the list is empty. + QList subTerms = term.subTerms(); + if (subTerms.isEmpty()) { + subTerms << term; + } + + foreach (const Baloo::Term& subTerm, subTerms) { + const QString property = subTerm.property(); + + if (property == QLatin1String("modified")) { + const QDate date = subTerm.value().toDate(); + setTimespan(date); + } else if (property == QLatin1String("rating")) { + const int stars = subTerm.value().toInt() / 2; + setRating(stars); + } + } +} + #endif +void DolphinFacetsWidget::setFacetType(const QString& type) +{ + if (type == QLatin1String("Document")) { + m_documents->setChecked(true); + } else if (type == QLatin1String("Image")) { + m_images->setChecked(true); + } else if (type == QLatin1String("Audio")) { + m_audio->setChecked(true); + } else if (type == QLatin1String("Video")) { + m_videos->setChecked(true); + } else { + m_anyType->setChecked(true); + } +} + +void DolphinFacetsWidget::setRating(const int stars) +{ + switch (stars) { + case 5: + m_maxRating->setChecked(true); + break; + + case 4: + m_fourOrMore->setChecked(true); + break; + + case 3: + m_threeOrMore->setChecked(true); + break; + + case 2: + m_twoOrMore->setChecked(true); + break; + + case 1: + m_oneOrMore->setChecked(true); + break; + + default: + m_anyRating->setChecked(true); + } +} + +void DolphinFacetsWidget::setTimespan(const QDate& date) +{ + const QDate currentDate = QDate::currentDate(); + const int days = date.daysTo(currentDate); + + if (days <= 0) { + m_today->setChecked(true); + } else if (days <= 1) { + m_yesterday->setChecked(true); + } else if (days <= currentDate.dayOfWeek()) { + m_thisWeek->setChecked(true); + } else if (days <= currentDate.day()) { + m_thisMonth->setChecked(true); + } else if (days <= currentDate.dayOfYear()) { + m_thisYear->setChecked(true); + } else { + m_anytime->setChecked(true); + } +} QRadioButton* DolphinFacetsWidget::createRadioButton(const QString& text, QButtonGroup* group) diff --git a/src/search/dolphinfacetswidget.h b/src/search/dolphinfacetswidget.h index 1fd1683da..8f6d8eb6f 100644 --- a/src/search/dolphinfacetswidget.h +++ b/src/search/dolphinfacetswidget.h @@ -58,12 +58,20 @@ public: #ifdef HAVE_BALOO Baloo::Term ratingTerm() const; QString facetType() const; + + bool isRatingTerm(const Baloo::Term& term) const; + void setRatingTerm(const Baloo::Term& term); #endif + void setFacetType(const QString& type); + signals: void facetChanged(); private: + void setRating(const int stars); + void setTimespan(const QDate& date); + /** * @return New radiobutton which is connected to the * slotFacedChanged() slot whenever it has diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp index 0a7056682..46ca01a4c 100644 --- a/src/search/dolphinsearchbox.cpp +++ b/src/search/dolphinsearchbox.cpp @@ -49,7 +49,6 @@ DolphinSearchBox::DolphinSearchBox(QWidget* parent) : QWidget(parent), m_startedSearching(false), - m_readOnly(false), m_active(true), m_topLayout(0), m_searchLabel(0), @@ -63,7 +62,6 @@ DolphinSearchBox::DolphinSearchBox(QWidget* parent) : m_facetsToggleButton(0), m_facetsWidget(0), m_searchPath(), - m_readOnlyQuery(), m_startSearchTimer(0) { } @@ -102,7 +100,7 @@ void DolphinSearchBox::setSearchPath(const KUrl& url) const QString elidedLocation = metrics.elidedText(location, Qt::ElideMiddle, maxWidth); m_fromHereButton->setText(i18nc("action:button", "From Here (%1)", elidedLocation)); - const bool showSearchFromButtons = url.isLocalFile() && !m_readOnly; + const bool showSearchFromButtons = url.isLocalFile(); m_separator->setVisible(showSearchFromButtons); m_fromHereButton->setVisible(showSearchFromButtons); m_everywhereButton->setVisible(showSearchFromButtons); @@ -152,23 +150,24 @@ KUrl DolphinSearchBox::urlForSearching() const return url; } -void DolphinSearchBox::selectAll() +void DolphinSearchBox::fromSearchUrl(const KUrl& url) { - m_searchInput->selectAll(); -} - -void DolphinSearchBox::setReadOnly(bool readOnly, const KUrl& query) -{ - if (m_readOnly != readOnly || m_readOnlyQuery != query) { - m_readOnly = readOnly; - m_readOnlyQuery = query; - applyReadOnlyState(); + if (url.protocol() == "baloosearch") { + fromBalooSearchUrl(url); + } else if (url.protocol() == "filenamesearch") { + const QMap& queryItems = url.queryItems(); + setText(queryItems.value("search")); + setSearchPath(queryItems.value("url")); + m_contentButton->setChecked(queryItems.value("checkContent") == "yes"); + } else { + setText(QString()); + setSearchPath(url); } } -bool DolphinSearchBox::isReadOnly() const +void DolphinSearchBox::selectAll() { - return m_readOnly; + m_searchInput->selectAll(); } void DolphinSearchBox::setActive(bool active) @@ -426,7 +425,6 @@ void DolphinSearchBox::init() connect(m_startSearchTimer, SIGNAL(timeout()), this, SLOT(emitSearchRequest())); updateFacetsToggleButton(); - applyReadOnlyState(); } KUrl DolphinSearchBox::balooUrlForSearching() const @@ -464,26 +462,46 @@ KUrl DolphinSearchBox::balooUrlForSearching() const #endif } -void DolphinSearchBox::applyReadOnlyState() +void DolphinSearchBox::fromBalooSearchUrl(const KUrl& url) { #ifdef HAVE_BALOO - if (m_readOnly) { - m_searchLabel->setText(Baloo::Query::titleFromQueryUrl(m_readOnlyQuery)); + const Baloo::Query query = Baloo::Query::fromSearchUrl(url); + const Baloo::Term term = query.term(); + + // Block all signals to avoid unnecessary "searchRequest" signals + // while we adjust the search text and the facet widget. + blockSignals(true); + + const QVariantHash customOptions = query.customOptions(); + if (customOptions.contains("includeFolder")) { + setSearchPath(customOptions.value("includeFolder").toString()); } else { -#else - { + setSearchPath(QDir::homePath()); + } + + if (!query.searchString().isEmpty()) { + setText(query.searchString()); + } + + QStringList types = query.types(); + types.removeOne("File"); // We are only interested in facet widget types + if (!types.isEmpty()) { + m_facetsWidget->setFacetType(types.first()); + } + + foreach (const Baloo::Term& subTerm, term.subTerms()) { + const QString property = subTerm.property(); + + if (property == QLatin1String("filename")) { + setText(subTerm.value().toString()); + } else if (m_facetsWidget->isRatingTerm(subTerm)) { + m_facetsWidget->setRatingTerm(subTerm); + } + } + + m_startSearchTimer->stop(); + blockSignals(false); #endif - m_searchLabel->setText(i18nc("@label:textbox", "Find:")); - } - - m_searchInput->setVisible(!m_readOnly); - m_optionsScrollArea->setVisible(!m_readOnly); - - if (m_readOnly) { - m_facetsWidget->hide(); - } else { - m_facetsWidget->setVisible(SearchSettings::showFacetsWidget()); - } } void DolphinSearchBox::updateFacetsToggleButton() diff --git a/src/search/dolphinsearchbox.h b/src/search/dolphinsearchbox.h index 6dc09f19e..53b12ffab 100644 --- a/src/search/dolphinsearchbox.h +++ b/src/search/dolphinsearchbox.h @@ -71,22 +71,17 @@ public: /** @return URL that will start the searching of files. */ KUrl urlForSearching() const; + /** + * Extracts information from the given search \a url to + * initialize the search box properly. + */ + void fromSearchUrl(const KUrl& url); + /** * Selects the whole text of the search box. */ void selectAll(); - /** - * @param readOnly If set to true the searchbox cannot be modified - * by the user and acts as visual indicator for - * an externally triggered search query. - * @param query If readOnly is true this URL will be used - * to show a human readable information about the - * query. - */ - void setReadOnly(bool readOnly, const KUrl& query = KUrl()); - bool isReadOnly() const; - /** * Set the search box to the active mode, if \a active * is true. The active mode is default. The inactive mode only differs @@ -155,12 +150,15 @@ private: */ KUrl balooUrlForSearching() const; - void applyReadOnlyState(); + /** + * Extracts information from the given Baloo search \a url to + * initialize the search box properly. + */ + void fromBalooSearchUrl(const KUrl& url); void updateFacetsToggleButton(); private: bool m_startedSearching; - bool m_readOnly; bool m_active; QVBoxLayout* m_topLayout; @@ -177,7 +175,6 @@ private: DolphinFacetsWidget* m_facetsWidget; KUrl m_searchPath; - KUrl m_readOnlyQuery; QTimer* m_startSearchTimer; }; From 05acaf934579d4be6a3446dc7c73b7cb95ca0cc0 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Mon, 31 Mar 2014 01:15:27 +0200 Subject: [PATCH 20/29] Make this thing compile CCMAIL: emmanuelpescosta099@gmail.com --- src/search/dolphinfacetswidget.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/search/dolphinfacetswidget.h b/src/search/dolphinfacetswidget.h index 8f6d8eb6f..757dcd482 100644 --- a/src/search/dolphinfacetswidget.h +++ b/src/search/dolphinfacetswidget.h @@ -29,6 +29,7 @@ class QButtonGroup; class QCheckBox; +class QDate; class QRadioButton; /** From 0d191c9da27a7ba7d017b6bb8eee39e83088d2c6 Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Thu, 3 Apr 2014 09:03:47 +0200 Subject: [PATCH 21/29] KDirectoryContentsCounter: do not delete currently active worker objects Before this patch, the destructor of KDirectoryContentsCounter might delete the worker object, which lives in another thread, while one of its methods was still being executed. This could cause a crash. Only if the destroyed KDirectoryContentsCounter was the last one, the worker thread was stopped, and the destructor waited until all workers are done. BUG: 332767 FIXED-IN: 4.13.0 REVIEW: 117209 --- .../private/kdirectorycontentscounter.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/kitemviews/private/kdirectorycontentscounter.cpp b/src/kitemviews/private/kdirectorycontentscounter.cpp index 65afb7c3e..7d1e76999 100644 --- a/src/kitemviews/private/kdirectorycontentscounter.cpp +++ b/src/kitemviews/private/kdirectorycontentscounter.cpp @@ -60,14 +60,23 @@ KDirectoryContentsCounter::~KDirectoryContentsCounter() { --m_workersCount; - if (m_workersCount == 0) { + if (m_workersCount > 0) { + // The worker thread will continue running. It could even be running + // a method of m_worker at the moment, so we delete it using + // deleteLater() to prevent a crash. + m_worker->deleteLater(); + } else { + // There are no remaining workers -> stop the worker thread. m_workerThread->quit(); m_workerThread->wait(); delete m_workerThread; m_workerThread = 0; - } - delete m_worker; + // The worker thread has finished running now, so it's safe to delete + // m_worker. deleteLater() would not work at all because the event loop + // which would deliver the event to m_worker is not running any more. + delete m_worker; + } } void KDirectoryContentsCounter::addDirectory(const QString& path) From ae5bcfcdeece23915e7272af1046a7e71e269474 Mon Sep 17 00:00:00 2001 From: Marco Nelles Date: Fri, 4 Apr 2014 11:41:28 +0200 Subject: [PATCH 22/29] Translate bookmark text on update. --- src/panels/places/placesitemmodel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/panels/places/placesitemmodel.cpp b/src/panels/places/placesitemmodel.cpp index baa770dfd..1f05e07f9 100644 --- a/src/panels/places/placesitemmodel.cpp +++ b/src/panels/places/placesitemmodel.cpp @@ -650,6 +650,7 @@ void PlacesItemModel::updateBookmarks() found = true; if (newBookmark.metaDataItem("UDI").isEmpty()) { item->setBookmark(newBookmark); + item->setText(i18nc("KFile System Bookmarks", newBookmark.text().toUtf8().data())); } break; } From a7562862e3f6ccbf5058d0885dff3675eaa2161c Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Mon, 14 Apr 2014 22:46:38 +0200 Subject: [PATCH 23/29] Update the "is cut" state of items if necessary The icons of items which are "cut" are shown faded in the view. The "is cut" state of the widget representing an item is updated if the clipboard contents change. Before this commit, if the sort order was changed however, then each widget kept the "is cut" state of the item which had been shown previously at its position. The solution is to update the "is cut" state also if any of the widget's data change. BUG: 332792 REVIEW: 117451 FIXED-IN: 4.12.5 --- src/kitemviews/kstandarditemlistwidget.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index acdf839ac..54546b440 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -589,6 +589,12 @@ void KStandardItemListWidget::dataChanged(const QHash& cur dirtyRoles = roles; } + // The URL might have changed (i.e., if the sort order of the items has + // been changed). Therefore, the "is cut" state must be updated. + KFileItemClipboard* clipboard = KFileItemClipboard::instance(); + const KUrl itemUrl = data().value("url").value(); + m_isCut = clipboard->isCut(itemUrl); + // The icon-state might depend from other roles and hence is // marked as dirty whenever a role has been changed dirtyRoles.insert("iconPixmap"); From bf4b163a0eb5938a587cd12cc9a77e6322c1de66 Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Thu, 24 Apr 2014 20:16:30 +0200 Subject: [PATCH 24/29] Scroll to the right position when going back and show hidden files is enabled. Instead of emitting the directoryLoadingCompleted signal (via slotCompleted) in KFileItemModel::setShowHiddenFiles directly, we now call dispatchPendingItemsToInsert instead. @Frank: Thanks for your help! FIXED-IN: 4.13.1 BUG: 332159 REVIEW: 117021 --- src/kitemviews/kfileitemmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index fd773e1e9..a0f9305cb 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -216,7 +216,7 @@ void KFileItemModel::setShowHiddenFiles(bool show) m_dirLister->setShowingDotFiles(show); m_dirLister->emitChanges(); if (show) { - slotCompleted(); + dispatchPendingItemsToInsert(); } } From 272cbbd16b03e51b30b6b9d472aa56054a5ea036 Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Thu, 24 Apr 2014 20:57:18 +0200 Subject: [PATCH 25/29] Fix memory leak with Dropbox version control plugin. In the current version we only call endRetrieval when beginRetrieval was successfully in UpdateItemStatesThread::run(). This causes some problems with version control plugins (like Dropbox plugin), which have to do cleanups in endRetrieval. Now we always call endRetrieval after beginRetrieval when updating the version states. FIXED-IN: 4.13.1 REVIEW: 117753 --- src/views/versioncontrol/updateitemstatesthread.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/versioncontrol/updateitemstatesthread.cpp b/src/views/versioncontrol/updateitemstatesthread.cpp index 6457f607d..62fcd09aa 100644 --- a/src/views/versioncontrol/updateitemstatesthread.cpp +++ b/src/views/versioncontrol/updateitemstatesthread.cpp @@ -64,9 +64,9 @@ void UpdateItemStatesThread::run() items[i].version = static_cast(state); } } - - m_plugin->endRetrieval(); } + + m_plugin->endRetrieval(); } } From afa1a8ef1179e8f8d99bf241389fcc2366290326 Mon Sep 17 00:00:00 2001 From: Renato Atilio Date: Sat, 26 Apr 2014 12:28:42 +0200 Subject: [PATCH 26/29] Enable the previous and next tab toolbar buttons when multiple tabs are opened. Disable them again when there is only one remaining tab. Additionally set the default state to disabled. BUG: 332628 FIXED-IN: 4.13.1 REVIEW: 117778 --- src/dolphinmainwindow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 847301434..28169cfb5 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -481,6 +481,8 @@ void DolphinMainWindow::openNewTab(const KUrl& url) m_viewTab.append(viewTab); actionCollection()->action("close_tab")->setEnabled(true); + actionCollection()->action("activate_prev_tab")->setEnabled(true); + actionCollection()->action("activate_next_tab")->setEnabled(true); // Provide a split view, if the startup settings are set this way if (GeneralSettings::splitView()) { @@ -1155,6 +1157,8 @@ void DolphinMainWindow::closeTab(int index) if (m_viewTab.count() == 1) { m_tabBar->removeTab(0); actionCollection()->action("close_tab")->setEnabled(false); + actionCollection()->action("activate_prev_tab")->setEnabled(false); + actionCollection()->action("activate_next_tab")->setEnabled(false); } else { m_tabBar->blockSignals(false); } @@ -1634,11 +1638,13 @@ void DolphinMainWindow::setupActions() KAction* activateNextTab = actionCollection()->addAction("activate_next_tab"); activateNextTab->setText(i18nc("@action:inmenu", "Activate Next Tab")); + activateNextTab->setEnabled(false); connect(activateNextTab, SIGNAL(triggered()), SLOT(activateNextTab())); activateNextTab->setShortcuts(QApplication::isRightToLeft() ? prevTabKeys : nextTabKeys); KAction* activatePrevTab = actionCollection()->addAction("activate_prev_tab"); activatePrevTab->setText(i18nc("@action:inmenu", "Activate Previous Tab")); + activatePrevTab->setEnabled(false); connect(activatePrevTab, SIGNAL(triggered()), SLOT(activatePrevTab())); activatePrevTab->setShortcuts(QApplication::isRightToLeft() ? nextTabKeys : prevTabKeys); From b5ca0e2de9001d2584073c043c1fbc1921e0174d Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Sat, 26 Apr 2014 12:29:36 +0200 Subject: [PATCH 27/29] Do not change the selection when re-sorting the view If a range of items has been selected by Shift-clicking or by pressing Shift+Arrow, then each of them is added individually to the selection before the items are re-sorted. Before this commit, the first and the last item in the range were moved, and all items between them were selected, even though these were not necessarily the items which had been selected before the re-sorting. BUG: 333457 REVIEW: 117603 FIXED-IN: 4.13.1 --- src/kitemviews/kitemlistselectionmanager.cpp | 11 ++++++--- src/tests/kitemlistselectionmanagertest.cpp | 26 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/kitemviews/kitemlistselectionmanager.cpp b/src/kitemviews/kitemlistselectionmanager.cpp index ebff1a30e..1f0a89d06 100644 --- a/src/kitemviews/kitemlistselectionmanager.cpp +++ b/src/kitemviews/kitemlistselectionmanager.cpp @@ -331,6 +331,11 @@ void KItemListSelectionManager::itemsMoved(const KItemRange& itemRange, const QL // Store the current selection (needed in the selectionChanged() signal) const KItemSet previousSelection = selectedItems(); + // endAnchoredSelection() adds all items between m_currentItem and + // m_anchorItem to m_selectedItems. They can then be moved + // individually later in this function. + endAnchoredSelection(); + // Update the current item if (m_currentItem >= itemRange.index && m_currentItem < itemRange.index + itemRange.count) { const int previousCurrentItem = m_currentItem; @@ -342,10 +347,8 @@ void KItemListSelectionManager::itemsMoved(const KItemRange& itemRange, const QL emit currentChanged(newCurrentItem, previousCurrentItem); } - // Update the anchor item - if (m_anchorItem >= itemRange.index && m_anchorItem < itemRange.index + itemRange.count) { - m_anchorItem = movedToIndexes.at(m_anchorItem - itemRange.index); - } + // Start a new anchored selection. + beginAnchoredSelection(m_currentItem); // Update the selections if (!m_selectedItems.isEmpty()) { diff --git a/src/tests/kitemlistselectionmanagertest.cpp b/src/tests/kitemlistselectionmanagertest.cpp index af2610d8c..492d0234f 100644 --- a/src/tests/kitemlistselectionmanagertest.cpp +++ b/src/tests/kitemlistselectionmanagertest.cpp @@ -78,6 +78,7 @@ private slots: void testChangeSelection(); void testDeleteCurrentItem_data(); void testDeleteCurrentItem(); + void testAnchoredSelectionAfterMovingItems(); private: void verifySelectionChange(QSignalSpy& spy, const KItemSet& currentSelection, const KItemSet& previousSelection) const; @@ -413,6 +414,15 @@ void KItemListSelectionManagerTest::testChangeSelection_data() << QVariant::fromValue(QList() << 4 << 5 << 2 << 3)) << (KItemSet() << 0 << 1 << 4 << 5); + QTest::newRow("Move items with active anchored selection") + << KItemSet() + << 0 << 3 + << (KItemSet() << 0 << 1 << 2 << 3) + << MoveItems + << (QList() << QVariant::fromValue(KItemRange(2, 4)) + << QVariant::fromValue(QList() << 4 << 5 << 2 << 3)) + << (KItemSet() << 0 << 1 << 4 << 5); + // Revert sort order QTest::newRow("Revert sort order") << (KItemSet() << 0 << 1) @@ -519,6 +529,22 @@ void KItemListSelectionManagerTest::testDeleteCurrentItem() QCOMPARE(m_selectionManager->currentItem(), newCurrentItemIndex); } +void KItemListSelectionManagerTest::testAnchoredSelectionAfterMovingItems() +{ + m_selectionManager->setCurrentItem(4); + m_selectionManager->beginAnchoredSelection(4); + + // Reverse the items between 0 and 5. + m_selectionManager->itemsMoved(KItemRange(0, 6), QList() << 5 << 4 << 3 << 2 << 1 << 0); + + QCOMPARE(m_selectionManager->currentItem(), 1); + QCOMPARE(m_selectionManager->m_anchorItem, 1); + + // Make 2 the current item -> 1 and 2 should be selected. + m_selectionManager->setCurrentItem(2); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 1 << 2); +} + void KItemListSelectionManagerTest::verifySelectionChange(QSignalSpy& spy, const KItemSet& currentSelection, const KItemSet& previousSelection) const From 5e82e598ea941c1f174d8e343feb2008552188a2 Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Thu, 24 Apr 2014 21:44:28 +0200 Subject: [PATCH 28/29] Mount partitions when you open them in a new tab. Instead of just emitting the slotItemMiddleClicked signal in PlacesPanel::slotItemContextMenuRequested we now use triggerItem with Qt::MiddleButton, which does set up the storage first and emit the slotItemMiddleClicked signal afterwards. BUG: 311226 FIXED-IN: 4.13.1 REVIEW: 117755 --- src/panels/places/placespanel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/panels/places/placespanel.cpp b/src/panels/places/placespanel.cpp index d5308eabe..f19fa1e25 100644 --- a/src/panels/places/placespanel.cpp +++ b/src/panels/places/placespanel.cpp @@ -283,8 +283,9 @@ void PlacesPanel::slotItemContextMenuRequested(int index, const QPointF& pos) } else if (action == hideAction) { item->setHidden(hideAction->isChecked()); } else if (action == openInNewTabAction) { - const KUrl url = m_model->item(index)->dataValue("url").value(); - emit placeMiddleClicked(url); + // TriggerItem does set up the storage first and then it will + // emit the slotItemMiddleClicked signal, because of Qt::MiddleButton. + triggerItem(index, Qt::MiddleButton); } else if (action == teardownAction) { m_model->requestTeardown(index); } else if (action == ejectAction) { From 5780fab172e02c3dd44082aa10d37cd87a98e29b Mon Sep 17 00:00:00 2001 From: Renato Atilio Date: Tue, 29 Apr 2014 21:54:33 +0200 Subject: [PATCH 29/29] Change the icon text for Previous and Next toolbar buttons In addition to the current long text for previous and next toolbar buttons ("Activate Previous/Next Tab"), this commit adds shorter icon texts for them to be used only on the toolbar ("Previous/Next Tab"). BUG: 332629 REVIEW: 117794 FIXED-IN: 4.14.0 --- src/dolphinmainwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 28169cfb5..e6b911209 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -1637,12 +1637,14 @@ void DolphinMainWindow::setupActions() prevTabKeys.append(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_Tab)); KAction* activateNextTab = actionCollection()->addAction("activate_next_tab"); + activateNextTab->setIconText(i18nc("@action:inmenu", "Next Tab")); activateNextTab->setText(i18nc("@action:inmenu", "Activate Next Tab")); activateNextTab->setEnabled(false); connect(activateNextTab, SIGNAL(triggered()), SLOT(activateNextTab())); activateNextTab->setShortcuts(QApplication::isRightToLeft() ? prevTabKeys : nextTabKeys); KAction* activatePrevTab = actionCollection()->addAction("activate_prev_tab"); + activatePrevTab->setIconText(i18nc("@action:inmenu", "Previous Tab")); activatePrevTab->setText(i18nc("@action:inmenu", "Activate Previous Tab")); activatePrevTab->setEnabled(false); connect(activatePrevTab, SIGNAL(triggered()), SLOT(activatePrevTab()));