From: Rafael Fernández López Date: Sun, 13 Jan 2008 15:44:04 +0000 (+0000) Subject: Move KCategorizedView to kdelibs. Use that one. X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/f6984788a8332b7273a77bf160e2790a0308661a Move KCategorizedView to kdelibs. Use that one. svn path=/trunk/KDE/kdebase/apps/; revision=760873 --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 18b3a2283..bd2d37812 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,8 +25,6 @@ set(dolphinprivate_LIB_SRCS dolphincategorydrawer.cpp dolphinview.cpp iconmanager.cpp - kcategorizedview.cpp - kcategorydrawer.cpp ratingpainter.cpp renamedialog.cpp viewproperties.cpp diff --git a/src/dolphincategorydrawer.h b/src/dolphincategorydrawer.h index ea70a922b..1cccc620e 100644 --- a/src/dolphincategorydrawer.h +++ b/src/dolphincategorydrawer.h @@ -21,7 +21,7 @@ #ifndef DOLPHINCATEGORYDRAWER_H #define DOLPHINCATEGORYDRAWER_H -#include "kcategorydrawer.h" +#include #include #include diff --git a/src/kcategorizedview.cpp b/src/kcategorizedview.cpp deleted file mode 100644 index 217fef10f..000000000 --- a/src/kcategorizedview.cpp +++ /dev/null @@ -1,1626 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2007 Rafael Fernández López - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "kcategorizedview.h" -#include "kcategorizedview_p.h" - -#include // trunc on C99 compliant systems -#include // trunc for not C99 compliant systems - -#include -#include -#include - -#include - -#include "kcategorydrawer.h" -#include "kcategorizedsortfilterproxymodel.h" - -// By defining DOLPHIN_DRAGANDDROP the custom drag and drop implementation of -// KCategorizedView is bypassed to have a consistent drag and drop look for all -// views. Hopefully transparent pixmaps for drag objects will be supported in -// Qt 4.4, so that this workaround can be skipped. -#define DOLPHIN_DRAGANDDROP - -KCategorizedView::Private::Private(KCategorizedView *listView) - : listView(listView) - , categoryDrawer(0) - , biggestItemSize(QSize(0, 0)) - , mouseButtonPressed(false) - , rightMouseButtonPressed(false) - , isDragging(false) - , dragLeftViewport(false) - , proxyModel(0) -{ -} - -KCategorizedView::Private::~Private() -{ -} - -const QModelIndexList &KCategorizedView::Private::intersectionSet(const QRect &rect) -{ - QModelIndex index; - QRect indexVisualRect; - - intersectedIndexes.clear(); - - int itemHeight; - - if (listView->gridSize().isEmpty()) - { - itemHeight = biggestItemSize.height(); - } - else - { - itemHeight = listView->gridSize().height(); - } - - // Lets find out where we should start - int top = proxyModel->rowCount() - 1; - int bottom = 0; - int middle = (top + bottom) / 2; - while (bottom <= top) - { - middle = (top + bottom) / 2; - - index = proxyModel->index(middle, 0); - indexVisualRect = visualRect(index); - // We need the whole height (not only the visualRect). This will help us to update - // all needed indexes correctly (ereslibre) - indexVisualRect.setHeight(indexVisualRect.height() + (itemHeight - indexVisualRect.height())); - - if (qMax(indexVisualRect.topLeft().y(), - indexVisualRect.bottomRight().y()) < qMin(rect.topLeft().y(), - rect.bottomRight().y())) - { - bottom = middle + 1; - } - else - { - top = middle - 1; - } - } - - for (int i = middle; i < proxyModel->rowCount(); i++) - { - index = proxyModel->index(i, 0); - indexVisualRect = visualRect(index); - - if (rect.intersects(indexVisualRect)) - intersectedIndexes.append(index); - - // If we passed next item, stop searching for hits - if (qMax(rect.bottomRight().y(), rect.topLeft().y()) < - qMin(indexVisualRect.topLeft().y(), - indexVisualRect.bottomRight().y())) - break; - } - - return intersectedIndexes; -} - -QRect KCategorizedView::Private::visualRectInViewport(const QModelIndex &index) const -{ - if (!index.isValid()) - return QRect(); - - QString curCategory = elementsInfo[index.row()].category; - - QRect retRect; - - if (listView->flow() == QListView::LeftToRight) - { - if (listView->layoutDirection() == Qt::LeftToRight) - { - retRect = QRect(listView->spacing(), listView->spacing() * 2 + - categoryDrawer->categoryHeight(index, listView->viewOptions()), 0, 0); - } - else - { - retRect = QRect(listView->viewport()->width() - listView->spacing(), listView->spacing() * 2 + - categoryDrawer->categoryHeight(index, listView->viewOptions()), 0, 0); - } - } - else - { - retRect = QRect(listView->spacing(), listView->spacing() * 2 + - categoryDrawer->categoryHeight(index, listView->viewOptions()), 0, 0); - } - - int viewportWidth = listView->viewport()->width() - listView->spacing(); - - int itemHeight; - int itemWidth; - - if (listView->gridSize().isEmpty() && (listView->flow() == QListView::LeftToRight)) - { - itemHeight = biggestItemSize.height(); - itemWidth = biggestItemSize.width(); - } - else if (listView->flow() == QListView::LeftToRight) - { - itemHeight = listView->gridSize().height(); - itemWidth = listView->gridSize().width(); - } - else if (listView->gridSize().isEmpty() && (listView->flow() == QListView::TopToBottom)) - { - itemHeight = biggestItemSize.height(); - itemWidth = listView->viewport()->width() - listView->spacing() * 2; - } - else - { - itemHeight = listView->gridSize().height(); - itemWidth = listView->gridSize().width() - listView->spacing() * 2; - } - - int itemWidthPlusSeparation = listView->spacing() + itemWidth; - if (!itemWidthPlusSeparation) - itemWidthPlusSeparation++; - int elementsPerRow = viewportWidth / itemWidthPlusSeparation; - if (!elementsPerRow) - elementsPerRow++; - - int column; - int row; - - if (listView->flow() == QListView::LeftToRight) - { - column = elementsInfo[index.row()].relativeOffsetToCategory % elementsPerRow; - row = elementsInfo[index.row()].relativeOffsetToCategory / elementsPerRow; - - if (listView->layoutDirection() == Qt::LeftToRight) - { - retRect.setLeft(retRect.left() + column * listView->spacing() + - column * itemWidth); - } - else - { - retRect.setLeft(retRect.right() - column * listView->spacing() - - column * itemWidth - itemWidth); - - retRect.setRight(retRect.right() - column * listView->spacing() - - column * itemWidth); - } - } - else - { - elementsPerRow = 1; - column = elementsInfo[index.row()].relativeOffsetToCategory % elementsPerRow; - row = elementsInfo[index.row()].relativeOffsetToCategory / elementsPerRow; - } - - foreach (const QString &category, categories) - { - if (category == curCategory) - break; - - float rows = (float) ((float) categoriesIndexes[category].count() / - (float) elementsPerRow); - - int rowsInt = categoriesIndexes[category].count() / elementsPerRow; - - if (rows - trunc(rows)) rowsInt++; - - retRect.setTop(retRect.top() + - (rowsInt * itemHeight) + - categoryDrawer->categoryHeight(index, listView->viewOptions()) + - listView->spacing() * 2); - - if (listView->gridSize().isEmpty()) - { - retRect.setTop(retRect.top() + - (rowsInt * listView->spacing())); - } - } - - if (listView->gridSize().isEmpty()) - { - retRect.setTop(retRect.top() + row * listView->spacing() + - (row * itemHeight)); - } - else - { - retRect.setTop(retRect.top() + (row * itemHeight)); - } - - retRect.setWidth(itemWidth); - - QModelIndex heightIndex = proxyModel->index(index.row(), 0); - if (listView->gridSize().isEmpty()) - { - retRect.setHeight(listView->sizeHintForIndex(heightIndex).height()); - } - else - { - retRect.setHeight(qMin(listView->sizeHintForIndex(heightIndex).height(), - listView->gridSize().height())); - } - - return retRect; -} - -QRect KCategorizedView::Private::visualCategoryRectInViewport(const QString &category) const -{ - QRect retRect(listView->spacing(), - listView->spacing(), - listView->viewport()->width() - listView->spacing() * 2, - 0); - - if (!proxyModel->rowCount() || !categories.contains(category)) - return QRect(); - - QModelIndex index = proxyModel->index(0, 0, QModelIndex()); - - int viewportWidth = listView->viewport()->width() - listView->spacing(); - - int itemHeight; - int itemWidth; - - if (listView->gridSize().isEmpty()) - { - itemHeight = biggestItemSize.height(); - itemWidth = biggestItemSize.width(); - } - else - { - itemHeight = listView->gridSize().height(); - itemWidth = listView->gridSize().width(); - } - - int itemWidthPlusSeparation = listView->spacing() + itemWidth; - int elementsPerRow = viewportWidth / itemWidthPlusSeparation; - - if (!elementsPerRow) - elementsPerRow++; - - if (listView->flow() == QListView::TopToBottom) - { - elementsPerRow = 1; - } - - foreach (const QString &itCategory, categories) - { - if (itCategory == category) - break; - - float rows = (float) ((float) categoriesIndexes[itCategory].count() / - (float) elementsPerRow); - int rowsInt = categoriesIndexes[itCategory].count() / elementsPerRow; - - if (rows - trunc(rows)) rowsInt++; - - retRect.setTop(retRect.top() + - (rowsInt * itemHeight) + - categoryDrawer->categoryHeight(index, listView->viewOptions()) + - listView->spacing() * 2); - - if (listView->gridSize().isEmpty()) - { - retRect.setTop(retRect.top() + - (rowsInt * listView->spacing())); - } - } - - retRect.setHeight(categoryDrawer->categoryHeight(index, listView->viewOptions())); - - return retRect; -} - -// We're sure elementsPosition doesn't contain index -const QRect &KCategorizedView::Private::cacheIndex(const QModelIndex &index) -{ - QRect rect = visualRectInViewport(index); - elementsPosition[index.row()] = rect; - - return elementsPosition[index.row()]; -} - -// We're sure categoriesPosition doesn't contain category -const QRect &KCategorizedView::Private::cacheCategory(const QString &category) -{ - QRect rect = visualCategoryRectInViewport(category); - categoriesPosition[category] = rect; - - return categoriesPosition[category]; -} - -const QRect &KCategorizedView::Private::cachedRectIndex(const QModelIndex &index) -{ - if (elementsPosition.contains(index.row())) // If we have it cached - { // return it - return elementsPosition[index.row()]; - } - else // Otherwise, cache it - { // and return it - return cacheIndex(index); - } -} - -const QRect &KCategorizedView::Private::cachedRectCategory(const QString &category) -{ - if (categoriesPosition.contains(category)) // If we have it cached - { // return it - return categoriesPosition[category]; - } - else // Otherwise, cache it and - { // return it - return cacheCategory(category); - } -} - -QRect KCategorizedView::Private::visualRect(const QModelIndex &index) -{ - QRect retRect = cachedRectIndex(index); - int dx = -listView->horizontalOffset(); - int dy = -listView->verticalOffset(); - retRect.adjust(dx, dy, dx, dy); - - return retRect; -} - -QRect KCategorizedView::Private::categoryVisualRect(const QString &category) -{ - QRect retRect = cachedRectCategory(category); - int dx = -listView->horizontalOffset(); - int dy = -listView->verticalOffset(); - retRect.adjust(dx, dy, dx, dy); - - return retRect; -} - -void KCategorizedView::Private::drawNewCategory(const QModelIndex &index, - int sortRole, - const QStyleOption &option, - QPainter *painter) -{ - if (!index.isValid()) - { - return; - } - - QStyleOption optionCopy = option; - const QString category = proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString(); - - optionCopy.state &= ~QStyle::State_Selected; - - if ((listView->selectionMode() != SingleSelection) && (listView->selectionMode() != NoSelection)) { - if ((category == hoveredCategory) && !mouseButtonPressed) - { - optionCopy.state |= QStyle::State_MouseOver; - } - else if ((category == hoveredCategory) && mouseButtonPressed) - { - QPoint initialPressPosition = listView->viewport()->mapFromGlobal(QCursor::pos()); - initialPressPosition.setY(initialPressPosition.y() + listView->verticalOffset()); - initialPressPosition.setX(initialPressPosition.x() + listView->horizontalOffset()); - - if (initialPressPosition == this->initialPressPosition) - { - optionCopy.state |= QStyle::State_Selected; - } - } - } - - categoryDrawer->drawCategory(index, - sortRole, - optionCopy, - painter); -} - - -void KCategorizedView::Private::updateScrollbars() -{ - // find the last index in the last category - QModelIndex lastIndex = categoriesIndexes.isEmpty() ? QModelIndex() : categoriesIndexes[categories.last()].last(); - - int lastItemBottom = cachedRectIndex(lastIndex).top() + - listView->spacing() + (listView->gridSize().isEmpty() ? biggestItemSize.height() : listView->gridSize().height()) - listView->viewport()->height(); - - listView->horizontalScrollBar()->setRange(0, 0); - - listView->verticalScrollBar()->setSingleStep(listView->viewport()->height() / 10); - listView->verticalScrollBar()->setPageStep(listView->viewport()->height()); - listView->verticalScrollBar()->setRange(0, lastItemBottom); -} - -void KCategorizedView::Private::drawDraggedItems(QPainter *painter) -{ - QStyleOptionViewItemV3 option = listView->viewOptions(); - option.state &= ~QStyle::State_MouseOver; - foreach (const QModelIndex &index, listView->selectionModel()->selectedIndexes()) - { - const int dx = mousePosition.x() - initialPressPosition.x() + listView->horizontalOffset(); - const int dy = mousePosition.y() - initialPressPosition.y() + listView->verticalOffset(); - - option.rect = visualRect(index); - option.rect.adjust(dx, dy, dx, dy); - - if (option.rect.intersects(listView->viewport()->rect())) - { - listView->itemDelegate(index)->paint(painter, option, index); - } - } -} - -void KCategorizedView::Private::layoutChanged(bool forceItemReload) -{ - if (proxyModel && categoryDrawer && proxyModel->isCategorizedModel() && - ((forceItemReload || - (modelSortRole != proxyModel->sortRole()) || - (modelSortColumn != proxyModel->sortColumn()) || - (modelSortOrder != proxyModel->sortOrder()) || - (modelLastRowCount != proxyModel->rowCount()) || - (modelCategorized != proxyModel->isCategorizedModel())))) - { - // Force the view to update all elements - listView->rowsInsertedArtifficial(QModelIndex(), 0, proxyModel->rowCount() - 1); - - if (!forceItemReload) - { - modelSortRole = proxyModel->sortRole(); - modelSortColumn = proxyModel->sortColumn(); - modelSortOrder = proxyModel->sortOrder(); - modelLastRowCount = proxyModel->rowCount(); - modelCategorized = proxyModel->isCategorizedModel(); - } - } - else if (proxyModel && categoryDrawer && proxyModel->isCategorizedModel()) - { - updateScrollbars(); - } -} - -void KCategorizedView::Private::drawDraggedItems() -{ - QRect rectToUpdate; - QRect currentRect; - foreach (const QModelIndex &index, listView->selectionModel()->selectedIndexes()) - { - int dx = mousePosition.x() - initialPressPosition.x() + listView->horizontalOffset(); - int dy = mousePosition.y() - initialPressPosition.y() + listView->verticalOffset(); - - currentRect = visualRect(index); - currentRect.adjust(dx, dy, dx, dy); - - if (currentRect.intersects(listView->viewport()->rect())) - { - rectToUpdate = rectToUpdate.united(currentRect); - } - } - - listView->viewport()->update(lastDraggedItemsRect.united(rectToUpdate)); - - lastDraggedItemsRect = rectToUpdate; -} - - -//============================================================================== - - -KCategorizedView::KCategorizedView(QWidget *parent) - : QListView(parent) - , d(new Private(this)) -{ - setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); - setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); -} - -KCategorizedView::~KCategorizedView() -{ - delete d; -} - -void KCategorizedView::setGridSize(const QSize &size) -{ - QListView::setGridSize(size); - - d->layoutChanged(true); -} - -void KCategorizedView::setModel(QAbstractItemModel *model) -{ - d->lastSelection = QItemSelection(); - d->forcedSelectionPosition = 0; - d->elementsInfo.clear(); - d->elementsPosition.clear(); - d->categoriesIndexes.clear(); - d->categoriesPosition.clear(); - d->categories.clear(); - d->intersectedIndexes.clear(); - d->modelIndexList.clear(); - d->hovered = QModelIndex(); - d->mouseButtonPressed = false; - d->rightMouseButtonPressed = false; - - if (d->proxyModel) - { - QObject::disconnect(d->proxyModel, - SIGNAL(layoutChanged()), - this, SLOT(slotLayoutChanged())); - - QObject::disconnect(d->proxyModel, - SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(slotLayoutChanged())); - - QObject::disconnect(d->proxyModel, - SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved(QModelIndex,int,int))); - } - - QListView::setModel(model); - - d->proxyModel = dynamic_cast(model); - - if (d->proxyModel) - { - d->modelSortRole = d->proxyModel->sortRole(); - d->modelSortColumn = d->proxyModel->sortColumn(); - d->modelSortOrder = d->proxyModel->sortOrder(); - d->modelLastRowCount = d->proxyModel->rowCount(); - d->modelCategorized = d->proxyModel->isCategorizedModel(); - - QObject::connect(d->proxyModel, - SIGNAL(layoutChanged()), - this, SLOT(slotLayoutChanged())); - - QObject::connect(d->proxyModel, - SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(slotLayoutChanged())); - - QObject::connect(d->proxyModel, - SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved(QModelIndex,int,int))); - - if (d->proxyModel->rowCount()) - { - d->layoutChanged(true); - } - } - else - { - d->modelCategorized = false; - } -} - -QRect KCategorizedView::visualRect(const QModelIndex &index) const -{ - if (!d->proxyModel || !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) - { - return QListView::visualRect(index); - } - - if (!qobject_cast(index.model())) - { - return d->visualRect(d->proxyModel->mapFromSource(index)); - } - - return d->visualRect(index); -} - -KCategoryDrawer *KCategorizedView::categoryDrawer() const -{ - return d->categoryDrawer; -} - -void KCategorizedView::setCategoryDrawer(KCategoryDrawer *categoryDrawer) -{ - d->lastSelection = QItemSelection(); - d->forcedSelectionPosition = 0; - d->elementsInfo.clear(); - d->elementsPosition.clear(); - d->categoriesIndexes.clear(); - d->categoriesPosition.clear(); - d->categories.clear(); - d->intersectedIndexes.clear(); - d->modelIndexList.clear(); - d->hovered = QModelIndex(); - d->mouseButtonPressed = false; - d->rightMouseButtonPressed = false; - - if (!categoryDrawer && d->proxyModel) - { - QObject::disconnect(d->proxyModel, - SIGNAL(layoutChanged()), - this, SLOT(slotLayoutChanged())); - - QObject::disconnect(d->proxyModel, - SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(slotLayoutChanged())); - - QObject::disconnect(d->proxyModel, - SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved(QModelIndex,int,int))); - } - else if (categoryDrawer && d->proxyModel) - { - QObject::connect(d->proxyModel, - SIGNAL(layoutChanged()), - this, SLOT(slotLayoutChanged())); - - QObject::connect(d->proxyModel, - SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(slotLayoutChanged())); - - QObject::connect(d->proxyModel, - SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved(QModelIndex,int,int))); - } - - d->categoryDrawer = categoryDrawer; - - if (categoryDrawer) - { - if (d->proxyModel) - { - if (d->proxyModel->rowCount()) - { - d->layoutChanged(true); - } - } - } - else - { - updateGeometries(); - } -} - -QModelIndex KCategorizedView::indexAt(const QPoint &point) const -{ - if (!d->proxyModel || !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) - { - return QListView::indexAt(point); - } - - QModelIndex index; - - QModelIndexList item = d->intersectionSet(QRect(point, point)); - - if (item.count() == 1) - { - index = item[0]; - } - - return index; -} - -void KCategorizedView::reset() -{ - QListView::reset(); - - d->lastSelection = QItemSelection(); - d->forcedSelectionPosition = 0; - d->elementsInfo.clear(); - d->elementsPosition.clear(); - d->categoriesIndexes.clear(); - d->categoriesPosition.clear(); - d->categories.clear(); - d->intersectedIndexes.clear(); - d->modelIndexList.clear(); - d->hovered = QModelIndex(); - d->biggestItemSize = QSize(0, 0); - d->mouseButtonPressed = false; - d->rightMouseButtonPressed = false; -} - -void KCategorizedView::paintEvent(QPaintEvent *event) -{ - if (!d->proxyModel || !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) - { - QListView::paintEvent(event); - return; - } - - QStyleOptionViewItemV3 option = viewOptions(); - option.widget = this; - if (wordWrap()) - { - option.features |= QStyleOptionViewItemV2::WrapText; - } - - QPainter painter(viewport()); - QRect area = event->rect(); - const bool focus = (hasFocus() || viewport()->hasFocus()) && - currentIndex().isValid(); - const QStyle::State state = option.state; - const bool enabled = (state & QStyle::State_Enabled) != 0; - - painter.save(); - - QModelIndexList dirtyIndexes = d->intersectionSet(area); - foreach (const QModelIndex &index, dirtyIndexes) - { - option.state = state; - option.rect = visualRect(index); - - if (selectionModel() && selectionModel()->isSelected(index)) - { - option.state |= QStyle::State_Selected; - } - - if (enabled) - { - QPalette::ColorGroup cg; - if ((d->proxyModel->flags(index) & Qt::ItemIsEnabled) == 0) - { - option.state &= ~QStyle::State_Enabled; - cg = QPalette::Disabled; - } - else - { - cg = QPalette::Normal; - } - option.palette.setCurrentColorGroup(cg); - } - - if (focus && currentIndex() == index) - { - option.state |= QStyle::State_HasFocus; - if (this->state() == EditingState) - option.state |= QStyle::State_Editing; - } - - // we are only interested to give the mouse over feedback when no - // dragging is happening (ereslibre) - if ((index == d->hovered) && !d->mouseButtonPressed && - (this->state() == QAbstractItemView::NoState)) - option.state |= QStyle::State_MouseOver; - else - option.state &= ~QStyle::State_MouseOver; - - itemDelegate(index)->paint(&painter, option, index); - } - - // Redraw categories - QStyleOptionViewItem otherOption; - bool intersectedInThePast = false; - foreach (const QString &category, d->categories) - { - otherOption = option; - otherOption.rect = d->categoryVisualRect(category); - otherOption.state &= ~QStyle::State_MouseOver; - - if (otherOption.rect.intersects(area)) - { - intersectedInThePast = true; - - QModelIndex indexToDraw = d->proxyModel->index(d->categoriesIndexes[category][0].row(), d->proxyModel->sortColumn()); - - d->drawNewCategory(indexToDraw, - d->proxyModel->sortRole(), otherOption, &painter); - } - else if (intersectedInThePast) - { - break; // the visible area has been finished, we don't need to keep asking, the rest won't intersect - // this is doable because we know that categories are correctly ordered on the list - } - } - - if ((selectionMode() != SingleSelection) && (selectionMode() != NoSelection)) - { - if (d->mouseButtonPressed && !d->isDragging) - { - QPoint start, end, initialPressPosition; - - initialPressPosition = d->initialPressPosition; - - initialPressPosition.setY(initialPressPosition.y() - verticalOffset()); - initialPressPosition.setX(initialPressPosition.x() - horizontalOffset()); - - if (d->initialPressPosition.x() > d->mousePosition.x() || - d->initialPressPosition.y() > d->mousePosition.y()) - { - start = d->mousePosition; - end = initialPressPosition; - } - else - { - start = initialPressPosition; - end = d->mousePosition; - } - - QStyleOptionRubberBand yetAnotherOption; - yetAnotherOption.initFrom(this); - yetAnotherOption.shape = QRubberBand::Rectangle; - yetAnotherOption.opaque = false; - yetAnotherOption.rect = QRect(start, end).intersected(viewport()->rect().adjusted(-16, -16, 16, 16)); - painter.save(); - style()->drawControl(QStyle::CE_RubberBand, &yetAnotherOption, &painter); - painter.restore(); - } - } - - if (d->isDragging && !d->dragLeftViewport) - { - painter.setOpacity(0.5); - d->drawDraggedItems(&painter); - } - - painter.restore(); -} - -void KCategorizedView::resizeEvent(QResizeEvent *event) -{ - QListView::resizeEvent(event); - - // Clear the items positions cache - d->elementsPosition.clear(); - d->categoriesPosition.clear(); - d->forcedSelectionPosition = 0; - - if (!d->proxyModel || !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) - { - return; - } - - d->updateScrollbars(); -} - -void KCategorizedView::setSelection(const QRect &rect, - QItemSelectionModel::SelectionFlags flags) -{ - if (!d->proxyModel || !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) - { - QListView::setSelection(rect, flags); - return; - } - - if (!flags) - return; - - if (flags & QItemSelectionModel::Clear) - { - selectionModel()->clear(); - d->lastSelection.clear(); - } - - QModelIndexList dirtyIndexes = d->intersectionSet(rect); - - // no items affected, just leave - if (!dirtyIndexes.count()) - { - selectionModel()->select(d->lastSelection, QItemSelectionModel::SelectCurrent); - - return; - } - - QModelIndex topLeft; - QModelIndex bottomRight; - - if (d->mouseButtonPressed || d->rightMouseButtonPressed) // selection with click + drag - { - QItemSelection selection; - - QModelIndex prev = dirtyIndexes[0]; - QModelIndex first = prev; - foreach (const QModelIndex &index, dirtyIndexes) - { - // we have a different interval. non-contiguous items - if ((index.row() - prev.row()) > 1) { - selection << QItemSelectionRange(first, prev); - - first = index; - } - - prev = index; - } - - selection << QItemSelectionRange(first, prev); - - if (flags & QItemSelectionModel::Current) - { - if (rect.topLeft() == rect.bottomRight()) - { - selectionModel()->setCurrentIndex(indexAt(rect.topLeft()), QItemSelectionModel::NoUpdate); - } - - selection.merge(d->lastSelection, flags); - } - else - { - selection.merge(selectionModel()->selection(), flags); - - selectionModel()->select(selection, QItemSelectionModel::SelectCurrent); - - return; - } - - selectionModel()->select(selection, flags); - } - else // selection with click + keyboard keys - { - QModelIndex topLeftIndex = indexAt(QPoint(rect.topLeft().x(), - rect.topLeft().y())); - QModelIndex bottomRightIndex = indexAt(QPoint(rect.bottomRight().x(), - rect.bottomRight().y())); - - // keyboard selection comes "upside down". Let's normalize it - if (topLeftIndex.row() > bottomRightIndex.row()) - { - QModelIndex auxIndex = topLeftIndex; - topLeftIndex = bottomRightIndex; - bottomRightIndex = auxIndex; - } - - int viewportWidth = viewport()->width() - spacing(); - int itemWidth; - - if (gridSize().isEmpty()) - { - itemWidth = d->biggestItemSize.width(); - } - else - { - itemWidth = gridSize().width(); - } - - int itemWidthPlusSeparation = spacing() + itemWidth; - if (!itemWidthPlusSeparation) - itemWidthPlusSeparation++; - int elementsPerRow = viewportWidth / itemWidthPlusSeparation; - if (!elementsPerRow) - elementsPerRow++; - - QModelIndexList theoricDirty(dirtyIndexes); - dirtyIndexes.clear(); - int first = model()->rowCount(); - int last = 0; - - foreach (const QModelIndex &index, theoricDirty) - { - if ((index.row() < first) && - ((((topLeftIndex.row() / elementsPerRow) == (index.row() / elementsPerRow)) && - ((topLeftIndex.row() % elementsPerRow) <= (index.row() % elementsPerRow))) || - (topLeftIndex.row() / elementsPerRow) != (index.row() / elementsPerRow))) - { - first = index.row(); - topLeft = index; - } - - if ((index.row() > last) && - ((((bottomRightIndex.row() / elementsPerRow) == (index.row() / elementsPerRow)) && - ((bottomRightIndex.row() % elementsPerRow) >= (index.row() % elementsPerRow))) || - (bottomRightIndex.row() / elementsPerRow) != (index.row() / elementsPerRow))) - { - last = index.row(); - bottomRight = index; - } - } - - for (int i = first; i <= last; i++) - { - dirtyIndexes << model()->index(i, theoricDirty[0].column(), theoricDirty[0].parent()); - } - - QItemSelection selection(topLeft, bottomRight); - - selectionModel()->select(selection, flags); - } -} - -void KCategorizedView::mouseMoveEvent(QMouseEvent *event) -{ - QListView::mouseMoveEvent(event); - - if (!d->proxyModel || !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) - { - return; - } - - QModelIndexList item = d->intersectionSet(QRect(event->pos(), event->pos())); - - if (item.count() == 1) - { - d->hovered = item[0]; - } - else - { - d->hovered = QModelIndex(); - } - - const QString previousHoveredCategory = d->hoveredCategory; - - d->mousePosition = event->pos(); - d->hoveredCategory = QString(); - - // Redraw categories - foreach (const QString &category, d->categories) - { - if (d->categoryVisualRect(category).intersects(QRect(event->pos(), event->pos()))) - { - d->hoveredCategory = category; - viewport()->update(d->categoryVisualRect(category)); - } - else if ((category == previousHoveredCategory) && - (!d->categoryVisualRect(previousHoveredCategory).intersects(QRect(event->pos(), event->pos())))) - { - viewport()->update(d->categoryVisualRect(category)); - } - } - - QRect rect; - if (d->mouseButtonPressed && !d->isDragging) - { - QPoint start, end, initialPressPosition; - - initialPressPosition = d->initialPressPosition; - - initialPressPosition.setY(initialPressPosition.y() - verticalOffset()); - initialPressPosition.setX(initialPressPosition.x() - horizontalOffset()); - - if (d->initialPressPosition.x() > d->mousePosition.x() || - d->initialPressPosition.y() > d->mousePosition.y()) - { - start = d->mousePosition; - end = initialPressPosition; - } - else - { - start = initialPressPosition; - end = d->mousePosition; - } - - rect = QRect(start, end).adjusted(-16, -16, 16, 16); - rect = rect.united(QRect(start, end).adjusted(16, 16, -16, -16)).intersected(viewport()->rect()); - - viewport()->update(rect); - } -} - -void KCategorizedView::mousePressEvent(QMouseEvent *event) -{ - d->dragLeftViewport = false; - - if (event->button() == Qt::LeftButton) - { - d->mouseButtonPressed = true; - - d->initialPressPosition = event->pos(); - d->initialPressPosition.setY(d->initialPressPosition.y() + - verticalOffset()); - d->initialPressPosition.setX(d->initialPressPosition.x() + - horizontalOffset()); - } - else if (event->button() == Qt::RightButton) - { - d->rightMouseButtonPressed = true; - } - - QListView::mousePressEvent(event); - - d->lastSelection = selectionModel()->selection(); - - viewport()->update(d->categoryVisualRect(d->hoveredCategory)); -} - -void KCategorizedView::mouseReleaseEvent(QMouseEvent *event) -{ - d->mouseButtonPressed = false; - d->rightMouseButtonPressed = false; - - QListView::mouseReleaseEvent(event); - - if (!d->proxyModel || !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) - { - return; - } - - QPoint initialPressPosition = viewport()->mapFromGlobal(QCursor::pos()); - initialPressPosition.setY(initialPressPosition.y() + verticalOffset()); - initialPressPosition.setX(initialPressPosition.x() + horizontalOffset()); - - if ((selectionMode() != SingleSelection) && (selectionMode() != NoSelection) && - (initialPressPosition == d->initialPressPosition)) - { - foreach(const QString &category, d->categories) - { - if (d->categoryVisualRect(category).contains(event->pos())) - { - QItemSelection selection = selectionModel()->selection(); - QModelIndexList indexList = d->categoriesIndexes[category]; - - foreach (const QModelIndex &index, indexList) - { - QModelIndex selectIndex = index.model()->index(index.row(), 0); - - selection << QItemSelectionRange(selectIndex); - } - - selectionModel()->select(selection, QItemSelectionModel::SelectCurrent); - - break; - } - } - } - - QRect rect; - if (!d->isDragging) - { - QPoint start, end, initialPressPosition; - - initialPressPosition = d->initialPressPosition; - - initialPressPosition.setY(initialPressPosition.y() - verticalOffset()); - initialPressPosition.setX(initialPressPosition.x() - horizontalOffset()); - - if (d->initialPressPosition.x() > d->mousePosition.x() || - d->initialPressPosition.y() > d->mousePosition.y()) - { - start = d->mousePosition; - end = initialPressPosition; - } - else - { - start = initialPressPosition; - end = d->mousePosition; - } - - rect = QRect(start, end).adjusted(-16, -16, 16, 16); - rect = rect.united(QRect(start, end).adjusted(16, 16, -16, -16)).intersected(viewport()->rect()); - - viewport()->update(rect); - } - - if (d->hovered.isValid()) - viewport()->update(visualRect(d->hovered)); - else if (!d->hoveredCategory.isEmpty()) - viewport()->update(d->categoryVisualRect(d->hoveredCategory)); -} - -void KCategorizedView::leaveEvent(QEvent *event) -{ - d->hovered = QModelIndex(); - d->hoveredCategory = QString(); - - QListView::leaveEvent(event); -} - -void KCategorizedView::startDrag(Qt::DropActions supportedActions) -{ - // FIXME: QAbstractItemView does far better here since it sets the - // pixmap of selected icons to the dragging cursor, but it sets a non - // ARGB window so it is no transparent. Use QAbstractItemView when - // this is fixed on Qt. - // QAbstractItemView::startDrag(supportedActions); -#if !defined(DOLPHIN_DRAGANDDROP) - QListView::startDrag(supportedActions); -#endif - - d->isDragging = false; - d->mouseButtonPressed = false; - d->rightMouseButtonPressed = false; - - viewport()->update(d->lastDraggedItemsRect); -} - -void KCategorizedView::dragMoveEvent(QDragMoveEvent *event) -{ - d->mousePosition = event->pos(); - - if (d->mouseButtonPressed) - { - d->isDragging = true; - } - else - { - d->isDragging = false; - } - - d->dragLeftViewport = false; - -#if defined(DOLPHIN_DRAGANDDROP) - QAbstractItemView::dragMoveEvent(event); -#else - QListView::dragMoveEvent(event); -#endif - - if (!d->proxyModel || !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) - { - return; - } - - d->drawDraggedItems(); -} - -void KCategorizedView::dragLeaveEvent(QDragLeaveEvent *event) -{ - d->dragLeftViewport = true; - -#if defined(DOLPHIN_DRAGANDDROP) - QAbstractItemView::dragLeaveEvent(event); -#else - QListView::dragLeaveEvent(event); -#endif -} - -void KCategorizedView::dropEvent(QDropEvent *event) -{ -#if defined(DOLPHIN_DRAGANDDROP) - QAbstractItemView::dropEvent(event); -#else - QListView::dropEvent(event); -#endif -} - -QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction, - Qt::KeyboardModifiers modifiers) -{ - if ((viewMode() != KCategorizedView::IconMode) || - !d->proxyModel || - !d->categoryDrawer || - d->categories.isEmpty() || - !d->proxyModel->isCategorizedModel()) - { - return QListView::moveCursor(cursorAction, modifiers); - } - - int viewportWidth = viewport()->width() - spacing(); - int itemWidth; - - if (gridSize().isEmpty()) - { - itemWidth = d->biggestItemSize.width(); - } - else - { - itemWidth = gridSize().width(); - } - - int itemWidthPlusSeparation = spacing() + itemWidth; - if (!itemWidthPlusSeparation) - itemWidthPlusSeparation++; - int elementsPerRow = viewportWidth / itemWidthPlusSeparation; - if (!elementsPerRow) - elementsPerRow++; - - QModelIndex current = selectionModel()->currentIndex(); - - if (!current.isValid()) - { - if (cursorAction == MoveEnd) - { - current = model()->index(model()->rowCount() - 1, 0, QModelIndex()); - d->forcedSelectionPosition = d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow; - } - else - { - current = model()->index(0, 0, QModelIndex()); - d->forcedSelectionPosition = 0; - } - - return current; - } - else if (!current.isValid()) - { - return QModelIndex(); - } - - QString lastCategory = d->categories.first(); - QString theCategory = d->categories.first(); - QString afterCategory = d->categories.first(); - - bool hasToBreak = false; - foreach (const QString &category, d->categories) - { - if (hasToBreak) - { - afterCategory = category; - - break; - } - - if (category == d->elementsInfo[current.row()].category) - { - theCategory = category; - - hasToBreak = true; - } - - if (!hasToBreak) - { - lastCategory = category; - } - } - - switch (cursorAction) - { - case QAbstractItemView::MoveUp: { - if (d->elementsInfo[current.row()].relativeOffsetToCategory >= elementsPerRow) - { - int indexToMove = current.row(); - indexToMove -= qMin(((d->elementsInfo[current.row()].relativeOffsetToCategory) + d->forcedSelectionPosition), elementsPerRow - d->forcedSelectionPosition + (d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow)); - - return d->proxyModel->index(indexToMove, 0); - } - else - { - int lastCategoryLastRow = (d->categoriesIndexes[lastCategory].count() - 1) % elementsPerRow; - int indexToMove = current.row() - d->elementsInfo[current.row()].relativeOffsetToCategory; - - if (d->forcedSelectionPosition >= lastCategoryLastRow) - { - indexToMove -= 1; - } - else - { - indexToMove -= qMin((lastCategoryLastRow - d->forcedSelectionPosition + 1), d->forcedSelectionPosition + elementsPerRow + 1); - } - - return d->proxyModel->index(indexToMove, 0); - } - } - - case QAbstractItemView::MoveDown: { - if (d->elementsInfo[current.row()].relativeOffsetToCategory < (d->categoriesIndexes[theCategory].count() - 1 - ((d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow))) - { - int indexToMove = current.row(); - indexToMove += qMin(elementsPerRow, d->categoriesIndexes[theCategory].count() - 1 - d->elementsInfo[current.row()].relativeOffsetToCategory); - - return d->proxyModel->index(indexToMove, 0); - } - else - { - int afterCategoryLastRow = qMin(elementsPerRow, d->categoriesIndexes[afterCategory].count()); - int indexToMove = current.row() + (d->categoriesIndexes[theCategory].count() - d->elementsInfo[current.row()].relativeOffsetToCategory); - - if (d->forcedSelectionPosition >= afterCategoryLastRow) - { - indexToMove += afterCategoryLastRow - 1; - } - else - { - indexToMove += qMin(d->forcedSelectionPosition, elementsPerRow); - } - - return d->proxyModel->index(indexToMove, 0); - } - } - - case QAbstractItemView::MoveLeft: - if (layoutDirection() == Qt::RightToLeft) - { - if (!(d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow)) - return current; - - d->forcedSelectionPosition = d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow; - -#if 0 //follow qt view behavior. lateral movements won't change visual row - if (d->forcedSelectionPosition < 0) - d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow; -#endif - - return d->proxyModel->index(current.row() + 1, 0); - } - - if (!(d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow)) - return current; - - d->forcedSelectionPosition = d->elementsInfo[current.row() - 1].relativeOffsetToCategory % elementsPerRow; - -#if 0 //follow qt view behavior. lateral movements won't change visual row - if (d->forcedSelectionPosition < 0) - d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow; -#endif - - return d->proxyModel->index(current.row() - 1, 0); - - case QAbstractItemView::MoveRight: - if (layoutDirection() == Qt::RightToLeft) - { - if (!(d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow)) - return current; - - d->forcedSelectionPosition = d->elementsInfo[current.row() - 1].relativeOffsetToCategory % elementsPerRow; - -#if 0 //follow qt view behavior. lateral movements won't change visual row - if (d->forcedSelectionPosition < 0) - d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow; -#endif - - return d->proxyModel->index(current.row() - 1, 0); - } - - if (!(d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow)) - return current; - - d->forcedSelectionPosition = d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow; - -#if 0 //follow qt view behavior. lateral movements won't change visual row - if (d->forcedSelectionPosition < 0) - d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow; -#endif - - return d->proxyModel->index(current.row() + 1, 0); - - default: - break; - } - - return QListView::moveCursor(cursorAction, modifiers); -} - -void KCategorizedView::rowsInserted(const QModelIndex &parent, - int start, - int end) -{ - QListView::rowsInserted(parent, start, end); - - if (!d->proxyModel || !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) - { - d->forcedSelectionPosition = 0; - d->elementsInfo.clear(); - d->elementsPosition.clear(); - d->categoriesIndexes.clear(); - d->categoriesPosition.clear(); - d->categories.clear(); - d->intersectedIndexes.clear(); - d->modelIndexList.clear(); - d->hovered = QModelIndex(); - d->biggestItemSize = QSize(0, 0); - d->mouseButtonPressed = false; - d->rightMouseButtonPressed = false; - - return; - } - - rowsInsertedArtifficial(parent, start, end); -} - -void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent, - int start, - int end) -{ - Q_UNUSED(parent); - - d->forcedSelectionPosition = 0; - d->elementsInfo.clear(); - d->elementsPosition.clear(); - d->categoriesIndexes.clear(); - d->categoriesPosition.clear(); - d->categories.clear(); - d->intersectedIndexes.clear(); - d->modelIndexList.clear(); - d->hovered = QModelIndex(); - d->biggestItemSize = QSize(0, 0); - d->mouseButtonPressed = false; - d->rightMouseButtonPressed = false; - - if (start > end || end < 0 || start < 0 || !d->proxyModel->rowCount()) - { - return; - } - - // Add all elements mapped to the source model and explore categories - QString prevCategory = d->proxyModel->data(d->proxyModel->index(0, d->proxyModel->sortColumn()), KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString(); - QString lastCategory = prevCategory; - QModelIndexList modelIndexList; - struct Private::ElementInfo elementInfo; - int offset = -1; - for (int k = 0; k < d->proxyModel->rowCount(); ++k) - { - QModelIndex index = d->proxyModel->index(k, d->proxyModel->sortColumn()); - QModelIndex indexSize = d->proxyModel->index(k, 0); - - d->biggestItemSize = QSize(qMax(sizeHintForIndex(indexSize).width(), - d->biggestItemSize.width()), - qMax(sizeHintForIndex(indexSize).height(), - d->biggestItemSize.height())); - - d->modelIndexList << index; - - lastCategory = d->proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString(); - - elementInfo.category = lastCategory; - - if (prevCategory != lastCategory) - { - offset = 0; - d->categoriesIndexes.insert(prevCategory, modelIndexList); - d->categories << prevCategory; - modelIndexList.clear(); - } - else - { - offset++; - } - - elementInfo.relativeOffsetToCategory = offset; - - modelIndexList << index; - prevCategory = lastCategory; - - d->elementsInfo.insert(index.row(), elementInfo); - } - - d->categoriesIndexes.insert(prevCategory, modelIndexList); - d->categories << prevCategory; - - d->updateScrollbars(); - - // FIXME: We need to safely save the last selection. This is on my TODO - // list (ereslibre). - selectionModel()->clear(); -} - -void KCategorizedView::rowsRemoved(const QModelIndex &parent, - int start, - int end) -{ - if (d->proxyModel && d->categoryDrawer && d->proxyModel->isCategorizedModel()) - { - // Force the view to update all elements - rowsInsertedArtifficial(QModelIndex(), 0, d->proxyModel->rowCount() - 1); - } -} - -void KCategorizedView::updateGeometries() -{ - if (!d->proxyModel || !d->categoryDrawer || !d->proxyModel->isCategorizedModel()) - { - QListView::updateGeometries(); - return; - } - - // Avoid QListView::updateGeometries(), since it will try to set another - // range to our scroll bars, what we don't want (ereslibre) - QAbstractItemView::updateGeometries(); -} - -void KCategorizedView::slotLayoutChanged() -{ - d->layoutChanged(); -} - -void KCategorizedView::currentChanged(const QModelIndex ¤t, - const QModelIndex &previous) -{ - // We need to update the forcedSelectionPosition property in order to correctly - // navigate after with keyboard using up & down keys - - int viewportWidth = viewport()->width() - spacing(); - - int itemHeight; - int itemWidth; - - if (gridSize().isEmpty()) - { - itemHeight = d->biggestItemSize.height(); - itemWidth = d->biggestItemSize.width(); - } - else - { - itemHeight = gridSize().height(); - itemWidth = gridSize().width(); - } - - int itemWidthPlusSeparation = spacing() + itemWidth; - if (!itemWidthPlusSeparation) - itemWidthPlusSeparation++; - int elementsPerRow = viewportWidth / itemWidthPlusSeparation; - if (!elementsPerRow) - elementsPerRow++; - - if (d->mouseButtonPressed || d->rightMouseButtonPressed) - d->forcedSelectionPosition = d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow; - - QListView::currentChanged(current, previous); -} - -#include "kcategorizedview.moc" diff --git a/src/kcategorizedview.h b/src/kcategorizedview.h deleted file mode 100644 index 015433ae3..000000000 --- a/src/kcategorizedview.h +++ /dev/null @@ -1,119 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2007 Rafael Fernández López - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef KCATEGORIZEDVIEW_H -#define KCATEGORIZEDVIEW_H - -#include - -#include - -class KCategoryDrawer; - -/** - * @short Item view for listing items - * - * KCategorizedView allows you to use it as it were a QListView. You can add an - * itemCategorizer to it, so your items became categorized depending on the - * KItemCategorizer inherited class rules. - * - * @see KItemCategorizer, KSortFilterProxyModel - * - * @author Rafael Fernández López - */ -class LIBDOLPHINPRIVATE_EXPORT KCategorizedView - : public QListView -{ - Q_OBJECT - -public: - KCategorizedView(QWidget *parent = 0); - - ~KCategorizedView(); - - virtual void setModel(QAbstractItemModel *model); - - void setGridSize(const QSize &size); - - virtual QRect visualRect(const QModelIndex &index) const; - - KCategoryDrawer *categoryDrawer() const; - - void setCategoryDrawer(KCategoryDrawer *categoryDrawer); - - virtual QModelIndex indexAt(const QPoint &point) const; - -public Q_SLOTS: - virtual void reset(); - -protected: - virtual void paintEvent(QPaintEvent *event); - - virtual void resizeEvent(QResizeEvent *event); - - virtual void setSelection(const QRect &rect, - QItemSelectionModel::SelectionFlags flags); - - virtual void mouseMoveEvent(QMouseEvent *event); - - virtual void mousePressEvent(QMouseEvent *event); - - virtual void mouseReleaseEvent(QMouseEvent *event); - - virtual void leaveEvent(QEvent *event); - - virtual void startDrag(Qt::DropActions supportedActions); - - virtual void dragMoveEvent(QDragMoveEvent *event); - - virtual void dragLeaveEvent(QDragLeaveEvent *event); - - virtual void dropEvent(QDropEvent *event); - - virtual QModelIndex moveCursor(CursorAction cursorAction, - Qt::KeyboardModifiers modifiers); - -protected Q_SLOTS: - virtual void rowsInserted(const QModelIndex &parent, - int start, - int end); - - virtual void rowsInsertedArtifficial(const QModelIndex &parent, - int start, - int end); - - virtual void rowsRemoved(const QModelIndex &parent, - int start, - int end); - - virtual void updateGeometries(); - - virtual void slotLayoutChanged(); - - virtual void currentChanged(const QModelIndex ¤t, - const QModelIndex &previous); - - -private: - class Private; - Private *d; -}; - -#endif // KCATEGORIZEDVIEW_H diff --git a/src/kcategorizedview_p.h b/src/kcategorizedview_p.h deleted file mode 100644 index a18854ba3..000000000 --- a/src/kcategorizedview_p.h +++ /dev/null @@ -1,164 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2007 Rafael Fernández López - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef KCATEGORIZEDVIEW_P_H -#define KCATEGORIZEDVIEW_P_H - -class KCategorizedSortFilterProxyModel; -class KCategoryDrawer; - -/** - * @internal - */ -class KCategorizedView::Private -{ -public: - Private(KCategorizedView *listView); - ~Private(); - - - // Methods - - /** - * Returns the list of items that intersects with @p rect - */ - const QModelIndexList &intersectionSet(const QRect &rect); - - /** - * Gets the item rect in the viewport for @p index - */ - QRect visualRectInViewport(const QModelIndex &index) const; - - /** - * Returns the category rect in the viewport for @p category - */ - QRect visualCategoryRectInViewport(const QString &category) const; - - /** - * Caches and returns the rect that corresponds to @p index - */ - const QRect &cacheIndex(const QModelIndex &index); - - /** - * Caches and returns the rect that corresponds to @p category - */ - const QRect &cacheCategory(const QString &category); - - /** - * Returns the rect that corresponds to @p index - * @note If the rect is not cached, it becomes cached - */ - const QRect &cachedRectIndex(const QModelIndex &index); - - /** - * Returns the rect that corresponds to @p category - * @note If the rect is not cached, it becomes cached - */ - const QRect &cachedRectCategory(const QString &category); - - /** - * Returns the visual rect (taking in count x and y offsets) for @p index - * @note If the rect is not cached, it becomes cached - */ - QRect visualRect(const QModelIndex &index); - - /** - * Returns the visual rect (taking in count x and y offsets) for @p category - * @note If the rect is not cached, it becomes cached - */ - QRect categoryVisualRect(const QString &category); - - /** - * This method will draw a new category represented by index - * @param index on the rect specified by @p option.rect, with - * painter @p painter - */ - void drawNewCategory(const QModelIndex &index, - int sortRole, - const QStyleOption &option, - QPainter *painter); - - /** - * This method will update scrollbars ranges. Called when our model changes - * or when the view is resized - */ - void updateScrollbars(); - - /** - * This method will draw dragged items in the painting operation - */ - void drawDraggedItems(QPainter *painter); - - /** - * This method will determine which rect needs to be updated because of a - * dragging operation - */ - void drawDraggedItems(); - - void layoutChanged(bool forceItemReload = false); - - - // Attributes - - struct ElementInfo - { - QString category; - int relativeOffsetToCategory; - }; - - // Basic data - KCategorizedView *listView; - KCategoryDrawer *categoryDrawer; - QSize biggestItemSize; - - // Behavior data - bool mouseButtonPressed; - bool rightMouseButtonPressed; - bool isDragging; - bool dragLeftViewport; - QModelIndex hovered; - QString hoveredCategory; - QPoint initialPressPosition; - QPoint mousePosition; - int forcedSelectionPosition; - - // Cache data - // We cannot merge some of them into structs because it would affect - // performance - QHash elementsInfo; - QHash elementsPosition; - QHash categoriesIndexes; - QHash categoriesPosition; - QStringList categories; - QModelIndexList intersectedIndexes; - QRect lastDraggedItemsRect; - int modelSortRole; - int modelSortColumn; - int modelLastRowCount; - bool modelCategorized; - Qt::SortOrder modelSortOrder; - QItemSelection lastSelection; - - // Attributes for speed reasons - KCategorizedSortFilterProxyModel *proxyModel; - QModelIndexList modelIndexList; -}; - -#endif // KCATEGORIZEDVIEW_P_H diff --git a/src/kcategorydrawer.cpp b/src/kcategorydrawer.cpp deleted file mode 100644 index 6d82bf96b..000000000 --- a/src/kcategorydrawer.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2007 Rafael Fernández López - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "kcategorydrawer.h" - -#include -#include - -#include -#include - -KCategoryDrawer::KCategoryDrawer() -{ -} - -KCategoryDrawer::~KCategoryDrawer() -{ -} - -void KCategoryDrawer::drawCategory(const QModelIndex &index, - int /*sortRole*/, - const QStyleOption &option, - QPainter *painter) const -{ - const QString category = index.model()->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString(); - - QColor color; - - if (option.state & QStyle::State_Selected) - { - color = option.palette.color(QPalette::HighlightedText); - } - else - { - color = option.palette.color(QPalette::Text); - } - - painter->save(); - painter->setRenderHint(QPainter::Antialiasing); - - if (option.state & QStyle::State_Selected) - { - QColor selected = option.palette.color(QPalette::Highlight); - - QLinearGradient gradient(option.rect.topLeft(), - option.rect.bottomRight()); - gradient.setColorAt(option.direction == Qt::LeftToRight ? 0 - : 1, selected); - gradient.setColorAt(option.direction == Qt::LeftToRight ? 1 - : 0, Qt::transparent); - - painter->fillRect(option.rect, gradient); - } - else if (option.state & QStyle::State_MouseOver) - { - QColor hover = option.palette.color(QPalette::Highlight).light(); - hover.setAlpha(88); - - QLinearGradient gradient(option.rect.topLeft(), - option.rect.bottomRight()); - gradient.setColorAt(option.direction == Qt::LeftToRight ? 0 - : 1, hover); - gradient.setColorAt(option.direction == Qt::LeftToRight ? 1 - : 0, Qt::transparent); - - painter->fillRect(option.rect, gradient); - } - - QFont painterFont = painter->font(); - painterFont.setWeight(QFont::Bold); - QFontMetrics metrics(painterFont); - painter->setFont(painterFont); - - QRect lineRect(option.rect.left(), - option.rect.bottom() - 1, - option.rect.width(), - 1); - - QLinearGradient gradient(option.rect.topLeft(), - option.rect.bottomRight()); - gradient.setColorAt(option.direction == Qt::LeftToRight ? 0 - : 1, color); - gradient.setColorAt(option.direction == Qt::LeftToRight ? 1 - : 0, Qt::transparent); - - painter->fillRect(lineRect, gradient); - - painter->setPen(color); - - painter->drawText(option.rect, Qt::AlignVCenter | Qt::AlignLeft, - metrics.elidedText(category, Qt::ElideRight, option.rect.width())); - - painter->restore(); -} - -int KCategoryDrawer::categoryHeight(const QModelIndex &index, const QStyleOption &option) const -{ - Q_UNUSED(index); - - return option.fontMetrics.height() + 4 /* 3 separator; 1 gradient */; -} diff --git a/src/kcategorydrawer.h b/src/kcategorydrawer.h deleted file mode 100644 index 6af0d73cd..000000000 --- a/src/kcategorydrawer.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2007 Rafael Fernández López - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef KCATEGORYDRAWER_H -#define KCATEGORYDRAWER_H - -#include - -class QPainter; -class QModelIndex; -class QStyleOption; - -class LIBDOLPHINPRIVATE_EXPORT 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; - - virtual int categoryHeight(const QModelIndex &index, const QStyleOption &option) const; -}; - -#endif // KCATEGORYDRAWER_H