File indexing completed on 2024-05-12 16:40:06

0001 /* This file is part of the KDE project
0002    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
0003    Copyright (C) 2011-2013 Jarosław Staniek <staniek@kde.org>
0004 
0005    Based on qmenu_p.h from Qt 4.7
0006 
0007    based on oxygenhelper.h
0008 
0009    Copyright 2009-2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
0010    Copyright 2008 Long Huynh Huu <long.upcase@googlemail.com>
0011    Copyright 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
0012    Copyright 2007 C. Boemann <cbo@boemann.dk>
0013    Copyright 2007 Fredrik Höglund <fredrik@kde.org>
0014 
0015    This library is free software; you can redistribute it and/or
0016    modify it under the terms of the GNU Library General Public
0017    License as published by the Free Software Foundation; either
0018    version 2 of the License, or (at your option) any later version.
0019 
0020    This library is distributed in the hope that it will be useful,
0021    but WITHOUT ANY WARRANTY; without even the implied warranty of
0022    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0023    Library General Public License for more details.
0024 
0025    You should have received a copy of the GNU Library General Public License
0026    along with this library; see the file COPYING.LIB.  If not, write to
0027    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0028  * Boston, MA 02110-1301, USA.
0029 */
0030 
0031 #ifndef KEXIMENUWIDGET_P_H
0032 #define KEXIMENUWIDGET_P_H
0033 
0034 #include "KexiMenuWidget.h"
0035 
0036 #include <KSharedConfig>
0037 
0038 #include <QStyleOption>
0039 #include <QCache>
0040 #include <QMap>
0041 #include <QHash>
0042 #include <QBasicTimer>
0043 #include <QPointer>
0044 #include <QAbstractButton>
0045 
0046 class QEventLoop;
0047 
0048 //! Used to define transparent clickable logo area
0049 class ClickableLogoArea : public QAbstractButton
0050 {
0051     Q_OBJECT
0052 public:
0053     explicit ClickableLogoArea(QWidget *parent = 0);
0054 protected Q_SLOTS:
0055     void slotClicked();
0056 protected:
0057     virtual void paintEvent(QPaintEvent*) override;
0058 };
0059 
0060 //used to walk up the popup list
0061 struct KexiMenuWidgetCaused {
0062     QPointer<QWidget> widget;
0063     QPointer<QAction> action;
0064 };
0065 
0066 class OxygenHelper
0067 {
0068 public:
0069     OxygenHelper();
0070     virtual ~OxygenHelper();
0071     bool lowThreshold(const QColor &color);
0072     bool highThreshold(const QColor &color);
0073     virtual const QColor& backgroundTopColor(const QColor &color);
0074     virtual const QColor& backgroundBottomColor(const QColor &color);
0075     virtual const QColor& backgroundRadialColor(const QColor &color);
0076     virtual QPixmap verticalGradient(const QColor &color, int height, int offset = 0);
0077     virtual QPixmap radialGradient(const QColor &color, int width, int height = 64);
0078     void renderOxygenWindowBackground(QPainter *p, const QRect &clipRect,
0079                                          const QWidget *widget, const QWidget* window,
0080                                          const QColor& color, int y_shift=-23,
0081                                          int gradientHeight = 64);
0082 
0083     //!@name window background gradients
0084     //@{
0085     /*!
0086     \par y_shift: shift the background gradient upwards, to fit with the windec
0087     \par gradientHeight: the height of the generated gradient.
0088     for different heights, the gradient is translated so that it is always at the same position from the bottom
0089     */
0090     void renderWindowBackground(QPainter *p, const QRect &clipRect,
0091                                 const QWidget *widget, const QPalette & pal,
0092                                 int y_shift=-23, int gradientHeight = 64);
0093 
0094     void renderMenuBackground(QPainter* p, const QRect& clipRect, const QWidget* widget,
0095                               const QPalette& pal);
0096     void renderMenuBackground(QPainter*, const QRect&, const QWidget*, const QColor&);
0097 
0098     //! draw frame that mimics some sort of shadows around a panel
0099     /*! it is used for menus, detached dock panels and toolbar,
0100         as well as window decoration when compositing is disabled */
0101 //     virtual void drawFloatFrame(
0102 //         QPainter *p, const QRect r, const QColor &color,
0103 //         bool drawUglyShadow=true, bool isActive=false,
0104 //         const QColor &frameColor=QColor(),
0105 //         TileSet::Tiles tiles = TileSet::Ring
0106 //     );
0107 
0108     typedef QCache<quint64, QPixmap> PixmapCache;
0109     typedef QCache<quint64, QColor> ColorCache;
0110     typedef QMap<quint32, bool> ColorMap;
0111 
0112     PixmapCache m_backgroundCache;
0113     ColorCache m_backgroundTopColorCache;
0114     ColorCache m_backgroundBottomColorCache;
0115     ColorCache m_backgroundRadialColorCache;
0116     ColorMap m_lowThreshold;
0117     ColorMap m_highThreshold;
0118 
0119     KSharedConfigPtr _config;
0120     qreal _contrast;
0121     qreal _bgcontrast;
0122 };
0123 
0124 class KexiMenuWidgetPrivate // : public QWidgetPrivate
0125 {
0126 public:
0127     explicit KexiMenuWidgetPrivate(KexiMenuWidget *menu) : q(menu), itemsDirty(0), maxIconWidth(0), tabWidth(0), ncols(0),
0128                       collapsibleSeparators(true), activationRecursionGuard(false), hasHadMouse(0), aboutToHide(0), motions(0),
0129                       currentAction(0),
0130                       scroll(0), eventLoop(0), /*tearoff(0),*/ /*tornoff(0),*/ /*tearoffHighlighted(0),*/
0131                       hasCheckableItems(0), sloppyAction(0), /* doChildEffects(false)*/
0132                       hasFrame(true), clickableLogoArea(0)
0133     {
0134     }
0135     virtual ~KexiMenuWidgetPrivate()
0136     {
0137         delete scroll;
0138 //! @todo KEXI3 port OxygenHelper
0139 #if 0
0140         delete oxygenHelper;
0141 #endif
0142     }
0143     void init();
0144 
0145     //static KexiMenuWidgetPrivate *get(KexiMenuWidgetPrivate *m) { return m->d_func(); }
0146     int scrollerHeight() const;
0147 
0148     KexiMenuWidget *q;
0149 
0150     //item calculations
0151     mutable int itemsDirty;
0152     mutable int maxIconWidth, tabWidth;
0153     QRect actionRect(QAction *) const;
0154 
0155     mutable QVector<QRect> actionRects;
0156     mutable QHash<QAction *, QWidget *> widgetItems;
0157     void updateActionRects() const;
0158     QRect popupGeometry(const QWidget *widget) const;
0159     QRect popupGeometry(int screen = -1) const;
0160     mutable int ncols : 4; //4 bits is probably plenty
0161     bool collapsibleSeparators;
0162 
0163     bool activationRecursionGuard;
0164 
0165     //selection
0166     static KexiMenuWidget *mouseDown;
0167     QPoint mousePopupPos;
0168     int hasHadMouse;
0169     int aboutToHide;
0170     int motions;
0171     QAction *currentAction;
0172     QBasicTimer menuDelayTimer;
0173     QWidget *topCausedWidget() const;
0174     QAction *actionAt(QPoint p) const;
0175     void setFirstActionActive();
0176     void setCurrentAction(QAction *, int popup = -1, KexiMenuWidget::SelectionReason reason = KexiMenuWidget::SelectedFromElsewhere, bool activateFirst = false);
0177     //void popupAction(QAction *, int, bool);
0178     void setSyncAction();
0179 
0180     //scrolling support
0181     struct QMenuScroller {
0182         enum ScrollLocation { ScrollStay, ScrollBottom, ScrollTop, ScrollCenter };
0183         enum ScrollDirection { ScrollNone=0, ScrollUp=0x01, ScrollDown=0x02 };
0184         uint scrollFlags : 2, scrollDirection : 2;
0185         int scrollOffset;
0186         QBasicTimer scrollTimer;
0187 
0188         QMenuScroller() : scrollFlags(ScrollNone), scrollDirection(ScrollNone), scrollOffset(0) { }
0189         ~QMenuScroller() { }
0190     } *scroll;
0191     void scrollMenu(QMenuScroller::ScrollLocation location, bool active=false);
0192     void scrollMenu(QMenuScroller::ScrollDirection direction, bool page=false, bool active=false);
0193     void scrollMenu(QAction *action, QMenuScroller::ScrollLocation location, bool active=false);
0194 
0195     //synchronous operation (ie exec())
0196     QEventLoop *eventLoop;
0197     QPointer<QAction> syncAction;
0198 
0199     //search buffer
0200     QString searchBuffer;
0201     QBasicTimer searchBufferTimer;
0202 
0203     //passing of mouse events up the parent hierarchy
0204     QPointer<KexiMenuWidget> activeMenu;
0205     bool mouseEventTaken(QMouseEvent *);
0206 
0207     virtual QList<QPointer<QWidget> > calcCausedStack() const;
0208     KexiMenuWidgetCaused causedPopup;
0209     void hideUpToMenuBar();
0210     void hideMenu(KexiMenuWidget *menu, bool justRegister = false);
0211 
0212     //index mappings
0213     inline QAction *actionAt(int i) const { return q->actions().at(i); }
0214     inline int indexOf(QAction *act) const { return q->actions().indexOf(act); }
0215 
0216     //tear off support
0217 //     uint tearoff : 1, tornoff : 1, tearoffHighlighted : 1;
0218 //    QPointer<QTornOffMenu> tornPopup;
0219 
0220     mutable bool hasCheckableItems;
0221 
0222     //sloppy selection
0223     static int sloppyDelayTimer;
0224     mutable QAction *sloppyAction;
0225     QRegion sloppyRegion;
0226 
0227     //default action
0228     QPointer<QAction> defaultAction;
0229 
0230     QAction *menuAction;
0231     QAction *defaultMenuAction;
0232 
0233     void setOverrideMenuAction(QAction *);
0234     void overrideMenuActionDestroyed();
0235 
0236     //firing of events
0237     void activateAction(QAction *, QAction::ActionEvent, bool self=true);
0238     void activateCausedStack(const QList<QPointer<QWidget> > &, QAction *, QAction::ActionEvent, bool);
0239 
0240     void actionTriggered();
0241     void actionHovered();
0242 
0243     bool hasMouseMoved(const QPoint &globalPos);
0244 
0245     void setLayoutDirection_helper(Qt::LayoutDirection direction);
0246 
0247     void updateLayoutDirection();
0248 
0249     void setLayoutDirection_helper(QWidget* w, Qt::LayoutDirection direction);
0250 
0251     int frameWidth(const QStyleOption* opt = 0) const;
0252 
0253     bool actionPersistentlySelected(const QAction* action) const;
0254 
0255     void setActionPersistentlySelected(QAction* action, bool set);
0256 
0257     void toggleActionPersistentlySelected(QAction* action);
0258 
0259     //menu fading/scrolling effects
0260     //bool doChildEffects;
0261 
0262     QPointer<QAction> actionAboutToTrigger;
0263     QPointer<QWidget> noReplayFor;
0264     //! Frame visibility
0265     bool hasFrame;
0266 
0267     QPointer<KexiMenuWidgetAction> previousPersistentlySelectedAction;
0268 
0269     //! True if persistent selections are enabled. False by default.
0270     //bool persistentSelectionsEnabled;
0271 
0272 //! @todo KEXI3 port OxygenHelper
0273 #if 0
0274     OxygenHelper *oxygenHelper;
0275 #endif
0276     bool bespin;
0277     bool qtcurve;
0278 
0279     //! @return y coordinate of bottom margin of last menu item
0280     int bottomOfLastItem() const;
0281     int logoBottomMargin() const;
0282     void updateLogo();
0283     void updateLogoPixmap();
0284     QPixmap calligraLogoPixmap;
0285     ClickableLogoArea *clickableLogoArea;
0286     QWidget *socialWidget;
0287     QFont smallTextFont;
0288 };
0289 
0290 #endif // KEXIMENUWIDGET_P_H