From: Peter Penz Date: Fri, 22 Jun 2007 10:18:46 +0000 (+0000) Subject: Allow to sort by rating, which can be quite useful in combination with the "Show... X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/4062c4cf2d9c3a6716ced8686fa2e2324261c0ec Allow to sort by rating, which can be quite useful in combination with the "Show in Groups" feature. Although still slow, it basically works. All the code is based on Rafael Fernández López patch available at http://media.ereslibre.es/2007/06/dolphin-21062007.diff. svn path=/trunk/KDE/kdebase/apps/; revision=678801 --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6ca332212..c305f3015 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,7 +34,16 @@ kde4_automoc(${dolphinprivate_LIB_SRCS}) kde4_add_library(dolphinprivate SHARED ${dolphinprivate_LIB_SRCS}) +find_package(Nepomuk) +macro_bool_to_01(Nepomuk_FOUND HAVE_NEPOMUK) + +configure_file(config-nepomuk.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-nepomuk.h ) + target_link_libraries(dolphinprivate ${KDE4_KDEUI_LIBS} ${KDE4_KFILE_LIBS} konq) +if (Nepomuk_FOUND) + target_link_libraries(dolphinprivate ${NEPOMUK_LIBRARIES}) +endif (Nepomuk_FOUND) + set_target_properties(dolphinprivate PROPERTIES VERSION 1.0.0 SOVERSION 1 ) install(TARGETS dolphinprivate DESTINATION ${LIB_INSTALL_DIR} ) diff --git a/src/dolphinitemcategorizer.cpp b/src/dolphinitemcategorizer.cpp index 38d0e2c16..7dc19ab92 100644 --- a/src/dolphinitemcategorizer.cpp +++ b/src/dolphinitemcategorizer.cpp @@ -22,9 +22,17 @@ #include "dolphinview.h" -#include -#include +#ifdef HAVE_NEPOMUK +#include +#include +#include +#endif + #include +#include +#include +#include +#include #include @@ -47,55 +55,24 @@ QString DolphinItemCategorizer::categoryForItem(const QModelIndex& index, return retString; } - int column; - - switch (sortRole) - { - case DolphinView::SortByName: // KDirModel::Name - column = KDirModel::Name; - break; - case DolphinView::SortBySize: // KDirModel::Size - column = KDirModel::Size; - break; - case DolphinView::SortByDate: // KDirModel::ModifiedTime - column = KDirModel::ModifiedTime; - break; - case DolphinView::SortByPermissions: // KDirModel::Permissions - column = KDirModel::Permissions; - break; - case DolphinView::SortByOwner: // KDirModel::Owner - column = KDirModel::Owner; - break; - case DolphinView::SortByGroup: // KDirModel::Group - column = KDirModel::Group; - break; - case DolphinView::SortByType: // KDirModel::Type - column = KDirModel::Type; - break; - default: - column = KDirModel::Name; - } - - // KDirModel checks columns to know to which role are - // we talking about - QModelIndex theIndex = index.model()->index(index.row(), - column, - index.parent()); - - if (!theIndex.isValid()) { - return retString; - } - - QVariant data = theIndex.model()->data(theIndex, Qt::DisplayRole); - const KDirModel *dirModel = qobject_cast(index.model()); KFileItem *item = dirModel->itemForIndex(index); - int fileSize; - KDateTime modifiedTime; switch (sortRole) { case DolphinView::SortByName: + { + // KDirModel checks columns to know to which role are + // we talking about + QModelIndex theIndex = index.model()->index(index.row(), + KDirModel::Name, + index.parent()); + + if (!theIndex.isValid()) { + return retString; + } + + QVariant data = theIndex.model()->data(theIndex, Qt::DisplayRole); if (data.toString().size()) { if (!item->isHidden() && data.toString().at(0).isLetter()) @@ -132,8 +109,11 @@ QString DolphinItemCategorizer::categoryForItem(const QModelIndex& index, } } break; + } case DolphinView::SortByDate: + { + KDateTime modifiedTime; modifiedTime.setTime_t(item->time(KIO::UDS_MODIFICATION_TIME)); modifiedTime = modifiedTime.toLocalZone(); @@ -150,6 +130,7 @@ QString DolphinItemCategorizer::categoryForItem(const QModelIndex& index, else retString = i18n("More than a year"); break; + } case DolphinView::SortByPermissions: retString = item->permissionsString(); @@ -163,8 +144,8 @@ QString DolphinItemCategorizer::categoryForItem(const QModelIndex& index, retString = item->group(); break; - case DolphinView::SortBySize: - fileSize = (item) ? item->size() : -1; + case DolphinView::SortBySize: { + const int fileSize = item ? item->size() : -1; if (item && item->isDir()) { retString = i18n("Folders"); } else if (fileSize < 5242880) { @@ -175,10 +156,25 @@ QString DolphinItemCategorizer::categoryForItem(const QModelIndex& index, retString = i18nc("Size", "Big"); } break; + } case DolphinView::SortByType: retString = item->mimeComment(); break; + +#ifdef HAVE_NEPOMUK + case DolphinView::SortByRating: { + KFileItem* item = dirModel->itemForIndex(index); + if (item != 0) { + const Nepomuk::Resource resource(item->url().url(), Nepomuk::NFO::File()); + const quint32 rating = resource.rating(); + retString = i18np("1 star", "%1 stars", rating); + } + break; + } + case DolphinView::SortByTags: + break; +#endif } return retString; diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 7d7a9f89b..7fec6908d 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -292,6 +292,15 @@ void DolphinMainWindow::slotSortingChanged(DolphinView::Sorting sorting) break; case DolphinView::SortByType: action = actionCollection()->action("by_type"); + break; +#ifdef HAVE_NEPOMUK + case DolphinView::SortByRating: + action = actionCollection()->action("by_rating"); + break; + case DolphinView::SortByTags: + action = actionCollection()->action("by_tags"); + break; +#endif default: break; } @@ -722,6 +731,16 @@ void DolphinMainWindow::sortByType() m_activeViewContainer->view()->setSorting(DolphinView::SortByType); } +void DolphinMainWindow::sortByRating() +{ + m_activeViewContainer->view()->setSorting(DolphinView::SortByRating); +} + +void DolphinMainWindow::sortByTags() +{ + m_activeViewContainer->view()->setSorting(DolphinView::SortByTags); +} + void DolphinMainWindow::toggleSortOrder() { DolphinView* view = m_activeViewContainer->view(); @@ -1157,6 +1176,26 @@ void DolphinMainWindow::setupActions() sortByType->setText(i18n("By Type")); connect(sortByType, SIGNAL(triggered()), this, SLOT(sortByType())); + KToggleAction* sortByRating = actionCollection()->add("by_rating"); + sortByRating->setText(i18n("By Rating")); + + KToggleAction* sortByTags = actionCollection()->add("by_tags"); + sortByTags->setText(i18n("By Tags")); + +#ifdef HAVE_NEPOMUK + if (MetaDataWidget::metaDataAvailable()) { + connect(sortByRating, SIGNAL(triggered()), this, SLOT(sortByRating())); + connect(sortByTags, SIGNAL(triggered()), this, SLOT(sortByTags())); + } + else { + sortByRating->setEnabled(false); + sortByTags->setEnabled(false); + } +#else + sortByRating->setEnabled(false); + sortByTags->setEnabled(false); +#endif + QActionGroup* sortGroup = new QActionGroup(this); sortGroup->addAction(sortByName); sortGroup->addAction(sortBySize); @@ -1165,6 +1204,8 @@ void DolphinMainWindow::setupActions() sortGroup->addAction(sortByOwner); sortGroup->addAction(sortByGroup); sortGroup->addAction(sortByType); + sortGroup->addAction(sortByRating); + sortGroup->addAction(sortByTags); KToggleAction* sortDescending = actionCollection()->add("descending"); sortDescending->setText(i18n("Descending")); diff --git a/src/dolphinmainwindow.h b/src/dolphinmainwindow.h index 5bbba5f21..93ab2762a 100644 --- a/src/dolphinmainwindow.h +++ b/src/dolphinmainwindow.h @@ -25,6 +25,8 @@ #include "dolphinview.h" #include "sidebarpage.h" +#include + #include #include #include @@ -278,6 +280,12 @@ private slots: /** The sorting of the current view should be done by the type. */ void sortByType(); + /** The sorting of the current view should be done by the rating. */ + void sortByRating(); + + /** The sorting of the current view should be done by tags. */ + void sortByTags(); + /** Switches between an ascending and descending sorting order. */ void toggleSortOrder(); diff --git a/src/dolphinsortfilterproxymodel.cpp b/src/dolphinsortfilterproxymodel.cpp index 5148af8ce..21194f66e 100644 --- a/src/dolphinsortfilterproxymodel.cpp +++ b/src/dolphinsortfilterproxymodel.cpp @@ -22,23 +22,17 @@ #include "dolphinsortfilterproxymodel.h" +#ifdef HAVE_NEPOMUK +#include +#include +#include +#endif + #include #include #include -static const int dolphinMapSize = 7; -static int dolphinViewToDirModelColumn[] = -{ - KDirModel::Name, // DolphinView::SortByName - KDirModel::Size, // DolphinView::SortBySize - KDirModel::ModifiedTime, // DolphinView::SortByDate - KDirModel::Permissions, // DolphinView::SortByPermissions - KDirModel::Owner, // DolphinView::SortByOwner - KDirModel::Group, // DolphinView::SortByGroup - KDirModel::Type // DolphinView::SortByType -}; - -static DolphinView::Sorting dirModelColumnToDolphinView[] = +static DolphinView::Sorting sortingTypeTable[] = { DolphinView::SortByName, // KDirModel::Name DolphinView::SortBySize, // KDirModel::Size @@ -47,12 +41,14 @@ static DolphinView::Sorting dirModelColumnToDolphinView[] = DolphinView::SortByOwner, // KDirModel::Owner DolphinView::SortByGroup, // KDirModel::Group DolphinView::SortByType // KDirModel::Type +#ifdef HAVE_NEPOMUK + , DolphinView::SortByRating + , DolphinView::SortByTags +#endif }; - DolphinSortFilterProxyModel::DolphinSortFilterProxyModel(QObject* parent) : KSortFilterProxyModel(parent), - m_sortColumn(0), m_sorting(DolphinView::SortByName), m_sortOrder(Qt::AscendingOrder) { @@ -70,27 +66,21 @@ DolphinSortFilterProxyModel::~DolphinSortFilterProxyModel() void DolphinSortFilterProxyModel::setSorting(DolphinView::Sorting sorting) { - // Update the sort column by mapping DolpginView::Sorting to - // KDirModel::ModelColumns. We will keep the sortOrder. - Q_ASSERT(static_cast(sorting) >= 0 && static_cast(sorting) < dolphinMapSize); - sort(dolphinViewToDirModelColumn[static_cast(sorting)], - m_sortOrder); + // change the sorting column by keeping the current sort order + sort(sorting, m_sortOrder); } void DolphinSortFilterProxyModel::setSortOrder(Qt::SortOrder sortOrder) { // change the sort order by keeping the current column - sort(dolphinViewToDirModelColumn[m_sorting], sortOrder); + sort(m_sorting, sortOrder); } void DolphinSortFilterProxyModel::sort(int column, Qt::SortOrder sortOrder) { - m_sortColumn = column; + m_sorting = sortingForColumn(column); m_sortOrder = sortOrder; - m_sorting = (column >= 0) && (column < dolphinMapSize) ? - dirModelColumnToDolphinView[column] : - DolphinView::SortByName; - setSortRole(dirModelColumnToDolphinView[column]); + setSortRole(m_sorting); KSortFilterProxyModel::sort(column, sortOrder); } @@ -108,10 +98,9 @@ bool DolphinSortFilterProxyModel::canFetchMore(const QModelIndex& parent) const DolphinView::Sorting DolphinSortFilterProxyModel::sortingForColumn(int column) { - if ((column >= 0) && (column < dolphinMapSize)) { - return dirModelColumnToDolphinView[column]; - } - return DolphinView::SortByName; + Q_ASSERT(column >= 0); + Q_ASSERT(column < static_cast(sizeof(sortingTypeTable) / sizeof(DolphinView::Sorting))); + return sortingTypeTable[column]; } bool DolphinSortFilterProxyModel::lessThanGeneralPurpose(const QModelIndex &left, @@ -168,7 +157,7 @@ bool DolphinSortFilterProxyModel::lessThanGeneralPurpose(const QModelIndex &left case DolphinView::SortByType: { // If we are sorting by size, show folders first. We will sort them - // correctly later + // correctly later. if (leftFileItem->isDir() && !rightFileItem->isDir()) { return true; } else if (!leftFileItem->isDir() && rightFileItem->isDir()) { @@ -178,6 +167,15 @@ bool DolphinSortFilterProxyModel::lessThanGeneralPurpose(const QModelIndex &left return naturalCompare(leftFileItem->mimeComment().toLower(), rightFileItem->mimeComment().toLower()) < 0; } +#ifdef HAVE_NEPOMUK + case DolphinView::SortByRating: { + const quint32 leftRating = ratingForIndex(left); + const quint32 rightRating = ratingForIndex(right); + return leftRating > rightRating; + } +#endif + default: + break; } return false; } @@ -187,13 +185,10 @@ bool DolphinSortFilterProxyModel::lessThan(const QModelIndex& left, { KDirModel* dirModel = static_cast(sourceModel()); - QVariant leftData = dirModel->data(left, dolphinViewToDirModelColumn[sortRole()]); - QVariant rightData = dirModel->data(right, dolphinViewToDirModelColumn[sortRole()]); - - const KFileItem *leftFileItem = dirModel->itemForIndex(left); - const KFileItem *rightFileItem = dirModel->itemForIndex(right); + const KFileItem* leftFileItem = dirModel->itemForIndex(left); + const KFileItem* rightFileItem = dirModel->itemForIndex(right); - // On our priority, folders go above regular files + // On our priority, folders go above regular files. if (leftFileItem->isDir() && !rightFileItem->isDir()) { return true; } else if (!leftFileItem->isDir() && rightFileItem->isDir()) { @@ -201,7 +196,7 @@ bool DolphinSortFilterProxyModel::lessThan(const QModelIndex& left, } // Hidden elements go before visible ones, if they both are - // folders or files + // folders or files. if (leftFileItem->isHidden() && !rightFileItem->isHidden()) { return true; } else if (!leftFileItem->isHidden() && rightFileItem->isHidden()) { @@ -210,12 +205,15 @@ bool DolphinSortFilterProxyModel::lessThan(const QModelIndex& left, switch (sortRole()) { case DolphinView::SortByName: { - // So we are in the same priority, what counts now is their names - QString leftValueString = leftData.toString(); - QString rightValueString = rightData.toString(); - - return sortCaseSensitivity() ? (naturalCompare(leftValueString, rightValueString) < 0) : - (naturalCompare(leftValueString.toLower(), rightValueString.toLower()) < 0); + // So we are in the same priority, what counts now is their names. + const QVariant leftData = dirModel->data(left, KDirModel::Name); + const QVariant rightData = dirModel->data(right, KDirModel::Name); + const QString leftValueString(leftData.toString()); + const QString rightValueString(rightData.toString()); + + return sortCaseSensitivity() ? + (naturalCompare(leftValueString, rightValueString) < 0) : + (naturalCompare(leftValueString.toLower(), rightValueString.toLower()) < 0); } case DolphinView::SortBySize: { @@ -230,25 +228,25 @@ bool DolphinSortFilterProxyModel::lessThan(const QModelIndex& left, // In the case they two have the same child items, we sort them by // their names. So we have always everything ordered. We also check - // if we are taking in count their cases + // if we are taking in count their cases. if (leftCount == rightCount) { return sortCaseSensitivity() ? (naturalCompare(leftFileItem->name(), rightFileItem->name()) < 0) : (naturalCompare(leftFileItem->name().toLower(), rightFileItem->name().toLower()) < 0); } // If they had different number of items, we sort them depending - // on how many items had each other + // on how many items had each other. return leftCount < rightCount; } // If what we are measuring is two files and they have the same size, - // sort them by their file names + // sort them by their file names. if (leftFileItem->size() == rightFileItem->size()) { return sortCaseSensitivity() ? (naturalCompare(leftFileItem->name(), rightFileItem->name()) < 0) : (naturalCompare(leftFileItem->name().toLower(), rightFileItem->name().toLower()) < 0); } - // If their sizes are different, sort them by their sizes, as expected + // If their sizes are different, sort them by their sizes, as expected. return leftFileItem->size() < rightFileItem->size(); } @@ -307,6 +305,21 @@ bool DolphinSortFilterProxyModel::lessThan(const QModelIndex& left, return naturalCompare(leftFileItem->mimeComment(), rightFileItem->mimeComment()) < 0; } + +#ifdef HAVE_NEPOMUK + case DolphinView::SortByRating: { + const quint32 leftRating = ratingForIndex(left); + const quint32 rightRating = ratingForIndex(right); + + if (leftRating == rightRating) { + return sortCaseSensitivity() ? + (naturalCompare(leftFileItem->name(), rightFileItem->name()) < 0) : + (naturalCompare(leftFileItem->name().toLower(), rightFileItem->name().toLower()) < 0); + } + + return leftRating > rightRating; + } +#endif } // We have set a SortRole and trust the ProxyModel to do @@ -314,6 +327,24 @@ bool DolphinSortFilterProxyModel::lessThan(const QModelIndex& left, return QSortFilterProxyModel::lessThan(left, right); } +quint32 DolphinSortFilterProxyModel::ratingForIndex(const QModelIndex& index) const +{ +#ifdef HAVE_NEPOMUK + quint32 rating = 0; + + const KDirModel* dirModel = static_cast(sourceModel()); + KFileItem* item = dirModel->itemForIndex(index); + if (item != 0) { + const Nepomuk::Resource resource(item->url().url(), Nepomuk::NFO::File()); + rating = resource.rating(); + } + return rating; +#else + Q_UNUSED(index); + return 0; +#endif +} + int DolphinSortFilterProxyModel::naturalCompare(const QString& a, const QString& b) { diff --git a/src/dolphinsortfilterproxymodel.h b/src/dolphinsortfilterproxymodel.h index c00032f3f..5bf4bc146 100644 --- a/src/dolphinsortfilterproxymodel.h +++ b/src/dolphinsortfilterproxymodel.h @@ -48,16 +48,10 @@ public: virtual ~DolphinSortFilterProxyModel(); void setSorting(DolphinView::Sorting sorting); - DolphinView::Sorting sorting() const - { - return m_sorting; - } + inline DolphinView::Sorting sorting() const; void setSortOrder(Qt::SortOrder sortOrder); - Qt::SortOrder sortOrder() const - { - return m_sortOrder; - } + inline Qt::SortOrder sortOrder() const; /** * @reimplemented, @internal @@ -89,12 +83,27 @@ protected: const QModelIndex& right) const; private: + /** + * Returns the rating for the item with the index \a index. 0 is + * returned if no item could be found. + */ + quint32 ratingForIndex(const QModelIndex& index) const; + static int naturalCompare(const QString& a, const QString& b); private: - int m_sortColumn; DolphinView::Sorting m_sorting; Qt::SortOrder m_sortOrder; }; +DolphinView::Sorting DolphinSortFilterProxyModel::sorting() const +{ + return m_sorting; +} + +Qt::SortOrder DolphinSortFilterProxyModel::sortOrder() const +{ + return m_sortOrder; +} + #endif diff --git a/src/dolphinui.rc b/src/dolphinui.rc index c2459a5c7..a7ecc78ed 100644 --- a/src/dolphinui.rc +++ b/src/dolphinui.rc @@ -31,6 +31,8 @@ + + diff --git a/src/dolphinview.h b/src/dolphinview.h index 1a240be7a..223c52dbf 100644 --- a/src/dolphinview.h +++ b/src/dolphinview.h @@ -22,6 +22,8 @@ #ifndef DOLPHINVIEW_H #define DOLPHINVIEW_H +#include + #include #include #include @@ -102,7 +104,9 @@ public: SortByOwner, SortByGroup, SortByType, - MaxSortEnum = SortByType + SortByRating, + SortByTags, + MaxSortEnum = SortByTags }; /** diff --git a/src/viewpropertiesdialog.cpp b/src/viewpropertiesdialog.cpp index 5d7fbc59f..a333d87b0 100644 --- a/src/viewpropertiesdialog.cpp +++ b/src/viewpropertiesdialog.cpp @@ -26,6 +26,9 @@ #include "dolphin_generalsettings.h" #include "viewproperties.h" +#include +#include + #include #include #include @@ -107,6 +110,12 @@ ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) : m_sorting->addItem(i18n("By Owner")); m_sorting->addItem(i18n("By Group")); m_sorting->addItem(i18n("By Type")); +#ifdef HAVE_NEPOMUK + if (!Nepomuk::ResourceManager::instance()->init()) { + m_sorting->addItem(i18n("By Rating")); + m_sorting->addItem(i18n("By Tags")); + } +#endif m_sorting->setCurrentIndex(m_viewProps->sorting()); QHBoxLayout* sortingLayout = new QHBoxLayout();