File indexing completed on 2025-04-27 03:58:28
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2010-01-16 0007 * Description : Item view for listing items in a categorized fashion optionally 0008 * 0009 * SPDX-FileCopyrightText: 2007 by Rafael Fernández López <ereslibre at kde dot org> 0010 * SPDX-FileCopyrightText: 2009-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0011 * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #ifndef DIGIKAM_DCATEGORIZED_VIEW_PRIVATE_H 0018 #define DIGIKAM_DCATEGORIZED_VIEW_PRIVATE_H 0019 0020 #include "dcategorizedview.h" 0021 0022 // C++ includes 0023 0024 #include <cmath> 0025 0026 // Qt includes 0027 0028 #include <QVector> 0029 #include <QPainter> 0030 #include <QScrollBar> 0031 #include <QPaintEvent> 0032 0033 // Local includes 0034 0035 #include "dcategorizedsortfilterproxymodel.h" 0036 #include "dcategorydrawer.h" 0037 0038 /** 0039 * NOTE: By defining DOLPHIN_DRAGANDDROP the custom drag and drop implementation of 0040 * DCategorizedView is bypassed to have a consistent drag and drop look for all 0041 * views. Hopefully transparent pixmaps for drag objects will be supported in 0042 * Qt 4.4, so that this workaround can be skipped. 0043 */ 0044 #define DOLPHIN_DRAGANDDROP 0045 0046 class DCategoryDrawer; 0047 0048 namespace Digikam 0049 { 0050 0051 class DCategorizedSortFilterProxyModel; 0052 0053 class Q_DECL_HIDDEN SparseModelIndexVector : public QVector<QModelIndex> 0054 { 0055 public: 0056 0057 explicit SparseModelIndexVector(int rowCount, QAbstractItemModel* const model_, int column_) 0058 : QVector<QModelIndex>(rowCount), 0059 model(model_), 0060 column(column_) 0061 { 0062 } 0063 0064 inline QModelIndex& operator[](int i) 0065 { 0066 QModelIndex& index = QVector<QModelIndex>::operator[](i); 0067 0068 if (!index.isValid()) 0069 { 0070 index = model->index(i, column); 0071 } 0072 0073 return index; 0074 } 0075 0076 private: 0077 0078 // not to be used 0079 0080 const QModelIndex& operator[](int i) const 0081 { 0082 return QVector<QModelIndex>::operator[](i); 0083 } 0084 0085 private: 0086 0087 QAbstractItemModel* model; 0088 int column; 0089 }; 0090 0091 // ------------------------------------------------------------------------------------ 0092 0093 class Q_DECL_HIDDEN DCategorizedView::Private 0094 { 0095 public: 0096 0097 explicit Private(DCategorizedView* const listView); 0098 ~Private(); 0099 0100 // Methods 0101 0102 /** 0103 * Returns the list of items that intersects with @p rect 0104 */ 0105 const QModelIndexList& intersectionSet(const QRect& rect); 0106 0107 /** 0108 * Gets the item rect in the viewport for @p index 0109 */ 0110 QRect visualRectInViewport(const QModelIndex& index) const; 0111 0112 /** 0113 * Returns the category rect in the viewport for @p category 0114 */ 0115 QRect visualCategoryRectInViewport(const QString& category) const; 0116 0117 /** 0118 * Caches and returns the rect that corresponds to @p index 0119 */ 0120 const QRect& cacheIndex(const QModelIndex& index); 0121 0122 /** 0123 * Caches and returns the rect that corresponds to @p category 0124 */ 0125 const QRect& cacheCategory(const QString& category); 0126 0127 /** 0128 * Returns the rect that corresponds to @p index 0129 * @note If the rect is not cached, it becomes cached 0130 */ 0131 const QRect& cachedRectIndex(const QModelIndex& index); 0132 0133 /** 0134 * Returns the rect that corresponds to @p category 0135 * @note If the rect is not cached, it becomes cached 0136 */ 0137 const QRect& cachedRectCategory(const QString& category); 0138 0139 /** 0140 * Returns the visual rect (taking in count x and y offsets) for @p index 0141 * @note If the rect is not cached, it becomes cached 0142 */ 0143 QRect visualRect(const QModelIndex& index); 0144 0145 /** 0146 * Returns the visual rect (taking in count x and y offsets) for @p category 0147 * @note If the rect is not cached, it becomes cached 0148 */ 0149 QRect categoryVisualRect(const QString& category); 0150 0151 /** 0152 * Returns the contents size of this view (topmost category to bottommost index + spacing) 0153 */ 0154 QSize contentsSize(); 0155 0156 /** 0157 * This method will draw a new category represented by index 0158 * @p index on the rect specified by @p option.rect, with 0159 * painter @p painter 0160 */ 0161 void drawNewCategory(const QModelIndex& index, 0162 int sortRole, 0163 const QStyleOption& option, 0164 QPainter* painter); 0165 0166 /** 0167 * This method will update scrollbars ranges. Called when our model changes 0168 * or when the view is resized 0169 */ 0170 void updateScrollbars(); 0171 0172 /** 0173 * This method will draw dragged items in the painting operation 0174 */ 0175 void drawDraggedItems(QPainter* painter); 0176 0177 /** 0178 * This method will determine which rect needs to be updated because of a 0179 * dragging operation 0180 */ 0181 void drawDraggedItems(); 0182 0183 /** 0184 * This method will, starting from the index at begin in the given (sorted) modelIndex List, 0185 * find the last index having the same category as the index to begin with. 0186 */ 0187 int categoryUpperBound(SparseModelIndexVector& modelIndexList, int begin, int averageSize = 0); 0188 0189 /** 0190 * Returns a QItemSelection for all items intersection rect. 0191 */ 0192 QItemSelection selectionForRect(const QRect& rect); 0193 0194 public: 0195 0196 /// Attributes 0197 class Q_DECL_HIDDEN ElementInfo 0198 { 0199 public: 0200 0201 explicit ElementInfo() 0202 : relativeOffsetToCategory(0) 0203 { 0204 } 0205 0206 QString category; 0207 int relativeOffsetToCategory; 0208 }; 0209 0210 public: 0211 0212 /// Basic data 0213 DCategorizedView* listView; 0214 DCategoryDrawer* categoryDrawer; 0215 QSize biggestItemSize; 0216 0217 /// Behavior data 0218 bool mouseButtonPressed; 0219 bool rightMouseButtonPressed; 0220 bool dragLeftViewport; 0221 bool drawItemsWhileDragging; 0222 QModelIndex hovered; 0223 QString hoveredCategory; 0224 QPoint initialPressPosition; 0225 QPoint mousePosition; 0226 int forcedSelectionPosition; 0227 0228 /** 0229 * Cache data 0230 * We cannot merge some of them into structs because it would affect 0231 * performance 0232 */ 0233 QVector<ElementInfo> elementsInfo; 0234 QHash<int, QRect> elementsPosition; 0235 QHash<QString, QVector<int> > categoriesIndexes; 0236 QHash<QString, QRect> categoriesPosition; 0237 QStringList categories; 0238 QModelIndexList intersectedIndexes; 0239 QRect lastDraggedItemsRect; 0240 QItemSelection lastSelection; 0241 0242 /// Attributes for speed reasons 0243 DCategorizedSortFilterProxyModel* proxyModel; 0244 }; 0245 0246 } // namespace Digikam 0247 0248 #endif // DIGIKAM_DCATEGORIZED_VIEW_PRIVATE_H