1 /*
2  * Cantata
3  *
4  * Copyright (c) 2011-2020 Craig Drummond <craig.p.drummond@gmail.com>
5  *
6  */
7 /**************************************************************************
8 **
9 ** This file is part of Qt Creator
10 **
11 ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
12 **
13 ** Contact: Nokia Corporation (qt-info@nokia.com)
14 **
15 ** Commercial Usage
16 **
17 ** Licensees holding valid Qt Commercial licenses may use this file in
18 ** accordance with the Qt Commercial License Agreement provided with the
19 ** Software or, alternatively, in accordance with the terms contained in
20 ** a written agreement between you and Nokia.
21 **
22 ** GNU Lesser General Public License Usage
23 **
24 ** Alternatively, this file may be used under the terms of the GNU Lesser
25 ** General Public License version 2.1 as published by the Free Software
26 ** Foundation and appearing in the file LICENSE.LGPL included in the
27 ** packaging of this file.  Please review the following information to
28 ** ensure the GNU Lesser General Public License version 2.1 requirements
29 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
30 **
31 ** If you are unsure which license is appropriate for your use, please
32 ** contact the sales department at http://qt.nokia.com/contact.
33 **
34 **************************************************************************/
35 
36 #ifndef FANCYTABWIDGET_H
37 #define FANCYTABWIDGET_H
38 
39 #include <QIcon>
40 #include <QProxyStyle>
41 #include <QTabBar>
42 #include <QWidget>
43 #include <QTimer>
44 #include <QScopedPointer>
45 #include <QStringList>
46 
47 class QMenu;
48 class QPainter;
49 class QSignalMapper;
50 class QStackedWidget;
51 class QStatusBar;
52 class QVBoxLayout;
53 
54 class FancyTabProxyStyle : public QProxyStyle
55 {
56     Q_OBJECT
57 
58 public:
59     void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *p, const QWidget *widget) const override;
60     void drawControl(ControlElement element, const QStyleOption *option, QPainter *p, const QWidget *widget) const override;
61     void polish(QWidget *widget) override;
62     void polish(QApplication *app) override;
63     void polish(QPalette &palette) override;
64 
65 protected:
66     bool eventFilter(QObject *o, QEvent *e) override;
67 };
68 
69 class FancyTabBar;
70 class FancyTab : public QWidget
71 {
72 public:
73     FancyTab(FancyTabBar *tabbar);
74 
75     QSize sizeHint() const override;
76     QIcon icon;
77     QString text;
78     bool underMouse;
79 
80 protected:
81     void enterEvent(QEvent *) override;
82     void leaveEvent(QEvent *) override;
83 
84 private:
85     FancyTabBar *tabbar;
86 };
87 
88 class FancyTabBar : public QWidget
89 {
90     Q_OBJECT
91 
92 public:
93     enum Pos {
94         Side,
95         Top,
96         Bot
97     };
98 
99     FancyTabBar(QWidget *parent, bool text, int iSize, Pos pos);
100     ~FancyTabBar() override;
101 
102     void paintEvent(QPaintEvent *event) override;
103     void paintTab(QPainter *painter, int tabIndex) const;
104     void mousePressEvent(QMouseEvent *) override;
105     void wheelEvent(QWheelEvent *ev) override;
validIndex(int index)106     bool validIndex(int index) const { return index >= 0 && index < tabs.count(); }
107 
108     QSize sizeHint() const override;
109     QSize minimumSizeHint() const override;
110 
111     void addTab(const QIcon &icon, const QString &label, const QString &tt);
112     void addSpacer(int size = 40);
removeTab(int index)113     void removeTab(int index) { delete tabs.takeAt(index); }
114     void setCurrentIndex(int index);
currentIndex()115     int currentIndex() const { return currentIdx; }
116 
117     void setTabToolTip(int index, const QString &toolTip);
118     QString tabToolTip(int index) const;
119 
tabIcon(int index)120     QIcon tabIcon(int index) const {return tabs.at(index)->icon; }
tabText(int index)121     QString tabText(int index) const { return tabs.at(index)->text; }
count()122     int count() const {return tabs.count(); }
123     QRect tabRect(int index) const;
showText()124     bool showText() const { return withText; }
iconSize()125     int iconSize() const { return icnSize; }
126     QSize tabSizeHint() const;
position()127     Pos position() const { return pos; }
128 
129 Q_SIGNALS:
130     void currentChanged(int);
131 
132 public Q_SLOTS:
133     void emitCurrentIndex();
134 
135 private:
136     int currentIdx;
137     QList<FancyTab*> tabs;
138     QTimer triggerTimer;
139     bool withText : 1;
140     Pos pos : 2;
141     int icnSize;
142 };
143 
144 class FancyTabWidget : public QWidget
145 {
146     Q_OBJECT
147 
148 public:
149     static void setup();
150     static int iconSize(bool large=true);
151 
152     FancyTabWidget(QWidget *parent);
153 
154     enum Style {
155         Side     = 0x0001,
156         Top      = 0x0002,
157         Bot      = 0x0003,
158 
159         Large    = 0x0010,
160         Small    = 0x0020,
161         Tab      = 0x0030,
162 
163         IconOnly = 0x0100,
164 
165         Position_Mask = 0x000F,
166         Style_Mask    = 0x00F0,
167         Options_Mask  = 0x0100,
168         All_Mask      = Position_Mask|Style_Mask|Options_Mask
169     };
170 
171     struct Item {
ItemItem172         Item(const QIcon &icon, const QString &label, const QString &tt, bool en)
173             : type(Type_Tab), tabLabel(label), tabTooltip(tt), tabIcon(icon), spacerSize(0), enabled(en), index(-1) {}
ItemItem174         Item(int size) : type(Type_Spacer), spacerSize(size), enabled(true), index(-1) {}
175 
176         enum Type {
177             Type_Tab,
178             Type_Spacer
179         };
180 
181         Type type;
182         QString tabLabel;
183         QString tabTooltip;
184         QIcon tabIcon;
185         int spacerSize;
186         bool enabled;
187         int index;
188     };
189 
190     void addTab(QWidget *tab, const QIcon &icon, const QString &label, const QString &tt=QString(), bool enabled=true);
191     int currentIndex() const;
192     QWidget * currentWidget() const;
isEnabled(int index)193     bool isEnabled(int index) const { return index>=0 && index<items.count() ? items[index].enabled : false; }
194     QWidget * widget(int index) const;
195     int count() const;
196     int visibleCount() const;
style()197     int style() const { return styleSetting; }
198     QSize tabSize() const;
199     void setIcon(int index, const QIcon &icon);
200     void setToolTip(int index, const QString &tt);
201     void recreate();
202     void setHiddenPages(const QStringList &hidden);
203     QStringList hiddenPages() const;
204 
205 public Q_SLOTS:
206     void setCurrentIndex(int index);
207     void setStyle(int s);
208     void toggleTab(int tab, bool show);
209 
210 Q_SIGNALS:
211     void currentChanged(int index);
212     void styleChanged(int styleSetting);
213     void tabToggled(int index);
214 
215 private Q_SLOTS:
216     void showWidget(int index);
217 
218 private:
219     void makeTabBar(QTabBar::Shape shape, bool text, bool icons, bool fancy);
220     int tabToIndex(int tab) const;
IndexToTab(int index)221     int IndexToTab(int index) const { return index>=0 && index<items.count() ? items[index].index : 0; }
222 
223 private:
224     int styleSetting;
225     QList<Item> items;
226     QWidget *tabBar;
227     QStackedWidget *stack_;
228     QWidget *sideWidget;
229     QVBoxLayout *sideLayout;
230     QVBoxLayout *topLayout;
231     QMenu *menu;
232     QScopedPointer<FancyTabProxyStyle> proxyStyle;
233 };
234 
235 
236 #endif // FANCYTABWIDGET_H
237