File indexing completed on 2024-05-12 04:58:23

0001 /* ============================================================
0002 * Falkon - Qt web browser
0003 * Copyright (C) 2013-2014 S. Razi Alavizadeh <s.r.alavizadeh@gmail.com>
0004 * Copyright (C) 2014-2018 David Rosca <nowrep@gmail.com>
0005 *
0006 * This program is free software: you can redistribute it and/or modify
0007 * it under the terms of the GNU General Public License as published by
0008 * the Free Software Foundation, either version 3 of the License, or
0009 * (at your option) any later version.
0010 *
0011 * This program is distributed in the hope that it will be useful,
0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014 * GNU General Public License for more details.
0015 *
0016 * You should have received a copy of the GNU General Public License
0017 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0018 * ============================================================ */
0019 #ifndef COMBOTABBAR_H
0020 #define COMBOTABBAR_H
0021 
0022 #include "qzcommon.h"
0023 #include "wheelhelper.h"
0024 
0025 #include <QTabBar>
0026 #include <QScrollBar>
0027 #include <QAbstractButton>
0028 #include <QEasingCurve>
0029 #include <QStyleOption>
0030 
0031 class QScrollArea;
0032 class QPropertyAnimation;
0033 class QHBoxLayout;
0034 
0035 class TabBarScrollWidget;
0036 class TabBarHelper;
0037 class ToolButton;
0038 
0039 class FALKON_EXPORT ComboTabBar : public QWidget
0040 {
0041     Q_OBJECT
0042     Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentChanged)
0043     Q_PROPERTY(int count READ count)
0044 
0045 public:
0046     enum SizeType {
0047         PinnedTabWidth,
0048         ActiveTabMinimumWidth,
0049         NormalTabMinimumWidth,
0050         NormalTabMaximumWidth,
0051         OverflowedTabWidth,
0052         ExtraReservedWidth
0053     };
0054 
0055     enum DropIndicatorPosition {
0056         BeforeTab,
0057         AfterTab
0058     };
0059 
0060     explicit ComboTabBar(QWidget* parent = nullptr);
0061 
0062     int addTab(const QString &text);
0063     int addTab(const QIcon &icon, const QString &text);
0064 
0065     int insertTab(int index, const QString &text);
0066     int insertTab(int index, const QIcon &icon, const QString &text, bool pinned = false);
0067 
0068     void removeTab(int index);
0069     void moveTab(int from, int to);
0070 
0071     bool isTabEnabled(int index) const;
0072     void setTabEnabled(int index, bool enabled);
0073 
0074     QColor tabTextColor(int index) const;
0075     void setTabTextColor(int index, const QColor &color);
0076 
0077     QRect tabRect(int index) const;
0078     QRect draggedTabRect() const;
0079     QPixmap tabPixmap(int index) const;
0080 
0081     // Returns tab index at pos, or -1
0082     int tabAt(const QPoint &pos) const;
0083 
0084     // Returns true if there is an empty area at pos
0085     // (returns false if there are buttons or other widgets on the pos)
0086     bool emptyArea(const QPoint &pos) const;
0087 
0088     int mainTabBarCurrentIndex() const;
0089     int currentIndex() const;
0090     int count() const;
0091 
0092     void setDrawBase(bool drawTheBase);
0093     bool drawBase() const;
0094 
0095     Qt::TextElideMode elideMode() const;
0096     void setElideMode(Qt::TextElideMode elide);
0097 
0098     QString tabText(int index) const;
0099     void setTabText(int index, const QString &text);
0100 
0101     void setTabToolTip(int index, const QString &tip);
0102     QString tabToolTip(int index) const;
0103 
0104     bool tabsClosable() const;
0105     void setTabsClosable(bool closable);
0106 
0107     void setTabButton(int index, QTabBar::ButtonPosition position, QWidget* widget);
0108     QWidget* tabButton(int index, QTabBar::ButtonPosition position) const;
0109 
0110     QTabBar::SelectionBehavior selectionBehaviorOnRemove() const;
0111     void setSelectionBehaviorOnRemove(QTabBar::SelectionBehavior behavior);
0112 
0113     bool expanding() const;
0114     void setExpanding(bool enabled);
0115 
0116     bool isMovable() const;
0117     void setMovable(bool movable);
0118 
0119     bool documentMode() const;
0120     void setDocumentMode(bool set);
0121 
0122     int pinnedTabsCount() const;
0123     int normalTabsCount() const;
0124     bool isPinned(int index) const;
0125 
0126     void setFocusPolicy(Qt::FocusPolicy policy);
0127     void setObjectName(const QString &name);
0128     void setMouseTracking(bool enable);
0129 
0130     void insertCloseButton(int index);
0131     void setCloseButtonsToolTip(const QString &tip);
0132 
0133     QTabBar::ButtonPosition iconButtonPosition() const;
0134     QTabBar::ButtonPosition closeButtonPosition() const;
0135 
0136     QSize iconButtonSize() const;
0137     QSize closeButtonSize() const;
0138 
0139     bool validIndex(int index) const;
0140     void setCurrentNextEnabledIndex(int offset);
0141 
0142     bool usesScrollButtons() const;
0143     void setUsesScrollButtons(bool useButtons);
0144 
0145     void showDropIndicator(int index, DropIndicatorPosition position);
0146     void clearDropIndicator();
0147 
0148     bool isDragInProgress() const;
0149     bool isScrollInProgress() const;
0150     bool isMainBarOverflowed() const;
0151 
0152     // Width of all widgets in the corner
0153     int cornerWidth(Qt::Corner corner) const;
0154     // Add widget to the left/right corner
0155     void addCornerWidget(QWidget* widget, Qt::Corner corner);
0156 
0157     // Duration of tab slide animation when releasing dragged tab
0158     static int slideAnimationDuration();
0159 
0160 public Q_SLOTS:
0161     void setUpLayout();
0162     void ensureVisible(int index = -1, int xmargin = -1);
0163     void setCurrentIndex(int index);
0164 
0165 Q_SIGNALS:
0166     void overFlowChanged(bool overFlow);
0167     void currentChanged(int index);
0168     void tabCloseRequested(int index);
0169     void tabMoved(int from, int to);
0170     void scrollBarValueChanged(int value);
0171 
0172 private Q_SLOTS:
0173     void setMinimumWidths();
0174     void slotCurrentChanged(int index);
0175     void slotTabCloseRequested(int index);
0176     void slotTabMoved(int from, int to);
0177     void closeTabFromButton();
0178     void updateTabBars();
0179     void emitOverFlowChanged();
0180 
0181 protected:
0182     int mainTabBarWidth() const;
0183     int pinTabBarWidth() const;
0184 
0185     bool event(QEvent *event) override;
0186     void wheelEvent(QWheelEvent* event) override;
0187     bool eventFilter(QObject* obj, QEvent* ev) override;
0188     void paintEvent(QPaintEvent* ev) override;
0189 
0190     virtual int comboTabBarPixelMetric(SizeType sizeType) const;
0191     virtual QSize tabSizeHint(int index, bool fast = false) const;
0192     virtual void tabInserted(int index);
0193     virtual void tabRemoved(int index);
0194 
0195 private:
0196     TabBarHelper* mainTabBar() const;
0197     TabBarHelper* localTabBar(int index = -1) const;
0198 
0199     int toLocalIndex(int globalIndex) const;
0200     QRect mapFromLocalTabRect(const QRect &rect, QWidget *tabBar) const;
0201     void updatePinnedTabBarVisibility();
0202 
0203     QHBoxLayout* m_mainLayout;
0204     QHBoxLayout* m_leftLayout;
0205     QHBoxLayout* m_rightLayout;
0206     QWidget* m_leftContainer;
0207     QWidget* m_rightContainer;
0208 
0209     TabBarHelper* m_mainTabBar;
0210     TabBarHelper* m_pinnedTabBar;
0211 
0212     TabBarScrollWidget* m_mainTabBarWidget;
0213     TabBarScrollWidget* m_pinnedTabBarWidget;
0214 
0215     QString m_closeButtonsToolTip;
0216     bool m_mainBarOverFlowed;
0217     bool m_lastAppliedOverflow;
0218     bool m_usesScrollButtons;
0219     bool m_blockCurrentChangedSignal;
0220 
0221     WheelHelper m_wheelHelper;
0222 
0223     friend class TabBarHelper;
0224     friend class TabStackedWidget;
0225 };
0226 
0227 class FALKON_EXPORT TabBarHelper : public QTabBar
0228 {
0229     Q_OBJECT
0230     Q_PROPERTY(int tabPadding READ tabPadding WRITE setTabPadding)
0231     Q_PROPERTY(QColor baseColor READ baseColor WRITE setBaseColor)
0232 
0233 public:
0234     explicit TabBarHelper(bool isPinnedTabBar, ComboTabBar* comboTabBar);
0235 
0236     int tabPadding() const;
0237     void setTabPadding(int padding);
0238 
0239     QColor baseColor() const;
0240     void setBaseColor(const QColor &color);
0241 
0242     void setTabButton(int index, QTabBar::ButtonPosition position, QWidget* widget);
0243 
0244     QSize tabSizeHint(int index) const override;
0245     QSize baseClassTabSizeHint(int index) const;
0246 
0247     QRect draggedTabRect() const;
0248     QPixmap tabPixmap(int index) const;
0249 
0250     bool isActiveTabBar();
0251     void setActiveTabBar(bool activate);
0252 
0253     void removeTab(int index);
0254 
0255     void setScrollArea(QScrollArea* scrollArea);
0256     void useFastTabSizeHint(bool enabled);
0257 
0258     void showDropIndicator(int index, ComboTabBar::DropIndicatorPosition position);
0259     void clearDropIndicator();
0260 
0261     bool isDisplayedOnViewPort(int globalLeft, int globalRight);
0262     bool isDragInProgress() const;
0263 
0264     static void initStyleBaseOption(QStyleOptionTabBarBase* optTabBase, QTabBar* tabbar, QSize size);
0265 
0266 public Q_SLOTS:
0267     void setCurrentIndex(int index);
0268 
0269 private:
0270     bool event(QEvent* ev) override;
0271     void paintEvent(QPaintEvent* event) override;
0272     void mousePressEvent(QMouseEvent* event) override;
0273     void mouseMoveEvent(QMouseEvent *event) override;
0274     void mouseReleaseEvent(QMouseEvent* event) override;
0275 
0276     int dragOffset(QStyleOptionTab *option, int tabIndex) const;
0277     void initStyleOption(QStyleOptionTab* option, int tabIndex) const;
0278 
0279     ComboTabBar* m_comboTabBar;
0280     QScrollArea* m_scrollArea;
0281 
0282     int m_tabPadding = -1;
0283     QColor m_baseColor;
0284     int m_pressedIndex;
0285     bool m_dragInProgress;
0286     QPoint m_dragStartPosition;
0287     class QMovableTabWidget *m_movingTab = nullptr;
0288     bool m_activeTabBar;
0289     bool m_isPinnedTabBar;
0290     bool m_useFastTabSizeHint;
0291     int m_dropIndicatorIndex = -1;
0292     ComboTabBar::DropIndicatorPosition m_dropIndicatorPosition;
0293 };
0294 
0295 class FALKON_EXPORT TabScrollBar : public QScrollBar
0296 {
0297     Q_OBJECT
0298 public:
0299     explicit TabScrollBar(QWidget* parent = nullptr);
0300     ~TabScrollBar();
0301 
0302     bool isScrolling() const;
0303 
0304     void animateToValue(int to, QEasingCurve::Type type = QEasingCurve::OutQuad);
0305 
0306 private:
0307     QPropertyAnimation* m_animation;
0308 };
0309 
0310 
0311 class FALKON_EXPORT TabBarScrollWidget : public QWidget
0312 {
0313     Q_OBJECT
0314 public:
0315     explicit TabBarScrollWidget(QTabBar* tabBar, QWidget* parent = nullptr);
0316 
0317     QTabBar* tabBar();
0318     QScrollArea* scrollArea();
0319     TabScrollBar* scrollBar();
0320 
0321     void scrollByWheel(QWheelEvent* event);
0322 
0323     int scrollButtonsWidth() const;
0324     bool usesScrollButtons() const;
0325     void setUsesScrollButtons(bool useButtons);
0326 
0327     bool isOverflowed() const;
0328     int tabAt(const QPoint &pos) const;
0329 
0330 public Q_SLOTS:
0331     void ensureVisible(int index = -1, int xmargin = 132);
0332     void scrollToLeft(int n = 5, QEasingCurve::Type type = QEasingCurve::OutQuad);
0333     void scrollToRight(int n = 5, QEasingCurve::Type type = QEasingCurve::OutQuad);
0334     void scrollToLeftEdge();
0335     void scrollToRightEdge();
0336     void setUpLayout();
0337 
0338 private Q_SLOTS:
0339     void overFlowChanged(bool overflowed);
0340     void scrollStart();
0341     void updateScrollButtonsState();
0342 
0343 private:
0344     void mouseMoveEvent(QMouseEvent* event) override;
0345     void resizeEvent(QResizeEvent* event) override;
0346 
0347     QTabBar* m_tabBar;
0348     QScrollArea* m_scrollArea;
0349     TabScrollBar* m_scrollBar;
0350     ToolButton* m_rightScrollButton;
0351     ToolButton* m_leftScrollButton;
0352     bool m_usesScrollButtons;
0353     int m_totalVerticalDeltas;
0354 };
0355 
0356 // Class for close button on tabs
0357 // * taken from qtabbar.cpp
0358 class CloseButton : public QAbstractButton
0359 {
0360     Q_OBJECT
0361 
0362 public:
0363     CloseButton(QWidget *parent = nullptr);
0364 
0365     QSize sizeHint() const override;
0366 
0367     void enterEvent(QEnterEvent *event) override;
0368     void leaveEvent(QEvent *event) override;
0369     void paintEvent(QPaintEvent *event) override;
0370 };
0371 #endif // COMBOTABBAR_H