1 /* ============================================================ 2 * 3 * This file is a part of digiKam project 4 * https://www.digikam.org 5 * 6 * Date : 2008-03-14 7 * Description : User interface for searches 8 * 9 * Copyright (C) 2008-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 10 * 11 * This program is free software; you can redistribute it 12 * and/or modify it under the terms of the GNU General 13 * Public License as published by the Free Software Foundation; 14 * either version 2, or (at your option) 15 * any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * ============================================================ */ 23 24 #ifndef DIGIKAM_COMBOBOX_UTILITIES_H 25 #define DIGIKAM_COMBOBOX_UTILITIES_H 26 27 // Qt includes 28 29 #include <QLabel> 30 #include <QListView> 31 #include <QComboBox> 32 #include <QPersistentModelIndex> 33 #include <QLineEdit> 34 35 // Local includes 36 37 #include "digikam_export.h" 38 39 class QVBoxLayout; 40 class QTreeView; 41 42 namespace Digikam 43 { 44 45 class DIGIKAM_EXPORT ProxyLineEdit : public QLineEdit 46 { 47 Q_OBJECT 48 49 public: 50 51 /** 52 * This class will not act as a QLineEdit at all, 53 * but present another widget (any kind of widget) 54 * instead in the space assigned to the QLineEdit. 55 * Use this class if you need to pass a QLineEdit but 56 * want actually to use a different widget. 57 */ 58 explicit ProxyLineEdit(QWidget* const parent = nullptr); 59 60 /** 61 * After constructing, set the actual widget here 62 */ 63 virtual void setWidget(QWidget* widget); 64 65 void setClearButtonShown(bool show); 66 67 Q_SIGNALS: 68 69 void signalClearButtonPressed(); 70 71 private Q_SLOTS: 72 73 void slotTextChanged(const QString& text); 74 75 protected: 76 77 QSize minimumSizeHint() const override; 78 QSize sizeHint() const override; 79 80 void mousePressEvent(QMouseEvent* event) override; 81 void mouseMoveEvent(QMouseEvent* event) override; 82 void mouseReleaseEvent(QMouseEvent* event) override; 83 void mouseDoubleClickEvent(QMouseEvent* event) override; 84 void keyPressEvent(QKeyEvent* event) override; 85 void focusInEvent(QFocusEvent* event) override; 86 void focusOutEvent(QFocusEvent* event) override; 87 void paintEvent(QPaintEvent* event) override; 88 void dragEnterEvent(QDragEnterEvent* event) override; 89 void dragMoveEvent(QDragMoveEvent* e) override; 90 void dragLeaveEvent(QDragLeaveEvent* e) override; 91 void dropEvent(QDropEvent* event) override; 92 void changeEvent(QEvent* event) override; 93 void contextMenuEvent(QContextMenuEvent* event) override; 94 void inputMethodEvent(QInputMethodEvent* event) override; 95 96 protected: 97 98 QWidget* m_widget; 99 QVBoxLayout* m_layout; 100 }; 101 102 // ------------------------------------------------------------------------- 103 104 class DIGIKAM_EXPORT ProxyClickLineEdit : public ProxyLineEdit 105 { 106 Q_OBJECT 107 108 public: 109 110 /** 111 * A ProxyLineEdit that emits leftClicked() on 112 * mouse press event. 113 * Press on the held widget will result in the signal 114 * if the widget does not accept() them. 115 */ 116 explicit ProxyClickLineEdit(QWidget* const parent = nullptr); 117 118 Q_SIGNALS: 119 120 void leftClicked(); 121 122 protected: 123 124 void mouseReleaseEvent(QMouseEvent* event) override; 125 }; 126 127 // ------------------------------------------------------------------------- 128 129 class DIGIKAM_EXPORT ModelIndexBasedComboBox : public QComboBox 130 { 131 Q_OBJECT 132 133 public: 134 135 /** 136 * QComboBox has a current index based on a single integer. 137 * This is not sufficient for more complex models. 138 * This class is a combo box that stores a current index 139 * based on QModelIndex. 140 */ 141 explicit ModelIndexBasedComboBox(QWidget* const parent = nullptr); 142 143 QModelIndex currentIndex() const; 144 void setCurrentIndex(const QModelIndex& index); 145 146 void hidePopup() override; 147 void showPopup() override; 148 149 protected: 150 151 QPersistentModelIndex m_currentIndex; 152 }; 153 154 // ------------------------------------------------------------------------- 155 156 class DIGIKAM_EXPORT StayPoppedUpComboBox : public ModelIndexBasedComboBox 157 { 158 Q_OBJECT 159 160 public: 161 162 /** 163 * This class provides an abstract QComboBox with a custom view 164 * (which is created by implementing subclasses) 165 * instead of the usual QListView. 166 * The Pop-up of the combo box will stay open after selecting an item; 167 * it will be closed by clicking outside, but not inside the widget. 168 * You need three steps: 169 * Construct the object, call setModel() with an appropriate 170 * QAbstractItemModel, then call installView() to replace 171 * the standard combo box view with a view. 172 */ 173 explicit StayPoppedUpComboBox(QWidget* const parent = nullptr); 174 175 protected: 176 177 /** 178 * Replace the standard combo box list view with the given view. 179 * The view will be set as the view of the combo box 180 * (including re-parenting) and be stored in the m_view variable. 181 */ 182 void installView(QAbstractItemView* view); 183 184 /** 185 * Implement in subclass: 186 * Send the given event to the viewportEvent() method of m_view. 187 * This method is protected for a usual QAbstractItemView. 188 * You can override, pass a view, and call parent implementation. 189 * The existing view will be used. You must then also 190 * reimplement sendViewportEventToView. 191 */ 192 virtual void sendViewportEventToView(QEvent* e) = 0; 193 194 bool eventFilter(QObject* watched, QEvent* event) override; 195 196 protected: 197 198 QAbstractItemView* m_view; 199 }; 200 201 // ------------------------------------------------------------------------- 202 203 class DIGIKAM_EXPORT TreeViewComboBox : public StayPoppedUpComboBox 204 { 205 Q_OBJECT 206 207 public: 208 209 /** 210 * This class provides a QComboBox with a QTreeView 211 * instead of the usual QListView. 212 * You need three steps: 213 * Construct the object, call setModel() with an appropriate 214 * QAbstractItemModel, then call installView() to replace 215 * the standard combo box view with a QTreeView. 216 */ 217 explicit TreeViewComboBox(QWidget* parent = nullptr); 218 219 /** 220 * Replace the standard combo box list view with a QTreeView. 221 * Call this after installing an appropriate model. 222 */ 223 virtual void installView(QAbstractItemView* view = nullptr); 224 225 /** 226 * Returns the QTreeView of this class. Valid after installView() has been called 227 */ 228 QTreeView* view() const; 229 230 protected: 231 232 void sendViewportEventToView(QEvent* e) override; 233 }; 234 235 // ------------------------------------------------------------------------- 236 237 class DIGIKAM_EXPORT ListViewComboBox : public StayPoppedUpComboBox 238 { 239 Q_OBJECT 240 241 public: 242 243 /** 244 * This class provides an implementation of a StayPoppedUpComboBox 245 * with a QListView. This is the standard view of a QComboBox, 246 * but in conjunction with StayPoppedUpComboBox some extra steps are needed. 247 * You need three steps: 248 * Construct the object, call setModel() with an appropriate 249 * QAbstractItemModel, then call installView(). 250 */ 251 explicit ListViewComboBox(QWidget* parent = nullptr); 252 253 /** 254 * Returns the QTreeView of this class. Valid after installView() has been called. 255 */ 256 QListView* view() const; 257 258 /** 259 * Replace the standard combo box list view with a QTreeView. 260 * Call this after installing an appropriate model. 261 */ 262 virtual void installView(QAbstractItemView* view = nullptr); 263 264 protected: 265 266 void sendViewportEventToView(QEvent* e) override; 267 }; 268 269 // ------------------------------------------------------------------------- 270 271 class DIGIKAM_EXPORT TreeViewLineEditComboBox : public TreeViewComboBox 272 { 273 Q_OBJECT 274 275 public: 276 277 /** 278 * This class provides a TreeViewComboBox 279 * with a read-only line edit. 280 * The text in the line edit can be adjusted. The combo box will 281 * open on a click on the line edit. 282 * You need three steps: 283 * Construct the object, call setModel() with an appropriate 284 * QAbstractItemModel, then call installView() to replace 285 * the standard combo box view with a QTreeView. 286 */ 287 explicit TreeViewLineEditComboBox(QWidget* const parent = nullptr); 288 289 /** 290 * Set the text of the line edit (the text that is visible 291 * if the popup is not opened). 292 * Applicable only for default installLineEdit() implementation. 293 */ 294 void setLineEditText(const QString& text); 295 296 void setLineEdit(QLineEdit* edit); 297 298 /** 299 * Replace the standard combo box list view with a QTreeView. 300 * Call this after installing an appropriate model. 301 */ 302 void installView(QAbstractItemView* view = nullptr) override; 303 304 protected: 305 306 /** 307 * Sets a line edit. Called by installView(). 308 * The default implementation is described above. 309 * An empty implementation will keep the default QComboBox line edit. 310 */ 311 virtual void installLineEdit(); 312 313 protected: 314 315 QLineEdit* m_comboLineEdit; 316 }; 317 318 } // namespace Digikam 319 320 #endif // DIGIKAM_COMBOBOX_UTILITIES_H 321