File indexing completed on 2025-04-27 03:58:30
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2005-03-22 0007 * Description : a widget to manage sidebar in GUI. 0008 * 0009 * SPDX-FileCopyrightText: 2005-2006 by Joern Ahrens <joern dot ahrens at kdemail dot net> 0010 * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * SPDX-FileCopyrightText: 2008-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0012 * SPDX-FileCopyrightText: 2001-2003 by Joseph Wenninger <jowenn at kde dot org> 0013 * 0014 * SPDX-License-Identifier: GPL-2.0-or-later 0015 * 0016 * ============================================================ */ 0017 0018 #ifndef DIGIKAM_SIDE_BAR_H 0019 #define DIGIKAM_SIDE_BAR_H 0020 0021 // Qt includes 0022 0023 #include <QIcon> 0024 #include <QPixmap> 0025 #include <QSplitter> 0026 #include <QPushButton> 0027 #include <QWidget> 0028 #include <QList> 0029 #include <QStyleOptionToolButton> 0030 #include <QBoxLayout> 0031 0032 // Local includes 0033 0034 #include "digikam_export.h" 0035 #include "statesavingobject.h" 0036 0037 class KConfigGroup; 0038 0039 namespace Digikam 0040 { 0041 0042 class DMultiTabBarButton; 0043 class DMultiTabBarTab; 0044 0045 /** 0046 * A Widget for horizontal and vertical tabs. 0047 */ 0048 class DIGIKAM_EXPORT DMultiTabBar : public QWidget 0049 { 0050 Q_OBJECT 0051 0052 public: 0053 0054 /** 0055 * The list of available styles for DMultiTabBar 0056 */ 0057 enum TextStyle 0058 { 0059 ActiveIconText = 0, ///< Always shows icon, only show the text of active tabs. 0060 AllIconsText = 2 ///< Always shows the text and icons. 0061 }; 0062 0063 public: 0064 0065 explicit DMultiTabBar(Qt::Edge pos, QWidget* const parent = nullptr); 0066 ~DMultiTabBar() override; 0067 0068 /** 0069 * append a new button to the button area. The button can later on be accessed with button(ID) 0070 * eg for connecting signals to it 0071 * @param pic a icon for the button 0072 * @param id an arbitrary ID value. It will be emitted in the clicked signal for identifying the button 0073 * if more than one button is connected to a signals. 0074 * @param popup A popup menu which should be displayed if the button is clicked 0075 * @param not_used_yet will be used for a popup text in the future 0076 */ 0077 void appendButton(const QIcon& pic, 0078 int id = -1, 0079 QMenu* const popup = nullptr, 0080 const QString& not_used_yet = QString()); 0081 0082 /** 0083 * remove a button with the given ID 0084 */ 0085 void removeButton(int id); 0086 0087 /** 0088 * append a new tab to the tab area. It can be accessed later on with tabb(id); 0089 * @param pic a icon for the tab 0090 * @param id an arbitrary ID which can be used later on to identify the tab 0091 * @param text if a mode with text is used it will be the tab text, otherwise a mouse over hint 0092 */ 0093 void appendTab(const QIcon& pic, 0094 int id = -1, 0095 const QString& text = QString()); 0096 0097 /** 0098 * remove a tab with a given ID 0099 */ 0100 void removeTab(int id); 0101 0102 /** 0103 * set a tab to "raised" 0104 * @param id The ID of the tab to manipulate 0105 * @param state true == activated/raised, false == not active 0106 */ 0107 void setTab(int id, bool state); 0108 0109 /** 0110 * return the state of a tab, identified by its ID 0111 */ 0112 bool isTabRaised(int id) const; 0113 0114 /** 0115 * get a pointer to a button within the button area identified by its ID 0116 */ 0117 DMultiTabBarButton* button(int id) const; 0118 0119 /** 0120 * get a pointer to a tab within the tab area, identified by its ID 0121 */ 0122 DMultiTabBarTab* tab(int id) const; 0123 0124 /** 0125 * set the real position of the widget. 0126 * @param pos if the mode is horizontal, only use top, bottom, if it is vertical use left or right 0127 */ 0128 void setPosition(Qt::Edge pos); 0129 0130 /** 0131 * get the tabbar position. 0132 * @return position 0133 */ 0134 Qt::Edge position() const; 0135 0136 /** 0137 * set the display style of the tabs 0138 */ 0139 void setStyle(TextStyle style); 0140 0141 /** 0142 * get the display style of the tabs 0143 * @return display style 0144 */ 0145 TextStyle tabStyle() const; 0146 0147 protected: 0148 0149 void updateSeparator(); 0150 0151 virtual void fontChange(const QFont&); 0152 0153 private: 0154 0155 friend class DMultiTabBarButton; 0156 0157 class Private; 0158 Private* const d; 0159 }; 0160 0161 // ------------------------------------------------------------------------------------- 0162 0163 class DIGIKAM_EXPORT DMultiTabBarButton: public QPushButton 0164 { 0165 Q_OBJECT 0166 0167 public: 0168 0169 ~DMultiTabBarButton() override; 0170 0171 int id() const; 0172 0173 public Q_SLOTS: 0174 0175 void setText(const QString& text); 0176 0177 Q_SIGNALS: 0178 0179 /** 0180 * this is emitted if the button is clicked 0181 * @param id the ID identifying the button 0182 */ 0183 void signalClicked(int id); 0184 0185 protected Q_SLOTS: 0186 0187 virtual void slotClicked(); 0188 0189 protected: 0190 0191 DMultiTabBarButton(const QIcon& pic, 0192 const QString&, 0193 int id, 0194 QWidget* const parent); 0195 0196 void hideEvent(QHideEvent*) override; 0197 void showEvent(QShowEvent*) override; 0198 void paintEvent(QPaintEvent*) override; 0199 0200 private: 0201 0202 friend class DMultiTabBar; 0203 0204 int m_id; 0205 }; 0206 0207 // ------------------------------------------------------------------------------------- 0208 0209 class DIGIKAM_EXPORT DMultiTabBarTab: public DMultiTabBarButton 0210 { 0211 Q_OBJECT 0212 0213 public: 0214 0215 ~DMultiTabBarTab() override; 0216 0217 QSize sizeHint() const override; 0218 QSize minimumSizeHint() const override; 0219 0220 public Q_SLOTS: 0221 0222 /** 0223 * this is used internally, but can be used by the user. 0224 * It the according call of DMultiTabBar is invoked though this modifications will be overwritten 0225 */ 0226 void setPosition(Qt::Edge); 0227 0228 /** 0229 * this is used internally, but can be used by the user. 0230 * It the according call of DMultiTabBar is invoked though this modifications will be overwritten 0231 */ 0232 void setStyle(DMultiTabBar::TextStyle); 0233 0234 /** 0235 * set the active state of the tab 0236 * @param state true==active false==not active 0237 */ 0238 void setState(bool state); 0239 0240 void setIcon(const QString&); 0241 void setIcon(const QIcon&); 0242 0243 protected: 0244 0245 void computeMargins (int* hMargin, int* vMargin) const; 0246 QSize computeSizeHint(bool withText) const; 0247 bool shouldDrawText() const; 0248 bool isVertical() const; 0249 QPixmap iconPixmap() const; 0250 void initButtonStyleOption(QStyleOptionToolButton* opt) const; 0251 0252 friend class DMultiTabBarFrame; 0253 0254 /** 0255 * This class should never be created except with the appendTab call of DMultiTabBar 0256 */ 0257 DMultiTabBarTab(const QIcon& pic, 0258 const QString&, 0259 int id, 0260 QWidget* const parent, 0261 Qt::Edge pos, 0262 DMultiTabBar::TextStyle style); 0263 0264 void paintEvent(QPaintEvent*) override; 0265 0266 private: 0267 0268 class Private; 0269 Private* const d; 0270 }; 0271 0272 // ------------------------------------------------------------------------------------- 0273 0274 class DMultiTabBarFrame: public QFrame 0275 { 0276 Q_OBJECT 0277 0278 public: 0279 0280 explicit DMultiTabBarFrame(QWidget* const parent, Qt::Edge pos); 0281 ~DMultiTabBarFrame() override; 0282 0283 void appendTab(const QIcon&, int = -1, const QString& = QString()); 0284 DMultiTabBarTab* tab(int) const; 0285 void removeTab(int); 0286 void setPosition(Qt::Edge pos); 0287 void setStyle(DMultiTabBar::TextStyle style); 0288 void showActiveTabTexts(bool show); 0289 QList<DMultiTabBarTab*>* tabs(); 0290 0291 protected: 0292 0293 /** 0294 * Reimplemented from QScrollView 0295 * in order to ignore all mouseEvents on the viewport, so that the 0296 * parent can handle them. 0297 */ 0298 virtual void contentsMousePressEvent(QMouseEvent*); 0299 void mousePressEvent(QMouseEvent*) override; 0300 0301 private: 0302 0303 friend class DMultiTabBar; 0304 0305 class Private; 0306 Private* const d; 0307 }; 0308 0309 // ------------------------------------------------------------------------------------- 0310 0311 class SidebarSplitter; 0312 0313 /** 0314 * This class handles a sidebar view 0315 * 0316 * Since this class derives from StateSavingObject, you can call 0317 * StateSavingObject#loadState() and StateSavingObject#saveState() 0318 * for loading/saving of settings. However, if you use multiple 0319 * sidebar instances in your program, you have to remember to either 0320 * call QObject#setObjectName(), StateSavingObject#setEntryPrefix() or 0321 * StateSavingObject#setConfigGroup() first. 0322 */ 0323 class DIGIKAM_EXPORT Sidebar : public DMultiTabBar, 0324 public StateSavingObject 0325 { 0326 Q_OBJECT 0327 0328 public: 0329 0330 /** 0331 * Creates a new sidebar 0332 * @param parent sidebar's parent 0333 * @param sp sets the splitter, which should handle the width. The splitter normally 0334 * is part of the main view. Internally, the width of the widget stack can 0335 * be changed by a QSplitter. 0336 * @param side where the sidebar should be displayed. At the left or right border. 0337 * Use Qt::LeftEdge or Qt::RightEdge. 0338 * @param minimizedDefault hide the sidebar when the program is started the first time. 0339 */ 0340 explicit Sidebar(QWidget* const parent, 0341 SidebarSplitter* const sp, 0342 Qt::Edge side = Qt::LeftEdge, 0343 bool minimizedDefault = false); 0344 0345 ~Sidebar() override; 0346 0347 SidebarSplitter* splitter() const; 0348 0349 /** 0350 * Appends a new tab to the sidebar 0351 * @param w widget which is activated by this tab 0352 * @param pic icon which is shown in this tab 0353 * @param title text which is shown it this tab 0354 */ 0355 void appendTab(QWidget* const w, const QIcon& pic, const QString& title); 0356 0357 /** 0358 * Deletes a tab from the tabbar 0359 */ 0360 void deleteTab(QWidget* const w); 0361 0362 /** 0363 * Activates a tab 0364 */ 0365 void setActiveTab(QWidget* const w); 0366 0367 /** 0368 * Activates a next tab from current one. If current one is last, first one is activated. 0369 */ 0370 void activeNextTab(); 0371 0372 /** 0373 * Activates a previous tab from current one. If current one is first, last one is activated. 0374 */ 0375 void activePreviousTab(); 0376 0377 /** 0378 * Returns the currently activated tab, or 0 if no tab is active 0379 */ 0380 QWidget* getActiveTab() const; 0381 0382 /** 0383 * Hides the sidebar (display only the activation buttons) 0384 */ 0385 void shrink(); 0386 0387 /** 0388 * Redisplays the whole sidebar 0389 */ 0390 void expand(); 0391 0392 /** 0393 * Hide sidebar and backup minimized state. 0394 */ 0395 void backup(); 0396 0397 /** 0398 * Hide sidebar and backup minimized state. 0399 * If there are other widgets in this splitter, stores 0400 * their sizes in the provided list. 0401 */ 0402 void backup(const QList<QWidget*>& thirdWidgetsToBackup, QList<int>* const sizes); 0403 0404 /** 0405 * Show sidebar and restore minimized state. 0406 */ 0407 void restore(); 0408 0409 /** 0410 * Show sidebar and restore minimized state. 0411 * Restores other widgets' sizes in splitter. 0412 */ 0413 void restore(const QList<QWidget*>& thirdWidgetsToRestore, const QList<int>& sizes); 0414 0415 /** 0416 * Return the visible status of current sidebar tab. 0417 */ 0418 bool isExpanded() const; 0419 0420 protected: 0421 0422 /** 0423 * Load the last view state from disk - called by StateSavingObject#loadState() 0424 */ 0425 void doLoadState() override; 0426 0427 /** 0428 * Save the view state to disk - called by StateSavingObject#saveState() 0429 */ 0430 void doSaveState() override; 0431 0432 private: 0433 0434 bool eventFilter(QObject* o, QEvent* e) override; 0435 void switchTabAndStackToTab(int tab); 0436 0437 private Q_SLOTS: 0438 0439 /** 0440 * Activates a tab 0441 */ 0442 void slotClicked(int tab); 0443 0444 void slotExpandTimer(); 0445 void slotDragSwitchTimer(); 0446 0447 void slotSplitterBtnClicked(); 0448 0449 Q_SIGNALS: 0450 0451 /** 0452 * Is emitted, when another tab is activated 0453 */ 0454 void signalChangedTab(QWidget* w); 0455 0456 /** 0457 * Is emitted, when tab is shrink or expanded 0458 */ 0459 void signalViewChanged(); 0460 0461 private: 0462 0463 friend class SidebarSplitter; 0464 0465 class Private; 0466 Private* const d; 0467 }; 0468 0469 // ----------------------------------------------------------------------------- 0470 0471 class DIGIKAM_EXPORT SidebarSplitter : public QSplitter 0472 { 0473 Q_OBJECT 0474 0475 public: 0476 0477 const static QString DEFAULT_CONFIG_KEY; 0478 0479 /** 0480 * This is a QSplitter with better support for storing its state 0481 * in config files, especially if Sidebars are contained in the splitter. 0482 */ 0483 explicit SidebarSplitter(QWidget* const parent = nullptr); 0484 explicit SidebarSplitter(Qt::Orientation orientation, QWidget* const parent = nullptr); 0485 0486 ~SidebarSplitter() override; 0487 0488 /** 0489 * Saves the splitter state to group, handling minimized sidebars correctly. 0490 * DEFAULT_CONFIG_KEY is used for storing the state. 0491 */ 0492 void saveState(KConfigGroup& group); 0493 0494 /** 0495 * Saves the splitter state to group, handling minimized sidebars correctly. 0496 * This version uses a specified key in the config group. 0497 */ 0498 void saveState(KConfigGroup& group, const QString& key); 0499 0500 /** 0501 * Restores the splitter state from group, handling minimized sidebars correctly. 0502 * DEFAULT_CONFIG_KEY is used for restoring the state. 0503 */ 0504 void restoreState(KConfigGroup& group); 0505 0506 /** 0507 * Restores the splitter state from group, handling minimized sidebars correctly. 0508 * This version uses a specified key in the config group. 0509 */ 0510 void restoreState(KConfigGroup& group, const QString& key); 0511 0512 /** 0513 * Returns the value of sizes() that corresponds to the given Sidebar or splitter child widget. 0514 */ 0515 int size(Sidebar* const bar) const; 0516 int size(QWidget* const widget) const; 0517 0518 /** 0519 * Sets the splitter size for the given sidebar or splitter child widget to size. 0520 * Special value -1: Sets the minimum size hint of the widget. 0521 */ 0522 void setSize(Sidebar* const bar, int size); 0523 void setSize(QWidget* const widget, int size); 0524 0525 void addSplitterCollapserButton(QWidget* const widget); 0526 0527 private Q_SLOTS: 0528 0529 void slotSplitterMoved(int pos, int index); 0530 0531 private: 0532 0533 friend class Sidebar; 0534 0535 class Private; 0536 Private* const d; 0537 }; 0538 0539 } // namespace Digikam 0540 0541 #endif // DIGIKAM_SIDE_BAR_H