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

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2008-03-14
0007  * Description : User interface for searches
0008  *
0009  * SPDX-FileCopyrightText: 2008-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #ifndef DIGIKAM_COMBOBOX_UTILITIES_H
0016 #define DIGIKAM_COMBOBOX_UTILITIES_H
0017 
0018 // Qt includes
0019 
0020 #include <QLabel>
0021 #include <QListView>
0022 #include <QComboBox>
0023 #include <QPersistentModelIndex>
0024 #include <QLineEdit>
0025 
0026 // Local includes
0027 
0028 #include "digikam_export.h"
0029 
0030 class QVBoxLayout;
0031 class QTreeView;
0032 
0033 namespace Digikam
0034 {
0035 
0036 class DIGIKAM_EXPORT ProxyLineEdit : public QLineEdit
0037 {
0038     Q_OBJECT
0039 
0040 public:
0041 
0042     /**
0043      * This class will not act as a QLineEdit at all,
0044      * but present another widget (any kind of widget)
0045      * instead in the space assigned to the QLineEdit.
0046      * Use this class if you need to pass a QLineEdit but
0047      * want actually to use a different widget.
0048      */
0049     explicit ProxyLineEdit(QWidget* const parent = nullptr);
0050 
0051     /**
0052      * After constructing, set the actual widget here
0053      */
0054     virtual void setWidget(QWidget* widget);
0055 
0056     void setClearButtonShown(bool show);
0057 
0058 Q_SIGNALS:
0059 
0060     void signalClearButtonPressed();
0061 
0062 private Q_SLOTS:
0063 
0064     void slotTextChanged(const QString& text);
0065 
0066 protected:
0067 
0068     QSize minimumSizeHint() const                   override;
0069     QSize sizeHint()        const                   override;
0070 
0071     void mousePressEvent(QMouseEvent* event)        override;
0072     void mouseMoveEvent(QMouseEvent* event)         override;
0073     void mouseReleaseEvent(QMouseEvent* event)      override;
0074     void mouseDoubleClickEvent(QMouseEvent* event)  override;
0075     void keyPressEvent(QKeyEvent* event)            override;
0076     void focusInEvent(QFocusEvent* event)           override;
0077     void focusOutEvent(QFocusEvent* event)          override;
0078     void paintEvent(QPaintEvent* event)             override;
0079     void dragEnterEvent(QDragEnterEvent* event)     override;
0080     void dragMoveEvent(QDragMoveEvent* e)           override;
0081     void dragLeaveEvent(QDragLeaveEvent* e)         override;
0082     void dropEvent(QDropEvent* event)               override;
0083     void changeEvent(QEvent* event)                 override;
0084     void contextMenuEvent(QContextMenuEvent* event) override;
0085     void inputMethodEvent(QInputMethodEvent* event) override;
0086 
0087 protected:
0088 
0089     QWidget*     m_widget;
0090     QVBoxLayout* m_layout;
0091 };
0092 
0093 // -------------------------------------------------------------------------
0094 
0095 class DIGIKAM_EXPORT ProxyClickLineEdit : public ProxyLineEdit
0096 {
0097     Q_OBJECT
0098 
0099 public:
0100 
0101     /**
0102      * A ProxyLineEdit that emits leftClicked() on
0103      * mouse press event.
0104      * Press on the held widget will result in the signal
0105      * if the widget does not accept() them.
0106      */
0107     explicit ProxyClickLineEdit(QWidget* const parent = nullptr);
0108 
0109 Q_SIGNALS:
0110 
0111     void leftClicked();
0112 
0113 protected:
0114 
0115     void mouseReleaseEvent(QMouseEvent* event) override;
0116 };
0117 
0118 // -------------------------------------------------------------------------
0119 
0120 class DIGIKAM_EXPORT ModelIndexBasedComboBox : public QComboBox
0121 {
0122     Q_OBJECT
0123 
0124 public:
0125 
0126     /**
0127      * QComboBox has a current index based on a single integer.
0128      * This is not sufficient for more complex models.
0129      * This class is a combo box that stores a current index
0130      * based on QModelIndex.
0131      */
0132     explicit ModelIndexBasedComboBox(QWidget* const  parent = nullptr);
0133 
0134     QModelIndex currentIndex() const;
0135     void setCurrentIndex(const QModelIndex& index);
0136 
0137     void hidePopup() override;
0138     void showPopup() override;
0139 
0140 protected:
0141 
0142     QPersistentModelIndex m_currentIndex;
0143 };
0144 
0145 // -------------------------------------------------------------------------
0146 
0147 class DIGIKAM_EXPORT StayPoppedUpComboBox : public ModelIndexBasedComboBox
0148 {
0149     Q_OBJECT
0150 
0151 public:
0152 
0153     /**
0154      * This class provides an abstract QComboBox with a custom view
0155      * (which is created by implementing subclasses)
0156      * instead of the usual QListView.
0157      * The Pop-up of the combo box will stay open after selecting an item;
0158      * it will be closed by clicking outside, but not inside the widget.
0159      * You need three steps:
0160      * Construct the object, call setModel() with an appropriate
0161      * QAbstractItemModel, then call installView() to replace
0162      * the standard combo box view with a view.
0163      */
0164     explicit StayPoppedUpComboBox(QWidget* const parent = nullptr);
0165 
0166 protected:
0167 
0168     /**
0169      * Replace the standard combo box list view with the given view.
0170      * The view will be set as the view of the combo box
0171      * (including re-parenting) and be stored in the m_view variable.
0172      */
0173     void installView(QAbstractItemView* view);
0174 
0175     /**
0176      * Implement in subclass:
0177      * Send the given event to the viewportEvent() method of m_view.
0178      * This method is protected for a usual QAbstractItemView.
0179      * You can override, pass a view, and call parent implementation.
0180      * The existing view will be used. You must then also
0181      * reimplement sendViewportEventToView.
0182      */
0183     virtual void sendViewportEventToView(QEvent* e) = 0;
0184 
0185     bool eventFilter(QObject* watched, QEvent* event) override;
0186 
0187 protected:
0188 
0189     QAbstractItemView* m_view;
0190 };
0191 
0192 // -------------------------------------------------------------------------
0193 
0194 class DIGIKAM_EXPORT TreeViewComboBox : public StayPoppedUpComboBox
0195 {
0196     Q_OBJECT
0197 
0198 public:
0199 
0200     /**
0201      * This class provides a QComboBox with a QTreeView
0202      * instead of the usual QListView.
0203      * You need three steps:
0204      * Construct the object, call setModel() with an appropriate
0205      * QAbstractItemModel, then call installView() to replace
0206      * the standard combo box view with a QTreeView.
0207      */
0208     explicit TreeViewComboBox(QWidget* parent = nullptr);
0209 
0210     /**
0211      * Replace the standard combo box list view with a QTreeView.
0212      * Call this after installing an appropriate model.
0213      */
0214     virtual void installView(QAbstractItemView* view = nullptr);
0215 
0216     /**
0217      * Returns the QTreeView of this class. Valid after installView() has been called
0218      */
0219     QTreeView* view() const;
0220 
0221 protected:
0222 
0223     void sendViewportEventToView(QEvent* e) override;
0224 };
0225 
0226 // -------------------------------------------------------------------------
0227 
0228 class DIGIKAM_EXPORT ListViewComboBox : public StayPoppedUpComboBox
0229 {
0230     Q_OBJECT
0231 
0232 public:
0233 
0234     /**
0235      * This class provides an implementation of a StayPoppedUpComboBox
0236      * with a QListView. This is the standard view of a QComboBox,
0237      * but in conjunction with StayPoppedUpComboBox some extra steps are needed.
0238      * You need three steps:
0239      * Construct the object, call setModel() with an appropriate
0240      * QAbstractItemModel, then call installView().
0241      */
0242     explicit ListViewComboBox(QWidget* parent = nullptr);
0243 
0244     /**
0245      * Returns the QTreeView of this class. Valid after installView() has been called.
0246      */
0247     QListView* view() const;
0248 
0249     /**
0250      * Replace the standard combo box list view with a QTreeView.
0251      * Call this after installing an appropriate model.
0252      */
0253     virtual void installView(QAbstractItemView* view = nullptr);
0254 
0255 protected:
0256 
0257     void sendViewportEventToView(QEvent* e) override;
0258 };
0259 
0260 // -------------------------------------------------------------------------
0261 
0262 class DIGIKAM_EXPORT TreeViewLineEditComboBox : public TreeViewComboBox
0263 {
0264     Q_OBJECT
0265 
0266 public:
0267 
0268     /**
0269      * This class provides a TreeViewComboBox
0270      * with a read-only line edit.
0271      * The text in the line edit can be adjusted. The combo box will
0272      * open on a click on the line edit.
0273      * You need three steps:
0274      * Construct the object, call setModel() with an appropriate
0275      * QAbstractItemModel, then call installView() to replace
0276      * the standard combo box view with a QTreeView.
0277      */
0278     explicit TreeViewLineEditComboBox(QWidget* const parent = nullptr);
0279 
0280     /**
0281      * Set the text of the line edit (the text that is visible
0282      * if the popup is not opened).
0283      * Applicable only for default installLineEdit() implementation.
0284      */
0285     void setLineEditText(const QString& text);
0286 
0287     void setLineEdit(QLineEdit* edit);
0288 
0289     /**
0290      * Replace the standard combo box list view with a QTreeView.
0291      * Call this after installing an appropriate model.
0292      */
0293     void installView(QAbstractItemView* view = nullptr) override;
0294 
0295 protected:
0296 
0297     /**
0298      * Sets a line edit. Called by installView().
0299      * The default implementation is described above.
0300      * An empty implementation will keep the default QComboBox line edit.
0301      */
0302     virtual void installLineEdit();
0303 
0304 protected:
0305 
0306     QLineEdit* m_comboLineEdit;
0307 };
0308 
0309 } // namespace Digikam
0310 
0311 #endif // DIGIKAM_COMBOBOX_UTILITIES_H