Commit 0f8595a4 authored by Peter Penz's avatar Peter Penz
Browse files

Allow to sort by rating, which can be quite useful in combination with the...

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
parent 655b58c9
......@@ -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} )
......
......@@ -22,9 +22,17 @@
#include "dolphinview.h"
#include <klocale.h>
#include <kdirmodel.h>
#ifdef HAVE_NEPOMUK
#include <config-nepomuk.h>
#include <nepomuk/global.h>
#include <nepomuk/resource.h>
#endif
#include <kdatetime.h>
#include <kdirmodel.h>
#include <kfileitem.h>
#include <klocale.h>
#include <kurl.h>
#include <QtGui/QSortFilterProxyModel>
......@@ -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<const KDirModel*>(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;
......
......@@ -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<KToggleAction>("by_rating");
sortByRating->setText(i18n("By Rating"));
KToggleAction* sortByTags = actionCollection()->add<KToggleAction>("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<KToggleAction>("descending");
sortDescending->setText(i18n("Descending"));
......
......@@ -25,6 +25,8 @@
#include "dolphinview.h"
#include "sidebarpage.h"
#include <config-nepomuk.h>
#include <kxmlguiwindow.h>
#include <ksortablelist.h>
#include <konq_undo.h>
......@@ -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();
......
......@@ -22,23 +22,17 @@
#include "dolphinsortfilterproxymodel.h"
#ifdef HAVE_NEPOMUK
#include <config-nepomuk.h>
#include <nepomuk/global.h>
#include <nepomuk/resource.h>
#endif
#include <kdirmodel.h>
#include <kfileitem.h>
#include <kdatetime.h>
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<int>(sorting) >= 0 && static_cast<int>(sorting) < dolphinMapSize);
sort(dolphinViewToDirModelColumn[static_cast<int>(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<int>(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<KDirModel*>(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<const KDirModel*>(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)
{
......
......@@ -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
......@@ -31,6 +31,8 @@
<Action name="by_owner" />
<Action name="by_group" />
<Action name="by_type" />
<Action name="by_rating" />
<Action name="by_tags" />
<Separator/>
<Action name="descending" />
</Menu>
......
......@@ -22,6 +22,8 @@
#ifndef DOLPHINVIEW_H
#define DOLPHINVIEW_H
#include <config-nepomuk.h>
#include <kparts/part.h>
#include <kfileitem.h>
#include <kfileitemdelegate.h>
......@@ -102,7 +104,9 @@ public:
SortByOwner,
SortByGroup,
SortByType,
MaxSortEnum = SortByType
SortByRating,
SortByTags,
MaxSortEnum = SortByTags
};
/**
......
......@@ -26,6 +26,9 @@
#include "dolphin_generalsettings.h"
#include "viewproperties.h"
#include <config-nepomuk.h>
#include <nepomuk/resourcemanager.h>
#include <kcomponentdata.h>
#include <klocale.h>
#include <kiconloader.h>
......@@ -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();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment