Group album cover search results by category

This commit is contained in:
David Sansome 2011-06-19 23:15:29 +00:00
parent 2552f6b232
commit c6e2981860
17 changed files with 3242 additions and 14 deletions

View File

@ -272,6 +272,9 @@ set(SOURCES
widgets/fileviewlist.cpp
widgets/freespacebar.cpp
widgets/fullscreenhypnotoad.cpp
widgets/kcategorizedsortfilterproxymodel.cpp
widgets/kcategorizedview.cpp
widgets/kcategorydrawer.cpp
widgets/lineedit.cpp
widgets/linetextedit.cpp
widgets/multiloadingindicator.cpp
@ -475,6 +478,8 @@ set(HEADERS
widgets/fileview.h
widgets/fileviewlist.h
widgets/freespacebar.h
widgets/kcategorizedview.h
widgets/kcategorydrawer.h
widgets/lineedit.h
widgets/linetextedit.h
widgets/multiloadingindicator.h

View File

@ -49,8 +49,13 @@ struct CoverSearchRequest {
// It contains an URL that leads to a found cover plus it's description (usually
// the "artist - album" string).
struct CoverSearchResult {
// used for grouping in the user interface. defaults to the name of the
// provider that this result came from.
QString category;
// description of this result (we suggest using the "artist - album" format)
QString description;
// an URL of a cover image described by this CoverSearchResult
QString image_url;
};

View File

@ -83,6 +83,14 @@ void AlbumCoverFetcherSearch::ProviderSearchFinished() {
if(reply->error() == QNetworkReply::NoError) {
CoverSearchResults partial_results = provider->ParseReply(reply);
// Add categories to the results if the provider didn't specify them
for (int i=0 ; i<partial_results.count() ; ++i) {
if (partial_results[i].category.isEmpty()) {
partial_results[i].category = provider->name();
}
}
// add results from the current provider to our pool
results_.append(partial_results);
} else {

View File

@ -48,7 +48,7 @@ class AlbumCoverFetcherSearch : public QObject {
signals:
// It's the end of search (when there was no fetch-me-a-cover request).
void SearchFinished(quint64, CoverSearchResults results);
void SearchFinished(quint64, const CoverSearchResults& results);
// It's the end of search and we've fetched a cover.
void AlbumCoverFetched(quint64, const QImage& cover);

View File

@ -172,6 +172,8 @@ PythonQtShell_CoverSearchResult* a = new PythonQtShell_CoverSearchResult();
*((CoverSearchResult*)a) = other;
return a; }
void delete_CoverSearchResult(CoverSearchResult* obj) { delete obj; }
void py_set_category(CoverSearchResult* theWrappedObject, QString category){ theWrappedObject->category = category; }
QString py_get_category(CoverSearchResult* theWrappedObject){ return theWrappedObject->category; }
void py_set_description(CoverSearchResult* theWrappedObject, QString description){ theWrappedObject->description = description; }
QString py_get_description(CoverSearchResult* theWrappedObject){ return theWrappedObject->description; }
void py_set_image_url(CoverSearchResult* theWrappedObject, QString image_url){ theWrappedObject->image_url = image_url; }

View File

@ -17,15 +17,69 @@
#include "albumcoversearcher.h"
#include "ui_albumcoversearcher.h"
#include "core/logging.h"
#include "covers/albumcoverfetcher.h"
#include "covers/albumcoverloader.h"
#include "widgets/kcategorizedsortfilterproxymodel.h"
#include <QKeyEvent>
#include <QListWidgetItem>
#include <QPainter>
#include <QStandardItemModel>
const int AlbumCoverCategoryDrawer::kBarThickness = 2;
const int AlbumCoverCategoryDrawer::kBarMarginTop = 3;
const int AlbumCoverCategoryDrawer::kBarMarginBottom = 10;
AlbumCoverCategoryDrawer::AlbumCoverCategoryDrawer(KCategorizedView* view)
: KCategoryDrawerV3(view),
total_height_(view->fontMetrics().height() +
kBarMarginTop + kBarThickness + kBarMarginBottom) {
setLeftMargin(kBarMarginBottom);
}
int AlbumCoverCategoryDrawer::categoryHeight(const QModelIndex&,
const QStyleOption&) const {
return total_height_;
}
void AlbumCoverCategoryDrawer::drawCategory(const QModelIndex& index, int,
const QStyleOption& option,
QPainter* painter) const {
painter->save();
// Bold font
QFont font(view()->font());
font.setBold(true);
QFontMetrics metrics(font);
// Draw text
const QString category = tr("Covers from %1").arg(
index.data(KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString());
painter->setFont(font);
painter->drawText(option.rect, category);
// Draw a line underneath
const QPoint start(option.rect.left(),
option.rect.top() + metrics.height() + kBarMarginTop);
const QPoint end(option.rect.right(), start.y());
painter->setRenderHint(QPainter::Antialiasing, true);
painter->setPen(QPen(option.palette.color(QPalette::Disabled, QPalette::Text),
kBarThickness, Qt::SolidLine, Qt::RoundCap));
painter->setOpacity(0.5);
painter->drawLine(start, end);
painter->restore();
}
AlbumCoverSearcher::AlbumCoverSearcher(const QIcon& no_cover_icon, QWidget* parent)
: QDialog(parent),
ui_(new Ui_AlbumCoverSearcher),
model_(new QStandardItemModel(this)),
no_cover_icon_(no_cover_icon),
loader_(new BackgroundThreadImplementation<AlbumCoverLoader, AlbumCoverLoader>(this)),
fetcher_(NULL),
@ -34,6 +88,12 @@ AlbumCoverSearcher::AlbumCoverSearcher(const QIcon& no_cover_icon, QWidget* pare
ui_->setupUi(this);
ui_->busy->hide();
KCategorizedSortFilterProxyModel* proxy = new KCategorizedSortFilterProxyModel(this);
proxy->setCategorizedModel(true);
proxy->setSourceModel(model_);
ui_->covers->setModel(proxy);
ui_->covers->setCategoryDrawer(new AlbumCoverCategoryDrawer(ui_->covers));
loader_->Start(true);
loader_->Worker()->SetDefaultOutputImage(QImage(":nocover.png"));
loader_->Worker()->SetScaleOutputImage(false);
@ -65,10 +125,12 @@ QImage AlbumCoverSearcher::Exec(const QString &query) {
if (exec() == QDialog::Rejected)
return QImage();
if (!ui_->covers->currentItem())
QModelIndex selected = ui_->covers->currentIndex();
if (!selected.isValid() || !selected.data(Role_ImageFetchFinished).toBool())
return QImage();
QIcon icon = ui_->covers->currentItem()->icon();
QIcon icon = selected.data(Qt::DecorationRole).value<QIcon>();
if (icon.cacheKey() == no_cover_icon_.cacheKey())
return QImage();
@ -81,7 +143,7 @@ void AlbumCoverSearcher::Search() {
ui_->query->setEnabled(false);
ui_->covers->setEnabled(false);
ui_->covers->clear();
model_->clear();
cover_loading_tasks_.clear();
id_ = fetcher_->SearchForCovers(ui_->query->text());
@ -102,12 +164,17 @@ void AlbumCoverSearcher::SearchFinished(quint64 id, const CoverSearchResults& re
quint64 id = loader_->Worker()->LoadImageAsync(result.image_url, QString());
QListWidgetItem* item = new QListWidgetItem(ui_->covers);
QStandardItem* item = new QStandardItem;
item->setIcon(no_cover_icon_);
item->setText(result.description);
item->setData(Role_ImageURL, result.image_url);
item->setData(Role_ImageRequestId, id);
item->setData(Qt::TextAlignmentRole, QVariant(Qt::AlignTop | Qt::AlignHCenter));
item->setData(result.image_url, Role_ImageURL);
item->setData(id, Role_ImageRequestId);
item->setData(false, Role_ImageFetchFinished);
item->setData(QVariant(Qt::AlignTop | Qt::AlignHCenter), Qt::TextAlignmentRole);
item->setData(result.category, KCategorizedSortFilterProxyModel::CategoryDisplayRole);
item->setData(result.category, KCategorizedSortFilterProxyModel::CategorySortRole);
model_->appendRow(item);
cover_loading_tasks_[id] = item;
}
@ -126,7 +193,8 @@ void AlbumCoverSearcher::ImageLoaded(quint64 id, const QImage& image) {
icon.addPixmap(QPixmap::fromImage(image.scaled(ui_->covers->iconSize(),
Qt::KeepAspectRatio, Qt::SmoothTransformation)));
QListWidgetItem* item = cover_loading_tasks_.take(id);
QStandardItem* item = cover_loading_tasks_.take(id);
item->setData(true, Role_ImageFetchFinished);
item->setIcon(icon);
item->setToolTip(item->text() + " (" + QString::number(image.width()) + "x" +
QString::number(image.height()) + ")");

View File

@ -20,6 +20,7 @@
#include "core/backgroundthread.h"
#include "covers/albumcoverfetcher.h"
#include "widgets/kcategorydrawer.h"
#include <QDialog>
#include <QIcon>
@ -29,8 +30,26 @@
class AlbumCoverLoader;
class Ui_AlbumCoverSearcher;
class QListWidgetItem;
class QModelIndex;
class QStandardItem;
class QStandardItemModel;
class AlbumCoverCategoryDrawer : public KCategoryDrawerV3 {
public:
AlbumCoverCategoryDrawer(KCategorizedView* view);
int categoryHeight(const QModelIndex& index, const QStyleOption& option) const;
void drawCategory(const QModelIndex& index, int sortRole,
const QStyleOption& option, QPainter* painter) const;
private:
static const int kBarThickness;
static const int kBarMarginTop;
static const int kBarMarginBottom;
int total_height_;
};
// This is a dialog that lets the user search for album covers
class AlbumCoverSearcher : public QDialog {
@ -43,6 +62,7 @@ public:
enum Role {
Role_ImageURL = Qt::UserRole + 1,
Role_ImageRequestId,
Role_ImageFetchFinished,
};
void Init(AlbumCoverFetcher* fetcher);
@ -62,12 +82,14 @@ private slots:
private:
Ui_AlbumCoverSearcher* ui_;
QStandardItemModel* model_;
QIcon no_cover_icon_;
BackgroundThread<AlbumCoverLoader>* loader_;
AlbumCoverFetcher* fetcher_;
quint64 id_;
QMap<quint64, QListWidgetItem*> cover_loading_tasks_;
QMap<quint64, QStandardItem*> cover_loading_tasks_;
};
#endif // ALBUMCOVERSEARCHER_H

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>556</width>
<height>354</height>
<width>829</width>
<height>518</height>
</rect>
</property>
<property name="windowTitle">
@ -36,7 +36,7 @@
</layout>
</item>
<item>
<widget class="QListWidget" name="covers">
<widget class="KCategorizedView" name="covers">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
@ -92,6 +92,11 @@
<extends>QLabel</extends>
<header>widgets/busyindicator.h</header>
</customwidget>
<customwidget>
<class>KCategorizedView</class>
<extends>QListView</extends>
<header>widgets/kcategorizedview.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>query</tabstop>

View File

@ -0,0 +1,167 @@
/**
* This file is part of the KDE project
* Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
* Copyright (C) 2007 John Tapsell <tapsell@kde.org>
*
* 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 "kcategorizedsortfilterproxymodel.h"
#include "kcategorizedsortfilterproxymodel_p.h"
#include <limits.h>
#include <QItemSelection>
#include <QStringList>
#include <QSize>
KCategorizedSortFilterProxyModel::KCategorizedSortFilterProxyModel(QObject *parent)
: QSortFilterProxyModel(parent)
, d(new Private())
{
}
KCategorizedSortFilterProxyModel::~KCategorizedSortFilterProxyModel()
{
delete d;
}
void KCategorizedSortFilterProxyModel::sort(int column, Qt::SortOrder order)
{
d->sortColumn = column;
d->sortOrder = order;
QSortFilterProxyModel::sort(column, order);
}
bool KCategorizedSortFilterProxyModel::isCategorizedModel() const
{
return d->categorizedModel;
}
void KCategorizedSortFilterProxyModel::setCategorizedModel(bool categorizedModel)
{
if (categorizedModel == d->categorizedModel)
{
return;
}
d->categorizedModel = categorizedModel;
invalidate();
}
int KCategorizedSortFilterProxyModel::sortColumn() const
{
return d->sortColumn;
}
Qt::SortOrder KCategorizedSortFilterProxyModel::sortOrder() const
{
return d->sortOrder;
}
void KCategorizedSortFilterProxyModel::setSortCategoriesByNaturalComparison(bool sortCategoriesByNaturalComparison)
{
if (sortCategoriesByNaturalComparison == d->sortCategoriesByNaturalComparison)
{
return;
}
d->sortCategoriesByNaturalComparison = sortCategoriesByNaturalComparison;
invalidate();
}
bool KCategorizedSortFilterProxyModel::sortCategoriesByNaturalComparison() const
{
return d->sortCategoriesByNaturalComparison;
}
bool KCategorizedSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
if (d->categorizedModel)
{
int compare = compareCategories(left, right);
if (compare > 0) // left is greater than right
{
return false;
}
else if (compare < 0) // left is less than right
{
return true;
}
}
return subSortLessThan(left, right);
}
bool KCategorizedSortFilterProxyModel::subSortLessThan(const QModelIndex &left, const QModelIndex &right) const
{
return QSortFilterProxyModel::lessThan(left, right);
}
int KCategorizedSortFilterProxyModel::compareCategories(const QModelIndex &left, const QModelIndex &right) const
{
QVariant l = (left.model() ? left.model()->data(left, CategorySortRole) : QVariant());
QVariant r = (right.model() ? right.model()->data(right, CategorySortRole) : QVariant());
Q_ASSERT(l.isValid());
Q_ASSERT(r.isValid());
Q_ASSERT(l.type() == r.type());
if (l.type() == QVariant::String)
{
QString lstr = l.toString();
QString rstr = r.toString();
if (d->sortCategoriesByNaturalComparison)
{
return QString::localeAwareCompare(lstr, rstr);
}
else
{
if (lstr < rstr)
{
return -1;
}
if (lstr > rstr)
{
return 1;
}
return 0;
}
}
qlonglong lint = l.toLongLong();
qlonglong rint = r.toLongLong();
if (lint < rint)
{
return -1;
}
if (lint > rint)
{
return 1;
}
return 0;
}

View File

@ -0,0 +1,172 @@
/*
* This file is part of the KDE project
* Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
* Copyright (C) 2007 John Tapsell <tapsell@kde.org>
*
* 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 KCATEGORIZEDSORTFILTERPROXYMODEL_H
#define KCATEGORIZEDSORTFILTERPROXYMODEL_H
#include <QtGui/QSortFilterProxyModel>
class QItemSelection;
/**
* This class lets you categorize a view. It is meant to be used along with
* KCategorizedView class.
*
* In general terms all you need to do is to reimplement subSortLessThan() and
* compareCategories() methods. In order to make categorization work, you need
* to also call setCategorizedModel() class to enable it, since the categorization
* is disabled by default.
*
* @see KCategorizedView
*
* @author Rafael Fernández López <ereslibre@kde.org>
*/
class KCategorizedSortFilterProxyModel
: public QSortFilterProxyModel
{
public:
enum AdditionalRoles {
// Note: use printf "0x%08X\n" $(($RANDOM*$RANDOM))
// to define additional roles.
CategoryDisplayRole = 0x17CE990A, ///< This role is used for asking the category to a given index
CategorySortRole = 0x27857E60 ///< This role is used for sorting categories. You can return a
///< string or a long long value. Strings will be sorted alphabetically
///< while long long will be sorted by their value. Please note that this
///< value won't be shown on the view, is only for sorting purposes. What will
///< be shown as "Category" on the view will be asked with the role
///< CategoryDisplayRole.
};
KCategorizedSortFilterProxyModel(QObject *parent = 0);
virtual ~KCategorizedSortFilterProxyModel();
/**
* Overridden from QSortFilterProxyModel. Sorts the source model using
* @p column for the given @p order.
*/
virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
/**
* @return whether the model is categorized or not. Disabled by default.
*/
bool isCategorizedModel() const;
/**
* Enables or disables the categorization feature.
*
* @param categorizedModel whether to enable or disable the categorization feature.
*/
void setCategorizedModel(bool categorizedModel);
/**
* @return the column being used for sorting.
*/
int sortColumn() const;
/**
* @return the sort order being used for sorting.
*/
Qt::SortOrder sortOrder() const;
/**
* Set if the sorting using CategorySortRole will use a natural comparison
* in the case that strings were returned. If enabled, QString::localeAwareCompare
* will be used for sorting.
*
* @param sortCategoriesByNaturalComparison whether to sort using a natural comparison or not.
*/
void setSortCategoriesByNaturalComparison(bool sortCategoriesByNaturalComparison);
/**
* @return whether it is being used a natural comparison for sorting. Enabled by default.
*/
bool sortCategoriesByNaturalComparison() const;
protected:
/**
* Overridden from QSortFilterProxyModel. If you are subclassing
* KCategorizedSortFilterProxyModel, you will probably not need to reimplement this
* method.
*
* It calls compareCategories() to sort by category. If the both items are in the
* same category (i.e. compareCategories returns 0), then subSortLessThan is called.
*
* @return Returns true if the item @p left is less than the item @p right when sorting.
*
* @warning You usually won't need to reimplement this method when subclassing
* from KCategorizedSortFilterProxyModel.
*/
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
/**
* This method has a similar purpose as lessThan() has on QSortFilterProxyModel.
* It is used for sorting items that are in the same category.
*
* @return Returns true if the item @p left is less than the item @p right when sorting.
*/
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const;
/**
* This method compares the category of the @p left index with the category
* of the @p right index.
*
* Internally and if not reimplemented, this method will ask for @p left and
* @p right models for role CategorySortRole. In order to correctly sort
* categories, the data() metod of the model should return a qlonglong (or numeric) value, or
* a QString object. QString objects will be sorted with QString::localeAwareCompare if
* sortCategoriesByNaturalComparison() is true.
*
* @note Please have present that:
* QString(QChar(QChar::ObjectReplacementCharacter)) >
* QString(QChar(QChar::ReplacementCharacter)) >
* [ all possible strings ] >
* QString();
*
* This means that QString() will be sorted the first one, while
* QString(QChar(QChar::ObjectReplacementCharacter)) and
* QString(QChar(QChar::ReplacementCharacter)) will be sorted in last
* position.
*
* @warning Please note that data() method of the model should return always
* information of the same type. If you return a QString for an index,
* you should return always QStrings for all indexes for role CategorySortRole
* in order to correctly sort categories. You can't mix by returning
* a QString for one index, and a qlonglong for other.
*
* @note If you need a more complex layout, you will have to reimplement this
* method.
*
* @return A negative value if the category of @p left should be placed before the
* category of @p right. 0 if @p left and @p right are on the same category, and
* a positive value if the category of @p left should be placed after the
* category of @p right.
*/
virtual int compareCategories(const QModelIndex &left, const QModelIndex &right) const;
private:
class Private;
Private *const d;
};
#endif // KCATEGORIZEDSORTFILTERPROXYMODEL_H

View File

@ -0,0 +1,48 @@
/**
* This file is part of the KDE project
* Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
* Copyright (C) 2007 John Tapsell <tapsell@kde.org>
*
* 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 KCATEGORIZEDSORTFILTERPROXYMODEL_P_H
#define KCATEGORIZEDSORTFILTERPROXYMODEL_P_H
class KCategorizedSortFilterProxyModel;
class KCategorizedSortFilterProxyModel::Private
{
public:
Private()
: sortColumn(0)
, sortOrder(Qt::AscendingOrder)
, categorizedModel(false)
, sortCategoriesByNaturalComparison(true)
{
}
~Private()
{
}
int sortColumn;
Qt::SortOrder sortOrder;
bool categorizedModel;
bool sortCategoriesByNaturalComparison;
};
#endif

View File

@ -0,0 +1,263 @@
diff --git a/src/widgets/kcategorizedsortfilterproxymodel.cpp b/src/widgets/kcategorizedsortfilterproxymodel.cpp
index c433c3d..0cb93ac 100644
--- a/src/widgets/kcategorizedsortfilterproxymodel.cpp
+++ b/src/widgets/kcategorizedsortfilterproxymodel.cpp
@@ -28,8 +28,6 @@
#include <QStringList>
#include <QSize>
-#include <kstringhandler.h>
-
KCategorizedSortFilterProxyModel::KCategorizedSortFilterProxyModel(QObject *parent)
: QSortFilterProxyModel(parent)
, d(new Private())
@@ -94,14 +92,6 @@ bool KCategorizedSortFilterProxyModel::sortCategoriesByNaturalComparison() const
return d->sortCategoriesByNaturalComparison;
}
-#ifndef KDE_NO_DEPRECATED
-int KCategorizedSortFilterProxyModel::naturalCompare(const QString &a,
- const QString &b)
-{
- return KStringHandler::naturalCompare(a, b);
-}
-#endif
-
bool KCategorizedSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
if (d->categorizedModel)
@@ -142,7 +132,7 @@ int KCategorizedSortFilterProxyModel::compareCategories(const QModelIndex &left,
if (d->sortCategoriesByNaturalComparison)
{
- return KStringHandler::naturalCompare(lstr, rstr);
+ return QString::localeAwareCompare(lstr, rstr);
}
else
{
diff --git a/src/widgets/kcategorizedsortfilterproxymodel.h b/src/widgets/kcategorizedsortfilterproxymodel.h
index a3146dc..de356c3 100644
--- a/src/widgets/kcategorizedsortfilterproxymodel.h
+++ b/src/widgets/kcategorizedsortfilterproxymodel.h
@@ -24,8 +24,6 @@
#include <QtGui/QSortFilterProxyModel>
-#include <kdeui_export.h>
-
class QItemSelection;
@@ -42,7 +40,7 @@ class QItemSelection;
*
* @author Rafael Fernández López <ereslibre@kde.org>
*/
-class KDEUI_EXPORT KCategorizedSortFilterProxyModel
+class KCategorizedSortFilterProxyModel
: public QSortFilterProxyModel
{
public:
@@ -104,17 +102,6 @@ public:
*/
bool sortCategoriesByNaturalComparison() const;
- /**
- * Does a natural comparing of the strings. A negative value is returned if \a a
- * is smaller than \a b. A positive value is returned if \a a is greater than \a b. 0
- * is returned if both values are equal.
- * @deprecated
- * Use KStringHandler::naturalCompare() instead.
- */
-#ifndef KDE_NO_DEPRECATED
- KDE_DEPRECATED static int naturalCompare(const QString &a, const QString &b);
-#endif
-
protected:
/**
* Overridden from QSortFilterProxyModel. If you are subclassing
diff --git a/src/widgets/kcategorizedview.cpp b/src/widgets/kcategorizedview.cpp
index 46a1cde..7e99468 100644
--- a/src/widgets/kcategorizedview.cpp
+++ b/src/widgets/kcategorizedview.cpp
@@ -33,7 +33,6 @@
#include "kcategorizedview_p.h"
#include <math.h> // trunc on C99 compliant systems
-#include <kdefakes.h> // trunc for not C99 compliant systems
#include <QPainter>
#include <QScrollBar>
@@ -1455,28 +1454,6 @@ void KCategorizedView::rowsInserted(const QModelIndex &parent,
d->rowsInserted(parent, start, end);
}
-#ifndef KDE_NO_DEPRECATED
-void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent,
- int start,
- int end)
-{
- Q_UNUSED(parent);
- Q_UNUSED(start);
- Q_UNUSED(end);
-}
-#endif
-
-#ifndef KDE_NO_DEPRECATED
-void KCategorizedView::rowsRemoved(const QModelIndex &parent,
- int start,
- int end)
-{
- Q_UNUSED(parent);
- Q_UNUSED(start);
- Q_UNUSED(end);
-}
-#endif
-
void KCategorizedView::slotLayoutChanged()
{
if (!d->isCategorized()) {
@@ -1492,5 +1469,3 @@ void KCategorizedView::slotLayoutChanged()
}
//END: Public part
-
-#include "kcategorizedview.moc"
diff --git a/src/widgets/kcategorizedview.h b/src/widgets/kcategorizedview.h
index b03744e..8f5ad9a 100644
--- a/src/widgets/kcategorizedview.h
+++ b/src/widgets/kcategorizedview.h
@@ -23,8 +23,6 @@
#include <QtGui/QListView>
-#include <kdeui_export.h>
-
class KCategoryDrawer;
class KCategoryDrawerV2;
@@ -76,7 +74,7 @@ class KCategoryDrawerV2;
*
* @author Rafael Fernández López <ereslibre@kde.org>
*/
-class KDEUI_EXPORT KCategorizedView
+class KCategorizedView
: public QListView
{
Q_OBJECT
@@ -310,26 +308,6 @@ protected:
protected Q_SLOTS:
/**
* @internal
- * @warning Deprecated since 4.4.
- */
-#ifndef KDE_NO_DEPRECATED
- virtual KDE_DEPRECATED void rowsInsertedArtifficial(const QModelIndex &parent,
- int start,
- int end);
-#endif
-
- /**
- * @internal
- * @warning Deprecated since 4.4.
- */
-#ifndef KDE_NO_DEPRECATED
- virtual KDE_DEPRECATED void rowsRemoved(const QModelIndex &parent,
- int start,
- int end);
-#endif
-
- /**
- * @internal
* Reposition items as needed.
*/
virtual void slotLayoutChanged();
@@ -341,4 +319,6 @@ private:
Q_PRIVATE_SLOT(d, void _k_slotCollapseOrExpandClicked(QModelIndex))
};
+#include "kcategorizedview_p.h"
+
#endif // KCATEGORIZEDVIEW_H
diff --git a/src/widgets/kcategorydrawer.cpp b/src/widgets/kcategorydrawer.cpp
index 2747e5b..5f5ce78 100644
--- a/src/widgets/kcategorydrawer.cpp
+++ b/src/widgets/kcategorydrawer.cpp
@@ -24,7 +24,6 @@
#include <QStyleOption>
#include <QApplication>
-#include <kiconloader.h>
#include <kcategorizedview.h>
#include <kcategorizedsortfilterproxymodel.h>
@@ -280,5 +279,3 @@ void KCategoryDrawerV3::mouseButtonDoubleClicked(const QModelIndex&, const QRect
void KCategoryDrawerV3::mouseLeft(const QModelIndex&, const QRect&)
{
}
-
-#include "kcategorydrawer.moc"
diff --git a/src/widgets/kcategorydrawer.h b/src/widgets/kcategorydrawer.h
index c24a0b8..d69b1b9 100644
--- a/src/widgets/kcategorydrawer.h
+++ b/src/widgets/kcategorydrawer.h
@@ -21,8 +21,6 @@
#ifndef KCATEGORYDRAWER_H
#define KCATEGORYDRAWER_H
-#include <kdeui_export.h>
-
#include <QtCore/QObject>
#include <QtGui/QMouseEvent>
@@ -40,10 +38,10 @@ class KCategorizedView;
*
* @warning Please use KCategoryDrawerV3 instead
*/
-class KDEUI_EXPORT KCategoryDrawer
+class KCategoryDrawer
{
public:
- KDE_DEPRECATED KCategoryDrawer();
+ KCategoryDrawer();
virtual ~KCategoryDrawer();
@@ -110,23 +108,23 @@ private:
*
* @warning Please use KCategoryDrawerV3 instead
*/
-class KDEUI_EXPORT KCategoryDrawerV2
+class KCategoryDrawerV2
: public QObject
, public KCategoryDrawer
{
Q_OBJECT
public:
- KDE_DEPRECATED KCategoryDrawerV2(QObject *parent = 0);
+ KCategoryDrawerV2(QObject *parent = 0);
virtual ~KCategoryDrawerV2();
- KDE_DEPRECATED virtual void mouseButtonPressed(const QModelIndex &index, QMouseEvent *event);
+ virtual void mouseButtonPressed(const QModelIndex &index, QMouseEvent *event);
- KDE_DEPRECATED virtual void mouseButtonReleased(const QModelIndex &index, QMouseEvent *event);
+ virtual void mouseButtonReleased(const QModelIndex &index, QMouseEvent *event);
- KDE_DEPRECATED virtual void mouseButtonMoved(const QModelIndex &index, QMouseEvent *event);
+ virtual void mouseButtonMoved(const QModelIndex &index, QMouseEvent *event);
- KDE_DEPRECATED virtual void mouseButtonDoubleClicked(const QModelIndex &index, QMouseEvent *event);
+ virtual void mouseButtonDoubleClicked(const QModelIndex &index, QMouseEvent *event);
Q_SIGNALS:
/**
@@ -147,7 +145,7 @@ Q_SIGNALS:
/**
* @since 4.5
*/
-class KDEUI_EXPORT KCategoryDrawerV3
+class KCategoryDrawerV3
: public KCategoryDrawerV2
{
friend class KCategorizedView;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,324 @@
/**
* This file is part of the KDE project
* Copyright (C) 2007, 2009 Rafael Fernández López <ereslibre@kde.org>
*
* 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 KCATEGORIZEDVIEW_H
#define KCATEGORIZEDVIEW_H
#include <QtGui/QListView>
class KCategoryDrawer;
class KCategoryDrawerV2;
/**
* @short Item view for listing items in a categorized fashion optionally
*
* KCategorizedView basically has the same functionality as QListView, only that it also lets you
* layout items in a way that they are categorized visually.
*
* For it to work you will need to set a KCategorizedSortFilterProxyModel and a KCategoryDrawer
* with methods setModel() and setCategoryDrawer() respectively. Also, the model will need to be
* flagged as categorized with KCategorizedSortFilterProxyModel::setCategorizedModel(true).
*
* The way it works (if categorization enabled):
*
* - When sorting, it does more things than QListView does. It will ask the model for the
* special role CategorySortRole (@see KCategorizedSortFilterProxyModel). This can return
* a QString or an int in order to tell the view the order of categories. In this sense, for
* instance, if we are sorting by name ascending, "A" would be before than "B". If we are
* sorting by size ascending, 512 bytes would be before 1024 bytes. This way categories are
* also sorted.
*
* - When the view has to paint, it will ask the model with the role CategoryDisplayRole
* (@see KCategorizedSortFilterProxyModel). It will for instance return "F" for "foo.pdf" if
* we are sorting by name ascending, or "Small" if a certain item has 100 bytes, for example.
*
* For drawing categories, KCategoryDrawer will be used. You can inherit this class to do your own
* drawing.
*
* @note All examples cited before talk about filesystems and such, but have present that this
* is a completely generic class, and it can be used for whatever your purpose is. For
* instance when talking about animals, you can separate them by "Mammal" and "Oviparous". In
* this very case, for example, the CategorySortRole and the CategoryDisplayRole could be the
* same ("Mammal" and "Oviparous").
*
* @note There is a really performance boost if CategorySortRole returns an int instead of a QString.
* Have present that this role is asked (n * log n) times when sorting and compared. Comparing
* ints is always faster than comparing strings, whithout mattering how fast the string
* comparison is. Consider thinking of a way of returning ints instead of QStrings if your
* model can contain a high number of items.
*
* @warning Note that for really drawing items in blocks you will need some things to be done:
* - The model set to this view has to be (or inherit if you want to do special stuff
* in it) KCategorizedSortFilterProxyModel.
* - This model needs to be set setCategorizedModel to true.
* - Set a category drawer by calling setCategoryDrawer.
*
* @see KCategorizedSortFilterProxyModel, KCategoryDrawer
*
* @author Rafael Fernández López <ereslibre@kde.org>
*/
class KCategorizedView
: public QListView
{
Q_OBJECT
Q_PROPERTY(int categorySpacing READ categorySpacing WRITE setCategorySpacing)
Q_PROPERTY(bool alternatingBlockColors READ alternatingBlockColors WRITE setAlternatingBlockColors)
Q_PROPERTY(bool collapsibleBlocks READ collapsibleBlocks WRITE setCollapsibleBlocks)
public:
KCategorizedView(QWidget *parent = 0);
~KCategorizedView();
/**
* Reimplemented from QAbstractItemView.
*/
virtual void setModel(QAbstractItemModel *model);
/**
* Calls to setGridSizeOwn().
*/
void setGridSize(const QSize &size);
/**
* @warning note that setGridSize is not virtual in the base class (QListView), so if you are
* calling to this method, make sure you have a KCategorizedView pointer around. This
* means that something like:
* @code
* QListView *lv = new KCategorizedView();
* lv->setGridSize(mySize);
* @endcode
*
* will not call to the expected setGridSize method. Instead do something like this:
*
* @code
* QListView *lv;
* ...
* KCategorizedView *cv = qobject_cast<KCategorizedView*>(lv);
* if (cv) {
* cv->setGridSizeOwn(mySize);
* } else {
* lv->setGridSize(mySize);
* }
* @endcode
*
* @note this method will call to QListView::setGridSize among other operations.
*
* @since 4.4
*/
void setGridSizeOwn(const QSize &size);
/**
* Reimplemented from QAbstractItemView.
*/
virtual QRect visualRect(const QModelIndex &index) const;
/**
* Returns the current category drawer.
*/
KCategoryDrawer *categoryDrawer() const;
/**
* The category drawer that will be used for drawing categories.
*/
void setCategoryDrawer(KCategoryDrawer *categoryDrawer);
/**
* @return Category spacing. The spacing between categories.
*
* @since 4.4
*/
int categorySpacing() const;
/**
* Stablishes the category spacing. This is the spacing between categories.
*
* @since 4.4
*/
void setCategorySpacing(int categorySpacing);
/**
* @return Whether blocks should be drawn with alternating colors.
*
* @since 4.4
*/
bool alternatingBlockColors() const;
/**
* Sets whether blocks should be drawn with alternating colors.
*
* @since 4.4
*/
void setAlternatingBlockColors(bool enable);
/**
* @return Whether blocks can be collapsed or not.
*
* @since 4.4
*/
bool collapsibleBlocks() const;
/**
* Sets whether blocks can be collapsed or not.
*
* @since 4.4
*/
void setCollapsibleBlocks(bool enable);
/**
* @return Block of indexes that are into @p category.
*
* @since 4.5
*/
QModelIndexList block(const QString &category);
/**
* @return Block of indexes that are represented by @p representative.
*
* @since 4.5
*/
QModelIndexList block(const QModelIndex &representative);
/**
* Reimplemented from QAbstractItemView.
*/
virtual QModelIndex indexAt(const QPoint &point) const;
/**
* Reimplemented from QAbstractItemView.
*/
virtual void reset();
protected:
/**
* Reimplemented from QWidget.
*/
virtual void paintEvent(QPaintEvent *event);
/**
* Reimplemented from QWidget.
*/
virtual void resizeEvent(QResizeEvent *event);
/**
* Reimplemented from QAbstractItemView.
*/
virtual void setSelection(const QRect &rect,
QItemSelectionModel::SelectionFlags flags);
/**
* Reimplemented from QWidget.
*/
virtual void mouseMoveEvent(QMouseEvent *event);
/**
* Reimplemented from QWidget.
*/
virtual void mousePressEvent(QMouseEvent *event);
/**
* Reimplemented from QWidget.
*/
virtual void mouseReleaseEvent(QMouseEvent *event);
/**
* Reimplemented from QWidget.
*/
virtual void leaveEvent(QEvent *event);
/**
* Reimplemented from QAbstractItemView.
*/
virtual void startDrag(Qt::DropActions supportedActions);
/**
* Reimplemented from QAbstractItemView.
*/
virtual void dragMoveEvent(QDragMoveEvent *event);
/**
* Reimplemented from QAbstractItemView.
*/
virtual void dragEnterEvent(QDragEnterEvent *event);
/**
* Reimplemented from QAbstractItemView.
*/
virtual void dragLeaveEvent(QDragLeaveEvent *event);
/**
* Reimplemented from QAbstractItemView.
*/
virtual void dropEvent(QDropEvent *event);
/**
* Reimplemented from QAbstractItemView.
*/
virtual QModelIndex moveCursor(CursorAction cursorAction,
Qt::KeyboardModifiers modifiers);
/**
* Reimplemented from QAbstractItemView.
*/
virtual void rowsAboutToBeRemoved(const QModelIndex &parent,
int start,
int end);
/**
* Reimplemented from QAbstractItemView.
*/
virtual void updateGeometries();
/**
* Reimplemented from QAbstractItemView.
*/
virtual void currentChanged(const QModelIndex &current,
const QModelIndex &previous);
/**
* Reimplemented from QAbstractItemView.
*/
virtual void dataChanged(const QModelIndex &topLeft,
const QModelIndex &bottomRight);
/**
* Reimplemented from QAbstractItemView.
*/
virtual void rowsInserted(const QModelIndex &parent,
int start,
int end);
protected Q_SLOTS:
/**
* @internal
* Reposition items as needed.
*/
virtual void slotLayoutChanged();
private:
class Private;
Private *const d;
Q_PRIVATE_SLOT(d, void _k_slotCollapseOrExpandClicked(QModelIndex))
};
#include "kcategorizedview_p.h"
#endif // KCATEGORIZEDVIEW_H

View File

@ -0,0 +1,159 @@
/**
* This file is part of the KDE project
* Copyright (C) 2007, 2009 Rafael Fernández López <ereslibre@kde.org>
*
* 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 KCATEGORIZEDVIEW_P_H
#define KCATEGORIZEDVIEW_P_H
class KCategorizedSortFilterProxyModel;
class KCategoryDrawer;
class KCategoryDrawerV2;
class KCategoryDrawerV3;
/**
* @internal
*/
class KCategorizedView::Private
{
public:
struct Block;
struct Item;
Private(KCategorizedView *q);
~Private();
/**
* @return whether this view has all required elements to be categorized.
*/
bool isCategorized() const;
/**
* @return the block rect for the representative @p representative.
*/
QStyleOptionViewItemV4 blockRect(const QModelIndex &representative);
/**
* Returns the first and last element that intersects with rect.
*
* @note see that here we cannot take out items between first and last (as we could
* do with the rubberband).
*
* Complexity: O(log(n)) where n is model()->rowCount().
*/
QPair<QModelIndex, QModelIndex> intersectingIndexesWithRect(const QRect &rect) const;
/**
* Returns the position of the block of @p category.
*
* Complexity: O(n) where n is the number of different categories when the block has been
* marked as in quarantine. O(1) the rest of the times (the vast majority).
*/
QPoint blockPosition(const QString &category);
/**
* Returns the height of the block determined by @p category.
*/
int blockHeight(const QString &category);
/**
* Returns the actual viewport width.
*/
int viewportWidth() const;
/**
* Marks all elements as in quarantine.
*
* Complexity: O(n) where n is model()->rowCount().
*
* @warning this is an expensive operation
*/
void regenerateAllElements();
/**
* Update internal information, and keep sync with the real information that the model contains.
*/
void rowsInserted(const QModelIndex &parent, int start, int end);
/**
* Returns @p rect in viewport terms, taking in count horizontal and vertical offsets.
*/
QRect mapToViewport(const QRect &rect) const;
/**
* Returns @p rect in absolute terms, converted from viewport position.
*/
QRect mapFromViewport(const QRect &rect) const;
/**
* Returns the height of the highest element in last row. This is only applicable if there is
* no grid set and uniformItemSizes is false.
*
* @param block in which block are we searching. Necessary to stop the search if we hit the
* first item in this block.
*/
int highestElementInLastRow(const Block &block) const;
/**
* Returns whether the view has a valid grid size.
*/
bool hasGrid() const;
/**
* Returns the category for the given index.
*/
QString categoryForIndex(const QModelIndex &index) const;
/**
* Updates the visual rect for item when flow is LeftToRight.
*/
void leftToRightVisualRect(const QModelIndex &index, Item &item,
const Block &block, const QPoint &blockPos) const;
/**
* Updates the visual rect for item when flow is TopToBottom.
* @note we only support viewMode == ListMode in this case.
*/
void topToBottomVisualRect(const QModelIndex &index, Item &item,
const Block &block, const QPoint &blockPos) const;
/**
* Called when expand or collapse has been clicked on the category drawer.
*/
void _k_slotCollapseOrExpandClicked(QModelIndex);
KCategorizedView *q;
KCategorizedSortFilterProxyModel *proxyModel;
KCategoryDrawer *categoryDrawer;
KCategoryDrawerV2 *categoryDrawerV2;
KCategoryDrawerV3 *categoryDrawerV3;
int categorySpacing;
bool alternatingBlockColors;
bool collapsibleBlocks;
Block *hoveredBlock;
QString hoveredCategory;
QModelIndex hoveredIndex;
QPoint pressedPosition;
QRect rubberBandRect;
QHash<QString, Block> blocks;
};
#endif // KCATEGORIZEDVIEW_P_H

View File

@ -0,0 +1,281 @@
/**
* This file is part of the KDE project
* Copyright (C) 2007, 2009 Rafael Fernández López <ereslibre@kde.org>
*
* 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 "kcategorydrawer.h"
#include <QPainter>
#include <QStyleOption>
#include <QApplication>
#include <kcategorizedview.h>
#include <kcategorizedsortfilterproxymodel.h>
#define HORIZONTAL_HINT 3
class KCategoryDrawer::Private
{
public:
Private()
: leftMargin(0)
, rightMargin(0)
{
}
~Private()
{
}
int leftMargin;
int rightMargin;
};
KCategoryDrawer::KCategoryDrawer()
: d(new Private)
{
setLeftMargin(2);
setRightMargin(2);
}
KCategoryDrawer::~KCategoryDrawer()
{
delete d;
}
void KCategoryDrawer::drawCategory(const QModelIndex &index,
int /*sortRole*/,
const QStyleOption &option,
QPainter *painter) const
{
painter->setRenderHint(QPainter::Antialiasing);
const QString category = index.model()->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
const QRect optRect = option.rect;
QFont font(QApplication::font());
font.setBold(true);
const QFontMetrics fontMetrics = QFontMetrics(font);
QColor outlineColor = option.palette.text().color();
outlineColor.setAlphaF(0.35);
//BEGIN: top left corner
{
painter->save();
painter->setPen(outlineColor);
const QPointF topLeft(optRect.topLeft());
QRectF arc(topLeft, QSizeF(4, 4));
arc.translate(0.5, 0.5);
painter->drawArc(arc, 1440, 1440);
painter->restore();
}
//END: top left corner
//BEGIN: left vertical line
{
QPoint start(optRect.topLeft());
start.ry() += 3;
QPoint verticalGradBottom(optRect.topLeft());
verticalGradBottom.ry() += fontMetrics.height() + 5;
QLinearGradient gradient(start, verticalGradBottom);
gradient.setColorAt(0, outlineColor);
gradient.setColorAt(1, Qt::transparent);
painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient);
}
//END: left vertical line
//BEGIN: horizontal line
{
QPoint start(optRect.topLeft());
start.rx() += 3;
QPoint horizontalGradTop(optRect.topLeft());
horizontalGradTop.rx() += optRect.width() - 6;
painter->fillRect(QRect(start, QSize(optRect.width() - 6, 1)), outlineColor);
}
//END: horizontal line
//BEGIN: top right corner
{
painter->save();
painter->setPen(outlineColor);
QPointF topRight(optRect.topRight());
topRight.rx() -= 4;
QRectF arc(topRight, QSizeF(4, 4));
arc.translate(0.5, 0.5);
painter->drawArc(arc, 0, 1440);
painter->restore();
}
//END: top right corner
//BEGIN: right vertical line
{
QPoint start(optRect.topRight());
start.ry() += 3;
QPoint verticalGradBottom(optRect.topRight());
verticalGradBottom.ry() += fontMetrics.height() + 5;
QLinearGradient gradient(start, verticalGradBottom);
gradient.setColorAt(0, outlineColor);
gradient.setColorAt(1, Qt::transparent);
painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient);
}
//END: right vertical line
//BEGIN: text
{
QRect textRect(option.rect);
textRect.setTop(textRect.top() + 7);
textRect.setLeft(textRect.left() + 7);
textRect.setHeight(fontMetrics.height());
textRect.setRight(textRect.right() - 7);
painter->save();
painter->setFont(font);
QColor penColor(option.palette.text().color());
penColor.setAlphaF(0.6);
painter->setPen(penColor);
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, category);
painter->restore();
}
//END: text
}
int KCategoryDrawer::categoryHeight(const QModelIndex &index, const QStyleOption &option) const
{
Q_UNUSED(index);
Q_UNUSED(option)
QFont font(QApplication::font());
font.setBold(true);
QFontMetrics fontMetrics(font);
const int height = fontMetrics.height() + 1 /* 1 pixel-width gradient */
+ 11 /* top and bottom separation */;
return height;
}
int KCategoryDrawer::leftMargin() const
{
return d->leftMargin;
}
void KCategoryDrawer::setLeftMargin(int leftMargin)
{
d->leftMargin = leftMargin;
}
int KCategoryDrawer::rightMargin() const
{
return d->rightMargin;
}
void KCategoryDrawer::setRightMargin(int rightMargin)
{
d->rightMargin = rightMargin;
}
KCategoryDrawer &KCategoryDrawer::operator=(const KCategoryDrawer &cd)
{
d->leftMargin = cd.d->leftMargin;
d->rightMargin = cd.d->rightMargin;
return *this;
}
KCategoryDrawerV2::KCategoryDrawerV2(QObject *parent)
: QObject(parent)
, KCategoryDrawer()
{
}
KCategoryDrawerV2::~KCategoryDrawerV2()
{
}
void KCategoryDrawerV2::mouseButtonPressed(const QModelIndex&, QMouseEvent *event)
{
event->ignore();
}
void KCategoryDrawerV2::mouseButtonReleased(const QModelIndex&, QMouseEvent *event)
{
event->ignore();
}
void KCategoryDrawerV2::mouseButtonMoved(const QModelIndex&, QMouseEvent *event)
{
event->ignore();
}
void KCategoryDrawerV2::mouseButtonDoubleClicked(const QModelIndex&, QMouseEvent *event)
{
event->ignore();
}
class KCategoryDrawerV3::Private
{
public:
Private(KCategorizedView *view)
: view(view)
{
}
~Private()
{
}
KCategorizedView *view;
};
KCategoryDrawerV3::KCategoryDrawerV3(KCategorizedView *view)
: KCategoryDrawerV2(view)
, d(new Private(view))
{
}
KCategoryDrawerV3::~KCategoryDrawerV3()
{
delete d;
}
KCategorizedView *KCategoryDrawerV3::view() const
{
return d->view;
}
void KCategoryDrawerV3::mouseButtonPressed(const QModelIndex&, const QRect&, QMouseEvent *event)
{
event->ignore();
}
void KCategoryDrawerV3::mouseButtonReleased(const QModelIndex&, const QRect&, QMouseEvent *event)
{
event->ignore();
}
void KCategoryDrawerV3::mouseMoved(const QModelIndex&, const QRect&, QMouseEvent *event)
{
event->ignore();
}
void KCategoryDrawerV3::mouseButtonDoubleClicked(const QModelIndex&, const QRect&, QMouseEvent *event)
{
event->ignore();
}
void KCategoryDrawerV3::mouseLeft(const QModelIndex&, const QRect&)
{
}

View File

@ -0,0 +1,228 @@
/**
* This file is part of the KDE project
* Copyright (C) 2007, 2009 Rafael Fernández López <ereslibre@kde.org>
*
* 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 KCATEGORYDRAWER_H
#define KCATEGORYDRAWER_H
#include <QtCore/QObject>
#include <QtGui/QMouseEvent>
class QPainter;
class QModelIndex;
class QStyleOption;
class KCategorizedView;
/**
* @deprecated
*
* The category drawing is performed by this class. It also gives information about the category
* height and margins.
*
* @warning Please use KCategoryDrawerV3 instead
*/
class KCategoryDrawer
{
public:
KCategoryDrawer();
virtual ~KCategoryDrawer();
/**
* This method purpose is to draw a category represented by the given
* @param index with the given @param sortRole sorting role
*
* @note This method will be called one time per category, always with the
* first element in that category
*/
virtual void drawCategory(const QModelIndex &index,
int sortRole,
const QStyleOption &option,
QPainter *painter) const;
/**
* @return The category height for the category representated by index @p index with
* style options @p option.
*/
virtual int categoryHeight(const QModelIndex &index, const QStyleOption &option) const;
//TODO KDE5: make virtual as leftMargin
/**
* @note 0 by default
*
* @since 4.4
*/
int leftMargin() const;
/**
* @note call to this method on the KCategoryDrawer constructor to set the left margin
*
* @since 4.4
*/
void setLeftMargin(int leftMargin);
//TODO KDE5: make virtual as rightMargin
/**
* @note 0 by default
*
* @since 4.4
*/
int rightMargin() const;
/**
* @note call to this method on the KCategoryDrawer constructor to set the right margin
*
* @since 4.4
*/
void setRightMargin(int rightMargin);
KCategoryDrawer &operator=(const KCategoryDrawer &cd);
private:
class Private;
Private *const d;
};
/**
* @deprecated
*
* @since 4.4
*
* @warning Please use KCategoryDrawerV3 instead
*/
class KCategoryDrawerV2
: public QObject
, public KCategoryDrawer
{
Q_OBJECT
public:
KCategoryDrawerV2(QObject *parent = 0);
virtual ~KCategoryDrawerV2();
virtual void mouseButtonPressed(const QModelIndex &index, QMouseEvent *event);
virtual void mouseButtonReleased(const QModelIndex &index, QMouseEvent *event);
virtual void mouseButtonMoved(const QModelIndex &index, QMouseEvent *event);
virtual void mouseButtonDoubleClicked(const QModelIndex &index, QMouseEvent *event);
Q_SIGNALS:
/**
* This signal becomes emitted when collapse or expand has been clicked.
*/
void collapseOrExpandClicked(const QModelIndex &index);
/**
* Emit this signal on your subclass implementation to notify that something happened. Usually
* this will be triggered when you have received an event, and its position matched some "hot spot".
*
* You give this action the integer you want, and having connected this signal to your code,
* the connected slot can perform the needed changes (view, model, selection model, delegate...)
*/
void actionRequested(int action, const QModelIndex &index);
};
/**
* @since 4.5
*/
class KCategoryDrawerV3
: public KCategoryDrawerV2
{
friend class KCategorizedView;
public:
KCategoryDrawerV3(KCategorizedView *view);
virtual ~KCategoryDrawerV3();
/**
* @return The view this category drawer is associated with.
*/
KCategorizedView *view() const;
using KCategoryDrawerV2::mouseButtonPressed;
using KCategoryDrawerV2::mouseButtonReleased;
using KCategoryDrawerV2::mouseButtonDoubleClicked;
protected:
/**
* Method called when the mouse button has been pressed.
*
* @param index The representative index of the block of items.
* @param blockRect The rect occupied by the block of items.
* @param event The mouse event.
*
* @warning You explicitly have to determine whether the event has been accepted or not. You
* have to call event->accept() or event->ignore() at all possible case branches in
* your code.
*/
virtual void mouseButtonPressed(const QModelIndex &index, const QRect &blockRect, QMouseEvent *event);
/**
* Method called when the mouse button has been released.
*
* @param index The representative index of the block of items.
* @param blockRect The rect occupied by the block of items.
* @param event The mouse event.
*
* @warning You explicitly have to determine whether the event has been accepted or not. You
* have to call event->accept() or event->ignore() at all possible case branches in
* your code.
*/
virtual void mouseButtonReleased(const QModelIndex &index, const QRect &blockRect, QMouseEvent *event);
/**
* Method called when the mouse has been moved.
*
* @param index The representative index of the block of items.
* @param blockRect The rect occupied by the block of items.
* @param event The mouse event.
*/
virtual void mouseMoved(const QModelIndex &index, const QRect &blockRect, QMouseEvent *event);
/**
* Method called when the mouse button has been double clicked.
*
* @param index The representative index of the block of items.
* @param blockRect The rect occupied by the block of items.
* @param event The mouse event.
*
* @warning You explicitly have to determine whether the event has been accepted or not. You
* have to call event->accept() or event->ignore() at all possible case branches in
* your code.
*/
virtual void mouseButtonDoubleClicked(const QModelIndex &index, const QRect &blockRect, QMouseEvent *event);
/**
* Method called when the mouse button has left this block.
*
* @param index The representative index of the block of items.
* @param blockRect The rect occupied by the block of items.
*/
virtual void mouseLeft(const QModelIndex &index, const QRect &blockRect);
private:
class Private;
Private *const d;
};
#endif // KCATEGORYDRAWER_H