From: Rafael Fernández López Date: Mon, 17 Sep 2007 04:02:17 +0000 (+0000) Subject: Create the new architecture for KCategorizedView. Now DolphinModel is created, inheri... X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/c8072005fada01d772595ec64adca449134f421e?hp=231436769d037a83afbf57fedea167b6fb9a5ad4 Create the new architecture for KCategorizedView. Now DolphinModel is created, inheriting KDirModel for returning valid data for the role of the category of an item. DolphinSortFilterProxyModel implements now methods lessThanCategoryMethod and lessThanGeneralMethod from KCategorizedSortFilterProxyModel. The only thing that needs to be adapted is the keyboard navigation on the KCategorizedView. CCMAIL: peter.penz@gmx.at svn path=/trunk/KDE/kdebase/apps/; revision=713319 --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8122e5241..758c9510f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,10 +14,11 @@ set(dolphinprivate_LIB_SRCS dolphindetailsview.cpp dolphiniconsview.cpp dolphincolumnview.cpp - dolphinitemcategorizer.cpp kcategorizedview.cpp - kitemcategorizer.cpp + kcategorydrawer.cpp + dolphinmodel.cpp dolphinsettings.cpp + dolphincategorydrawer.cpp viewproperties.cpp dolphinsortfilterproxymodel.cpp renamedialog.cpp diff --git a/src/dolphincategorydrawer.cpp b/src/dolphincategorydrawer.cpp new file mode 100644 index 000000000..2479f2755 --- /dev/null +++ b/src/dolphincategorydrawer.cpp @@ -0,0 +1,302 @@ +/** + * This file is part of the KDE project + * Copyright (C) 2007 Rafael Fernández López + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "dolphincategorydrawer.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#ifdef HAVE_NEPOMUK +#include +#include +#include +#endif + +#include "dolphinview.h" +#include "dolphinmodel.h" + +DolphinCategoryDrawer::DolphinCategoryDrawer() +{ +} + +DolphinCategoryDrawer::~DolphinCategoryDrawer() +{ +} + +void DolphinCategoryDrawer::drawCategory(const QModelIndex &index, int sortRole, + const QStyleOption &option, QPainter *painter) const +{ + QRect starRect = option.rect; + + int iconSize = KIconLoader::global()->currentSize(K3Icon::Small); + QVariant categoryVariant = index.model()->data(index, KCategorizedSortFilterProxyModel::CategoryRole); + + if (!categoryVariant.isValid()) + { + return; + } + + const QString category = categoryVariant.toString(); + + QColor color = option.palette.color(QPalette::Text); + + painter->save(); + painter->setRenderHint(QPainter::Antialiasing); + + QStyleOptionButton opt; + + opt.rect = option.rect; + opt.palette = option.palette; + opt.direction = option.direction; + opt.text = category; + + if (option.state & QStyle::State_MouseOver) + { + QColor hover = option.palette.color(QPalette::Highlight).light(); + hover.setAlpha(88); + + QLinearGradient gradient(option.rect.topLeft(), + option.rect.bottomRight()); + gradient.setColorAt(option.direction == Qt::LeftToRight ? 0 + : 1, hover); + gradient.setColorAt(option.direction == Qt::LeftToRight ? 1 + : 0, Qt::transparent); + + painter->fillRect(option.rect, gradient); + } + + QFont painterFont = painter->font(); + painterFont.setWeight(QFont::Bold); + QFontMetrics metrics(painterFont); + painter->setFont(painterFont); + + QPainterPath path; + path.addRect(option.rect.left(), + option.rect.bottom() - 2, + option.rect.width(), + 2); + + QLinearGradient gradient(option.rect.topLeft(), + option.rect.bottomRight()); + gradient.setColorAt(option.direction == Qt::LeftToRight ? 0 + : 1, color); + gradient.setColorAt(option.direction == Qt::LeftToRight ? 1 + : 0, Qt::transparent); + + painter->setBrush(gradient); + painter->fillPath(path, gradient); + + if (option.direction == Qt::LeftToRight) + { + opt.rect.setLeft(opt.rect.left() + (iconSize / 4)); + starRect.setLeft(starRect.left() + (iconSize / 4)); + starRect.setRight(starRect.right() + (iconSize / 4)); + } + else + { + opt.rect.setRight(opt.rect.width() - (iconSize / 4)); + starRect.setLeft(starRect.width() - iconSize); + starRect.setRight(starRect.width() - (iconSize / 4)); + } + + bool paintIcon = true; + bool paintText = true; + + QPixmap icon; + switch (index.column()) { + case KDirModel::Name: + paintIcon = false; + break; + + case KDirModel::Size: + paintIcon = false; + break; + + case KDirModel::ModifiedTime: + paintIcon = false; + break; + + case KDirModel::Permissions: + paintIcon = false; // TODO: let's think about how to represent permissions + break; + + case KDirModel::Owner: { + opt.rect.setTop(option.rect.top() + (iconSize / 4)); + KUser user(category); + if (QFile::exists(user.homeDir() + QDir::separator() + ".face.icon")) + { + icon = QPixmap::fromImage(QImage(user.homeDir() + QDir::separator() + ".face.icon")).scaled(iconSize, iconSize); + } + else + { + icon = KIconLoader::global()->loadIcon("user", K3Icon::Small); + } + break; + } + + case KDirModel::Group: + paintIcon = false; + break; + + case KDirModel::Type: { + opt.rect.setTop(option.rect.top() + (option.rect.height() / 2) - (iconSize / 2)); + const KCategorizedSortFilterProxyModel *proxyModel = static_cast(index.model()); + const DolphinModel *model = static_cast(proxyModel->sourceModel()); + KFileItem item = model->itemForIndex(proxyModel->mapToSource(index)); + // This is the only way of getting the icon right. Others will fail on corner + // cases like the item representing this group has been set a different icon, + // so the group icon drawn is that one particularly. This way assures the drawn + // icon is the one of the mimetype of the group itself. (ereslibre) + icon = KIconLoader::global()->loadMimeTypeIcon(item.mimeTypePtr()->iconName(), + K3Icon::Small); + break; + } + +#ifdef HAVE_NEPOMUK + case DolphinModel::Rating: { + paintText = false; + paintIcon = false; + + starRect.setTop(option.rect.top() + (option.rect.height() / 2) - (iconSize / 2)); + starRect.setSize(QSize(iconSize, iconSize)); + + QPixmap pixmap = KIconLoader::global()->loadIcon("rating", K3Icon::Small); + QPixmap smallPixmap = KIconLoader::global()->loadIcon("rating", K3Icon::NoGroup, iconSize / 2); + QPixmap disabledPixmap = KIconLoader::global()->loadIcon("rating", K3Icon::Small); + + KPixmapEffect::toGray(disabledPixmap, false); + + int rating = category.toInt(); + + for (int i = 0; i < rating - (rating % 2); i += 2) { + painter->drawPixmap(starRect, pixmap); + + if (option.direction == Qt::LeftToRight) + { + starRect.setLeft(starRect.left() + iconSize + (iconSize / 4) /* separator between stars */); + starRect.setRight(starRect.right() + iconSize + (iconSize / 4) /* separator between stars */); + } + else + { + starRect.setLeft(starRect.left() - iconSize - (iconSize / 4) /* separator between stars */); + starRect.setRight(starRect.right() - iconSize - (iconSize / 4) /* separator between stars */); + } + } + + if (rating && rating % 2) { + if (option.direction == Qt::RightToLeft) + { + starRect.setLeft(starRect.left() + (iconSize / 2) /* separator between stars */); + //starRect.setRight(starRect.right() + (iconSize / 2) /* separator between stars */); + } + + starRect.setTop(option.rect.top() + (option.rect.height() / 2) - (iconSize / 4)); + starRect.setSize(QSize(iconSize / 2, iconSize / 2)); + painter->drawPixmap(starRect, smallPixmap); + starRect.setTop(opt.rect.top() + (option.rect.height() / 2) - (iconSize / 2)); + //starRect.setSize(QSize(iconSize / 2, iconSize / 2)); + + if (option.direction == Qt::LeftToRight) + { + starRect.setLeft(starRect.left() + (iconSize / 2) + (iconSize / 4)); + starRect.setRight(starRect.right() + (iconSize / 2) + (iconSize / 4)); + } + else + { + starRect.setLeft(starRect.left() - (iconSize / 2) - (iconSize / 4)); + starRect.setRight(starRect.right() - (iconSize / 2) - (iconSize / 4)); + } + + if (option.direction == Qt::RightToLeft) + { + starRect.setLeft(starRect.left() - (iconSize / 2)); + starRect.setRight(starRect.right() - (iconSize / 2)); + } + + starRect.setSize(QSize(iconSize, iconSize)); + } + + for (int i = rating; i < 9; i += 2) { + painter->drawPixmap(starRect, disabledPixmap); + + if (option.direction == Qt::LeftToRight) + { + starRect.setLeft(starRect.left() + iconSize + (iconSize / 4)); + starRect.setRight(starRect.right() + iconSize + (iconSize / 4)); + } + else + { + starRect.setLeft(starRect.left() - iconSize - (iconSize / 4)); + starRect.setRight(starRect.right() - iconSize - (iconSize / 4)); + } + } + + break; + } + + case DolphinModel::Tags: + paintIcon = false; + break; +#endif + } + + if (paintIcon) { + painter->drawPixmap(QRect(option.direction == Qt::LeftToRight ? opt.rect.left() + : opt.rect.right() - iconSize, opt.rect.top(), iconSize, iconSize), icon); + + if (option.direction == Qt::LeftToRight) + { + opt.rect.setLeft(opt.rect.left() + iconSize + (iconSize / 4)); + } + } + + if (paintText) { + opt.rect.setTop(option.rect.top() + (iconSize / 4)); + opt.rect.setBottom(opt.rect.bottom() - 2); + painter->setPen(color); + + QRect textRect = opt.rect; + + if (option.direction == Qt::RightToLeft) + { + textRect.setWidth(textRect.width() - (paintIcon ? iconSize + (iconSize / 4) + : (iconSize / 4))); + } + + painter->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, + metrics.elidedText(category, Qt::ElideRight, textRect.width())); + } + + painter->restore(); +} + +int DolphinCategoryDrawer::categoryHeight(const QStyleOption &option) const +{ + int iconSize = KIconLoader::global()->currentSize(K3Icon::Small); + + return qMax(option.fontMetrics.height() + (iconSize / 4) * 2 + 2, iconSize + (iconSize / 4) * 2 + 2) /* 2 gradient */; +} diff --git a/src/dolphinitemcategorizer.h b/src/dolphincategorydrawer.h similarity index 75% rename from src/dolphinitemcategorizer.h rename to src/dolphincategorydrawer.h index 65a7340ac..6ddea3ea6 100644 --- a/src/dolphinitemcategorizer.h +++ b/src/dolphincategorydrawer.h @@ -18,23 +18,28 @@ * Boston, MA 02110-1301, USA. */ -#ifndef DOLPHINITEMCATEGORIZER_H -#define DOLPHINITEMCATEGORIZER_H +#ifndef DOLPHINCATEGORYDRAWER_H +#define DOLPHINCATEGORYDRAWER_H -#include -#include +#include "kcategorydrawer.h" + +#include +#include -class QModelIndex; +#include -class LIBDOLPHINPRIVATE_EXPORT DolphinItemCategorizer : public KItemCategorizer +class LIBDOLPHINPRIVATE_EXPORT DolphinCategoryDrawer + : public KCategoryDrawer { public: - DolphinItemCategorizer(); - virtual ~DolphinItemCategorizer(); - virtual QString categoryForItem(const QModelIndex &index, int sortRole) const; + DolphinCategoryDrawer(); + + virtual ~DolphinCategoryDrawer(); + virtual void drawCategory(const QModelIndex &index, int sortRole, const QStyleOption &option, QPainter *painter) const; + virtual int categoryHeight(const QStyleOption &option) const; }; -#endif // DOLPHINITEMCATEGORIZER_H +#endif // DOLPHINCATEGORYDRAWER_H diff --git a/src/dolphincolumnview.cpp b/src/dolphincolumnview.cpp index 3c3c8e828..658bd8587 100644 --- a/src/dolphincolumnview.cpp +++ b/src/dolphincolumnview.cpp @@ -19,6 +19,7 @@ #include "dolphincolumnview.h" +#include "dolphinmodel.h" #include "dolphincontroller.h" #include "dolphinsettings.h" @@ -27,7 +28,6 @@ #include #include #include -#include #include #include @@ -239,8 +239,8 @@ void ColumnWidget::paintEvent(QPaintEvent* event) if (!m_childUrl.isEmpty()) { // indicate the shown URL of the next column by highlighting the shown folder item const QAbstractProxyModel* proxyModel = static_cast(m_view->model()); - const KDirModel* dirModel = static_cast(proxyModel->sourceModel()); - const QModelIndex dirIndex = dirModel->indexForUrl(m_childUrl); + const DolphinModel* dolphinModel = static_cast(proxyModel->sourceModel()); + const QModelIndex dirIndex = dolphinModel->indexForUrl(m_childUrl); const QModelIndex proxyIndex = proxyModel->mapFromSource(dirIndex); if (proxyIndex.isValid() && !selectionModel()->isSelected(proxyIndex)) { const QRect itemRect = visualRect(proxyIndex); @@ -420,8 +420,6 @@ QRect DolphinColumnView::visualRect(const QModelIndex& index) const void DolphinColumnView::setModel(QAbstractItemModel* model) { - // TODO: remove all columns - activeColumn()->setModel(model); QAbstractItemView::setModel(model); } diff --git a/src/dolphindetailsview.cpp b/src/dolphindetailsview.cpp index d7c8c5ab1..defe93192 100644 --- a/src/dolphindetailsview.cpp +++ b/src/dolphindetailsview.cpp @@ -20,6 +20,7 @@ #include "dolphindetailsview.h" +#include "dolphinmodel.h" #include "dolphincontroller.h" #include "dolphinsettings.h" #include "dolphinsortfilterproxymodel.h" @@ -27,8 +28,6 @@ #include "dolphin_detailsmodesettings.h" -#include - #include #include #include @@ -122,23 +121,23 @@ bool DolphinDetailsView::event(QEvent* event) const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings(); Q_ASSERT(settings != 0); if (!settings->showDate()) { - hideColumn(KDirModel::ModifiedTime); + hideColumn(DolphinModel::ModifiedTime); } if (!settings->showPermissions()) { - hideColumn(KDirModel::Permissions); + hideColumn(DolphinModel::Permissions); } if (!settings->showOwner()) { - hideColumn(KDirModel::Owner); + hideColumn(DolphinModel::Owner); } if (!settings->showGroup()) { - hideColumn(KDirModel::Group); + hideColumn(DolphinModel::Group); } if (!settings->showType()) { - hideColumn(KDirModel::Type); + hideColumn(DolphinModel::Type); } } @@ -163,7 +162,7 @@ void DolphinDetailsView::mousePressEvent(QMouseEvent* event) QTreeView::mousePressEvent(event); const QModelIndex index = indexAt(event->pos()); - if (!index.isValid() || (index.column() != KDirModel::Name)) { + if (!index.isValid() || (index.column() != DolphinModel::Name)) { const Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers(); if (!(modifier & Qt::ShiftModifier) && !(modifier & Qt::ControlModifier)) { clearSelection(); @@ -227,7 +226,7 @@ void DolphinDetailsView::dragMoveEvent(QDragMoveEvent* event) // TODO: remove this code when the issue #160611 is solved in Qt 4.4 setDirtyRegion(m_dropRect); const QModelIndex index = indexAt(event->pos()); - if (!index.isValid() || (index.column() != KDirModel::Name)) { + if (!index.isValid() || (index.column() != DolphinModel::Name)) { m_dragging = false; } else { m_dragging = true; @@ -314,7 +313,7 @@ void DolphinDetailsView::synchronizeSortingState(int column) void DolphinDetailsView::slotEntered(const QModelIndex& index) { const QPoint pos = viewport()->mapFromGlobal(QCursor::pos()); - const int nameColumnWidth = header()->sectionSize(KDirModel::Name); + const int nameColumnWidth = header()->sectionSize(DolphinModel::Name); if (pos.x() < nameColumnWidth) { m_controller->emitItemEntered(index); } diff --git a/src/dolphiniconsview.cpp b/src/dolphiniconsview.cpp index d287318d0..42a039c8c 100644 --- a/src/dolphiniconsview.cpp +++ b/src/dolphiniconsview.cpp @@ -21,7 +21,6 @@ #include "dolphincontroller.h" #include "dolphinsettings.h" -#include "dolphinitemcategorizer.h" #include "dolphin_iconsmodesettings.h" @@ -191,6 +190,7 @@ void DolphinIconsView::dropEvent(QDropEvent* event) event->acceptProposedAction(); } } + KCategorizedView::dropEvent(event); m_dragging = false; } diff --git a/src/dolphiniconsview.h b/src/dolphiniconsview.h index 6cd5b2201..592137e54 100644 --- a/src/dolphiniconsview.h +++ b/src/dolphiniconsview.h @@ -21,7 +21,6 @@ #define DOLPHINICONSVIEW_H #include -#include #include #include diff --git a/src/dolphinitemcategorizer.cpp b/src/dolphinitemcategorizer.cpp deleted file mode 100644 index f338ac47d..000000000 --- a/src/dolphinitemcategorizer.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2007 Rafael Fernández López - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "dolphinitemcategorizer.h" - -#include "dolphinview.h" -#include "dolphinsortfilterproxymodel.h" - -#ifdef HAVE_NEPOMUK -#include -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -DolphinItemCategorizer::DolphinItemCategorizer() : - KItemCategorizer() -{ -} - -DolphinItemCategorizer::~DolphinItemCategorizer() -{ -} - -QString DolphinItemCategorizer::categoryForItem(const QModelIndex& index, - int sortRole) const -{ - QString retString; - - if (!index.isValid()) - { - return retString; - } - - const KDirModel *dirModel = qobject_cast(index.model()); - KFileItem item = dirModel->itemForIndex(index); - - 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()) - retString = data.toString().toUpper().at(0); - else if (item.isHidden() && data.toString().at(0) == '.' && - data.toString().at(1).isLetter()) - retString = data.toString().toUpper().at(1); - else if (item.isHidden() && data.toString().at(0) == '.' && - !data.toString().at(1).isLetter()) - retString = i18nc("@title:group Name", "Others"); - else if (item.isHidden() && data.toString().at(0) != '.') - retString = data.toString().toUpper().at(0); - else if (item.isHidden()) - retString = data.toString().toUpper().at(0); - else - { - bool validCategory = false; - - const QString str(data.toString().toUpper()); - const QChar* currA = str.unicode(); - while (!currA->isNull() && !validCategory) { - if (currA->isLetter()) - validCategory = true; - else if (currA->isDigit()) - return i18nc("@title:group", "Others"); - else - ++currA; - } - - if (!validCategory) - retString = i18nc("@title:group Name", "Others"); - else - retString = *currA; - } - } - break; - } - - case DolphinView::SortByDate: - { - KDateTime modifiedTime = item.time(KFileItem::ModificationTime); - modifiedTime = modifiedTime.toLocalZone(); - - if (modifiedTime.daysTo(KDateTime::currentLocalDateTime()) == 0) - retString = i18nc("@title:group Date", "Today"); - else if (modifiedTime.daysTo(KDateTime::currentLocalDateTime()) == 1) - retString = i18nc("@title:group Date", "Yesterday"); - else if (modifiedTime.daysTo(KDateTime::currentLocalDateTime()) < 7) - retString = i18nc("@title:group Date", "Less than a week"); - else if (modifiedTime.daysTo(KDateTime::currentLocalDateTime()) < 31) - retString = i18nc("@title:group Date", "Less than a month"); - else if (modifiedTime.daysTo(KDateTime::currentLocalDateTime()) < 365) - retString = i18nc("@title:group Date", "Less than a year"); - else - retString = i18nc("@title:group Date", "More than a year"); - break; - } - - case DolphinView::SortByPermissions: - retString = item.permissionsString(); - break; - - case DolphinView::SortByOwner: - retString = item.user(); - break; - - case DolphinView::SortByGroup: - retString = item.group(); - break; - - case DolphinView::SortBySize: { - const int fileSize = !item.isNull() ? item.size() : -1; - if (!item.isNull() && item.isDir()) { - retString = i18nc("@title:group Size", "Folders"); - } else if (fileSize < 5242880) { - retString = i18nc("@title:group Size", "Small"); - } else if (fileSize < 10485760) { - retString = i18nc("@title:group Size", "Medium"); - } else { - retString = i18nc("@title:group Size", "Big"); - } - break; - } - - case DolphinView::SortByType: - retString = item.mimeComment(); - break; - -#ifdef HAVE_NEPOMUK - case DolphinView::SortByRating: { - const quint32 rating = DolphinSortFilterProxyModel::ratingForIndex(index); - - retString = QString::number(rating); - break; - } - - case DolphinView::SortByTags: { - retString = DolphinSortFilterProxyModel::tagsForIndex(index); - - if (retString.isEmpty()) - retString = i18nc("@title:group Tags", "Not yet tagged"); - - break; - } -#endif - } - - return retString; -} - -void DolphinItemCategorizer::drawCategory(const QModelIndex &index, - int sortRole, - const QStyleOption &option, - QPainter *painter) const -{ - QRect starRect = option.rect; - - int iconSize = KIconLoader::global()->currentSize(K3Icon::Small); - const QString category = categoryForItem(index, sortRole); - - QColor color = option.palette.color(QPalette::Text); - - painter->save(); - painter->setRenderHint(QPainter::Antialiasing); - - QStyleOptionButton opt; - - opt.rect = option.rect; - opt.palette = option.palette; - opt.direction = option.direction; - opt.text = category; - - if (option.state & QStyle::State_MouseOver) - { - const QPalette::ColorGroup group = - option.state & QStyle::State_Enabled ? - QPalette::Normal : QPalette::Disabled; - - QLinearGradient gradient(option.rect.topLeft(), - option.rect.bottomRight()); - gradient.setColorAt(0, - option.palette.color(group, - QPalette::Highlight).light()); - gradient.setColorAt(1, Qt::transparent); - - painter->fillRect(option.rect, gradient); - } - - QFont painterFont = painter->font(); - painterFont.setWeight(QFont::Bold); - QFontMetrics metrics(painterFont); - painter->setFont(painterFont); - - QPainterPath path; - path.addRect(option.rect.left(), - option.rect.bottom() - 2, - option.rect.width(), - 2); - - QLinearGradient gradient(option.rect.topLeft(), - option.rect.bottomRight()); - gradient.setColorAt(0, color); - gradient.setColorAt(1, Qt::transparent); - - painter->setBrush(gradient); - painter->fillPath(path, gradient); - - opt.rect.setLeft(opt.rect.left() + (iconSize / 4)); - starRect.setLeft(starRect.left() + (iconSize / 4)); - starRect.setRight(starRect.right() + (iconSize / 4)); - - bool paintIcon = true; - bool paintText = true; - - QPixmap icon; - switch (sortRole) { - case DolphinView::SortByName: - paintIcon = false; - break; - - case DolphinView::SortByDate: - paintIcon = false; - break; - - case DolphinView::SortByPermissions: - paintIcon = false; // FIXME: let's think about how to represent permissions - break; - - case DolphinView::SortByOwner: { - opt.rect.setTop(option.rect.top() + (iconSize / 4)); - KUser user(category); - if (QFile::exists(user.homeDir() + QDir::separator() + ".face.icon")) - { - icon = QPixmap::fromImage(QImage(user.homeDir() + QDir::separator() + ".face.icon")).scaled(iconSize, iconSize); - } - else - { - icon = KIconLoader::global()->loadIcon("user", K3Icon::Small); - } - break; - } - - case DolphinView::SortByGroup: - paintIcon = false; - break; - - case DolphinView::SortBySize: - paintIcon = false; - break; - - case DolphinView::SortByType: { - opt.rect.setTop(option.rect.top() + (option.rect.height() / 2) - (iconSize / 2)); - const KDirModel *model = static_cast(index.model()); - KFileItem item = model->itemForIndex(index); - icon = KIconLoader::global()->loadIcon(KMimeType::iconNameForUrl(item.url()), - K3Icon::Small); - break; - } - -#ifdef HAVE_NEPOMUK - case DolphinView::SortByRating: { - paintText = false; - paintIcon = false; - - starRect.setTop(option.rect.top() + (option.rect.height() / 2) - (iconSize / 2)); - starRect.setSize(QSize(iconSize, iconSize)); - - QPixmap pixmap = KIconLoader::global()->loadIcon("rating", K3Icon::Small); - QPixmap smallPixmap = KIconLoader::global()->loadIcon("rating", K3Icon::NoGroup, iconSize / 2); - QPixmap disabledIcon = KIconLoader::global()->loadIcon("rating", K3Icon::Small); - - QImage disabledImage = disabledIcon.toImage(); - KIconEffect::toGray(disabledImage, 1.0); - QPixmap disabledPixmap = QPixmap::fromImage(disabledImage); - - int rating = category.toInt(); - - for (int i = 0; i < rating - (rating % 2); i += 2) { - painter->drawPixmap(starRect, pixmap); - starRect.setLeft(starRect.left() + iconSize + (iconSize / 4) /* separator between stars */); - } - - if (rating && rating % 2) { - starRect.setTop(option.rect.top() + (option.rect.height() / 2) - (iconSize / 4)); - starRect.setSize(QSize(iconSize / 2, iconSize / 2)); - painter->drawPixmap(starRect, smallPixmap); - starRect.setTop(opt.rect.top() + (option.rect.height() / 2) - (iconSize / 2)); - starRect.setSize(QSize(iconSize / 2, iconSize / 2)); - starRect.setLeft(starRect.left() + (iconSize / 2) + (iconSize / 4)); - starRect.setSize(QSize(iconSize, iconSize)); - } - - for (int i = rating; i < 9; i += 2) { - painter->drawPixmap(starRect, disabledPixmap); - starRect.setLeft(starRect.left() + iconSize + (iconSize / 4)); - } - - break; - } - - case DolphinView::SortByTags: - paintIcon = false; - break; -#endif - } - - if (paintIcon) { - painter->drawPixmap(QRect(opt.rect.left(), opt.rect.top(), iconSize, iconSize), icon); - opt.rect.setLeft(opt.rect.left() + iconSize + (iconSize / 4)); - } - - if (paintText) { - opt.rect.setTop(option.rect.top() + (iconSize / 4)); - opt.rect.setBottom(opt.rect.bottom() - 2); - painter->setPen(color); - - painter->drawText(opt.rect, Qt::AlignVCenter | Qt::AlignLeft, - metrics.elidedText(category, Qt::ElideRight, opt.rect.width())); - } - - painter->restore(); -} - -int DolphinItemCategorizer::categoryHeight(const QStyleOption &option) const -{ - int iconSize = KIconLoader::global()->currentSize(K3Icon::Small); - - return qMax(option.fontMetrics.height() + (iconSize / 4) * 2 + 2, iconSize + (iconSize / 4) * 2 + 2) /* 2 gradient */; -} diff --git a/src/dolphinmodel.cpp b/src/dolphinmodel.cpp new file mode 100644 index 000000000..6ca2dd8e6 --- /dev/null +++ b/src/dolphinmodel.cpp @@ -0,0 +1,256 @@ +/** + * This file is part of the KDE project + * Copyright (C) 2007 Rafael Fernández López + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "dolphinmodel.h" + +#include "dolphinsortfilterproxymodel.h" + +#include "kcategorizedview.h" + +#include +#ifdef HAVE_NEPOMUK +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +DolphinModel::DolphinModel(QObject *parent) + : KDirModel(parent) +{ +} + +DolphinModel::~DolphinModel() +{ +} + +QVariant DolphinModel::data(const QModelIndex &index, int role) const +{ + if (role == KCategorizedSortFilterProxyModel::CategoryRole) + { + QString retString; + + if (!index.isValid()) + { + return retString; + } + + const KDirModel *dirModel = qobject_cast(index.model()); + KFileItem item = dirModel->itemForIndex(index); + + switch (index.column()) + { + case KDirModel::Name: + { + // 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()) + retString = data.toString().toUpper().at(0); + else if (item.isHidden() && data.toString().at(0) == '.' && + data.toString().at(1).isLetter()) + retString = data.toString().toUpper().at(1); + else if (item.isHidden() && data.toString().at(0) == '.' && + !data.toString().at(1).isLetter()) + retString = i18nc("@title:group Name", "Others"); + else if (item.isHidden() && data.toString().at(0) != '.') + retString = data.toString().toUpper().at(0); + else if (item.isHidden()) + retString = data.toString().toUpper().at(0); + else + { + bool validCategory = false; + + const QString str(data.toString().toUpper()); + const QChar* currA = str.unicode(); + while (!currA->isNull() && !validCategory) { + if (currA->isLetter()) + validCategory = true; + else if (currA->isDigit()) + return i18nc("@title:group", "Others"); + else + ++currA; + } + + if (!validCategory) + retString = i18nc("@title:group Name", "Others"); + else + retString = *currA; + } + } + break; + } + + case KDirModel::Size: { + const int fileSize = !item.isNull() ? item.size() : -1; + if (!item.isNull() && item.isDir()) { + retString = i18nc("@title:group Size", "Folders"); + } else if (fileSize < 5242880) { + retString = i18nc("@title:group Size", "Small"); + } else if (fileSize < 10485760) { + retString = i18nc("@title:group Size", "Medium"); + } else { + retString = i18nc("@title:group Size", "Big"); + } + break; + } + + case KDirModel::ModifiedTime: + { + KDateTime modifiedTime; + modifiedTime.setTime_t(item.time(KIO::UDSEntry::UDS_MODIFICATION_TIME)); + modifiedTime = modifiedTime.toLocalZone(); + + if (modifiedTime.daysTo(KDateTime::currentLocalDateTime()) == 0) + retString = i18nc("@title:group Date", "Today"); + else if (modifiedTime.daysTo(KDateTime::currentLocalDateTime()) == 1) + retString = i18nc("@title:group Date", "Yesterday"); + else if (modifiedTime.daysTo(KDateTime::currentLocalDateTime()) < 7) + retString = i18nc("@title:group Date", "Less than a week"); + else if (modifiedTime.daysTo(KDateTime::currentLocalDateTime()) < 31) + retString = i18nc("@title:group Date", "Less than a month"); + else if (modifiedTime.daysTo(KDateTime::currentLocalDateTime()) < 365) + retString = i18nc("@title:group Date", "Less than a year"); + else + retString = i18nc("@title:group Date", "More than a year"); + break; + } + + case KDirModel::Permissions: + retString = item.permissionsString(); + break; + + case KDirModel::Owner: + retString = item.user(); + break; + + case KDirModel::Group: + retString = item.group(); + break; + + case KDirModel::Type: + retString = item.mimeComment(); + break; + +#ifdef HAVE_NEPOMUK + case DolphinModel::Rating: { + const quint32 rating = ratingForIndex(index); + + retString = QString::number(rating); + break; + } + + case DolphinModel::Tags: { + retString = tagsForIndex(index); + + if (retString.isEmpty()) + retString = i18nc("@title:group Tags", "Not yet tagged"); + + break; + } +#endif + } + + return retString; + } + + return KDirModel::data(index, role); +} + +int DolphinModel::columnCount(const QModelIndex &parent) const +{ + return KDirModel::columnCount(parent) + (ExtraColumnCount - ColumnCount); +} + +quint32 DolphinModel::ratingForIndex(const QModelIndex& index) +{ +#ifdef HAVE_NEPOMUK + quint32 rating = 0; + + const DolphinModel* dolphinModel = static_cast(index.model()); + KFileItem item = dolphinModel->itemForIndex(index); + if (!item.isNull()) { + const Nepomuk::Resource resource(item.url().url(), Nepomuk::NFO::File()); + rating = resource.rating(); + } + return rating; +#else + Q_UNUSED(index); + return 0; +#endif +} + +QString DolphinModel::tagsForIndex(const QModelIndex& index) +{ +#ifdef HAVE_NEPOMUK + QString tagsString; + + const DolphinModel* dolphinModel = static_cast(index.model()); + KFileItem item = dolphinModel->itemForIndex(index); + if (!item.isNull()) { + const Nepomuk::Resource resource(item.url().url(), Nepomuk::NFO::File()); + const QList tags = resource.tags(); + QStringList stringList; + foreach (const Nepomuk::Tag& tag, tags) { + stringList.append(tag.label()); + } + stringList.sort(); + + foreach (const QString& str, stringList) { + tagsString += str; + tagsString += ", "; + } + + if (!tagsString.isEmpty()) { + tagsString.resize(tagsString.size() - 2); + } + } + + return tagsString; +#else + Q_UNUSED(index); + return QString(); +#endif +} diff --git a/src/dolphinmodel.h b/src/dolphinmodel.h new file mode 100644 index 000000000..681bd4d04 --- /dev/null +++ b/src/dolphinmodel.h @@ -0,0 +1,58 @@ +/** + * This file is part of the KDE project + * Copyright (C) 2007 Rafael Fernández López + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef DOLPHINMODEL_H +#define DOLPHINMODEL_H + +#include + +#include + +class LIBDOLPHINPRIVATE_EXPORT DolphinModel + : public KDirModel +{ +public: + enum AdditionalColumns { + Rating = ColumnCount, // ColumnCount defined at KDirModel + Tags, + ExtraColumnCount + }; + + DolphinModel(QObject *parent = 0); + virtual ~DolphinModel(); + + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + + /** + * Returns the rating for the item with the index \a index. 0 is + * returned if no item could be found. + */ + static quint32 ratingForIndex(const QModelIndex& index); + + /** + * Returns the tags for the item with the index \a index. If no + * tag is applied, a predefined string will be returned. + */ + static QString tagsForIndex(const QModelIndex& index); +}; + +#endif // DOLPHINMODEL_H diff --git a/src/dolphinpart.cpp b/src/dolphinpart.cpp index 1bc1edac0..bb9a1ea59 100644 --- a/src/dolphinpart.cpp +++ b/src/dolphinpart.cpp @@ -20,9 +20,9 @@ #include "dolphinpart.h" #include "dolphinsortfilterproxymodel.h" #include "dolphinview.h" +#include "dolphinmodel.h" #include -#include #include #include #include @@ -53,16 +53,16 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent, const QStringLi connect(m_dirLister, SIGNAL(completed(KUrl)), this, SLOT(slotCompleted(KUrl))); connect(m_dirLister, SIGNAL(canceled(KUrl)), this, SLOT(slotCanceled(KUrl))); - m_dirModel = new KDirModel(this); - m_dirModel->setDirLister(m_dirLister); + m_dolphinModel = new DolphinModel(this); + m_dolphinModel->setDirLister(m_dirLister); m_proxyModel = new DolphinSortFilterProxyModel(this); - m_proxyModel->setSourceModel(m_dirModel); + m_proxyModel->setSourceModel(m_dolphinModel); m_view = new DolphinView(parentWidget, KUrl(), m_dirLister, - m_dirModel, + m_dolphinModel, m_proxyModel); setWidget(m_view); diff --git a/src/dolphinpart.h b/src/dolphinpart.h index 3ca066a57..b0def14f4 100644 --- a/src/dolphinpart.h +++ b/src/dolphinpart.h @@ -24,7 +24,7 @@ class KFileItem; class DolphinPartBrowserExtension; class DolphinSortFilterProxyModel; -class KDirModel; +class DolphinModel; class KDirLister; class DolphinView; class QLineEdit; @@ -71,7 +71,7 @@ private Q_SLOTS: private: DolphinView* m_view; KDirLister* m_dirLister; - KDirModel* m_dirModel; + DolphinModel* m_dolphinModel; DolphinSortFilterProxyModel* m_proxyModel; DolphinPartBrowserExtension* m_extension; Q_DISABLE_COPY(DolphinPart) diff --git a/src/dolphinsortfilterproxymodel.cpp b/src/dolphinsortfilterproxymodel.cpp index 903d34393..7121036e2 100644 --- a/src/dolphinsortfilterproxymodel.cpp +++ b/src/dolphinsortfilterproxymodel.cpp @@ -22,27 +22,28 @@ #include "dolphinsortfilterproxymodel.h" -#ifdef HAVE_NEPOMUK #include +#ifdef HAVE_NEPOMUK #include #include #include #endif -#include +#include "dolphinmodel.h" + #include #include #include static DolphinView::Sorting sortingTypeTable[] = { - DolphinView::SortByName, // KDirModel::Name - DolphinView::SortBySize, // KDirModel::Size - DolphinView::SortByDate, // KDirModel::ModifiedTime - DolphinView::SortByPermissions, // KDirModel::Permissions - DolphinView::SortByOwner, // KDirModel::Owner - DolphinView::SortByGroup, // KDirModel::Group - DolphinView::SortByType // KDirModel::Type + DolphinView::SortByName, // DolphinModel::Name + DolphinView::SortBySize, // DolphinModel::Size + DolphinView::SortByDate, // DolphinModel::ModifiedTime + DolphinView::SortByPermissions, // DolphinModel::Permissions + DolphinView::SortByOwner, // DolphinModel::Owner + DolphinView::SortByGroup, // DolphinModel::Group + DolphinView::SortByType // DolphinModel::Type #ifdef HAVE_NEPOMUK , DolphinView::SortByRating , DolphinView::SortByTags @@ -62,23 +63,27 @@ DolphinSortFilterProxyModel::~DolphinSortFilterProxyModel() void DolphinSortFilterProxyModel::setSorting(DolphinView::Sorting sorting) { + m_sorting = sorting; + // change the sorting column by keeping the current sort order - sort(sorting, m_sortOrder); + KDirSortFilterProxyModel::sort((int) m_sorting, m_sortOrder); } void DolphinSortFilterProxyModel::setSortOrder(Qt::SortOrder sortOrder) { + m_sortOrder = sortOrder; + // change the sort order by keeping the current column - sort(m_sorting, sortOrder); + KDirSortFilterProxyModel::sort((int) m_sorting, m_sortOrder); } void DolphinSortFilterProxyModel::sort(int column, Qt::SortOrder sortOrder) { m_sorting = sortingForColumn(column); m_sortOrder = sortOrder; - setSortRole(m_sorting); - KDirSortFilterProxyModel::sort(column, sortOrder); + emit sortingRoleChanged(); + KDirSortFilterProxyModel::sort((int) m_sorting, sortOrder); } DolphinView::Sorting DolphinSortFilterProxyModel::sortingForColumn(int column) @@ -91,100 +96,56 @@ DolphinView::Sorting DolphinSortFilterProxyModel::sortingForColumn(int column) bool DolphinSortFilterProxyModel::lessThanGeneralPurpose(const QModelIndex &left, const QModelIndex &right) const { - KDirModel* dirModel = static_cast(sourceModel()); - - const KFileItem leftFileItem = dirModel->itemForIndex(left); - const KFileItem rightFileItem = dirModel->itemForIndex(right); - - //FIXME left.column() should be used instead! - switch (sortRole()) { - case DolphinView::SortByName: { - QString leftFileName(leftFileItem.name()); - if (leftFileName.at(0) == '.') { - leftFileName = leftFileName.mid(1); - } - - QString rightFileName(rightFileItem.name()); - if (rightFileName.at(0) == '.') { - rightFileName = rightFileName.mid(1); - } - - // We don't care about case for building categories. We also don't - // want here to compare by a natural comparison. - return naturalCompare(leftFileName, rightFileName) < 0; - } - - case DolphinView::SortBySize: - // If we are sorting by size, show folders first. We will sort them - // correctly later. - return leftFileItem.isDir() && !rightFileItem.isDir(); - - case DolphinView::SortByDate: { - KDateTime leftTime = leftFileItem.time(KFileItem::ModificationTime); - KDateTime rightTime = rightFileItem.time(KFileItem::ModificationTime); - return leftTime > rightTime; - } - - case DolphinView::SortByPermissions: { - return naturalCompare(leftFileItem.permissionsString(), - rightFileItem.permissionsString()) < 0; - } +#ifdef HAVE_NEPOMUK + DolphinModel* dolphinModel = static_cast(sourceModel()); - case DolphinView::SortByOwner: { - return naturalCompare(leftFileItem.user().toLower(), - rightFileItem.user().toLower()) < 0; - } + const KFileItem leftFileItem = dolphinModel->itemForIndex(left); + const KFileItem rightFileItem = dolphinModel->itemForIndex(right); - case DolphinView::SortByGroup: { - return naturalCompare(leftFileItem.group().toLower(), - rightFileItem.group().toLower()) < 0; - } + switch (left.column()) { - case DolphinView::SortByType: { - // If we are sorting by size, show folders first. We will sort them - // correctly later. - if (leftFileItem.isDir() && !rightFileItem.isDir()) { - return true; - } else if (!leftFileItem.isDir() && rightFileItem.isDir()) { - return false; - } - - 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); + const quint32 leftRating = DolphinModel::ratingForIndex(left); + const quint32 rightRating = DolphinModel::ratingForIndex(right); return leftRating > rightRating; } + case DolphinView::SortByTags: { - const QString leftTags = tagsForIndex(left); - const QString rightTags = tagsForIndex(right); + const QString leftTags = DolphinModel::tagsForIndex(left); + const QString rightTags = DolphinModel::tagsForIndex(right); if (leftTags.isEmpty() && !rightTags.isEmpty()) return false; else if (!leftTags.isEmpty() && rightTags.isEmpty()) return true; - return naturalCompare(tagsForIndex(left), tagsForIndex(right)) < 0; + return naturalCompare(DolphinModel::tagsForIndex(left), DolphinModel::tagsForIndex(right)) < 0; } -#endif + default: break; + } - return false; +#endif + + return KDirSortFilterProxyModel::lessThanGeneralPurpose(left, right); } bool DolphinSortFilterProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const { #ifdef HAVE_NEPOMUK - KDirModel* dirModel = static_cast(sourceModel()); + DolphinModel* dolphinModel = static_cast(sourceModel()); - const KFileItem leftFileItem = dirModel->itemForIndex(left); - const KFileItem rightFileItem = dirModel->itemForIndex(right); + const KFileItem leftFileItem = dolphinModel->itemForIndex(left); + const KFileItem rightFileItem = dolphinModel->itemForIndex(right); + // On our priority, folders go above regular files. + if (leftFileItem.isDir() && !rightFileItem.isDir()) { + return true; + } else if (!leftFileItem.isDir() && rightFileItem.isDir()) { + return false; + } // Hidden elements go before visible ones, if they both are // folders or files. @@ -194,11 +155,11 @@ bool DolphinSortFilterProxyModel::lessThan(const QModelIndex& left, return false; } - //FIXME left.column() should be used instead! - switch (sortRole()) { + switch (left.column()) { + case DolphinView::SortByRating: { - const quint32 leftRating = ratingForIndex(left); - const quint32 rightRating = ratingForIndex(right); + const quint32 leftRating = DolphinModel::ratingForIndex(left); + const quint32 rightRating = DolphinModel::ratingForIndex(right); if (leftRating == rightRating) { // On our priority, folders go above regular files. @@ -222,8 +183,8 @@ bool DolphinSortFilterProxyModel::lessThan(const QModelIndex& left, } case DolphinView::SortByTags: { - const QString leftTags = tagsForIndex(left); - const QString rightTags = tagsForIndex(right); + const QString leftTags = DolphinModel::tagsForIndex(left); + const QString rightTags = DolphinModel::tagsForIndex(right); if (leftTags == rightTags) { // On our priority, folders go above regular files. @@ -245,61 +206,14 @@ bool DolphinSortFilterProxyModel::lessThan(const QModelIndex& left, return naturalCompare(leftTags, rightTags) < 0; } - } -#endif - return KDirSortFilterProxyModel::lessThan(left, right); -} - -quint32 DolphinSortFilterProxyModel::ratingForIndex(const QModelIndex& index) -{ -#ifdef HAVE_NEPOMUK - quint32 rating = 0; + default: + break; - const KDirModel* dirModel = static_cast(index.model()); - KFileItem item = dirModel->itemForIndex(index); - if (!item.isNull()) { - const Nepomuk::Resource resource(item.url().url(), Nepomuk::NFO::File()); - rating = resource.rating(); } - return rating; -#else - Q_UNUSED(index); - return 0; #endif -} - -QString DolphinSortFilterProxyModel::tagsForIndex(const QModelIndex& index) -{ -#ifdef HAVE_NEPOMUK - QString tagsString; - - const KDirModel* dirModel = static_cast(index.model()); - KFileItem item = dirModel->itemForIndex(index); - if (!item.isNull()) { - const Nepomuk::Resource resource(item.url().url(), Nepomuk::NFO::File()); - const QList tags = resource.tags(); - QStringList stringList; - foreach (const Nepomuk::Tag& tag, tags) { - stringList.append(tag.label()); - } - stringList.sort(); - foreach (const QString& str, stringList) { - tagsString += str; - tagsString += ", "; - } - - if (!tagsString.isEmpty()) { - tagsString.resize(tagsString.size() - 2); - } - } - - return tagsString; -#else - Q_UNUSED(index); - return QString(); -#endif + return KDirSortFilterProxyModel::lessThan(left, right); } #include "dolphinsortfilterproxymodel.moc" diff --git a/src/dolphinsortfilterproxymodel.h b/src/dolphinsortfilterproxymodel.h index 2638f043a..d40dd17c1 100644 --- a/src/dolphinsortfilterproxymodel.h +++ b/src/dolphinsortfilterproxymodel.h @@ -25,7 +25,7 @@ #include /** - * @brief Acts as proxy model for KDirModel to sort and filter + * @brief Acts as proxy model for DolphinModel to sort and filter * KFileItems. * * A natural sorting is done. This means that items like: @@ -37,7 +37,10 @@ * - item_2.png * - item_10.png * - * It is assured that directories are always sorted before files. + * @note It is NOT assured that directories are always sorted before files. + * For example, on a Nepomuk based sorting, it is possible to have a file + * rated with 10 stars, and a directory rated with 5 stars. The file will + * be shown before the directory. */ class LIBDOLPHINPRIVATE_EXPORT DolphinSortFilterProxyModel : public KDirSortFilterProxyModel { @@ -84,13 +87,6 @@ public: virtual bool lessThanGeneralPurpose(const QModelIndex &left, const QModelIndex &right) const; - /** - * For each category, that exists due to lessThanGeneralPurpose(), the - * lessThanCategoryPurpose() will be applied. - */ - inline bool lessThanCategoryPurpose(const QModelIndex &left, - const QModelIndex &right) const; - signals: void sortingRoleChanged(); @@ -98,24 +94,9 @@ protected: virtual bool lessThan(const QModelIndex& left, 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. - */ - static quint32 ratingForIndex(const QModelIndex& index); - - /** - * Returns the tags for the item with the index \a index. If no - * tag is applied, a predefined string will be returned. - */ - static QString tagsForIndex(const QModelIndex& index); - private: DolphinView::Sorting m_sorting:16; Qt::SortOrder m_sortOrder:16; - - friend class DolphinItemCategorizer; }; DolphinView::Sorting DolphinSortFilterProxyModel::sorting() const @@ -128,10 +109,4 @@ Qt::SortOrder DolphinSortFilterProxyModel::sortOrder() const return m_sortOrder; } -bool DolphinSortFilterProxyModel::lessThanCategoryPurpose(const QModelIndex &left, - const QModelIndex &right) const -{ - return lessThan(left, right); -} - #endif diff --git a/src/dolphinview.cpp b/src/dolphinview.cpp index 0041ab35d..31ee64fed 100644 --- a/src/dolphinview.cpp +++ b/src/dolphinview.cpp @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -42,21 +41,22 @@ #include #include +#include "dolphinmodel.h" #include "dolphincolumnview.h" #include "dolphincontroller.h" #include "dolphinsortfilterproxymodel.h" #include "dolphindetailsview.h" #include "dolphiniconsview.h" -#include "dolphinitemcategorizer.h" #include "renamedialog.h" #include "viewproperties.h" #include "dolphinsettings.h" #include "dolphin_generalsettings.h" +#include "dolphincategorydrawer.h" DolphinView::DolphinView(QWidget* parent, const KUrl& url, KDirLister* dirLister, - KDirModel* dirModel, + DolphinModel* dolphinModel, DolphinSortFilterProxyModel* proxyModel) : QWidget(parent), m_active(true), @@ -69,7 +69,7 @@ DolphinView::DolphinView(QWidget* parent, m_detailsView(0), m_columnView(0), m_fileItemDelegate(0), - m_dirModel(dirModel), + m_dolphinModel(dolphinModel), m_dirLister(dirLister), m_proxyModel(proxyModel) { @@ -224,30 +224,20 @@ void DolphinView::setCategorizedSorting(bool categorized) } Q_ASSERT(m_iconsView != 0); - if (categorized) { - Q_ASSERT(m_iconsView->itemCategorizer() == 0); - m_iconsView->setItemCategorizer(new DolphinItemCategorizer()); - } else { - KItemCategorizer* categorizer = m_iconsView->itemCategorizer(); - m_iconsView->setItemCategorizer(0); - delete categorizer; - } ViewProperties props(viewPropertiesUrl()); props.setCategorizedSorting(categorized); props.save(); + m_proxyModel->setCategorizedModel(categorized); + m_proxyModel->sort(m_proxyModel->sortColumn(), m_proxyModel->sortOrder()); + emit categorizedSortingChanged(); } bool DolphinView::categorizedSorting() const { - if (!supportsCategorizedSorting()) { - return false; - } - - Q_ASSERT(m_iconsView != 0); - return m_iconsView->itemCategorizer() != 0; + return m_proxyModel->isCategorizedModel(); } bool DolphinView::supportsCategorizedSorting() const @@ -287,7 +277,7 @@ QList DolphinView::selectedItems() const { const QAbstractItemView* view = itemView(); - // Our view has a selection, we will map them back to the DirModel + // Our view has a selection, we will map them back to the DolphinModel // and then fill the KFileItemList. Q_ASSERT((view != 0) && (view->selectionModel() != 0)); @@ -296,7 +286,7 @@ QList DolphinView::selectedItems() const const QModelIndexList indexList = selection.indexes(); foreach (QModelIndex index, indexList) { - KFileItem item = m_dirModel->itemForIndex(index); + KFileItem item = m_dolphinModel->itemForIndex(index); if (!item.isNull()) { itemList.append(item); } @@ -318,8 +308,8 @@ KUrl::List DolphinView::selectedUrls() const KFileItem DolphinView::fileItem(const QModelIndex& index) const { - const QModelIndex dirModelIndex = m_proxyModel->mapToSource(index); - return m_dirModel->itemForIndex(dirModelIndex); + const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index); + return m_dolphinModel->itemForIndex(dolphinModelIndex); } void DolphinView::setContentsPosition(int x, int y) @@ -453,7 +443,8 @@ void DolphinView::triggerItem(const QModelIndex& index) return; } - const KFileItem item = m_dirModel->itemForIndex(m_proxyModel->mapToSource(index)); + const KFileItem item = m_dolphinModel->itemForIndex(m_proxyModel->mapToSource(index)); + if (item.isNull()) { return; } @@ -479,15 +470,15 @@ void DolphinView::showPreview(const KFileItem& item, const QPixmap& pixmap) return; } - const QModelIndex idx = m_dirModel->indexForItem(item); + const QModelIndex idx = m_dolphinModel->indexForItem(item); if (idx.isValid() && (idx.column() == 0)) { const QMimeData* mimeData = QApplication::clipboard()->mimeData(); if (KonqMimeData::decodeIsCutSelection(mimeData) && isCutItem(item)) { KIconEffect iconEffect; const QPixmap cutPixmap = iconEffect.apply(pixmap, K3Icon::Desktop, K3Icon::DisabledState); - m_dirModel->setData(idx, QIcon(cutPixmap), Qt::DecorationRole); + m_dolphinModel->setData(idx, QIcon(cutPixmap), Qt::DecorationRole); } else { - m_dirModel->setData(idx, QIcon(pixmap), Qt::DecorationRole); + m_dolphinModel->setData(idx, QIcon(pixmap), Qt::DecorationRole); } } } @@ -600,17 +591,7 @@ void DolphinView::applyViewProperties(const KUrl& url) const bool categorized = props.categorizedSorting(); if (categorized != categorizedSorting()) { - if (supportsCategorizedSorting()) { - Q_ASSERT(m_iconsView != 0); - if (categorized) { - Q_ASSERT(m_iconsView->itemCategorizer() == 0); - m_iconsView->setItemCategorizer(new DolphinItemCategorizer()); - } else { - KItemCategorizer* categorizer = m_iconsView->itemCategorizer(); - m_iconsView->setItemCategorizer(0); - delete categorizer; - } - } + m_proxyModel->setCategorizedModel(categorized); emit categorizedSortingChanged(); } @@ -652,7 +633,7 @@ void DolphinView::changeSelection(const QList& selection) foreach(const KFileItem& item, selection) { url = item.url().upUrl(); if (baseUrl.equals(url, KUrl::CompareWithoutTrailingSlash)) { - QModelIndex index = m_proxyModel->mapFromSource(m_dirModel->indexForItem(item)); + QModelIndex index = m_proxyModel->mapFromSource(m_dolphinModel->indexForItem(item)); new_selection.select(index, index); } } @@ -744,9 +725,9 @@ void DolphinView::updateCutItems() QList::const_iterator it = m_cutItemsCache.begin(); QList::const_iterator end = m_cutItemsCache.end(); while (it != end) { - const QModelIndex index = m_dirModel->indexForUrl((*it).url); + const QModelIndex index = m_dolphinModel->indexForUrl((*it).url); if (index.isValid()) { - m_dirModel->setData(index, QIcon((*it).pixmap), Qt::DecorationRole); + m_dolphinModel->setData(index, QIcon((*it).pixmap), Qt::DecorationRole); } ++it; } @@ -781,11 +762,6 @@ void DolphinView::createView() if (view != 0) { m_topLayout->removeWidget(view); view->close(); - if (view == m_iconsView) { - KItemCategorizer* categorizer = m_iconsView->itemCategorizer(); - m_iconsView->setItemCategorizer(0); - delete categorizer; - } view->deleteLater(); view = 0; m_iconsView = 0; @@ -802,6 +778,7 @@ void DolphinView::createView() switch (m_mode) { case IconsView: m_iconsView = new DolphinIconsView(this, m_controller); + m_iconsView->setCategoryDrawer(new DolphinCategoryDrawer()); view = m_iconsView; break; @@ -824,7 +801,7 @@ void DolphinView::createView() view->setModel(m_proxyModel); view->setSelectionMode(QAbstractItemView::ExtendedSelection); - new KMimeTypeResolver(view, m_dirModel); + new KMimeTypeResolver(view, m_dolphinModel); m_topLayout->insertWidget(1, view); connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), @@ -849,7 +826,7 @@ QAbstractItemView* DolphinView::itemView() const bool DolphinView::isValidNameIndex(const QModelIndex& index) const { - return index.isValid() && (index.column() == KDirModel::Name); + return index.isValid() && (index.column() == DolphinModel::Name); } bool DolphinView::isCutItem(const KFileItem& item) const @@ -883,10 +860,10 @@ void DolphinView::applyCutItemEffect() while (it != end) { KFileItem* item = *it; if (isCutItem(*item)) { - const QModelIndex index = m_dirModel->indexForItem(*item); + const QModelIndex index = m_dolphinModel->indexForItem(*item); // Huh? the item is already known - //const KFileItem item = m_dirModel->itemForIndex(index); - const QVariant value = m_dirModel->data(index, Qt::DecorationRole); + //const KFileItem item = m_dolphinModel->itemForIndex(index); + const QVariant value = m_dolphinModel->data(index, Qt::DecorationRole); if (value.type() == QVariant::Icon) { const QIcon icon(qvariant_cast(value)); QPixmap pixmap = icon.pixmap(128, 128); @@ -901,7 +878,7 @@ void DolphinView::applyCutItemEffect() // apply icon effect to the cut item KIconEffect iconEffect; pixmap = iconEffect.apply(pixmap, K3Icon::Desktop, K3Icon::DisabledState); - m_dirModel->setData(index, QIcon(pixmap), Qt::DecorationRole); + m_dolphinModel->setData(index, QIcon(pixmap), Qt::DecorationRole); } } ++it; diff --git a/src/dolphinview.h b/src/dolphinview.h index fa47ba8a5..159613cd9 100644 --- a/src/dolphinview.h +++ b/src/dolphinview.h @@ -41,7 +41,7 @@ class DolphinController; class KDirLister; class KFileItemDelegate; class KUrl; -class KDirModel; +class DolphinModel; class DolphinColumnView; class DolphinDetailsView; class DolphinIconsView; @@ -116,7 +116,7 @@ public: * @param url Specifies the content which should be shown. * @param dirLister Used directory lister. The lister is not owned * by the view and won't get deleted. - * @param dirModel Used directory model. The model is not owned + * @param dolphinModel Used directory model. The model is not owned * by the view and won't get deleted. * @param proxyModel Used proxy model which specifies the sorting. The * model is not owned by the view and won't get @@ -125,7 +125,7 @@ public: DolphinView(QWidget* parent, const KUrl& url, KDirLister* dirLister, - KDirModel* dirModel, + DolphinModel* dolphinModel, DolphinSortFilterProxyModel* proxyModel); virtual ~DolphinView(); @@ -509,7 +509,7 @@ private: /** * Returns true if the index is valid and represents - * the column KDirModel::Name. + * the column DolphinModel::Name. */ bool isValidNameIndex(const QModelIndex& index) const; @@ -563,7 +563,7 @@ private: DolphinColumnView* m_columnView; KFileItemDelegate* m_fileItemDelegate; - KDirModel* m_dirModel; + DolphinModel* m_dolphinModel; KDirLister* m_dirLister; DolphinSortFilterProxyModel* m_proxyModel; diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp index 379c238d9..c30b2d0bc 100644 --- a/src/dolphinviewcontainer.cpp +++ b/src/dolphinviewcontainer.cpp @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -41,6 +40,7 @@ #include #include +#include "dolphinmodel.h" #include "dolphincolumnview.h" #include "dolphincontroller.h" #include "dolphinstatusbar.h" @@ -50,7 +50,6 @@ #include "dolphindetailsview.h" #include "dolphiniconsview.h" #include "dolphincontextmenu.h" -#include "dolphinitemcategorizer.h" #include "filterbar.h" #include "renamedialog.h" #include "kurlnavigator.h" @@ -71,7 +70,6 @@ DolphinViewContainer::DolphinViewContainer(DolphinMainWindow* mainWindow, m_view(0), m_filterBar(0), m_statusBar(0), - m_dirModel(0), m_dirLister(0), m_proxyModel(0) { @@ -96,12 +94,13 @@ DolphinViewContainer::DolphinViewContainer(DolphinMainWindow* mainWindow, m_dirLister->setMainWindow(this); m_dirLister->setDelayedMimeTypes(true); - m_dirModel = new KDirModel(); - m_dirModel->setDirLister(m_dirLister); - m_dirModel->setDropsAllowed(KDirModel::DropOnDirectory); + m_dolphinModel = new DolphinModel(); + m_dolphinModel->setDirLister(m_dirLister); + m_dolphinModel->setDropsAllowed(DolphinModel::DropOnDirectory); + m_proxyModel = new DolphinSortFilterProxyModel(this); - m_proxyModel->setSourceModel(m_dirModel); + m_proxyModel->setSourceModel(m_dolphinModel); connect(m_dirLister, SIGNAL(clear()), this, SLOT(updateStatusBar())); @@ -119,7 +118,7 @@ DolphinViewContainer::DolphinViewContainer(DolphinMainWindow* mainWindow, m_view = new DolphinView(this, url, m_dirLister, - m_dirModel, + m_dolphinModel, m_proxyModel); connect(m_view, SIGNAL(urlChanged(const KUrl&)), m_urlNavigator, SLOT(setUrl(const KUrl&))); @@ -268,8 +267,8 @@ bool DolphinViewContainer::isUrlEditable() const KFileItem DolphinViewContainer::fileItem(const QModelIndex& index) const { - const QModelIndex dirModelIndex = m_proxyModel->mapToSource(index); - return m_dirModel->itemForIndex(dirModelIndex); + const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index); + return m_dolphinModel->itemForIndex(dolphinModelIndex); } void DolphinViewContainer::updateProgress(int percent) @@ -349,6 +348,21 @@ void DolphinViewContainer::closeFilterBar() QString DolphinViewContainer::defaultStatusBarText() const { + int m_fileCount = 0; + int m_folderCount = 0; + + for (int i = 0; i < m_proxyModel->rowCount(); i++) + { + if (m_dolphinModel->itemForIndex(m_proxyModel->mapToSource(m_proxyModel->index(i, m_proxyModel->sortColumn()))).isDir()) + { + m_folderCount++; + } + else + { + m_fileCount++; + } + } + return KIO::itemsSummaryString(m_fileCount + m_folderCount, m_fileCount, m_folderCount, @@ -448,6 +462,8 @@ void DolphinViewContainer::changeNameFilter(const QString& nameFilter) #else m_proxyModel->setFilterRegExp(nameFilter); #endif + + updateStatusBar(); } void DolphinViewContainer::openContextMenu(const KFileItem& item, diff --git a/src/dolphinviewcontainer.h b/src/dolphinviewcontainer.h index 3c9223f19..f73fb8a26 100644 --- a/src/dolphinviewcontainer.h +++ b/src/dolphinviewcontainer.h @@ -23,7 +23,6 @@ #include "dolphinview.h" -#include #include #include #include @@ -38,7 +37,7 @@ class FilterBar; class KUrl; -class KDirModel; +class DolphinModel; class KUrlNavigator; class DolphinDirLister; class DolphinMainWindow; @@ -231,7 +230,7 @@ private: FilterBar* m_filterBar; DolphinStatusBar* m_statusBar; - KDirModel* m_dirModel; + DolphinModel* m_dolphinModel; DolphinDirLister* m_dirLister; DolphinSortFilterProxyModel* m_proxyModel; }; diff --git a/src/kcategorizedview.cpp b/src/kcategorizedview.cpp index e178760ee..7bc0055ae 100644 --- a/src/kcategorizedview.cpp +++ b/src/kcategorizedview.cpp @@ -29,55 +29,14 @@ #include #include -#include #include -#include "kitemcategorizer.h" -#include "dolphinsortfilterproxymodel.h" - -class LessThan -{ -public: - enum Purpose - { - GeneralPurpose = 0, - CategoryPurpose - }; - - inline LessThan(const DolphinSortFilterProxyModel *proxyModel, - Purpose purpose) - : proxyModel(proxyModel) - , purpose(purpose) - { - } - - inline bool operator()(const QModelIndex &left, - const QModelIndex &right) const - { - if (purpose == GeneralPurpose) - { - return proxyModel->sortOrder() == Qt::AscendingOrder ? - proxyModel->lessThanGeneralPurpose(left, right) : - !proxyModel->lessThanGeneralPurpose(left, right); - } - - return proxyModel->sortOrder() == Qt::AscendingOrder ? - proxyModel->lessThanCategoryPurpose(left, right) : - !proxyModel->lessThanCategoryPurpose(left, right); - } - -private: - const DolphinSortFilterProxyModel *proxyModel; - const Purpose purpose; -}; - - -//============================================================================== - +#include "kcategorydrawer.h" +#include "kcategorizedsortfilterproxymodel.h" KCategorizedView::Private::Private(KCategorizedView *listView) : listView(listView) - , itemCategorizer(0) + , categoryDrawer(0) , biggestItemSize(QSize(0, 0)) , mouseButtonPressed(false) , isDragging(false) @@ -116,7 +75,7 @@ const QModelIndexList &KCategorizedView::Private::intersectionSet(const QRect &r { middle = (top + bottom) / 2; - index = elementDictionary[proxyModel->index(middle, 0)]; + index = proxyModel->index(middle, 0); indexVisualRect = visualRect(index); // We need the whole height (not only the visualRect). This will help us to update // all needed indexes correctly (ereslibre) @@ -136,7 +95,7 @@ const QModelIndexList &KCategorizedView::Private::intersectionSet(const QRect &r for (int i = middle; i < proxyModel->rowCount(); i++) { - index = elementDictionary[proxyModel->index(i, 0)]; + index = proxyModel->index(i, 0); indexVisualRect = visualRect(index); if (rect.intersects(indexVisualRect)) @@ -157,10 +116,20 @@ QRect KCategorizedView::Private::visualRectInViewport(const QModelIndex &index) if (!index.isValid()) return QRect(); - QString curCategory = elementsInfo[index].category; + QString curCategory = elementsInfo[index.row()].category; - QRect retRect(listView->spacing(), listView->spacing() * 2 + - itemCategorizer->categoryHeight(listView->viewOptions()), 0, 0); + QRect retRect; + + if (listView->layoutDirection() == Qt::LeftToRight) + { + retRect = QRect(listView->spacing(), listView->spacing() * 2 + + categoryDrawer->categoryHeight(listView->viewOptions()), 0, 0); + } + else + { + retRect = QRect(listView->viewport()->width() - listView->spacing(), listView->spacing() * 2 + + categoryDrawer->categoryHeight(listView->viewOptions()), 0, 0); + } int viewportWidth = listView->viewport()->width() - listView->spacing(); @@ -183,11 +152,22 @@ QRect KCategorizedView::Private::visualRectInViewport(const QModelIndex &index) if (!elementsPerRow) elementsPerRow++; - int column = elementsInfo[index].relativeOffsetToCategory % elementsPerRow; - int row = elementsInfo[index].relativeOffsetToCategory / elementsPerRow; + int column = elementsInfo[index.row()].relativeOffsetToCategory % elementsPerRow; + int row = elementsInfo[index.row()].relativeOffsetToCategory / elementsPerRow; - retRect.setLeft(retRect.left() + column * listView->spacing() + - column * itemWidth); + if (listView->layoutDirection() == Qt::LeftToRight) + { + retRect.setLeft(retRect.left() + column * listView->spacing() + + column * itemWidth); + } + else + { + retRect.setLeft(retRect.right() - column * listView->spacing() - + column * itemWidth - itemWidth); + + retRect.setRight(retRect.right() - column * listView->spacing() - + column * itemWidth); + } foreach (const QString &category, categories) { @@ -196,13 +176,14 @@ QRect KCategorizedView::Private::visualRectInViewport(const QModelIndex &index) float rows = (float) ((float) categoriesIndexes[category].count() / (float) elementsPerRow); + int rowsInt = categoriesIndexes[category].count() / elementsPerRow; if (rows - trunc(rows)) rowsInt++; retRect.setTop(retRect.top() + (rowsInt * itemHeight) + - itemCategorizer->categoryHeight(listView->viewOptions()) + + categoryDrawer->categoryHeight(listView->viewOptions()) + listView->spacing() * 2); if (listView->gridSize().isEmpty()) @@ -212,7 +193,6 @@ QRect KCategorizedView::Private::visualRectInViewport(const QModelIndex &index) } } - if (listView->gridSize().isEmpty()) { retRect.setTop(retRect.top() + row * listView->spacing() + @@ -225,13 +205,14 @@ QRect KCategorizedView::Private::visualRectInViewport(const QModelIndex &index) retRect.setWidth(itemWidth); + QModelIndex heightIndex = proxyModel->index(index.row(), 0); if (listView->gridSize().isEmpty()) { - retRect.setHeight(listView->sizeHintForIndex(proxyModel->mapFromSource(index)).height()); + retRect.setHeight(listView->sizeHintForIndex(heightIndex).height()); } else { - retRect.setHeight(qMin(listView->sizeHintForIndex(proxyModel->mapFromSource(index)).height(), + retRect.setHeight(qMin(listView->sizeHintForIndex(heightIndex).height(), listView->gridSize().height())); } @@ -286,7 +267,7 @@ QRect KCategorizedView::Private::visualCategoryRectInViewport(const QString &cat retRect.setTop(retRect.top() + (rowsInt * itemHeight) + - itemCategorizer->categoryHeight(listView->viewOptions()) + + categoryDrawer->categoryHeight(listView->viewOptions()) + listView->spacing() * 2); if (listView->gridSize().isEmpty()) @@ -296,7 +277,7 @@ QRect KCategorizedView::Private::visualCategoryRectInViewport(const QString &cat } } - retRect.setHeight(itemCategorizer->categoryHeight(listView->viewOptions())); + retRect.setHeight(categoryDrawer->categoryHeight(listView->viewOptions())); return retRect; } @@ -305,9 +286,9 @@ QRect KCategorizedView::Private::visualCategoryRectInViewport(const QString &cat const QRect &KCategorizedView::Private::cacheIndex(const QModelIndex &index) { QRect rect = visualRectInViewport(index); - elementsPosition[index] = rect; + elementsPosition[index.row()] = rect; - return elementsPosition[index]; + return elementsPosition[index.row()]; } // We're sure categoriesPosition doesn't contain category @@ -321,9 +302,9 @@ const QRect &KCategorizedView::Private::cacheCategory(const QString &category) const QRect &KCategorizedView::Private::cachedRectIndex(const QModelIndex &index) { - if (elementsPosition.contains(index)) // If we have it cached + if (elementsPosition.contains(index.row())) // If we have it cached { // return it - return elementsPosition[index]; + return elementsPosition[index.row()]; } else // Otherwise, cache it { // and return it @@ -345,9 +326,7 @@ const QRect &KCategorizedView::Private::cachedRectCategory(const QString &catego QRect KCategorizedView::Private::visualRect(const QModelIndex &index) { - QModelIndex mappedIndex = proxyModel->mapToSource(index); - - QRect retRect = cachedRectIndex(mappedIndex); + QRect retRect = cachedRectIndex(index); int dx = -listView->horizontalOffset(); int dy = -listView->verticalOffset(); retRect.adjust(dx, dy, dx, dy); @@ -366,29 +345,34 @@ QRect KCategorizedView::Private::categoryVisualRect(const QString &category) } void KCategorizedView::Private::drawNewCategory(const QModelIndex &index, - int sortRole, - const QStyleOption &option, - QPainter *painter) + int sortRole, + const QStyleOption &option, + QPainter *painter) { + if (!index.isValid()) + { + return; + } + QStyleOption optionCopy = option; - const QString category = itemCategorizer->categoryForItem(index, sortRole); + const QString category = proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryRole).toString(); if ((category == hoveredCategory) && !mouseButtonPressed) { optionCopy.state |= QStyle::State_MouseOver; } - itemCategorizer->drawCategory(index, - sortRole, - optionCopy, - painter); + categoryDrawer->drawCategory(index, + sortRole, + optionCopy, + painter); } void KCategorizedView::Private::updateScrollbars() { - // find the last index in the last category - QModelIndex lastIndex = categoriesIndexes.isEmpty() ? QModelIndex() : categoriesIndexes[categories.last()].last(); + // find the last index in the last category + QModelIndex lastIndex = categoriesIndexes.isEmpty() ? QModelIndex() : categoriesIndexes[categories.last()].last(); int lastItemBottom = cachedRectIndex(lastIndex).top() + listView->spacing() + (listView->gridSize().isEmpty() ? 0 : listView->gridSize().height()) - listView->viewport()->height(); @@ -455,6 +439,13 @@ KCategorizedView::~KCategorizedView() delete d; } +void KCategorizedView::setGridSize(const QSize &size) +{ + QListView::setGridSize(size); + + slotLayoutChanged(); +} + void KCategorizedView::setModel(QAbstractItemModel *model) { d->lastSelection = QItemSelection(); @@ -462,47 +453,45 @@ void KCategorizedView::setModel(QAbstractItemModel *model) d->forcedSelectionPosition = 0; d->elementsInfo.clear(); d->elementsPosition.clear(); - d->elementDictionary.clear(); - d->invertedElementDictionary.clear(); d->categoriesIndexes.clear(); d->categoriesPosition.clear(); d->categories.clear(); d->intersectedIndexes.clear(); - d->sourceModelIndexList.clear(); + d->modelIndexList.clear(); d->hovered = QModelIndex(); d->mouseButtonPressed = false; if (d->proxyModel) { QObject::disconnect(d->proxyModel, - SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved(QModelIndex,int,int))); + SIGNAL(layoutChanged()), + this, SLOT(slotLayoutChanged())); QObject::disconnect(d->proxyModel, - SIGNAL(sortingRoleChanged()), - this, SLOT(slotSortingRoleChanged())); + SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(slotLayoutChanged())); } QListView::setModel(model); - d->proxyModel = dynamic_cast(model); + d->proxyModel = dynamic_cast(model); if (d->proxyModel) { QObject::connect(d->proxyModel, - SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved(QModelIndex,int,int))); + SIGNAL(layoutChanged()), + this, SLOT(slotLayoutChanged())); QObject::connect(d->proxyModel, - SIGNAL(sortingRoleChanged()), - this, SLOT(slotSortingRoleChanged())); + SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(slotLayoutChanged())); } } QRect KCategorizedView::visualRect(const QModelIndex &index) const { if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { return QListView::visualRect(index); } @@ -515,54 +504,55 @@ QRect KCategorizedView::visualRect(const QModelIndex &index) const return d->visualRect(index); } -KItemCategorizer *KCategorizedView::itemCategorizer() const +KCategoryDrawer *KCategorizedView::categoryDrawer() const { - return d->itemCategorizer; + return d->categoryDrawer; } -void KCategorizedView::setItemCategorizer(KItemCategorizer *itemCategorizer) +void KCategorizedView::setCategoryDrawer(KCategoryDrawer *categoryDrawer) { d->lastSelection = QItemSelection(); d->currentViewIndex = QModelIndex(); d->forcedSelectionPosition = 0; d->elementsInfo.clear(); d->elementsPosition.clear(); - d->elementDictionary.clear(); - d->invertedElementDictionary.clear(); d->categoriesIndexes.clear(); d->categoriesPosition.clear(); d->categories.clear(); d->intersectedIndexes.clear(); - d->sourceModelIndexList.clear(); + d->modelIndexList.clear(); d->hovered = QModelIndex(); d->mouseButtonPressed = false; - if (!itemCategorizer && d->proxyModel) + if (!categoryDrawer && d->proxyModel) { QObject::disconnect(d->proxyModel, - SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved(QModelIndex,int,int))); + SIGNAL(layoutChanged()), + this, SLOT(slotLayoutChanged())); QObject::disconnect(d->proxyModel, - SIGNAL(sortingRoleChanged()), - this, SLOT(slotSortingRoleChanged())); + SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(slotLayoutChanged())); } - else if (itemCategorizer && d->proxyModel) + else if (categoryDrawer && d->proxyModel) { QObject::connect(d->proxyModel, - SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved(QModelIndex,int,int))); + SIGNAL(layoutChanged()), + this, SLOT(slotLayoutChanged())); QObject::connect(d->proxyModel, - SIGNAL(sortingRoleChanged()), - this, SLOT(slotSortingRoleChanged())); + SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(slotLayoutChanged())); } - d->itemCategorizer = itemCategorizer; + d->categoryDrawer = categoryDrawer; - if (itemCategorizer) + if (categoryDrawer) { - rowsInserted(QModelIndex(), 0, d->proxyModel->rowCount() - 1); + if (d->proxyModel) + { + rowsInserted(QModelIndex(), 0, d->proxyModel->rowCount() - 1); + } } else { @@ -573,7 +563,7 @@ void KCategorizedView::setItemCategorizer(KItemCategorizer *itemCategorizer) QModelIndex KCategorizedView::indexAt(const QPoint &point) const { if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { return QListView::indexAt(point); } @@ -601,13 +591,11 @@ void KCategorizedView::reset() d->forcedSelectionPosition = 0; d->elementsInfo.clear(); d->elementsPosition.clear(); - d->elementDictionary.clear(); - d->invertedElementDictionary.clear(); d->categoriesIndexes.clear(); d->categoriesPosition.clear(); d->categories.clear(); d->intersectedIndexes.clear(); - d->sourceModelIndexList.clear(); + d->modelIndexList.clear(); d->hovered = QModelIndex(); d->biggestItemSize = QSize(0, 0); d->mouseButtonPressed = false; @@ -616,7 +604,7 @@ void KCategorizedView::reset() void KCategorizedView::paintEvent(QPaintEvent *event) { if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { QListView::paintEvent(event); return; @@ -689,7 +677,9 @@ void KCategorizedView::paintEvent(QPaintEvent *event) if (otherOption.rect.intersects(area)) { - d->drawNewCategory(d->categoriesIndexes[category][0], + QModelIndex indexToDraw = d->proxyModel->index(d->categoriesIndexes[category][0].row(), d->proxyModel->sortColumn()); + + d->drawNewCategory(indexToDraw, d->proxyModel->sortRole(), otherOption, &painter); } } @@ -744,7 +734,7 @@ void KCategorizedView::resizeEvent(QResizeEvent *event) d->forcedSelectionPosition = 0; if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { return; } @@ -756,7 +746,7 @@ void KCategorizedView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags) { if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { QListView::setSelection(rect, flags); return; @@ -830,7 +820,7 @@ void KCategorizedView::mouseMoveEvent(QMouseEvent *event) QListView::mouseMoveEvent(event); if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { return; } @@ -910,7 +900,7 @@ void KCategorizedView::mouseReleaseEvent(QMouseEvent *event) QListView::mouseReleaseEvent(event); if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { return; } @@ -929,7 +919,9 @@ void KCategorizedView::mouseReleaseEvent(QMouseEvent *event) { foreach (const QModelIndex &index, d->categoriesIndexes[category]) { - selection << QItemSelectionRange(d->proxyModel->mapFromSource(index)); + QModelIndex selectIndex = index.model()->index(index.row(), 0); + + selection << QItemSelectionRange(selectIndex); } selectionModel()->select(selection, QItemSelectionModel::Select); @@ -981,7 +973,7 @@ void KCategorizedView::dragMoveEvent(QDragMoveEvent *event) d->dragLeftViewport = false; if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { QListView::dragMoveEvent(event); return; @@ -1000,10 +992,11 @@ void KCategorizedView::dragLeaveEvent(QDragLeaveEvent *event) QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) { - if ( (viewMode() != KCategorizedView::IconMode) || - !d->proxyModel || - !d->itemCategorizer || - d->categories.isEmpty() + if ((viewMode() != KCategorizedView::IconMode) || + !d->proxyModel || + !d->categoryDrawer || + d->categories.isEmpty() || + !d->proxyModel->isCategorizedModel() ) { return QListView::moveCursor(cursorAction, modifiers); @@ -1040,7 +1033,7 @@ QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, break; } - if (category == d->elementsInfo[d->proxyModel->mapToSource(current)].category) + if (category == d->elementsInfo[d->proxyModel->mapToSource(current).row()].category) { theCategory = category; @@ -1052,21 +1045,22 @@ QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, lastCategory = category; } } - +// ### FIXME !!! +#if 0 switch (cursorAction) { case QAbstractItemView::MoveUp: { - if (d->elementsInfo[d->proxyModel->mapToSource(current)].relativeOffsetToCategory >= elementsPerRow) + if (d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory >= elementsPerRow) { - int indexToMove = d->invertedElementDictionary[current].row(); - indexToMove -= qMin(((d->elementsInfo[d->proxyModel->mapToSource(current)].relativeOffsetToCategory) + d->forcedSelectionPosition), elementsPerRow - d->forcedSelectionPosition + (d->elementsInfo[d->proxyModel->mapToSource(current)].relativeOffsetToCategory % elementsPerRow)); + int indexToMove = d->invertedElementDictionary[current.row()].row(); + indexToMove -= qMin(((d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory) + d->forcedSelectionPosition), elementsPerRow - d->forcedSelectionPosition + (d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory % elementsPerRow)); - return d->elementDictionary[d->proxyModel->index(indexToMove, 0)]; + return d->elementDictionary[indexToMove]; } else { int lastCategoryLastRow = (d->categoriesIndexes[lastCategory].count() - 1) % elementsPerRow; - int indexToMove = d->invertedElementDictionary[current].row() - d->elementsInfo[d->proxyModel->mapToSource(current)].relativeOffsetToCategory; + int indexToMove = d->invertedElementDictionary[current.row()].row() - d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory; if (d->forcedSelectionPosition >= lastCategoryLastRow) { @@ -1077,22 +1071,22 @@ QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, indexToMove -= qMin((lastCategoryLastRow - d->forcedSelectionPosition + 1), d->forcedSelectionPosition + elementsPerRow + 1); } - return d->elementDictionary[d->proxyModel->index(indexToMove, 0)]; + return d->elementDictionary[indexToMove]; } } case QAbstractItemView::MoveDown: { - if (d->elementsInfo[d->proxyModel->mapToSource(current)].relativeOffsetToCategory < (d->categoriesIndexes[theCategory].count() - 1 - ((d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow))) + if (d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory < (d->categoriesIndexes[theCategory].count() - 1 - ((d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow))) { - int indexToMove = d->invertedElementDictionary[current].row(); - indexToMove += qMin(elementsPerRow, d->categoriesIndexes[theCategory].count() - 1 - d->elementsInfo[d->proxyModel->mapToSource(current)].relativeOffsetToCategory); + int indexToMove = d->invertedElementDictionary[current.row()].row(); + indexToMove += qMin(elementsPerRow, d->categoriesIndexes[theCategory].count() - 1 - d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory); - return d->elementDictionary[d->proxyModel->index(indexToMove, 0)]; + return d->elementDictionary[indexToMove]; } else { int afterCategoryLastRow = qMin(elementsPerRow, d->categoriesIndexes[afterCategory].count()); - int indexToMove = d->invertedElementDictionary[current].row() + (d->categoriesIndexes[theCategory].count() - d->elementsInfo[d->proxyModel->mapToSource(current)].relativeOffsetToCategory); + int indexToMove = d->invertedElementDictionary[current.row()].row() + (d->categoriesIndexes[theCategory].count() - d->elementsInfo[d->proxyModel->mapToSource(current).row()].relativeOffsetToCategory); if (d->forcedSelectionPosition >= afterCategoryLastRow) { @@ -1103,30 +1097,30 @@ QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, indexToMove += qMin(d->forcedSelectionPosition, elementsPerRow); } - return d->elementDictionary[d->proxyModel->index(indexToMove, 0)]; + return d->elementDictionary[indexToMove]; } } case QAbstractItemView::MoveLeft: - d->forcedSelectionPosition = d->elementsInfo[d->proxyModel->mapToSource(d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current].row() - 1, 0)])].relativeOffsetToCategory % elementsPerRow; + d->forcedSelectionPosition = d->elementsInfo[d->proxyModel->mapToSource(d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current.row()].row() - 1, 0).row()]).row()].relativeOffsetToCategory % elementsPerRow; if (d->forcedSelectionPosition < 0) d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow; - return d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current].row() - 1, 0)]; + return d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current.row()].row() - 1, 0).row()]; case QAbstractItemView::MoveRight: - d->forcedSelectionPosition = d->elementsInfo[d->proxyModel->mapToSource(d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current].row() + 1, 0)])].relativeOffsetToCategory % elementsPerRow; + d->forcedSelectionPosition = d->elementsInfo[d->proxyModel->mapToSource(d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current.row()].row() + 1, 0).row()]).row()].relativeOffsetToCategory % elementsPerRow; if (d->forcedSelectionPosition < 0) d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow; - return d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current].row() + 1, 0)]; + return d->elementDictionary[d->proxyModel->index(d->invertedElementDictionary[current.row()].row() + 1, 0).row()]; default: break; } - +#endif return QListView::moveCursor(cursorAction, modifiers); } @@ -1137,20 +1131,18 @@ void KCategorizedView::rowsInserted(const QModelIndex &parent, QListView::rowsInserted(parent, start, end); if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { d->lastSelection = QItemSelection(); d->currentViewIndex = QModelIndex(); d->forcedSelectionPosition = 0; d->elementsInfo.clear(); d->elementsPosition.clear(); - d->elementDictionary.clear(); - d->invertedElementDictionary.clear(); d->categoriesIndexes.clear(); d->categoriesPosition.clear(); d->categories.clear(); d->intersectedIndexes.clear(); - d->sourceModelIndexList.clear(); + d->modelIndexList.clear(); d->hovered = QModelIndex(); d->biggestItemSize = QSize(0, 0); d->mouseButtonPressed = false; @@ -1172,13 +1164,11 @@ void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent, d->forcedSelectionPosition = 0; d->elementsInfo.clear(); d->elementsPosition.clear(); - d->elementDictionary.clear(); - d->invertedElementDictionary.clear(); d->categoriesIndexes.clear(); d->categoriesPosition.clear(); d->categories.clear(); d->intersectedIndexes.clear(); - d->sourceModelIndexList.clear(); + d->modelIndexList.clear(); d->hovered = QModelIndex(); d->biggestItemSize = QSize(0, 0); d->mouseButtonPressed = false; @@ -1196,84 +1186,44 @@ void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent, qMax(sizeHintForIndex(d->proxyModel->index(k, 0)).height(), d->biggestItemSize.height())); - d->sourceModelIndexList << - d->proxyModel->mapToSource(d->proxyModel->index(k, 0)); + d->modelIndexList << d->proxyModel->index(k, d->proxyModel->sortColumn()); } - // Sort them with the general purpose lessThan method - LessThan generalLessThan(d->proxyModel, - LessThan::GeneralPurpose); - - qStableSort(d->sourceModelIndexList.begin(), d->sourceModelIndexList.end(), - generalLessThan); - // Explore categories - QString prevCategory = - d->itemCategorizer->categoryForItem(d->sourceModelIndexList[0], - d->proxyModel->sortRole()); + QString prevCategory = d->proxyModel->data(d->modelIndexList[0], KCategorizedSortFilterProxyModel::CategoryRole).toString(); QString lastCategory = prevCategory; QModelIndexList modelIndexList; struct Private::ElementInfo elementInfo; - foreach (const QModelIndex &index, d->sourceModelIndexList) + int offset = -1; + foreach (const QModelIndex &index, d->modelIndexList) { - lastCategory = d->itemCategorizer->categoryForItem(index, - d->proxyModel->sortRole()); + lastCategory = d->proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryRole).toString(); elementInfo.category = lastCategory; if (prevCategory != lastCategory) { + offset = 0; d->categoriesIndexes.insert(prevCategory, modelIndexList); d->categories << prevCategory; modelIndexList.clear(); } + else + { + offset++; + } + + elementInfo.relativeOffsetToCategory = offset; modelIndexList << index; prevCategory = lastCategory; - d->elementsInfo.insert(index, elementInfo); + d->elementsInfo.insert(index.row(), elementInfo); } d->categoriesIndexes.insert(prevCategory, modelIndexList); d->categories << prevCategory; - // Sort items locally in their respective categories with the category - // purpose lessThan - LessThan categoryLessThan(d->proxyModel, - LessThan::CategoryPurpose); - - foreach (const QString &key, d->categories) - { - QModelIndexList &indexList = d->categoriesIndexes[key]; - - qStableSort(indexList.begin(), indexList.end(), categoryLessThan); - } - - // Finally, fill data information of items situation. This will help when - // trying to compute an item place in the viewport - int i = 0; // position relative to the category beginning - int j = 0; // number of elements before current - foreach (const QString &key, d->categories) - { - foreach (const QModelIndex &index, d->categoriesIndexes[key]) - { - struct Private::ElementInfo &elementInfo = d->elementsInfo[index]; - - elementInfo.relativeOffsetToCategory = i; - - d->elementDictionary.insert(d->proxyModel->index(j, 0), - d->proxyModel->mapFromSource(index)); - - d->invertedElementDictionary.insert(d->proxyModel->mapFromSource(index), - d->proxyModel->index(j, 0)); - - i++; - j++; - } - - i = 0; - } - d->updateScrollbars(); } @@ -1282,7 +1232,7 @@ void KCategorizedView::rowsRemoved(const QModelIndex &parent, int end) { if ((viewMode() == KCategorizedView::IconMode) && d->proxyModel && - d->itemCategorizer) + d->categoryDrawer && d->proxyModel->isCategorizedModel()) { // Force the view to update all elements rowsInsertedArtifficial(parent, start, end); @@ -1292,7 +1242,7 @@ void KCategorizedView::rowsRemoved(const QModelIndex &parent, void KCategorizedView::updateGeometries() { if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel || - !d->itemCategorizer) + !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) { QListView::updateGeometries(); return; @@ -1303,10 +1253,10 @@ void KCategorizedView::updateGeometries() QAbstractItemView::updateGeometries(); } -void KCategorizedView::slotSortingRoleChanged() +void KCategorizedView::slotLayoutChanged() { if ((viewMode() == KCategorizedView::IconMode) && d->proxyModel && - d->itemCategorizer) + d->categoryDrawer && d->proxyModel->isCategorizedModel()) { // Force the view to update all elements rowsInsertedArtifficial(QModelIndex(), 0, d->proxyModel->rowCount() - 1); diff --git a/src/kcategorizedview.h b/src/kcategorizedview.h index 8741a6654..e0fbec9d5 100644 --- a/src/kcategorizedview.h +++ b/src/kcategorizedview.h @@ -25,7 +25,7 @@ #include -class KItemCategorizer; +class KCategoryDrawer; /** * @short Item view for listing items @@ -50,18 +50,13 @@ public: virtual void setModel(QAbstractItemModel *model); + void setGridSize(const QSize &size); + virtual QRect visualRect(const QModelIndex &index) const; - /** - * Will return the current categorizer. If none set, this method will - * return 0 - */ - KItemCategorizer *itemCategorizer() const; + KCategoryDrawer *categoryDrawer() const; - /** - * Sets the categorizer to be used. Causes the item view to repaint - */ - void setItemCategorizer(KItemCategorizer *itemCategorizer); + void setCategoryDrawer(KCategoryDrawer *categoryDrawer); virtual QModelIndex indexAt(const QPoint &point) const; @@ -108,7 +103,7 @@ protected Q_SLOTS: virtual void updateGeometries(); - virtual void slotSortingRoleChanged(); + virtual void slotLayoutChanged(); private: diff --git a/src/kcategorizedview_p.h b/src/kcategorizedview_p.h index 690db5ba9..d72753b1d 100644 --- a/src/kcategorizedview_p.h +++ b/src/kcategorizedview_p.h @@ -21,7 +21,8 @@ #ifndef KCATEGORIZEDVIEW_P_H #define KCATEGORIZEDVIEW_P_H -class DolphinSortFilterProxyModel; +class KCategorizedSortFilterProxyModel; +class KCategoryDrawer; /** * @internal @@ -122,7 +123,7 @@ public: // Basic data KCategorizedView *listView; - KItemCategorizer *itemCategorizer; + KCategoryDrawer *categoryDrawer; QSize biggestItemSize; // Behavior data @@ -140,10 +141,8 @@ public: // Cache data // We cannot merge some of them into structs because it would affect // performance - QHash elementsInfo; // in source model - QHash elementsPosition; // in source model - QHash elementDictionary; // mapped indexes - QHash invertedElementDictionary; // mapped indexes + QHash elementsInfo; + QHash elementsPosition; QHash categoriesIndexes; QHash categoriesPosition; QStringList categories; @@ -152,8 +151,8 @@ public: QRect lastSelectionRect; // Attributes for speed reasons - DolphinSortFilterProxyModel *proxyModel; - QModelIndexList sourceModelIndexList; // in source model + KCategorizedSortFilterProxyModel *proxyModel; + QModelIndexList modelIndexList; }; #endif // KCATEGORIZEDVIEW_P_H diff --git a/src/kitemcategorizer.cpp b/src/kcategorydrawer.cpp similarity index 83% rename from src/kitemcategorizer.cpp rename to src/kcategorydrawer.cpp index 93969c3a8..ebe77f4de 100644 --- a/src/kitemcategorizer.cpp +++ b/src/kcategorydrawer.cpp @@ -18,25 +18,27 @@ * Boston, MA 02110-1301, USA. */ -#include "kitemcategorizer.h" +#include "kcategorydrawer.h" #include #include -KItemCategorizer::KItemCategorizer() +#include + +KCategoryDrawer::KCategoryDrawer() { } -KItemCategorizer::~KItemCategorizer() +KCategoryDrawer::~KCategoryDrawer() { } -void KItemCategorizer::drawCategory(const QModelIndex &index, - int sortRole, - const QStyleOption &option, - QPainter *painter) const +void KCategoryDrawer::drawCategory(const QModelIndex &index, + int sortRole, + const QStyleOption &option, + QPainter *painter) const { - const QString category = categoryForItem(index, sortRole); + const QString category = index.model()->data(index, KCategorizedSortFilterProxyModel::CategoryRole).toString(); QColor color = option.palette.color(QPalette::Text); @@ -94,7 +96,7 @@ void KItemCategorizer::drawCategory(const QModelIndex &index, painter->restore(); } -int KItemCategorizer::categoryHeight(const QStyleOption &option) const +int KCategoryDrawer::categoryHeight(const QStyleOption &option) const { return option.fontMetrics.height() + 6 /* 4 separator; 2 gradient */; } diff --git a/src/kitemcategorizer.h b/src/kcategorydrawer.h similarity index 64% rename from src/kitemcategorizer.h rename to src/kcategorydrawer.h index aff048e29..c93e3fa40 100644 --- a/src/kitemcategorizer.h +++ b/src/kcategorydrawer.h @@ -18,41 +18,21 @@ * Boston, MA 02110-1301, USA. */ -#ifndef KITEMCATEGORIZER_H -#define KITEMCATEGORIZER_H +#ifndef KCATEGORYDRAWER_H +#define KCATEGORYDRAWER_H #include -class QString; class QPainter; class QModelIndex; class QStyleOption; -/** - * @short Class for item categorizing on KListView - * - * This class is meant to be used with KListView class. Its purpose is - * to decide to which category belongs a given index with the given role. - * Additionally it will let you to customize the way categories are drawn, - * only in the case that you want to do so - * - * @see KListView - * - * @author Rafael Fernández López - */ -class LIBDOLPHINPRIVATE_EXPORT KItemCategorizer +class LIBDOLPHINPRIVATE_EXPORT KCategoryDrawer { public: - KItemCategorizer(); - - virtual ~KItemCategorizer(); + KCategoryDrawer(); - /** - * This method will return the category where @param index fit on with the - * given @param sortRole role - */ - virtual QString categoryForItem(const QModelIndex &index, - int sortRole) const = 0; + virtual ~KCategoryDrawer(); /** * This method purpose is to draw a category represented by the given @@ -69,4 +49,4 @@ public: virtual int categoryHeight(const QStyleOption &option) const; }; -#endif // KITEMCATEGORIZER_H +#endif // KCATEGORYDRAWER_H diff --git a/src/sidebartreeview.cpp b/src/sidebartreeview.cpp index 92e8e2908..7bbddfdf2 100644 --- a/src/sidebartreeview.cpp +++ b/src/sidebartreeview.cpp @@ -20,8 +20,8 @@ #include "sidebartreeview.h" #include "dolphincontroller.h" +#include "dolphinmodel.h" -#include #include #include #include @@ -59,12 +59,12 @@ bool SidebarTreeView::event(QEvent* event) { if (event->type() == QEvent::Polish) { // hide all columns except of the 'Name' column - hideColumn(KDirModel::Size); - hideColumn(KDirModel::ModifiedTime); - hideColumn(KDirModel::Permissions); - hideColumn(KDirModel::Owner); - hideColumn(KDirModel::Group); - hideColumn(KDirModel::Type); + hideColumn(DolphinModel::Size); + hideColumn(DolphinModel::ModifiedTime); + hideColumn(DolphinModel::Permissions); + hideColumn(DolphinModel::Owner); + hideColumn(DolphinModel::Group); + hideColumn(DolphinModel::Type); header()->hide(); } diff --git a/src/treeviewsidebarpage.cpp b/src/treeviewsidebarpage.cpp index 1bcee405d..eac1e6cf4 100644 --- a/src/treeviewsidebarpage.cpp +++ b/src/treeviewsidebarpage.cpp @@ -19,6 +19,7 @@ #include "treeviewsidebarpage.h" +#include "dolphinmodel.h" #include "dolphinmainwindow.h" #include "dolphinsortfilterproxymodel.h" #include "dolphinview.h" @@ -28,7 +29,6 @@ #include #include -#include #include #include @@ -39,7 +39,7 @@ TreeViewSidebarPage::TreeViewSidebarPage(QWidget* parent) : SidebarPage(parent), m_dirLister(0), - m_dirModel(0), + m_dolphinModel(0), m_proxyModel(0), m_treeView(0), m_leafDir() @@ -89,16 +89,16 @@ void TreeViewSidebarPage::showEvent(QShowEvent* event) m_dirLister->setDelayedMimeTypes(true); m_dirLister->setAutoErrorHandlingEnabled(false, this); - Q_ASSERT(m_dirModel == 0); - m_dirModel = new KDirModel(this); - m_dirModel->setDirLister(m_dirLister); - m_dirModel->setDropsAllowed(KDirModel::DropOnDirectory); - connect(m_dirModel, SIGNAL(expand(const QModelIndex&)), + Q_ASSERT(m_dolphinModel == 0); + m_dolphinModel = new DolphinModel(this); + m_dolphinModel->setDirLister(m_dirLister); + m_dolphinModel->setDropsAllowed(DolphinModel::DropOnDirectory); + connect(m_dolphinModel, SIGNAL(expand(const QModelIndex&)), this, SLOT(triggerExpanding(const QModelIndex&))); Q_ASSERT(m_proxyModel == 0); m_proxyModel = new DolphinSortFilterProxyModel(this); - m_proxyModel->setSourceModel(m_dirModel); + m_proxyModel->setSourceModel(m_dolphinModel); Q_ASSERT(m_treeView == 0); m_treeView = new SidebarTreeView(this); @@ -130,8 +130,8 @@ void TreeViewSidebarPage::contextMenuEvent(QContextMenuEvent* event) return; } - const QModelIndex dirModelIndex = m_proxyModel->mapToSource(index); - KFileItem item = m_dirModel->itemForIndex(dirModelIndex); + const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index); + KFileItem item = m_dolphinModel->itemForIndex(dolphinModelIndex); emit changeSelection(QList()); TreeViewContextMenu contextMenu(this, item); @@ -149,13 +149,13 @@ void TreeViewSidebarPage::expandSelectionParent() return; } - QModelIndex index = m_dirModel->indexForUrl(parentUrl); + QModelIndex index = m_dolphinModel->indexForUrl(parentUrl); if (index.isValid()) { QModelIndex proxyIndex = m_proxyModel->mapFromSource(index); m_treeView->setExpanded(proxyIndex, true); // select the item and assure that the item is visible - index = m_dirModel->indexForUrl(url()); + index = m_dolphinModel->indexForUrl(url()); if (index.isValid()) { proxyIndex = m_proxyModel->mapFromSource(index); m_treeView->scrollTo(proxyIndex); @@ -169,7 +169,7 @@ void TreeViewSidebarPage::expandSelectionParent() void TreeViewSidebarPage::updateActiveView(const QModelIndex& index) { const QModelIndex dirIndex = m_proxyModel->mapToSource(index); - const KFileItem item = m_dirModel->itemForIndex(dirIndex); + const KFileItem item = m_dolphinModel->itemForIndex(dirIndex); if (!item.isNull()) { emit changeUrl(item.url()); } @@ -180,7 +180,7 @@ void TreeViewSidebarPage::dropUrls(const KUrl::List& urls, { if (index.isValid()) { const QModelIndex dirIndex = m_proxyModel->mapToSource(index); - KFileItem item = m_dirModel->itemForIndex(dirIndex); + KFileItem item = m_dolphinModel->itemForIndex(dirIndex); Q_ASSERT(!item.isNull()); if (item.isDir()) { emit urlsDropped(urls, item.url()); @@ -200,12 +200,12 @@ void TreeViewSidebarPage::expandToLeafDir() { // expand all directories until the parent directory of m_leafDir const KUrl parentUrl = m_leafDir.upUrl(); - QModelIndex dirIndex = m_dirModel->indexForUrl(parentUrl); + QModelIndex dirIndex = m_dolphinModel->indexForUrl(parentUrl); QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); m_treeView->setExpanded(proxyIndex, true); // assure that m_leafDir gets selected - dirIndex = m_dirModel->indexForUrl(m_leafDir); + dirIndex = m_dolphinModel->indexForUrl(m_leafDir); proxyIndex = m_proxyModel->mapFromSource(dirIndex); m_treeView->scrollTo(proxyIndex); @@ -227,7 +227,7 @@ void TreeViewSidebarPage::loadSubTree() return; } - const QModelIndex index = m_dirModel->indexForUrl(m_leafDir); + const QModelIndex index = m_dolphinModel->indexForUrl(m_leafDir); if (index.isValid()) { // the item with the given URL is already part of the model const QModelIndex proxyIndex = m_proxyModel->mapFromSource(index); @@ -237,7 +237,7 @@ void TreeViewSidebarPage::loadSubTree() // Load all sub directories that need to get expanded for making // the leaf directory visible. The slot triggerExpanding() will // get invoked if the expanding has been finished. - m_dirModel->expandToUrl(m_leafDir); + m_dolphinModel->expandToUrl(m_leafDir); } } diff --git a/src/treeviewsidebarpage.h b/src/treeviewsidebarpage.h index fae94b47d..1124dcf3f 100644 --- a/src/treeviewsidebarpage.h +++ b/src/treeviewsidebarpage.h @@ -24,7 +24,7 @@ #include class KDirLister; -class KDirModel; +class DolphinModel; class DolphinSortFilterProxyModel; class SidebarTreeView; @@ -110,7 +110,7 @@ private: private: KDirLister* m_dirLister; - KDirModel* m_dirModel; + DolphinModel* m_dolphinModel; DolphinSortFilterProxyModel* m_proxyModel; SidebarTreeView* m_treeView; KUrl m_leafDir; diff --git a/src/viewpropertiesdialog.cpp b/src/viewpropertiesdialog.cpp index 3f5197076..040e9f6be 100644 --- a/src/viewpropertiesdialog.cpp +++ b/src/viewpropertiesdialog.cpp @@ -26,8 +26,8 @@ #include "dolphin_generalsettings.h" #include "viewproperties.h" -#ifdef HAVE_NEPOMUK #include +#ifdef HAVE_NEPOMUK #include #endif