]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Allow showing Nepomuk metadata inside views
authorPeter Penz <peter.penz19@gmail.com>
Sun, 1 Apr 2012 14:42:46 +0000 (16:42 +0200)
committerPeter Penz <peter.penz19@gmail.com>
Sun, 1 Apr 2012 14:46:54 +0000 (16:46 +0200)
Metadata like image-size, rating, comments, tags, ... can be shown
now in the view (e.g. as column in the Details mode).

Still open: The rating-information needs to be shown as stars.

In the context of this feature also the following bugs have been
fixed:
- Fix visual glitches in the header of the Details mode
- Improve the minimum column width calculation to respect also
  the headling and not only the content

BUG: 296782
FIXED-IN: 4.9.0

16 files changed:
src/CMakeLists.txt
src/kitemviews/kfileitemlistwidget.cpp
src/kitemviews/kfileitemlistwidget.h
src/kitemviews/kfileitemmodel.cpp
src/kitemviews/kfileitemmodel.h
src/kitemviews/kfileitemmodelrolesupdater.cpp
src/kitemviews/kfileitemmodelrolesupdater.h
src/kitemviews/kitemlistheaderwidget.cpp
src/kitemviews/kitemlistheaderwidget_p.h
src/kitemviews/kitemlistview.cpp
src/kitemviews/knepomukrolesprovider.cpp [new file with mode: 0644]
src/kitemviews/knepomukrolesprovider_p.h [new file with mode: 0644]
src/settings/additionalinfodialog.cpp
src/views/dolphinitemlistcontainer.cpp
src/views/dolphinview.cpp
src/views/dolphinviewactionhandler.cpp

index 2ab5e9cdda99f70161c411ed5ad92804e569ea1c..45d7c495f4fd13c527b2d070110c985beb65bb47 100644 (file)
@@ -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)
index 022f3b472f66050556c2d5fbed085231fa07926b..4511b3b37c14fc4a60aa26b8951df0412fcff9a4 100644 (file)
@@ -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<int>(m_textPos[Name].y() - 2 * padding);
+        const TextInfo* textInfo = m_textInfo.value("name");
+        scaledIconSize = static_cast<int>(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<QByteArray, TextId> rolesHash;
+    static QHash<QByteArray, RoleType> 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<QByteArray, QVariant>& values)
@@ -999,17 +1001,7 @@ QString KFileItemListWidget::roleText(const QByteArray& role, const QHash<QByteA
     QString text;
     const QVariant roleValue = values.value(role);
 
-    switch (roleTextId(role)) {
-    case Name:
-    case Permissions:
-    case Owner:
-    case Group:
-    case Type:
-    case Destination:
-    case Path:
-        text = roleValue.toString();
-        break;
-
+    switch (roleType(role)) {
     case Size: {
         if (values.value("isDir").toBool()) {
             // The item represents a directory. Show the number of sub directories
@@ -1038,6 +1030,11 @@ QString KFileItemListWidget::roleText(const QByteArray& role, const QHash<QByteA
         break;
     }
 
+    case Name:
+    case Generic:
+        text = roleValue.toString();
+        break;
+
     default:
         Q_ASSERT(false);
         break;
index 76d090040870a5f2e3779e48ac81812fff810ba1..d68a2240561a56d40b3d83e68797fcbc7f8c72b2 100644 (file)
@@ -109,17 +109,11 @@ private slots:
     void slotCutItemsChanged();
 
 private:
-    enum TextId {
+    enum RoleType {
         Name,
         Size,
         Date,
-        Permissions,
-        Owner,
-        Group,
-        Type,
-        Destination,
-        Path,
-        TextIdCount // Mandatory last entry
+        Generic  // Mandatory last entry
     };
 
     void triggerCacheRefreshing();
@@ -139,7 +133,7 @@ private:
     static QPixmap pixmapForIcon(const QString& name, int size);
     static void applyCutEffect(QPixmap& pixmap);
     static void applyHiddenEffect(QPixmap& pixmap);
-    static TextId roleTextId(const QByteArray& role);
+    static RoleType roleType(const QByteArray& role);
 
     /**
      * @return Shown string for the role \p role of the item with the values \p values.
@@ -164,8 +158,13 @@ private:
     QRectF m_iconRect;          // Cache for KItemListWidget::iconRect()
     QPixmap m_hoverPixmap;      // Cache for modified m_pixmap when hovering the item
 
-    QPointF m_textPos[TextIdCount];
-    QStaticText m_text[TextIdCount];
+    struct TextInfo
+    {
+        QPointF pos;
+        QStaticText staticText;
+    };
+    QHash<QByteArray, TextInfo*> m_textInfo;
+
     QRectF m_textRect;
 
     QList<QByteArray> m_sortedVisibleRoles;
index efc7b326e61e3510f1df929796ceab5e35d35d7e..1d7366cb2216a7248e3756360d004cde7fcb7a6f 100644 (file)
@@ -274,19 +274,8 @@ QList<QPair<int, QVariant> > 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::RoleInfo> 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);
index 0b1885a8cb9d8b93b6b9217bba789827199b5c5e..4824dec3d8dd882afb2e7f9a11a6c37171aa756c 100644 (file)
@@ -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<RoleInfo> 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;
     };
 
     /**
index 7b0d75dba2762238608d81f88eacdcd8b72977b2..efcf6b4ccd27184d386da10edc955d3ac7493fb5 100644 (file)
 #include <QElapsedTimer>
 #include <QTimer>
 
+#ifdef HAVE_NEPOMUK
+    #include "knepomukrolesprovider_p.h"
+#endif
+
 // Required includes for subItemsCount():
 #ifdef Q_WS_WIN
     #include <QDir>
@@ -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<QByteArray>& 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<QByteArray> 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<QByteArray, QVariant> KFileItemModelRolesUpdater::rolesData(const KFileIte
 
     data.insert("iconOverlays", item.overlays());
 
+#ifdef HAVE_NEPOMUK
+    if (m_resolveNepomukRoles) {
+        const KNepomukRolesProvider& rolesProvider = KNepomukRolesProvider::instance();
+        QHashIterator<QByteArray, QVariant> it(rolesProvider.roleValues(item.url(), m_roles));
+        while (it.hasNext()) {
+            it.next();
+            data.insert(it.key(), it.value());
+        }
+    }
+#endif
+
     return data;
 }
 
index 4db2dde973c0c44e61dfd42ee14fb033ea2b994e..47255b03fe3ef08991d58c462f760866da8d8944 100644 (file)
@@ -20,6 +20,7 @@
 #ifndef KFILEITEMMODELROLESUPDATER_H
 #define KFILEITEMMODELROLESUPDATER_H
 
+#include <config-nepomuk.h>
 #include <libdolphin_export.h>
 
 #include <KFileItem>
@@ -204,6 +205,13 @@ private:
     // of time.
     QTimer* m_changedItemsTimer;
     QSet<KFileItem> m_changedItems;
+
+#ifdef HAVE_NEPOMUK
+    // True if roles must be resolved with the help of Nepomuk inside
+    // KFileItemModelRolesUpdater::rolesData().
+    bool m_resolveNepomukRoles;
+#endif
+
 };
 
 #endif
index d3a8f001b53bf139c1c356718e79a46b8e13e289..2105b674c132a17f2da7a6e64a9a074dc3353fd7 100644 (file)
@@ -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;
index e271060660f521ba1652e1daaf556e08a360a9da..f8bba977bfbd227fea4c44eb21895cdfc4906dd3 100644 (file)
@@ -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<QByteArray> m_columns;
     QHash<QByteArray, qreal> m_columnWidths;
     QHash<QByteArray, qreal> m_preferredColumnWidths;
index 8a18991a09fd800f984e38bee757e274269e78b6..ddc65c3871ce7e803532520e5d3765039251670f 100644 (file)
@@ -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 <QGraphicsScene>
+#include <QGraphicsView>
 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<QByteArray, qreal> KItemListView::preferredColumnWidths(const KItemRangeLi
 
     QHash<QByteArray, qreal> 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<int, KItemListWidget*> 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<int, KItemListWidget*> it(m_visibleItems);
diff --git a/src/kitemviews/knepomukrolesprovider.cpp b/src/kitemviews/knepomukrolesprovider.cpp
new file mode 100644 (file)
index 0000000..1612d57
--- /dev/null
@@ -0,0 +1,153 @@
+/***************************************************************************
+ *   Copyright (C) 2012 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 <KDebug>
+#include <KGlobal>
+
+#include <Nepomuk/Resource>
+#include <Nepomuk/Tag>
+#include <Nepomuk/Types/Property>
+#include <Nepomuk/Variant>
+
+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<QByteArray, QVariant> KNepomukRolesProvider::roleValues(const QUrl& url,
+                                                              const QSet<QByteArray>& roles) const
+{
+    const Nepomuk::Resource resource(url);
+    if (!resource.isValid()) {
+        return QHash<QByteArray, QVariant>();
+    }
+
+    QHash<QByteArray, QVariant> values;
+
+    int width = -1;
+    int height = -1;
+
+    QHashIterator<QUrl, Nepomuk::Variant> 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 (file)
index 0000000..7955093
--- /dev/null
@@ -0,0 +1,66 @@
+/***************************************************************************
+ *   Copyright (C) 2012 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 <QHash>
+#include <QSet>
+#include <QUrl>
+
+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<QByteArray, QVariant> roleValues(const QUrl& url, const QSet<QByteArray>& roles) const;
+
+protected:
+    KNepomukRolesProvider();
+
+private:
+    QString tagsFromValues(const QStringList& values) const;
+
+private:
+    QSet<QByteArray> m_roles;
+    QHash<QUrl, QByteArray> m_roleForUri;
+
+    friend class KNepomukRolesProviderSingleton;
+};
+
+#endif
+
index 9e5f170dae36882d31c2244d2ab1f8af1d184574..3cac35b7b1f16f65a5f856ee3bbb49a728ce7fd4 100644 (file)
 
 #include "additionalinfodialog.h"
 
+#include <config-nepomuk.h>
+
 #include <KLocale>
 #include "kitemviews/kfileitemmodel.h"
 #include <QCheckBox>
 #include <QLabel>
 #include <QVBoxLayout>
 
+#ifdef HAVE_NEPOMUK
+    #include <Nepomuk/ResourceManager>
+#endif
+
 AdditionalInfoDialog::AdditionalInfoDialog(QWidget* parent,
                                            const QList<QByteArray>& 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<KFileItemModel::RoleInfo> 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);
index 8224399487c4715e1e0a5042b78965ae59b2aaf1..391dc648f8150371d21a8a95ff475d6108c78f1c 100644 (file)
@@ -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);
index ab81316e113605a574317adce44f84193a879397..78fd56d50374f4289062c81596b571e76011020f 100644 (file)
@@ -20,6 +20,8 @@
 
 #include "dolphinview.h"
 
+#include <config-nepomuk.h>
+
 #include <QAbstractItemView>
 #include <QApplication>
 #include <QBoxLayout>
 #include "views/tooltips/tooltipmanager.h"
 #include "zoomlevelinfo.h"
 
+#ifdef HAVE_NEPOMUK
+    #include <Nepomuk/ResourceManager>
+#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<QByteArray> 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<int> 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);
         }
index aead11d2502854e4631bac8e23a11609eda854b3..eb127e2f71028ad4a1d11b97277aaedf6b0b1a22 100644 (file)
@@ -20,6 +20,8 @@
 
 #include "dolphinviewactionhandler.h"
 
+#include <config-nepomuk.h>
+
 #include "settings/viewpropertiesdialog.h"
 #include "views/dolphinview.h"
 #include "views/zoomlevelinfo.h"
 #include <KRun>
 #include <KPropertiesDialog>
 
+#ifdef HAVE_NEPOMUK
+    #include <Nepomuk/ResourceManager>
+#endif
+
 #include <KDebug>
 
 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<KFileItemModel::RoleInfo> 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 {