Replace the KCategorizedView with a custom widget that works better.
This commit is contained in:
parent
d6bafe88e2
commit
2ef9ab6f6e
@ -271,9 +271,7 @@ set(SOURCES
|
|||||||
widgets/fileviewlist.cpp
|
widgets/fileviewlist.cpp
|
||||||
widgets/freespacebar.cpp
|
widgets/freespacebar.cpp
|
||||||
widgets/fullscreenhypnotoad.cpp
|
widgets/fullscreenhypnotoad.cpp
|
||||||
widgets/kcategorizedsortfilterproxymodel.cpp
|
widgets/groupediconview.cpp
|
||||||
widgets/kcategorizedview.cpp
|
|
||||||
widgets/kcategorydrawer.cpp
|
|
||||||
widgets/lineedit.cpp
|
widgets/lineedit.cpp
|
||||||
widgets/linetextedit.cpp
|
widgets/linetextedit.cpp
|
||||||
widgets/multiloadingindicator.cpp
|
widgets/multiloadingindicator.cpp
|
||||||
@ -476,8 +474,7 @@ set(HEADERS
|
|||||||
widgets/fileview.h
|
widgets/fileview.h
|
||||||
widgets/fileviewlist.h
|
widgets/fileviewlist.h
|
||||||
widgets/freespacebar.h
|
widgets/freespacebar.h
|
||||||
widgets/kcategorizedview.h
|
widgets/groupediconview.h
|
||||||
widgets/kcategorydrawer.h
|
|
||||||
widgets/lineedit.h
|
widgets/lineedit.h
|
||||||
widgets/linetextedit.h
|
widgets/linetextedit.h
|
||||||
widgets/multiloadingindicator.h
|
widgets/multiloadingindicator.h
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
#include "covers/albumcoverfetcher.h"
|
#include "covers/albumcoverfetcher.h"
|
||||||
#include "covers/albumcoverloader.h"
|
#include "covers/albumcoverloader.h"
|
||||||
#include "widgets/kcategorizedsortfilterproxymodel.h"
|
#include "widgets/groupediconview.h"
|
||||||
|
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QListWidgetItem>
|
#include <QListWidgetItem>
|
||||||
@ -28,54 +28,6 @@
|
|||||||
#include <QStandardItemModel>
|
#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)
|
AlbumCoverSearcher::AlbumCoverSearcher(const QIcon& no_cover_icon, QWidget* parent)
|
||||||
: QDialog(parent),
|
: QDialog(parent),
|
||||||
ui_(new Ui_AlbumCoverSearcher),
|
ui_(new Ui_AlbumCoverSearcher),
|
||||||
@ -88,11 +40,8 @@ AlbumCoverSearcher::AlbumCoverSearcher(const QIcon& no_cover_icon, QWidget* pare
|
|||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
ui_->busy->hide();
|
ui_->busy->hide();
|
||||||
|
|
||||||
KCategorizedSortFilterProxyModel* proxy = new KCategorizedSortFilterProxyModel(this);
|
ui_->covers->set_header_text(tr("Covers from %1"));
|
||||||
proxy->setCategorizedModel(true);
|
ui_->covers->setModel(model_);
|
||||||
proxy->setSourceModel(model_);
|
|
||||||
ui_->covers->setModel(proxy);
|
|
||||||
ui_->covers->setCategoryDrawer(new AlbumCoverCategoryDrawer(ui_->covers));
|
|
||||||
|
|
||||||
loader_->Start(true);
|
loader_->Start(true);
|
||||||
loader_->Worker()->SetDefaultOutputImage(QImage(":nocover.png"));
|
loader_->Worker()->SetDefaultOutputImage(QImage(":nocover.png"));
|
||||||
@ -174,8 +123,7 @@ void AlbumCoverSearcher::SearchFinished(quint64 id, const CoverSearchResults& re
|
|||||||
item->setData(id, Role_ImageRequestId);
|
item->setData(id, Role_ImageRequestId);
|
||||||
item->setData(false, Role_ImageFetchFinished);
|
item->setData(false, Role_ImageFetchFinished);
|
||||||
item->setData(QVariant(Qt::AlignTop | Qt::AlignHCenter), Qt::TextAlignmentRole);
|
item->setData(QVariant(Qt::AlignTop | Qt::AlignHCenter), Qt::TextAlignmentRole);
|
||||||
item->setData(result.category, KCategorizedSortFilterProxyModel::CategoryDisplayRole);
|
item->setData(result.category, GroupedIconView::Role_Group);
|
||||||
item->setData(result.category, KCategorizedSortFilterProxyModel::CategorySortRole);
|
|
||||||
|
|
||||||
model_->appendRow(item);
|
model_->appendRow(item);
|
||||||
|
|
||||||
@ -192,9 +140,21 @@ void AlbumCoverSearcher::ImageLoaded(quint64 id, const QImage& image) {
|
|||||||
|
|
||||||
QIcon icon(QPixmap::fromImage(image));
|
QIcon icon(QPixmap::fromImage(image));
|
||||||
|
|
||||||
// Add an icon that's the right size for the view
|
// Create a pixmap that's padded and exactly the right size for the icon.
|
||||||
icon.addPixmap(QPixmap::fromImage(image.scaled(ui_->covers->iconSize(),
|
QImage scaled_image(image.scaled(ui_->covers->iconSize(),
|
||||||
Qt::KeepAspectRatio, Qt::SmoothTransformation)));
|
Qt::KeepAspectRatio,
|
||||||
|
Qt::SmoothTransformation));
|
||||||
|
|
||||||
|
QImage padded_image(ui_->covers->iconSize(), QImage::Format_ARGB32_Premultiplied);
|
||||||
|
padded_image.fill(0);
|
||||||
|
|
||||||
|
QPainter p(&padded_image);
|
||||||
|
p.drawImage((padded_image.width() - scaled_image.width()) / 2,
|
||||||
|
(padded_image.height() - scaled_image.height()) / 2,
|
||||||
|
scaled_image);
|
||||||
|
p.end();
|
||||||
|
|
||||||
|
icon.addPixmap(QPixmap::fromImage(padded_image));
|
||||||
|
|
||||||
QStandardItem* item = cover_loading_tasks_.take(id);
|
QStandardItem* item = cover_loading_tasks_.take(id);
|
||||||
item->setData(true, Role_ImageFetchFinished);
|
item->setData(true, Role_ImageFetchFinished);
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
#include "core/backgroundthread.h"
|
#include "core/backgroundthread.h"
|
||||||
#include "covers/albumcoverfetcher.h"
|
#include "covers/albumcoverfetcher.h"
|
||||||
#include "widgets/kcategorydrawer.h"
|
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
@ -34,22 +33,6 @@ class QModelIndex;
|
|||||||
class QStandardItem;
|
class QStandardItem;
|
||||||
class QStandardItemModel;
|
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
|
// This is a dialog that lets the user search for album covers
|
||||||
class AlbumCoverSearcher : public QDialog {
|
class AlbumCoverSearcher : public QDialog {
|
||||||
|
@ -49,8 +49,11 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="KCategorizedView" name="covers">
|
<widget class="GroupedIconView" name="covers">
|
||||||
<property name="verticalScrollBarPolicy">
|
<property name="verticalScrollBarPolicy">
|
||||||
|
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||||
|
</property>
|
||||||
|
<property name="horizontalScrollBarPolicy">
|
||||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
@ -59,27 +62,9 @@
|
|||||||
<height>120</height>
|
<height>120</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="movement">
|
|
||||||
<enum>QListView::Free</enum>
|
|
||||||
</property>
|
|
||||||
<property name="flow">
|
|
||||||
<enum>QListView::LeftToRight</enum>
|
|
||||||
</property>
|
|
||||||
<property name="resizeMode">
|
|
||||||
<enum>QListView::Adjust</enum>
|
|
||||||
</property>
|
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="viewMode">
|
|
||||||
<enum>QListView::IconMode</enum>
|
|
||||||
</property>
|
|
||||||
<property name="uniformItemSizes">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -106,9 +91,9 @@
|
|||||||
<header>widgets/busyindicator.h</header>
|
<header>widgets/busyindicator.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>KCategorizedView</class>
|
<class>GroupedIconView</class>
|
||||||
<extends>QListView</extends>
|
<extends>QListView</extends>
|
||||||
<header>widgets/kcategorizedview.h</header>
|
<header>widgets/groupediconview.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
|
347
src/widgets/groupediconview.cpp
Normal file
347
src/widgets/groupediconview.cpp
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
|
||||||
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Clementine is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "groupediconview.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPaintEvent>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QtDebug>
|
||||||
|
|
||||||
|
const int GroupedIconView::kBarThickness = 2;
|
||||||
|
const int GroupedIconView::kBarMarginTop = 3;
|
||||||
|
|
||||||
|
|
||||||
|
GroupedIconView::GroupedIconView(QWidget* parent)
|
||||||
|
: QListView(parent),
|
||||||
|
proxy_model_(new QSortFilterProxyModel(this)),
|
||||||
|
default_header_height_(fontMetrics().height() +
|
||||||
|
kBarMarginTop + kBarThickness),
|
||||||
|
header_spacing_(10),
|
||||||
|
header_indent_(5),
|
||||||
|
item_indent_(10),
|
||||||
|
header_text_("%1")
|
||||||
|
{
|
||||||
|
setFlow(LeftToRight);
|
||||||
|
setViewMode(IconMode);
|
||||||
|
setResizeMode(Adjust);
|
||||||
|
setWordWrap(true);
|
||||||
|
setDragEnabled(false);
|
||||||
|
|
||||||
|
proxy_model_->setSortRole(Role_Group);
|
||||||
|
proxy_model_->setDynamicSortFilter(true);
|
||||||
|
|
||||||
|
connect(proxy_model_, SIGNAL(modelReset()), SLOT(LayoutItems()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupedIconView::setModel(QAbstractItemModel* model) {
|
||||||
|
proxy_model_->setSourceModel(model);
|
||||||
|
proxy_model_->sort(0);
|
||||||
|
|
||||||
|
QListView::setModel(proxy_model_);
|
||||||
|
LayoutItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GroupedIconView::header_height() const {
|
||||||
|
return default_header_height_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupedIconView::DrawHeader(const QModelIndex& index,
|
||||||
|
const QRect& rect, QPainter* painter) {
|
||||||
|
painter->save();
|
||||||
|
|
||||||
|
// Bold font
|
||||||
|
QFont bold_font(font());
|
||||||
|
bold_font.setBold(true);
|
||||||
|
QFontMetrics metrics(bold_font);
|
||||||
|
|
||||||
|
// Draw text
|
||||||
|
const QString category = header_text_.arg(index.data(Role_Group).toString());
|
||||||
|
painter->setFont(bold_font);
|
||||||
|
painter->drawText(rect, category);
|
||||||
|
|
||||||
|
// Draw a line underneath
|
||||||
|
const QPoint start(rect.left(), rect.top() + metrics.height());
|
||||||
|
const QPoint end(rect.right(), start.y());
|
||||||
|
|
||||||
|
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||||
|
painter->setPen(QPen(palette().color(QPalette::Disabled, QPalette::Text),
|
||||||
|
kBarThickness, Qt::SolidLine, Qt::RoundCap));
|
||||||
|
painter->setOpacity(0.5);
|
||||||
|
painter->drawLine(start, end);
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupedIconView::resizeEvent(QResizeEvent* e) {
|
||||||
|
QListView::resizeEvent(e);
|
||||||
|
LayoutItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupedIconView::rowsInserted(const QModelIndex& parent, int start, int end) {
|
||||||
|
QListView::rowsInserted(parent, start, end);
|
||||||
|
LayoutItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupedIconView::LayoutItems() {
|
||||||
|
if (!model())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int count = model()->rowCount();
|
||||||
|
|
||||||
|
QString last_group;
|
||||||
|
QPoint next_position(0, 0);
|
||||||
|
int max_row_height = 0;
|
||||||
|
|
||||||
|
visual_rects_.clear();
|
||||||
|
visual_rects_.reserve(count);
|
||||||
|
headers_.clear();
|
||||||
|
|
||||||
|
for (int i=0 ; i<count ; ++i) {
|
||||||
|
const QModelIndex index(model()->index(i, 0));
|
||||||
|
const QString group = index.data(Role_Group).toString();
|
||||||
|
const QSize size(rectForIndex(index).size());
|
||||||
|
|
||||||
|
// Is this the first item in a new group?
|
||||||
|
if (group != last_group) {
|
||||||
|
// Add the group header.
|
||||||
|
Header header;
|
||||||
|
header.y = next_position.y() + max_row_height + header_indent_;
|
||||||
|
header.first_row = i;
|
||||||
|
header.text = group;
|
||||||
|
|
||||||
|
if (!last_group.isNull()) {
|
||||||
|
header.y += header_spacing_;
|
||||||
|
}
|
||||||
|
|
||||||
|
headers_ << header;
|
||||||
|
|
||||||
|
// Remember this group so we don't add it again.
|
||||||
|
last_group = group;
|
||||||
|
|
||||||
|
// Move the next item immediately below the header.
|
||||||
|
next_position.setX(0);
|
||||||
|
next_position.setY(header.y + header_height() + header_indent_ + header_spacing_);
|
||||||
|
max_row_height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take into account padding and spacing
|
||||||
|
QPoint this_position(next_position);
|
||||||
|
if (this_position.x() == 0) {
|
||||||
|
this_position.setX(this_position.x() + item_indent_);
|
||||||
|
} else {
|
||||||
|
this_position.setX(this_position.x() + spacing());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should this item wrap?
|
||||||
|
if (next_position.x() != 0 && this_position.x() + size.width() >= viewport()->width()) {
|
||||||
|
next_position.setX(0);
|
||||||
|
next_position.setY(next_position.y() + max_row_height);
|
||||||
|
this_position = next_position;
|
||||||
|
this_position.setX(this_position.x() + item_indent_);
|
||||||
|
|
||||||
|
max_row_height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set this item's geometry
|
||||||
|
visual_rects_.append(QRect(this_position, size));
|
||||||
|
|
||||||
|
// Update next index
|
||||||
|
next_position.setX(this_position.x() + size.width());
|
||||||
|
max_row_height = qMax(max_row_height, size.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
verticalScrollBar()->setRange(0, next_position.y() + max_row_height - viewport()->height());
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect GroupedIconView::visualRect(const QModelIndex& index) const {
|
||||||
|
if (index.row() < 0 || index.row() >= visual_rects_.count())
|
||||||
|
return QRect();
|
||||||
|
return visual_rects_[index.row()].translated(-horizontalOffset(), -verticalOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex GroupedIconView::indexAt(const QPoint& p) const {
|
||||||
|
const QPoint viewport_p = p + QPoint(horizontalOffset(), verticalOffset());
|
||||||
|
|
||||||
|
const int count = visual_rects_.count();
|
||||||
|
for (int i=0 ; i<count ; ++i) {
|
||||||
|
if (visual_rects_[i].contains(viewport_p)) {
|
||||||
|
return model()->index(i, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupedIconView::paintEvent(QPaintEvent* e) {
|
||||||
|
// This code was adapted from QListView::paintEvent(), changed to use the
|
||||||
|
// visualRect() of items, and to draw headers.
|
||||||
|
|
||||||
|
QStyleOptionViewItemV4 option(viewOptions());
|
||||||
|
if (isWrapping())
|
||||||
|
option.features = QStyleOptionViewItemV2::WrapText;
|
||||||
|
option.locale = locale();
|
||||||
|
option.locale.setNumberOptions(QLocale::OmitGroupSeparator);
|
||||||
|
option.widget = this;
|
||||||
|
|
||||||
|
QPainter painter(viewport());
|
||||||
|
|
||||||
|
const QRect viewport_rect(e->rect().translated(horizontalOffset(), verticalOffset()));
|
||||||
|
QVector<QModelIndex> toBeRendered = IntersectingItems(viewport_rect);
|
||||||
|
|
||||||
|
const QModelIndex current = currentIndex();
|
||||||
|
const QAbstractItemModel *itemModel = model();
|
||||||
|
const QItemSelectionModel *selections = selectionModel();
|
||||||
|
const bool focus = (hasFocus() || viewport()->hasFocus()) && current.isValid();
|
||||||
|
const QStyle::State state = option.state;
|
||||||
|
const QAbstractItemView::State viewState = this->state();
|
||||||
|
const bool enabled = (state & QStyle::State_Enabled) != 0;
|
||||||
|
|
||||||
|
int maxSize = (flow() == TopToBottom)
|
||||||
|
? viewport()->size().width() - 2 * spacing()
|
||||||
|
: viewport()->size().height() - 2 * spacing();
|
||||||
|
|
||||||
|
QVector<QModelIndex>::const_iterator end = toBeRendered.constEnd();
|
||||||
|
for (QVector<QModelIndex>::const_iterator it = toBeRendered.constBegin(); it != end; ++it) {
|
||||||
|
if (!it->isValid()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
option.rect = visualRect(*it);
|
||||||
|
|
||||||
|
if (flow() == TopToBottom)
|
||||||
|
option.rect.setWidth(qMin(maxSize, option.rect.width()));
|
||||||
|
else
|
||||||
|
option.rect.setHeight(qMin(maxSize, option.rect.height()));
|
||||||
|
|
||||||
|
option.state = state;
|
||||||
|
if (selections && selections->isSelected(*it))
|
||||||
|
option.state |= QStyle::State_Selected;
|
||||||
|
if (enabled) {
|
||||||
|
QPalette::ColorGroup cg;
|
||||||
|
if ((itemModel->flags(*it) & Qt::ItemIsEnabled) == 0) {
|
||||||
|
option.state &= ~QStyle::State_Enabled;
|
||||||
|
cg = QPalette::Disabled;
|
||||||
|
} else {
|
||||||
|
cg = QPalette::Normal;
|
||||||
|
}
|
||||||
|
option.palette.setCurrentColorGroup(cg);
|
||||||
|
}
|
||||||
|
if (focus && current == *it) {
|
||||||
|
option.state |= QStyle::State_HasFocus;
|
||||||
|
if (viewState == EditingState)
|
||||||
|
option.state |= QStyle::State_Editing;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemDelegate()->paint(&painter, option, *it);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw headers
|
||||||
|
foreach (const Header& header, headers_) {
|
||||||
|
const QRect header_rect = QRect(
|
||||||
|
header_indent_, header.y,
|
||||||
|
viewport()->width() - header_indent_ * 2, header_height());
|
||||||
|
|
||||||
|
// Is this header contained in the area we're drawing?
|
||||||
|
if (!header_rect.intersects(viewport_rect)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the header
|
||||||
|
DrawHeader(model()->index(header.first_row, 0),
|
||||||
|
header_rect.translated(-horizontalOffset(), -verticalOffset()),
|
||||||
|
&painter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupedIconView::setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags command) {
|
||||||
|
QVector<QModelIndex> indexes(IntersectingItems(rect.translated(horizontalOffset(), verticalOffset())));
|
||||||
|
QItemSelection selection;
|
||||||
|
|
||||||
|
foreach (const QModelIndex& index, indexes) {
|
||||||
|
selection << QItemSelectionRange(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectionModel()->select(selection, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QModelIndex> GroupedIconView::IntersectingItems(const QRect& rect) const {
|
||||||
|
QVector<QModelIndex> ret;
|
||||||
|
|
||||||
|
const int count = visual_rects_.count();
|
||||||
|
for (int i=0 ; i<count ; ++i) {
|
||||||
|
if (rect.intersects(visual_rects_[i])) {
|
||||||
|
ret.append(model()->index(i, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRegion GroupedIconView::visualRegionForSelection(const QItemSelection& selection) const {
|
||||||
|
QRegion ret;
|
||||||
|
foreach (const QModelIndex& index, selection.indexes()) {
|
||||||
|
ret += visual_rects_[index.row()];
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex GroupedIconView::moveCursor(CursorAction action, Qt::KeyboardModifiers) {
|
||||||
|
if (model()->rowCount() == 0) {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = currentIndex().row();
|
||||||
|
if (ret == -1) {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case MoveUp: ret = IndexAboveOrBelow(ret, -1); break;
|
||||||
|
case MovePrevious:
|
||||||
|
case MoveLeft: ret --; break;
|
||||||
|
case MoveDown: ret = IndexAboveOrBelow(ret, +1); break;
|
||||||
|
case MoveNext:
|
||||||
|
case MoveRight: ret ++; break;
|
||||||
|
case MovePageUp:
|
||||||
|
case MoveHome: ret = 0; break;
|
||||||
|
case MovePageDown:
|
||||||
|
case MoveEnd: ret = model()->rowCount() - 1; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return model()->index(qBound(0, ret, model()->rowCount()), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GroupedIconView::IndexAboveOrBelow(int index, int d) const {
|
||||||
|
const QRect orig_rect(visual_rects_[index]);
|
||||||
|
|
||||||
|
while (index >= 0 && index < visual_rects_.count()) {
|
||||||
|
const QRect rect(visual_rects_[index]);
|
||||||
|
const QPoint center(rect.center());
|
||||||
|
|
||||||
|
if ((center.y() <= orig_rect.top() || center.y() >= orig_rect.bottom()) &&
|
||||||
|
center.x() >= orig_rect.left() &&
|
||||||
|
center.x() <= orig_rect.right()) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
index += d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
108
src/widgets/groupediconview.h
Normal file
108
src/widgets/groupediconview.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
|
||||||
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Clementine is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GROUPEDICONVIEW_H
|
||||||
|
#define GROUPEDICONVIEW_H
|
||||||
|
|
||||||
|
#include <QListView>
|
||||||
|
|
||||||
|
class QSortFilterProxyModel;
|
||||||
|
|
||||||
|
|
||||||
|
class GroupedIconView : public QListView {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
// Vertical space separating a header from the items above and below it.
|
||||||
|
Q_PROPERTY(int header_spacing READ header_spacing WRITE set_header_spacing)
|
||||||
|
|
||||||
|
// Horizontal space separating a header from the left and right edges of the widget.
|
||||||
|
Q_PROPERTY(int header_indent READ header_indent WRITE set_header_indent)
|
||||||
|
|
||||||
|
// Horizontal space separating an item from the left and right edges of the widget.
|
||||||
|
Q_PROPERTY(int item_indent READ item_indent WRITE set_item_indent)
|
||||||
|
|
||||||
|
// The text of each group's header. Must contain "%1".
|
||||||
|
Q_PROPERTY(QString header_text READ header_text WRITE set_header_text);
|
||||||
|
|
||||||
|
public:
|
||||||
|
GroupedIconView(QWidget* parent = 0);
|
||||||
|
|
||||||
|
enum Role {
|
||||||
|
Role_Group = 1158300,
|
||||||
|
};
|
||||||
|
|
||||||
|
int header_spacing() const { return header_spacing_; }
|
||||||
|
int header_indent() const { return header_indent_; }
|
||||||
|
int item_indent() const { return item_indent_; }
|
||||||
|
const QString& header_text() const { return header_text_;}
|
||||||
|
|
||||||
|
void set_header_spacing(int value) { header_spacing_ = value; }
|
||||||
|
void set_header_indent(int value) { header_indent_ = value; }
|
||||||
|
void set_item_indent(int value) { item_indent_ = value; }
|
||||||
|
void set_header_text(const QString& value) { header_text_ = value; }
|
||||||
|
|
||||||
|
// QAbstractItemView
|
||||||
|
QModelIndex moveCursor(CursorAction action, Qt::KeyboardModifiers modifiers);
|
||||||
|
void setModel(QAbstractItemModel* model);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int header_height() const;
|
||||||
|
virtual void DrawHeader(const QModelIndex& first_child, const QRect& rect,
|
||||||
|
QPainter* painter);
|
||||||
|
|
||||||
|
// QWidget
|
||||||
|
void paintEvent(QPaintEvent* e);
|
||||||
|
void resizeEvent(QResizeEvent* e);
|
||||||
|
|
||||||
|
// QAbstractItemView
|
||||||
|
QModelIndex indexAt(const QPoint& p) const;
|
||||||
|
void rowsInserted(const QModelIndex& parent, int start, int end);
|
||||||
|
void setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags command);
|
||||||
|
QRect visualRect(const QModelIndex& index) const;
|
||||||
|
QRegion visualRegionForSelection(const QItemSelection& selection) const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void LayoutItems();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const int kBarThickness;
|
||||||
|
static const int kBarMarginTop;
|
||||||
|
|
||||||
|
struct Header {
|
||||||
|
int y;
|
||||||
|
int first_row;
|
||||||
|
QString text;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the items that are wholly or partially inside the rect.
|
||||||
|
QVector<QModelIndex> IntersectingItems(const QRect& rect) const;
|
||||||
|
|
||||||
|
// Returns the index of the item above (d=-1) or below (d=+1) the given item.
|
||||||
|
int IndexAboveOrBelow(int index, int d) const;
|
||||||
|
|
||||||
|
QSortFilterProxyModel* proxy_model_;
|
||||||
|
QVector<QRect> visual_rects_;
|
||||||
|
QVector<Header> headers_;
|
||||||
|
|
||||||
|
const int default_header_height_;
|
||||||
|
int header_spacing_;
|
||||||
|
int header_indent_;
|
||||||
|
int item_indent_;
|
||||||
|
QString header_text_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GROUPEDICONVIEW_H
|
@ -1,167 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
@ -1,172 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
@ -1,48 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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
|
|
@ -1,263 +0,0 @@
|
|||||||
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
@ -1,324 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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 ¤t,
|
|
||||||
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
|
|
@ -1,159 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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
|
|
@ -1,281 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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&)
|
|
||||||
{
|
|
||||||
}
|
|
@ -1,228 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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
|
|
Loading…
x
Reference in New Issue
Block a user