File indexing completed on 2025-04-27 03:58:29

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2010-01-16
0007  * Description : Qt item view for images
0008  *
0009  * SPDX-FileCopyrightText: 2009-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0010  * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #ifndef DIGIKAM_ITEM_VIEW_CATEGORIZED_H
0017 #define DIGIKAM_ITEM_VIEW_CATEGORIZED_H
0018 
0019 // Local includes
0020 
0021 #include "digikam_export.h"
0022 #include "dcategorizedview.h"
0023 #include "dragdropimplementations.h"
0024 
0025 class QSortFilterProxyModel;
0026 
0027 namespace Digikam
0028 {
0029 
0030 class DItemDelegate;
0031 class ItemViewToolTip;
0032 
0033 class DIGIKAM_EXPORT ItemViewCategorized : public DCategorizedView,
0034                                            public DragDropViewImplementation
0035 {
0036     Q_OBJECT
0037 
0038 public:
0039 
0040     explicit ItemViewCategorized(QWidget* const parent = nullptr);
0041     ~ItemViewCategorized() override;
0042 
0043     DItemDelegate* delegate()                                                       const;
0044     int            numberOfSelectedIndexes()                                        const;
0045 
0046     /**
0047      * Selects the index as current and scrolls to it
0048      */
0049     void toFirstIndex();
0050     void toLastIndex();
0051     void toNextIndex();
0052     void toPreviousIndex();
0053     void toIndex(const QModelIndex& index);
0054     void awayFromSelection();
0055 
0056     /**
0057      * Scroll automatically the current index to center of the view.
0058      */
0059     void setScrollCurrentToCenter(bool enabled);
0060 
0061     /**
0062      * Like scrollTo, but only scrolls if the index is not visible, regardless of hint.
0063      */
0064     void scrollToRelaxed(const QModelIndex& index, ScrollHint hint = EnsureVisible);
0065 
0066     void invertSelection();
0067     void setSelectedIndexes(const QList<QModelIndex>& indexes);
0068 
0069     void setToolTipEnabled(bool enabled);
0070     bool isToolTipEnabled()                                                         const;
0071 
0072     /**
0073      * Sets the spacing. Does not use setSpacing()/spacing() from QListView
0074      */
0075     void setSpacing(int spacing);
0076 
0077     /**
0078      * Set if the PointingHand Cursor should be shown over the activation area
0079      */
0080     void setUsePointingHandCursor(bool useCursor);
0081 
0082     /**
0083      * Determine a step size for scrolling: The larger this number,
0084      * the smaller and more precise is the scrolling. Default is 10.
0085      */
0086     void setScrollStepGranularity(int factor);
0087 
0088     virtual QSortFilterProxyModel* filterModel()                                    const = 0;
0089     void scrollTo(const QModelIndex& index, ScrollHint hint = EnsureVisible)              override;
0090 
0091 public Q_SLOTS:
0092 
0093     void showIndexNotification(const QModelIndex& index, const QString& message);
0094     void hideIndexNotification();
0095 
0096     void cut()   override { DragDropViewImplementation::cut();   }
0097     void copy()  override { DragDropViewImplementation::copy();  }
0098     void paste() override { DragDropViewImplementation::paste(); }
0099 
0100 Q_SIGNALS:
0101 
0102     /**
0103      * Emitted when any selection change occurs. Any of the signals below will be emitted before.
0104      */
0105     void selectionChanged();
0106 
0107     /**
0108      * Emitted when the selection is completely cleared.
0109      */
0110     void selectionCleared();
0111 
0112     void zoomOutStep();
0113     void zoomInStep();
0114 
0115     /**
0116      * For overlays: Like the respective parent class signals, but with additional info.
0117      * Do not change the mouse events.
0118      */
0119     void clicked(const QMouseEvent* e, const QModelIndex& index);
0120     void entered(const QMouseEvent* e, const QModelIndex& index);
0121 
0122     /**
0123      * While clicked() is emitted with a valid index, this corresponds to clicking on empty space
0124      */
0125     void viewportClicked(const QMouseEvent* e);
0126 
0127     /**
0128      * Remember you may want to check if the event is accepted or ignored.
0129      * This signal is emitted after being handled by this widget.
0130      * You can accept it if ignored.
0131      */
0132     void keyPressed(QKeyEvent* e);
0133 
0134 
0135 protected Q_SLOTS:
0136 
0137     void slotActivated(const QModelIndex& index);
0138     void slotClicked(const QModelIndex& index);
0139     void slotEntered(const QModelIndex& index);
0140     void layoutAboutToBeChanged();
0141     void layoutWasChanged();
0142 
0143     virtual void slotThemeChanged();
0144     virtual void slotSetupChanged();
0145 
0146 protected:
0147 
0148     void encodeIsCutSelection(QMimeData* mime, bool isCutSelection);
0149     bool decodeIsCutSelection(const QMimeData* mimeData);
0150 
0151     void setToolTip(ItemViewToolTip* tip);
0152     void setItemDelegate(DItemDelegate* delegate);
0153     void updateDelegateSizes();
0154     void userInteraction();
0155 
0156     /**
0157      * Returns an index that is representative for the category at position pos
0158      */
0159     QModelIndex indexForCategoryAt(const QPoint& pos) const;
0160 
0161     /// reimplemented from parent class
0162     void contextMenuEvent(QContextMenuEvent* event)                                       override;
0163     void keyPressEvent(QKeyEvent* event)                                                  override;
0164     void leaveEvent(QEvent* event)                                                        override;
0165     void mouseMoveEvent(QMouseEvent* event)                                               override;
0166     void mousePressEvent(QMouseEvent* event)                                              override;
0167     void mouseReleaseEvent(QMouseEvent* event)                                            override;
0168     void resizeEvent(QResizeEvent* e)                                                     override;
0169     void reset()                                                                          override;
0170     void rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end)              override;
0171     void rowsInserted(const QModelIndex& parent, int start, int end)                      override;
0172     void rowsRemoved(const QModelIndex& parent, int start, int end)                       override;
0173     void selectionChanged(const QItemSelection&, const QItemSelection&)                   override;
0174     bool viewportEvent(QEvent* event)                                                     override;
0175     void wheelEvent(QWheelEvent* event)                                                   override;
0176     QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)    override;
0177 
0178     /// Reimplement these in a subclass
0179     virtual void showContextMenuOnIndex(QContextMenuEvent* event, const QModelIndex& index);
0180     virtual void showContextMenu(QContextMenuEvent* event);
0181     virtual void indexActivated(const QModelIndex& index, Qt::KeyboardModifiers modifiers);
0182 
0183     /**
0184      * Provides default behavior, can reimplement in a subclass.
0185      * Returns true if a tooltip was shown.
0186      * The help event is optional.
0187      */
0188     virtual bool showToolTip(const QModelIndex& index,
0189                              QStyleOptionViewItem& option,
0190                              QHelpEvent* e = nullptr);
0191 
0192     DECLARE_VIEW_DRAG_DROP_METHODS(DCategorizedView)
0193 
0194     /**
0195      * Note: pure virtual dragDropHandler() still open from DragDropViewImplementation
0196      */
0197     QModelIndex mapIndexForDragDrop(const QModelIndex& index)                       const override;
0198     QPixmap     pixmapForDrag(const QList<QModelIndex>& indexes)                    const override;
0199 
0200     /**
0201      * Assuming the given indexes would be removed (hypothetically!),
0202      * return the index to be selected instead, starting from anchor.
0203      * The default implementation returns the next remaining sibling.
0204      */
0205     virtual QModelIndex nextIndexHint(const QModelIndex& indexToAnchor,
0206                                       const QItemSelectionRange& removed)           const;
0207 
0208 private Q_SLOTS:
0209 
0210     void slotGridSizeChanged(const QSize&);
0211 
0212 private:
0213 
0214     // Disable
0215     ItemViewCategorized(const ItemViewCategorized&)            = delete;
0216     ItemViewCategorized& operator=(const ItemViewCategorized&) = delete;
0217 
0218 private:
0219 
0220     void ensureSelectionAfterChanges();
0221 
0222 private:
0223 
0224     class Private;
0225     Private* const d;
0226 };
0227 
0228 } // namespace Digikam
0229 
0230 #endif // DIGIKAM_ITEM_VIEW_CATEGORIZED_H