diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2ab5e9cdda..45d7c495f4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -67,6 +67,13 @@ set(dolphinprivate_LIB_SRCS views/zoomlevelinfo.cpp ) +if (Nepomuk_FOUND) + set(dolphinprivate_LIB_SRCS + ${dolphinprivate_LIB_SRCS} + kitemviews/knepomukrolesprovider.cpp + ) +endif (Nepomuk_FOUND) + kde4_add_kcfg_files(dolphinprivate_LIB_SRCS settings/dolphin_compactmodesettings.kcfgc settings/dolphin_directoryviewpropertysettings.kcfgc @@ -80,18 +87,16 @@ kde4_add_library(dolphinprivate SHARED ${dolphinprivate_LIB_SRCS}) target_link_libraries(dolphinprivate ${KDE4_KFILE_LIBS} konq ${KDE4_KNEWSTUFF3_LIBS}) if (Nepomuk_FOUND) - target_link_libraries(dolphinprivate ${NEPOMUK_LIBRARIES} ${NEPOMUK_QUERY_LIBRARIES} nepomukutils ${SOPRANO_LIBRARIES}) + target_link_libraries(dolphinprivate ${NEPOMUK_LIBRARIES} ${NEPOMUK_QUERY_LIBRARIES} nepomukutils ${SOPRANO_LIBRARIES}) endif (Nepomuk_FOUND) + if(X11_Xrender_FOUND) - target_link_libraries(dolphinprivate ${X11_Xrender_LIB} ) + target_link_libraries(dolphinprivate ${X11_Xrender_LIB} ) endif(X11_Xrender_FOUND) - - set_target_properties(dolphinprivate PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} ) install(TARGETS dolphinprivate ${INSTALL_TARGETS_DEFAULT_ARGS}) - ########################################## set(dolphinpart_SRCS @@ -165,10 +170,7 @@ kde4_add_kcfg_files(dolphin_SRCS ) if(Nepomuk_FOUND) - set(dolphin_SRCS - ${dolphin_SRCS} - panels/search/searchpanel.cpp - ) + set(dolphin_SRCS ${dolphin_SRCS} panels/search/searchpanel.cpp) endif(Nepomuk_FOUND) if(NOT WIN32) diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp index 022f3b472f..4511b3b37c 100644 --- a/src/kitemviews/kfileitemlistwidget.cpp +++ b/src/kitemviews/kfileitemlistwidget.cpp @@ -55,8 +55,7 @@ KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) : m_scaledPixmapSize(), m_iconRect(), m_hoverPixmap(), - m_textPos(), - m_text(), + m_textInfo(), m_textRect(), m_sortedVisibleRoles(), m_expansionArea(), @@ -64,14 +63,12 @@ KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) : m_additionalInfoTextColor(), m_overlay() { - for (int i = 0; i < TextIdCount; ++i) { - m_text[i].setTextFormat(Qt::PlainText); - m_text[i].setPerformanceHint(QStaticText::AggressiveCaching); - } } KFileItemListWidget::~KFileItemListWidget() { + qDeleteAll(m_textInfo); + m_textInfo.clear(); } void KFileItemListWidget::setLayout(Layout layout) @@ -131,7 +128,8 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte painter->setFont(itemListStyleOption.font); painter->setPen(textColor()); - painter->drawStaticText(m_textPos[Name], m_text[Name]); + const TextInfo* textInfo = m_textInfo.value("name"); + painter->drawStaticText(textInfo->pos, textInfo->staticText); bool clipAdditionalInfoBounds = false; if (m_supportsItemExpanding) { @@ -139,7 +137,7 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte // with the icon. This can happen if the user has minimized the width // of the name-column to a very small value. const qreal minX = m_pixmapPos.x() + m_pixmap.width() + 4 * itemListStyleOption.padding; - if (m_textPos[Name].x() + columnWidth("name") > minX) { + if (textInfo->pos.x() + columnWidth("name") > minX) { clipAdditionalInfoBounds = true; painter->save(); painter->setClipRect(minX, 0, size().width() - minX, size().height(), Qt::IntersectClip); @@ -148,8 +146,10 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte painter->setPen(m_additionalInfoTextColor); painter->setFont(itemListStyleOption.font); - for (int i = Name + 1; i < TextIdCount; ++i) { - painter->drawStaticText(m_textPos[i], m_text[i]); + + for (int i = 1; i < m_sortedVisibleRoles.count(); ++i) { + const TextInfo* textInfo = m_textInfo.value(m_sortedVisibleRoles[i]); + painter->drawStaticText(textInfo->pos, textInfo->staticText); } if (clipAdditionalInfoBounds) { @@ -579,7 +579,8 @@ void KFileItemListWidget::updatePixmapCache() int scaledIconSize = 0; if (iconOnTop) { - scaledIconSize = static_cast(m_textPos[Name].y() - 2 * padding); + const TextInfo* textInfo = m_textInfo.value("name"); + scaledIconSize = static_cast(textInfo->pos.y() - 2 * padding); } else { const int textRowsCount = (m_layout == CompactLayout) ? visibleRoles().count() : 1; const qreal requiredTextHeight = textRowsCount * option.fontMetrics.height(); @@ -599,7 +600,8 @@ void KFileItemListWidget::updatePixmapCache() m_pixmapPos.setY(padding + scaledIconSize - m_scaledPixmapSize.height()); } else { // Center horizontally and vertically within the icon-area - m_pixmapPos.setX(m_textPos[Name].x() - 2 * padding + const TextInfo* textInfo = m_textInfo.value("name"); + m_pixmapPos.setX(textInfo->pos.x() - 2 * padding - (scaledIconSize + m_scaledPixmapSize.width()) / 2); m_pixmapPos.setY(padding + (scaledIconSize - m_scaledPixmapSize.height()) / 2); @@ -641,9 +643,14 @@ void KFileItemListWidget::updateTextsCache() break; } - for (int i = 0; i < TextIdCount; ++i) { - m_text[i].setText(QString()); - m_text[i].setTextOption(textOption); + qDeleteAll(m_textInfo); + m_textInfo.clear(); + for (int i = 0; i < m_sortedVisibleRoles.count(); ++i) { + TextInfo* textInfo = new TextInfo(); + textInfo->staticText.setTextFormat(Qt::PlainText); + textInfo->staticText.setPerformanceHint(QStaticText::AggressiveCaching); + textInfo->staticText.setTextOption(textOption); + m_textInfo.insert(m_sortedVisibleRoles[i], textInfo); } switch (m_layout) { @@ -676,15 +683,16 @@ void KFileItemListWidget::updateIconsLayoutTextCache() // Initialize properties for the "name" role. It will be used as anchor // for initializing the position of the other roles. - m_text[Name].setText(KStringHandler::preProcessWrap(values["name"].toString())); + TextInfo* nameTextInfo = m_textInfo.value("name"); + nameTextInfo->staticText.setText(KStringHandler::preProcessWrap(values["name"].toString())); // Calculate the number of lines required for the name and the required width int textLinesCountForName = 0; qreal requiredWidthForName = 0; QTextLine line; - QTextLayout layout(m_text[Name].text(), option.font); - layout.setTextOption(m_text[Name].textOption()); + QTextLayout layout(nameTextInfo->staticText.text(), option.font); + layout.setTextOption(nameTextInfo->staticText.textOption()); layout.beginLayout(); while ((line = layout.createLine()).isValid()) { line.setLineWidth(maxWidth); @@ -698,28 +706,28 @@ void KFileItemListWidget::updateIconsLayoutTextCache() const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0); textLinesCount += additionalRolesCount; - m_text[Name].setTextWidth(maxWidth); - m_textPos[Name] = QPointF(padding, widgetHeight - textLinesCount * fontHeight - padding); + nameTextInfo->staticText.setTextWidth(maxWidth); + nameTextInfo->pos = QPointF(padding, widgetHeight - textLinesCount * fontHeight - padding); m_textRect = QRectF(padding + (maxWidth - requiredWidthForName) / 2, - m_textPos[Name].y(), + nameTextInfo->pos.y(), requiredWidthForName, textLinesCountForName * fontHeight); // Calculate the position for each additional information - qreal y = m_textPos[Name].y() + textLinesCountForName * fontHeight; + qreal y = nameTextInfo->pos.y() + textLinesCountForName * fontHeight; foreach (const QByteArray& role, m_sortedVisibleRoles) { - const TextId textId = roleTextId(role); - if (textId == Name) { + if (role == "name") { continue; } const QString text = roleText(role, values); - m_text[textId].setText(text); + TextInfo* textInfo = m_textInfo.value(role); + textInfo->staticText.setText(text); qreal requiredWidth = 0; QTextLayout layout(text, option.font); - layout.setTextOption(m_text[textId].textOption()); + layout.setTextOption(textInfo->staticText.textOption()); layout.beginLayout(); QTextLine textLine = layout.createLine(); if (textLine.isValid()) { @@ -731,13 +739,13 @@ void KFileItemListWidget::updateIconsLayoutTextCache() // not get elided although it does not fit into the given width. As workaround // the padding is substracted. const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth - padding); - m_text[textId].setText(elidedText); + textInfo->staticText.setText(elidedText); } } layout.endLayout(); - m_textPos[textId] = QPointF(padding, y); - m_text[textId].setTextWidth(maxWidth); + textInfo->pos = QPointF(padding, y); + textInfo->staticText.setTextWidth(maxWidth); const QRectF textRect(padding + (maxWidth - requiredWidth) / 2, y, requiredWidth, fontHeight); m_textRect |= textRect; @@ -768,20 +776,19 @@ void KFileItemListWidget::updateCompactLayoutTextCache() qreal y = (widgetHeight - textLinesHeight) / 2; const qreal maxWidth = size().width() - x - option.padding; foreach (const QByteArray& role, m_sortedVisibleRoles) { - const TextId textId = roleTextId(role); - const QString text = roleText(role, values); - m_text[textId].setText(text); + TextInfo* textInfo = m_textInfo.value(role); + textInfo->staticText.setText(text); qreal requiredWidth = option.fontMetrics.width(text); if (requiredWidth > maxWidth) { requiredWidth = maxWidth; const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth); - m_text[textId].setText(elidedText); + textInfo->staticText.setText(elidedText); } - m_textPos[textId] = QPointF(x, y); - m_text[textId].setTextWidth(maxWidth); + textInfo->pos = QPointF(x, y); + textInfo->staticText.setTextWidth(maxWidth); maximumRequiredTextWidth = qMax(maximumRequiredTextWidth, requiredWidth); @@ -820,7 +827,7 @@ void KFileItemListWidget::updateDetailsLayoutTextCache() const qreal y = qMax(qreal(option.padding), (widgetHeight - fontHeight) / 2); foreach (const QByteArray& role, m_sortedVisibleRoles) { - const TextId textId = roleTextId(role); + const RoleType type = roleType(role); QString text = roleText(role, values); @@ -828,7 +835,7 @@ void KFileItemListWidget::updateDetailsLayoutTextCache() qreal requiredWidth = option.fontMetrics.width(text); const qreal roleWidth = columnWidth(role); qreal availableTextWidth = roleWidth - 2 * columnPadding; - if (textId == Name) { + if (type == Name) { availableTextWidth -= firstColumnInc; } @@ -837,16 +844,17 @@ void KFileItemListWidget::updateDetailsLayoutTextCache() requiredWidth = option.fontMetrics.width(text); } - m_text[textId].setText(text); - m_textPos[textId] = QPointF(x + columnPadding, y); + TextInfo* textInfo = m_textInfo.value(role); + textInfo->staticText.setText(text); + textInfo->pos = QPointF(x + columnPadding, y); x += roleWidth; - switch (textId) { + switch (type) { case Name: { const qreal textWidth = option.extendedSelectionRegion - ? size().width() - m_textPos[textId].x() + ? size().width() - textInfo->pos.x() : requiredWidth + 2 * option.padding; - m_textRect = QRectF(m_textPos[textId].x() - option.padding, 0, + m_textRect = QRectF(textInfo->pos.x() - option.padding, 0, textWidth, size().height()); // The column after the name should always be aligned on the same x-position independent @@ -856,7 +864,7 @@ void KFileItemListWidget::updateDetailsLayoutTextCache() } case Size: // The values for the size should be right aligned - m_textPos[textId].rx() += roleWidth - requiredWidth - 2 * columnPadding; + textInfo->pos.rx() += roleWidth - requiredWidth - 2 * columnPadding; break; default: @@ -976,22 +984,16 @@ void KFileItemListWidget::applyHiddenEffect(QPixmap& pixmap) KIconEffect::semiTransparent(pixmap); } -KFileItemListWidget::TextId KFileItemListWidget::roleTextId(const QByteArray& role) +KFileItemListWidget::RoleType KFileItemListWidget::roleType(const QByteArray& role) { - static QHash rolesHash; + static QHash rolesHash; if (rolesHash.isEmpty()) { rolesHash.insert("name", Name); rolesHash.insert("size", Size); rolesHash.insert("date", Date); - rolesHash.insert("permissions", Permissions); - rolesHash.insert("owner", Owner); - rolesHash.insert("group", Group); - rolesHash.insert("type", Type); - rolesHash.insert("destination", Destination); - rolesHash.insert("path", Path); } - return rolesHash.value(role); + return rolesHash.value(role, Generic); } QString KFileItemListWidget::roleText(const QByteArray& role, const QHash& values) @@ -999,17 +1001,7 @@ QString KFileItemListWidget::roleText(const QByteArray& role, const QHash m_textInfo; + QRectF m_textRect; QList m_sortedVisibleRoles; diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index efc7b326e6..1d7366cb22 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -274,19 +274,8 @@ QList > KFileItemModel::groups() const case SizeRole: m_groups = sizeRoleGroups(); break; case DateRole: m_groups = dateRoleGroups(); break; case PermissionsRole: m_groups = permissionRoleGroups(); break; - case OwnerRole: m_groups = genericStringRoleGroups("owner"); break; - case GroupRole: m_groups = genericStringRoleGroups("group"); break; - case TypeRole: m_groups = genericStringRoleGroups("type"); break; - case DestinationRole: m_groups = genericStringRoleGroups("destination"); break; - case PathRole: m_groups = genericStringRoleGroups("path"); break; - case CommentRole: m_groups = genericStringRoleGroups("comment"); break; - case TagsRole: m_groups = genericStringRoleGroups("tags"); break; case RatingRole: m_groups = ratingRoleGroups(); break; - case NoRole: break; - case IsDirRole: break; - case IsExpandedRole: break; - case ExpandedParentsCountRole: break; - default: Q_ASSERT(false); break; + default: m_groups = genericStringRoleGroups(sortRole()); break; } #ifdef KFILEITEMMODEL_DEBUG @@ -558,6 +547,8 @@ QList KFileItemModel::rolesInformation() info.role = map[i].role; info.translation = map[i].roleTranslation; info.group = map[i].groupTranslation; + info.requiresNepomuk = map[i].requiresNepomuk; + info.requiresIndexer = map[i].requiresIndexer; rolesInfo.append(info); } } @@ -1344,6 +1335,15 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b) const break; } + case ImageSizeRole: { + // Alway use a natural comparing to interpret the numbers of a string like + // "1600 x 1200" for having a correct sorting. + result = KStringHandler::naturalCompare(a->values.value("imageSize").toString(), + b->values.value("imageSize").toString(), + Qt::CaseSensitive); + break; + } + case PermissionsRole: case OwnerRole: case GroupRole: @@ -1953,29 +1953,29 @@ KFileItemList KFileItemModel::childItems(const KFileItem& item) const const KFileItemModel::RoleInfoMap* KFileItemModel::rolesInfoMap(int& count) { static const RoleInfoMap rolesInfoMap[] = { - // role roleType role translation group translation - { 0, NoRole, 0, 0, 0, 0 }, - { "name", NameRole, I18N_NOOP2_NOSTRIP("@label", "Name"), 0, 0 }, - { "size", SizeRole, I18N_NOOP2_NOSTRIP("@label", "Size"), 0, 0 }, - { "date", DateRole, I18N_NOOP2_NOSTRIP("@label", "Date"), 0, 0 }, - { "type", TypeRole, I18N_NOOP2_NOSTRIP("@label", "Type"), 0, 0 }, - { "rating", RatingRole, I18N_NOOP2_NOSTRIP("@label", "Rating"), 0, 0 }, - { "tags", TagsRole, I18N_NOOP2_NOSTRIP("@label", "Tags"), 0, 0 }, - { "comment", CommentRole, I18N_NOOP2_NOSTRIP("@label", "Comment"), 0, 0 }, - { "wordCount", WordCountRole, I18N_NOOP2_NOSTRIP("@label", "Word Count"), I18N_NOOP2_NOSTRIP("@label", "Document") }, - { "lineCount", LineCountRole, I18N_NOOP2_NOSTRIP("@label", "Line Count"), I18N_NOOP2_NOSTRIP("@label", "Document") }, - { "imageSize", ImageSizeRole, I18N_NOOP2_NOSTRIP("@label", "Image Size"), I18N_NOOP2_NOSTRIP("@label", "Image") }, - { "orientation", OrientationRole, I18N_NOOP2_NOSTRIP("@label", "Orientation"), I18N_NOOP2_NOSTRIP("@label", "Image") }, - { "artist", ArtistRole, I18N_NOOP2_NOSTRIP("@label", "Artist"), I18N_NOOP2_NOSTRIP("@label", "Music") }, - { "album", AlbumRole, I18N_NOOP2_NOSTRIP("@label", "Album"), I18N_NOOP2_NOSTRIP("@label", "Music") }, - { "duration", DurationRole, I18N_NOOP2_NOSTRIP("@label", "Duration"), I18N_NOOP2_NOSTRIP("@label", "Music") }, - { "track", TrackRole, I18N_NOOP2_NOSTRIP("@label", "Track"), I18N_NOOP2_NOSTRIP("@label", "Music") }, - { "path", PathRole, I18N_NOOP2_NOSTRIP("@label", "Path"), I18N_NOOP2_NOSTRIP("@label", "Other") }, - { "destination", DestinationRole, I18N_NOOP2_NOSTRIP("@label", "Link Destination"), I18N_NOOP2_NOSTRIP("@label", "Other") }, - { "copiedFrom", CopiedFromRole, I18N_NOOP2_NOSTRIP("@label", "Copied From"), I18N_NOOP2_NOSTRIP("@label", "Other") }, - { "permissions", PermissionsRole, I18N_NOOP2_NOSTRIP("@label", "Permissions"), I18N_NOOP2_NOSTRIP("@label", "Other") }, - { "owner", OwnerRole, I18N_NOOP2_NOSTRIP("@label", "Owner"), I18N_NOOP2_NOSTRIP("@label", "Other") }, - { "group", GroupRole, I18N_NOOP2_NOSTRIP("@label", "Group"), I18N_NOOP2_NOSTRIP("@label", "Other") }, + // | role | roleType | role translation | group translation | requires Nepomuk | requires indexer + { 0, NoRole, 0, 0, 0, 0, false, false }, + { "name", NameRole, I18N_NOOP2_NOSTRIP("@label", "Name"), 0, 0, false, false }, + { "size", SizeRole, I18N_NOOP2_NOSTRIP("@label", "Size"), 0, 0, false, false }, + { "date", DateRole, I18N_NOOP2_NOSTRIP("@label", "Date"), 0, 0, false, false }, + { "type", TypeRole, I18N_NOOP2_NOSTRIP("@label", "Type"), 0, 0, false, false }, + { "rating", RatingRole, I18N_NOOP2_NOSTRIP("@label", "Rating"), 0, 0, true, false }, + { "tags", TagsRole, I18N_NOOP2_NOSTRIP("@label", "Tags"), 0, 0, true, false }, + { "comment", CommentRole, I18N_NOOP2_NOSTRIP("@label", "Comment"), 0, 0, true, false }, + { "wordCount", WordCountRole, I18N_NOOP2_NOSTRIP("@label", "Word Count"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true }, + { "lineCount", LineCountRole, I18N_NOOP2_NOSTRIP("@label", "Line Count"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true }, + { "imageSize", ImageSizeRole, I18N_NOOP2_NOSTRIP("@label", "Image Size"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true }, + { "orientation", OrientationRole, I18N_NOOP2_NOSTRIP("@label", "Orientation"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true }, + { "artist", ArtistRole, I18N_NOOP2_NOSTRIP("@label", "Artist"), I18N_NOOP2_NOSTRIP("@label", "Music"), true, true }, + { "album", AlbumRole, I18N_NOOP2_NOSTRIP("@label", "Album"), I18N_NOOP2_NOSTRIP("@label", "Music"), true, true }, + { "duration", DurationRole, I18N_NOOP2_NOSTRIP("@label", "Duration"), I18N_NOOP2_NOSTRIP("@label", "Music"), true, true }, + { "track", TrackRole, I18N_NOOP2_NOSTRIP("@label", "Track"), I18N_NOOP2_NOSTRIP("@label", "Music"), true, true }, + { "path", PathRole, I18N_NOOP2_NOSTRIP("@label", "Path"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false }, + { "destination", DestinationRole, I18N_NOOP2_NOSTRIP("@label", "Link Destination"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false }, + { "copiedFrom", CopiedFromRole, I18N_NOOP2_NOSTRIP("@label", "Copied From"), I18N_NOOP2_NOSTRIP("@label", "Other"), true, false }, + { "permissions", PermissionsRole, I18N_NOOP2_NOSTRIP("@label", "Permissions"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false }, + { "owner", OwnerRole, I18N_NOOP2_NOSTRIP("@label", "Owner"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false }, + { "group", GroupRole, I18N_NOOP2_NOSTRIP("@label", "User Group"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false }, }; count = sizeof(rolesInfoMap) / sizeof(RoleInfoMap); diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index 0b1885a8cb..4824dec3d8 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -162,8 +162,16 @@ public: { QByteArray role; QString translation; QString group; + bool requiresNepomuk; + bool requiresIndexer; }; + /** + * @return Provides static information for all available roles that + * are supported by KFileItemModel. Some roles can only be + * determined if Nepomuk is enabled and/or the Nepomuk + * indexing is enabled. + */ static QList rolesInformation(); signals: @@ -344,6 +352,8 @@ private: const char* const roleTranslation; const char* const groupTranslationContext; const char* const groupTranslation; + const bool requiresNepomuk; + const bool requiresIndexer; }; /** diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp index 7b0d75dba2..efcf6b4ccd 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.cpp +++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp @@ -33,6 +33,10 @@ #include #include +#ifdef HAVE_NEPOMUK + #include "knepomukrolesprovider_p.h" +#endif + // Required includes for subItemsCount(): #ifdef Q_WS_WIN #include @@ -74,6 +78,10 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO m_previewJobs(), m_changedItemsTimer(0), m_changedItems() + #ifdef HAVE_NEPOMUK + , m_resolveNepomukRoles(false) + #endif + { Q_ASSERT(model); @@ -219,6 +227,23 @@ void KFileItemModelRolesUpdater::setRoles(const QSet& roles) if (m_roles != roles) { m_roles = roles; +#ifdef HAVE_NEPOMUK + // Check whether there is at least one role that must be resolved + // with the help of Nepomuk. If this is the case, m_resolveNepomukRoles + // will be set to true and the (quite expensive) resolving will be done + // in KFileItemModelRolesUpdater::rolesData(). + const KNepomukRolesProvider& rolesProvider = KNepomukRolesProvider::instance(); + m_resolveNepomukRoles = false; + QSetIterator it(roles); + while (it.hasNext()) { + const QByteArray& role = it.next(); + if (rolesProvider.isNepomukRole(role)) { + m_resolveNepomukRoles = true; + break; + } + } +#endif + if (m_paused) { m_rolesChangedDuringPausing = true; } else { @@ -754,6 +779,17 @@ QHash KFileItemModelRolesUpdater::rolesData(const KFileIte data.insert("iconOverlays", item.overlays()); +#ifdef HAVE_NEPOMUK + if (m_resolveNepomukRoles) { + const KNepomukRolesProvider& rolesProvider = KNepomukRolesProvider::instance(); + QHashIterator it(rolesProvider.roleValues(item.url(), m_roles)); + while (it.hasNext()) { + it.next(); + data.insert(it.key(), it.value()); + } + } +#endif + return data; } diff --git a/src/kitemviews/kfileitemmodelrolesupdater.h b/src/kitemviews/kfileitemmodelrolesupdater.h index 4db2dde973..47255b03fe 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.h +++ b/src/kitemviews/kfileitemmodelrolesupdater.h @@ -20,6 +20,7 @@ #ifndef KFILEITEMMODELROLESUPDATER_H #define KFILEITEMMODELROLESUPDATER_H +#include #include #include @@ -204,6 +205,13 @@ private: // of time. QTimer* m_changedItemsTimer; QSet m_changedItems; + +#ifdef HAVE_NEPOMUK + // True if roles must be resolved with the help of Nepomuk inside + // KFileItemModelRolesUpdater::rolesData(). + bool m_resolveNepomukRoles; +#endif + }; #endif diff --git a/src/kitemviews/kitemlistheaderwidget.cpp b/src/kitemviews/kitemlistheaderwidget.cpp index d3a8f001b5..2105b674c1 100644 --- a/src/kitemviews/kitemlistheaderwidget.cpp +++ b/src/kitemviews/kitemlistheaderwidget.cpp @@ -34,6 +34,7 @@ KItemListHeaderWidget::KItemListHeaderWidget(QGraphicsWidget* parent) : QGraphicsWidget(parent), m_automaticColumnResizing(true), m_model(0), + m_offset(0), m_columns(), m_columnWidths(), m_preferredColumnWidths(), @@ -48,10 +49,6 @@ KItemListHeaderWidget::KItemListHeaderWidget(QGraphicsWidget* parent) : m_movingRole.index = -1; setAcceptHoverEvents(true); - - QStyleOptionHeader option; - const QSize headerSize = style()->sizeFromContents(QStyle::CT_HeaderSection, &option, QSize()); - resize(0, headerSize.height()); } KItemListHeaderWidget::~KItemListHeaderWidget() @@ -142,6 +139,19 @@ qreal KItemListHeaderWidget::preferredColumnWidth(const QByteArray& role) const return m_preferredColumnWidths.value(role); } +void KItemListHeaderWidget::setOffset(qreal offset) +{ + if (m_offset != offset) { + m_offset = offset; + update(); + } +} + +qreal KItemListHeaderWidget::offset() const +{ + return m_offset; +} + qreal KItemListHeaderWidget::minimumColumnWidth() const { QFontMetricsF fontMetrics(font()); @@ -161,7 +171,7 @@ void KItemListHeaderWidget::paint(QPainter* painter, const QStyleOptionGraphicsI painter->setFont(font()); painter->setPen(palette().text().color()); - qreal x = 0; + qreal x = -m_offset; int orderIndex = 0; foreach (const QByteArray& role, m_columns) { const qreal roleWidth = m_columnWidths.value(role); @@ -265,7 +275,7 @@ void KItemListHeaderWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* event) } else { m_movingRole.pixmap = createRolePixmap(roleIndex); - qreal roleX = 0; + qreal roleX = -m_offset; for (int i = 0; i < roleIndex; ++i) { const QByteArray role = m_columns[i]; roleX += m_columnWidths.value(role); @@ -429,7 +439,7 @@ int KItemListHeaderWidget::roleIndexAt(const QPointF& pos) const { int index = -1; - qreal x = 0; + qreal x = -m_offset; foreach (const QByteArray& role, m_columns) { ++index; x += m_columnWidths.value(role); @@ -443,7 +453,7 @@ int KItemListHeaderWidget::roleIndexAt(const QPointF& pos) const bool KItemListHeaderWidget::isAboveRoleGrip(const QPointF& pos, int roleIndex) const { - qreal x = 0; + qreal x = -m_offset; for (int i = 0; i <= roleIndex; ++i) { const QByteArray role = m_columns[i]; x += m_columnWidths.value(role); @@ -484,7 +494,7 @@ int KItemListHeaderWidget::targetOfMovingRole() const const int movingRight = movingLeft + movingWidth - 1; int targetIndex = 0; - qreal targetLeft = 0; + qreal targetLeft = -m_offset; while (targetIndex < m_columns.count()) { const QByteArray role = m_columns[targetIndex]; const qreal targetWidth = m_columnWidths.value(role); @@ -510,7 +520,7 @@ int KItemListHeaderWidget::targetOfMovingRole() const qreal KItemListHeaderWidget::roleXPosition(const QByteArray& role) const { - qreal x = 0; + qreal x = -m_offset; foreach (const QByteArray& visibleRole, m_columns) { if (visibleRole == role) { return x; diff --git a/src/kitemviews/kitemlistheaderwidget_p.h b/src/kitemviews/kitemlistheaderwidget_p.h index e271060660..f8bba977bf 100644 --- a/src/kitemviews/kitemlistheaderwidget_p.h +++ b/src/kitemviews/kitemlistheaderwidget_p.h @@ -59,6 +59,9 @@ public: void setPreferredColumnWidth(const QByteArray& role, qreal width); qreal preferredColumnWidth(const QByteArray& role) const; + void setOffset(qreal offset); + qreal offset() const; + qreal minimumColumnWidth() const; virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0); @@ -144,6 +147,7 @@ private: bool m_automaticColumnResizing; KItemModelBase* m_model; + qreal m_offset; QList m_columns; QHash m_columnWidths; QHash m_preferredColumnWidths; diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index 8a18991a09..ddc65c3871 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -237,7 +237,7 @@ void KItemListView::setItemOffset(qreal offset) m_layouter->setItemOffset(offset); if (m_headerWidget->isVisible()) { - m_headerWidget->setPos(-offset, 0); + m_headerWidget->setOffset(offset); } // Don't check whether the m_layoutTimer is active: Changing the @@ -418,6 +418,7 @@ void KItemListView::setGeometry(const QRectF& rect) const QSizeF newSize = rect.size(); if (m_itemSize.isEmpty()) { + m_headerWidget->resize(rect.width(), m_headerWidget->size().height()); if (m_headerWidget->automaticColumnResizing()) { applyAutomaticColumnWidths(); } else { @@ -425,7 +426,6 @@ void KItemListView::setGeometry(const QRectF& rect) const QSizeF dynamicItemSize(qMax(newSize.width(), requiredWidth), m_itemSize.height()); m_layouter->setItemSize(dynamicItemSize); - m_headerWidget->resize(dynamicItemSize.width(), m_headerWidget->size().height()); } // Triggering a synchronous layout is fine from a performance point of view, @@ -604,10 +604,18 @@ bool KItemListView::isTransactionActive() const return m_activeTransactions > 0; } +// TODO: +#include +#include void KItemListView::setHeaderVisible(bool visible) { if (visible && !m_headerWidget->isVisible()) { - m_headerWidget->setPos(0, 0); + QStyleOptionHeader option; + const QSize headerSize = style()->sizeFromContents(QStyle::CT_HeaderSection, + &option, QSize()); + + m_headerWidget->setPos(0, 0); + m_headerWidget->resize(size().width(), headerSize.height()); m_headerWidget->setModel(m_model); m_headerWidget->setColumns(m_visibleRoles); m_headerWidget->setZValue(1); @@ -621,7 +629,7 @@ void KItemListView::setHeaderVisible(bool visible) connect(m_headerWidget, SIGNAL(sortRoleChanged(QByteArray,QByteArray)), this, SIGNAL(sortRoleChanged(QByteArray,QByteArray))); - m_layouter->setHeaderHeight(m_headerWidget->size().height()); + m_layouter->setHeaderHeight(headerSize.height()); m_headerWidget->setVisible(true); } else if (!visible && m_headerWidget->isVisible()) { disconnect(m_headerWidget, SIGNAL(columnWidthChanged(QByteArray,qreal,qreal)), @@ -1898,6 +1906,19 @@ QHash KItemListView::preferredColumnWidths(const KItemRangeLi QHash widths; + // Calculate the minimum width for each column that is required + // to show the headline unclipped. + const QFontMetricsF fontMetrics(m_headerWidget->font()); + const int gripMargin = m_headerWidget->style()->pixelMetric(QStyle::PM_HeaderGripMargin); + const int headerMargin = m_headerWidget->style()->pixelMetric(QStyle::PM_HeaderMargin); + foreach (const QByteArray& visibleRole, visibleRoles()) { + const QString headerText = m_model->roleDescription(visibleRole); + const qreal headerWidth = fontMetrics.width(headerText) + gripMargin + headerMargin * 2; + widths.insert(visibleRole, headerWidth); + } + + // Calculate the preferred column withs for each item and ignore values + // smaller than the width for showing the headline unclipped. int calculatedItemCount = 0; bool maxTimeExceeded = false; foreach (const KItemRange& itemRange, itemRanges) { @@ -1936,7 +1957,6 @@ void KItemListView::applyColumnWidthsFromHeader() const QSizeF dynamicItemSize(qMax(size().width(), requiredWidth), m_itemSize.height()); m_layouter->setItemSize(dynamicItemSize); - m_headerWidget->resize(dynamicItemSize.width(), m_headerWidget->size().height()); // Update the role sizes for all visible widgets QHashIterator it(m_visibleItems); @@ -2001,13 +2021,8 @@ void KItemListView::updatePreferredColumnWidths(const KItemRangeList& itemRanges void KItemListView::updatePreferredColumnWidths() { - if (!m_model) { - return; - } - - const int itemCount = m_model->count(); - if (itemCount > 0) { - updatePreferredColumnWidths(KItemRangeList() << KItemRange(0, itemCount)); + if (m_model) { + updatePreferredColumnWidths(KItemRangeList() << KItemRange(0, m_model->count())); } } @@ -2056,7 +2071,6 @@ void KItemListView::applyAutomaticColumnWidths() dynamicItemSize.rwidth() = qMax(requiredWidth, availableWidth); m_layouter->setItemSize(dynamicItemSize); - m_headerWidget->resize(dynamicItemSize.width(), m_headerWidget->size().height()); // Update the role sizes for all visible widgets QHashIterator it(m_visibleItems); diff --git a/src/kitemviews/knepomukrolesprovider.cpp b/src/kitemviews/knepomukrolesprovider.cpp new file mode 100644 index 0000000000..1612d57b63 --- /dev/null +++ b/src/kitemviews/knepomukrolesprovider.cpp @@ -0,0 +1,153 @@ +/*************************************************************************** + * Copyright (C) 2012 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "knepomukrolesprovider_p.h" + +#include +#include + +#include +#include +#include +#include + +struct KNepomukRolesProviderSingleton +{ + KNepomukRolesProvider instance; +}; +K_GLOBAL_STATIC(KNepomukRolesProviderSingleton, s_nepomukRolesProvider) + + +KNepomukRolesProvider& KNepomukRolesProvider::instance() +{ + return s_nepomukRolesProvider->instance; +} + +KNepomukRolesProvider::~KNepomukRolesProvider() +{ +} + +bool KNepomukRolesProvider::isNepomukRole(const QByteArray& role) const +{ + return m_roles.contains(role); +} + +QHash KNepomukRolesProvider::roleValues(const QUrl& url, + const QSet& roles) const +{ + const Nepomuk::Resource resource(url); + if (!resource.isValid()) { + return QHash(); + } + + QHash values; + + int width = -1; + int height = -1; + + QHashIterator it(resource.properties()); + while (it.hasNext()) { + it.next(); + + const Nepomuk::Types::Property property = it.key(); + const QByteArray role = m_roleForUri.value(property.uri()); + if (role.isEmpty() || !roles.contains(role)) { + continue; + } + + const Nepomuk::Variant value = it.value(); + + if (role == "imageSize") { + // Merge the two Nepomuk properties for width and height + // as one string into the "imageSize" role + const QString uri = property.uri().toString(); + if (uri.endsWith("#width")) { + width = value.toInt(); + } else if (uri.endsWith("#height")) { + height = value.toInt(); + } + + if (width >= 0 && height >= 0) { + const QString widthAndHeight = QString::number(width) + + QLatin1String(" x ") + + QString::number(height); + values.insert(role, widthAndHeight); + } + } else if (role == "tags") { + const QString tags = tagsFromValues(value.toStringList()); + values.insert(role, tags); + } else { + values.insert(role, value.toString()); + } + } + + return values; +} + +KNepomukRolesProvider::KNepomukRolesProvider() : + m_roles(), + m_roleForUri() +{ + struct UriInfo + { + const char* const uri; + const char* const role; + }; + + // Mapping from the URIs to the KFileItemModel roles. Note that this must not be + // a 1:1 mapping: One role may contain several URI-values (e.g. the URIs for height and + // width of an image are mapped to the role "imageSize") + static const UriInfo uriInfoList[] = { + { "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#numericRating", "rating" }, + { "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTag", "tags" }, + { "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#description", "comment" }, + { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#wordCount", "wordCount" }, + { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#lineCount", "lineCount" }, + { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#width", "imageSize" }, + { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#height", "imageSize" }, + { "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#orientation", "orientation", }, + { "http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#performer", "artist" }, + { "http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#musicAlbum", "album" }, + { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#duration", "duration" }, + { "http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#trackNumber", "track" }, + { "http://www.semanticdesktop.org/ontologies/2010/04/30/ndo#copiedFrom", "copiedFrom" } + }; + + for (unsigned int i = 0; i < sizeof(uriInfoList) / sizeof(UriInfo); ++i) { + m_roleForUri.insert(QUrl(uriInfoList[i].uri), uriInfoList[i].role); + m_roles.insert(uriInfoList[i].role); + } +} + +QString KNepomukRolesProvider::tagsFromValues(const QStringList& values) const +{ + QString tags; + + for (int i = 0; i < values.count(); ++i) { + if (i > 0) { + tags.append(QLatin1String(", ")); + } + + const Nepomuk::Tag tag(values[i]); + tags += tag.genericLabel(); + } + + return tags; +} + diff --git a/src/kitemviews/knepomukrolesprovider_p.h b/src/kitemviews/knepomukrolesprovider_p.h new file mode 100644 index 0000000000..7955093330 --- /dev/null +++ b/src/kitemviews/knepomukrolesprovider_p.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (C) 2012 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef KNEPOMUKROLESPROVIDER_H +#define KNEPOMUKROLESPROVIDER_H + +#include +#include +#include + +class QUrl; + +/** + * @brief Allows accessing metadata of a file by providing KFileItemModel roles. + * + * Is a helper class for KFileItemModelRolesUpdater to retrieve roles that + * are only accessible with Nepomuk. + */ +class KNepomukRolesProvider +{ +public: + static KNepomukRolesProvider& instance(); + virtual ~KNepomukRolesProvider(); + + /** + * @return True if the values of the role can be determined by Nepomuk. + */ + bool isNepomukRole(const QByteArray& role) const; + + /** + * @return Values for the roles \a roles that can be determined from the file + * with the URL \a url. + */ + QHash roleValues(const QUrl& url, const QSet& roles) const; + +protected: + KNepomukRolesProvider(); + +private: + QString tagsFromValues(const QStringList& values) const; + +private: + QSet m_roles; + QHash m_roleForUri; + + friend class KNepomukRolesProviderSingleton; +}; + +#endif + diff --git a/src/settings/additionalinfodialog.cpp b/src/settings/additionalinfodialog.cpp index 9e5f170dae..3cac35b7b1 100644 --- a/src/settings/additionalinfodialog.cpp +++ b/src/settings/additionalinfodialog.cpp @@ -19,12 +19,18 @@ #include "additionalinfodialog.h" +#include + #include #include "kitemviews/kfileitemmodel.h" #include #include #include +#ifdef HAVE_NEPOMUK + #include +#endif + AdditionalInfoDialog::AdditionalInfoDialog(QWidget* parent, const QList& visibleRoles) : KDialog(parent), @@ -44,12 +50,30 @@ AdditionalInfoDialog::AdditionalInfoDialog(QWidget* parent, header->setWordWrap(true); // Add checkboxes + bool nepomukRunning = false; + bool indexingEnabled = false; +#ifdef HAVE_NEPOMUK + nepomukRunning = (Nepomuk::ResourceManager::instance()->init() == 0); + if (nepomukRunning) { + KConfig config("nepomukserverrc"); + indexingEnabled = config.group("Service-nepomukfileindexer").readEntry("autostart", false); + } +#endif + m_listWidget = new QListWidget(mainWidget); m_listWidget->setSelectionMode(QAbstractItemView::NoSelection); const QList rolesInfo = KFileItemModel::rolesInformation(); foreach (const KFileItemModel::RoleInfo& info, rolesInfo) { QListWidgetItem* item = new QListWidgetItem(info.translation, m_listWidget); item->setCheckState(visibleRoles.contains(info.role) ? Qt::Checked : Qt::Unchecked); + + const bool enable = (!info.requiresNepomuk && !info.requiresIndexer) || + (info.requiresNepomuk && nepomukRunning) || + (info.requiresIndexer && indexingEnabled); + + if (!enable) { + item->setFlags(item->flags() & ~Qt::ItemIsEnabled); + } } QVBoxLayout* layout = new QVBoxLayout(mainWidget); diff --git a/src/views/dolphinitemlistcontainer.cpp b/src/views/dolphinitemlistcontainer.cpp index 8224399487..391dc648f8 100644 --- a/src/views/dolphinitemlistcontainer.cpp +++ b/src/views/dolphinitemlistcontainer.cpp @@ -140,6 +140,7 @@ void DolphinItemListContainer::setItemLayout(KFileItemListView::Layout layout) m_fileItemListView->setScrollOrientation(Qt::Vertical); m_fileItemListView->setHeaderVisible(true); m_fileItemListView->setSupportsItemExpanding(DetailsModeSettings::expandableFolders()); + break; case KFileItemListView::CompactLayout: m_fileItemListView->setScrollOrientation(Qt::Horizontal); diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index ab81316e11..78fd56d503 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -20,6 +20,8 @@ #include "dolphinview.h" +#include + #include #include #include @@ -70,6 +72,10 @@ #include "views/tooltips/tooltipmanager.h" #include "zoomlevelinfo.h" +#ifdef HAVE_NEPOMUK + #include +#endif + namespace { const int MaxModeEnum = DolphinView::CompactView; }; @@ -784,6 +790,16 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos) KItemListView* view = m_container->controller()->view(); const QSet visibleRolesSet = view->visibleRoles().toSet(); + bool nepomukRunning = false; + bool indexingEnabled = false; +#ifdef HAVE_NEPOMUK + nepomukRunning = (Nepomuk::ResourceManager::instance()->init() == 0); + if (nepomukRunning) { + KConfig config("nepomukserverrc"); + indexingEnabled = config.group("Service-nepomukfileindexer").readEntry("autostart", false); + } +#endif + QString groupName; QMenu* groupMenu = 0; @@ -811,6 +827,11 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos) action->setCheckable(true); action->setChecked(visibleRolesSet.contains(info.role)); action->setData(info.role); + + const bool enable = (!info.requiresNepomuk && !info.requiresIndexer) || + (info.requiresNepomuk && nepomukRunning) || + (info.requiresIndexer && indexingEnabled); + action->setEnabled(enable); } menu->addSeparator(); @@ -861,8 +882,10 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos) props.setVisibleRoles(visibleRoles); QList columnWidths; - foreach (const QByteArray& role, view->visibleRoles()) { - columnWidths.append(header->columnWidth(role)); + if (!header->automaticColumnResizing()) { + foreach (const QByteArray& role, view->visibleRoles()) { + columnWidths.append(header->columnWidth(role)); + } } props.setHeaderColumnWidths(columnWidths); } diff --git a/src/views/dolphinviewactionhandler.cpp b/src/views/dolphinviewactionhandler.cpp index aead11d250..eb127e2f71 100644 --- a/src/views/dolphinviewactionhandler.cpp +++ b/src/views/dolphinviewactionhandler.cpp @@ -20,6 +20,8 @@ #include "dolphinviewactionhandler.h" +#include + #include "settings/viewpropertiesdialog.h" #include "views/dolphinview.h" #include "views/zoomlevelinfo.h" @@ -37,6 +39,10 @@ #include #include +#ifdef HAVE_NEPOMUK + #include +#endif + #include DolphinViewActionHandler::DolphinViewActionHandler(KActionCollection* collection, QObject* parent) : @@ -228,6 +234,16 @@ QActionGroup* DolphinViewActionHandler::createFileItemRolesActionGroup(const QSt KActionMenu* groupMenu = 0; QActionGroup* groupMenuGroup = 0; + bool nepomukRunning = false; + bool indexingEnabled = false; +#ifdef HAVE_NEPOMUK + nepomukRunning = (Nepomuk::ResourceManager::instance()->init() == 0); + if (nepomukRunning) { + KConfig config("nepomukserverrc"); + indexingEnabled = config.group("Service-nepomukfileindexer").readEntry("autostart", false); + } +#endif + const QList rolesInfo = KFileItemModel::rolesInformation(); foreach (const KFileItemModel::RoleInfo& info, rolesInfo) { if (!isSortGroup && info.role == "name") { @@ -265,6 +281,11 @@ QActionGroup* DolphinViewActionHandler::createFileItemRolesActionGroup(const QSt action->setText(info.translation); action->setData(info.role); + const bool enable = (!info.requiresNepomuk && !info.requiresIndexer) || + (info.requiresNepomuk && nepomukRunning) || + (info.requiresIndexer && indexingEnabled); + action->setEnabled(enable); + if (isSortGroup) { m_sortByActions.insert(info.role, action); } else {