1 /* This file is part of the KDE project
2    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
3    Copyright (C) 2011-2013 Jarosław Staniek <staniek@kde.org>
4 
5    Based on qmenu_p.h from Qt 4.7
6 
7    based on oxygenhelper.h
8 
9    Copyright 2009-2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
10    Copyright 2008 Long Huynh Huu <long.upcase@googlemail.com>
11    Copyright 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
12    Copyright 2007 C. Boemann <cbo@boemann.dk>
13    Copyright 2007 Fredrik Höglund <fredrik@kde.org>
14 
15    This library is free software; you can redistribute it and/or
16    modify it under the terms of the GNU Library General Public
17    License as published by the Free Software Foundation; either
18    version 2 of the License, or (at your option) any later version.
19 
20    This library is distributed in the hope that it will be useful,
21    but WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23    Library General Public License for more details.
24 
25    You should have received a copy of the GNU Library General Public License
26    along with this library; see the file COPYING.LIB.  If not, write to
27    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28  * Boston, MA 02110-1301, USA.
29 */
30 
31 #ifndef KEXIMENUWIDGET_P_H
32 #define KEXIMENUWIDGET_P_H
33 
34 #include "KexiMenuWidget.h"
35 
36 #include <KSharedConfig>
37 
38 #include <QStyleOption>
39 #include <QCache>
40 #include <QMap>
41 #include <QHash>
42 #include <QBasicTimer>
43 #include <QPointer>
44 #include <QAbstractButton>
45 
46 class QEventLoop;
47 
48 //! Used to define transparent clickable logo area
49 class ClickableLogoArea : public QAbstractButton
50 {
51     Q_OBJECT
52 public:
53     explicit ClickableLogoArea(QWidget *parent = 0);
54 protected Q_SLOTS:
55     void slotClicked();
56 protected:
57     virtual void paintEvent(QPaintEvent*);
58 };
59 
60 //used to walk up the popup list
61 struct KexiMenuWidgetCaused {
62     QPointer<QWidget> widget;
63     QPointer<QAction> action;
64 };
65 
66 class OxygenHelper
67 {
68 public:
69     OxygenHelper();
70     virtual ~OxygenHelper();
71     bool lowThreshold(const QColor &color);
72     bool highThreshold(const QColor &color);
73     virtual const QColor& backgroundTopColor(const QColor &color);
74     virtual const QColor& backgroundBottomColor(const QColor &color);
75     virtual const QColor& backgroundRadialColor(const QColor &color);
76     virtual QPixmap verticalGradient(const QColor &color, int height, int offset = 0);
77     virtual QPixmap radialGradient(const QColor &color, int width, int height = 64);
78     void renderOxygenWindowBackground(QPainter *p, const QRect &clipRect,
79                                          const QWidget *widget, const QWidget* window,
80                                          const QColor& color, int y_shift=-23,
81                                          int gradientHeight = 64);
82 
83     //!@name window background gradients
84     //@{
85     /*!
86     \par y_shift: shift the background gradient upwards, to fit with the windec
87     \par gradientHeight: the height of the generated gradient.
88     for different heights, the gradient is translated so that it is always at the same position from the bottom
89     */
90     void renderWindowBackground(QPainter *p, const QRect &clipRect,
91                                 const QWidget *widget, const QPalette & pal,
92                                 int y_shift=-23, int gradientHeight = 64);
93 
94     void renderMenuBackground(QPainter* p, const QRect& clipRect, const QWidget* widget,
95                               const QPalette& pal);
96     void renderMenuBackground(QPainter*, const QRect&, const QWidget*, const QColor&);
97 
98     //! draw frame that mimics some sort of shadows around a panel
99     /*! it is used for menus, detached dock panels and toolbar,
100         as well as window decoration when compositing is disabled */
101 //     virtual void drawFloatFrame(
102 //         QPainter *p, const QRect r, const QColor &color,
103 //         bool drawUglyShadow=true, bool isActive=false,
104 //         const QColor &frameColor=QColor(),
105 //         TileSet::Tiles tiles = TileSet::Ring
106 //     );
107 
108     typedef QCache<quint64, QPixmap> PixmapCache;
109     typedef QCache<quint64, QColor> ColorCache;
110     typedef QMap<quint32, bool> ColorMap;
111 
112     PixmapCache m_backgroundCache;
113     ColorCache m_backgroundTopColorCache;
114     ColorCache m_backgroundBottomColorCache;
115     ColorCache m_backgroundRadialColorCache;
116     ColorMap m_lowThreshold;
117     ColorMap m_highThreshold;
118 
119     KSharedConfigPtr _config;
120     qreal _contrast;
121     qreal _bgcontrast;
122 };
123 
124 class KexiMenuWidgetPrivate // : public QWidgetPrivate
125 {
126 public:
KexiMenuWidgetPrivate(KexiMenuWidget * menu)127     explicit KexiMenuWidgetPrivate(KexiMenuWidget *menu) : q(menu), itemsDirty(0), maxIconWidth(0), tabWidth(0), ncols(0),
128                       collapsibleSeparators(true), activationRecursionGuard(false), hasHadMouse(0), aboutToHide(0), motions(0),
129                       currentAction(0),
130                       scroll(0), eventLoop(0), /*tearoff(0),*/ /*tornoff(0),*/ /*tearoffHighlighted(0),*/
131                       hasCheckableItems(0), sloppyAction(0), /* doChildEffects(false)*/
132                       hasFrame(true), clickableLogoArea(0)
133     {
134     }
~KexiMenuWidgetPrivate()135     virtual ~KexiMenuWidgetPrivate()
136     {
137         delete scroll;
138 //! @todo KEXI3 port OxygenHelper
139 #if 0
140         delete oxygenHelper;
141 #endif
142     }
143     void init();
144 
145     //static KexiMenuWidgetPrivate *get(KexiMenuWidgetPrivate *m) { return m->d_func(); }
146     int scrollerHeight() const;
147 
148     KexiMenuWidget *q;
149 
150     //item calculations
151     mutable int itemsDirty;
152     mutable int maxIconWidth, tabWidth;
153     QRect actionRect(QAction *) const;
154 
155     mutable QVector<QRect> actionRects;
156     mutable QHash<QAction *, QWidget *> widgetItems;
157     void updateActionRects() const;
158     QRect popupGeometry(const QWidget *widget) const;
159     QRect popupGeometry(int screen = -1) const;
160     mutable int ncols : 4; //4 bits is probably plenty
161     bool collapsibleSeparators;
162 
163     bool activationRecursionGuard;
164 
165     //selection
166     static KexiMenuWidget *mouseDown;
167     QPoint mousePopupPos;
168     int hasHadMouse;
169     int aboutToHide;
170     int motions;
171     QAction *currentAction;
172     QBasicTimer menuDelayTimer;
173     QWidget *topCausedWidget() const;
174     QAction *actionAt(QPoint p) const;
175     void setFirstActionActive();
176     void setCurrentAction(QAction *, int popup = -1, KexiMenuWidget::SelectionReason reason = KexiMenuWidget::SelectedFromElsewhere, bool activateFirst = false);
177     //void popupAction(QAction *, int, bool);
178     void setSyncAction();
179 
180     //scrolling support
181     struct QMenuScroller {
182         enum ScrollLocation { ScrollStay, ScrollBottom, ScrollTop, ScrollCenter };
183         enum ScrollDirection { ScrollNone=0, ScrollUp=0x01, ScrollDown=0x02 };
184         uint scrollFlags : 2, scrollDirection : 2;
185         int scrollOffset;
186         QBasicTimer scrollTimer;
187 
QMenuScrollerQMenuScroller188         QMenuScroller() : scrollFlags(ScrollNone), scrollDirection(ScrollNone), scrollOffset(0) { }
~QMenuScrollerQMenuScroller189         ~QMenuScroller() { }
190     } *scroll;
191     void scrollMenu(QMenuScroller::ScrollLocation location, bool active=false);
192     void scrollMenu(QMenuScroller::ScrollDirection direction, bool page=false, bool active=false);
193     void scrollMenu(QAction *action, QMenuScroller::ScrollLocation location, bool active=false);
194 
195     //synchronous operation (ie exec())
196     QEventLoop *eventLoop;
197     QPointer<QAction> syncAction;
198 
199     //search buffer
200     QString searchBuffer;
201     QBasicTimer searchBufferTimer;
202 
203     //passing of mouse events up the parent hierarchy
204     QPointer<KexiMenuWidget> activeMenu;
205     bool mouseEventTaken(QMouseEvent *);
206 
207     virtual QList<QPointer<QWidget> > calcCausedStack() const;
208     KexiMenuWidgetCaused causedPopup;
209     void hideUpToMenuBar();
210     void hideMenu(KexiMenuWidget *menu, bool justRegister = false);
211 
212     //index mappings
actionAt(int i)213     inline QAction *actionAt(int i) const { return q->actions().at(i); }
indexOf(QAction * act)214     inline int indexOf(QAction *act) const { return q->actions().indexOf(act); }
215 
216     //tear off support
217 //     uint tearoff : 1, tornoff : 1, tearoffHighlighted : 1;
218 //    QPointer<QTornOffMenu> tornPopup;
219 
220     mutable bool hasCheckableItems;
221 
222     //sloppy selection
223     static int sloppyDelayTimer;
224     mutable QAction *sloppyAction;
225     QRegion sloppyRegion;
226 
227     //default action
228     QPointer<QAction> defaultAction;
229 
230     QAction *menuAction;
231     QAction *defaultMenuAction;
232 
233     void setOverrideMenuAction(QAction *);
234     void overrideMenuActionDestroyed();
235 
236     //firing of events
237     void activateAction(QAction *, QAction::ActionEvent, bool self=true);
238     void activateCausedStack(const QList<QPointer<QWidget> > &, QAction *, QAction::ActionEvent, bool);
239 
240     void actionTriggered();
241     void actionHovered();
242 
243     bool hasMouseMoved(const QPoint &globalPos);
244 
245     void setLayoutDirection_helper(Qt::LayoutDirection direction);
246 
247     void updateLayoutDirection();
248 
249     void setLayoutDirection_helper(QWidget* w, Qt::LayoutDirection direction);
250 
251     int frameWidth(const QStyleOption* opt = 0) const;
252 
253     bool actionPersistentlySelected(const QAction* action) const;
254 
255     void setActionPersistentlySelected(QAction* action, bool set);
256 
257     void toggleActionPersistentlySelected(QAction* action);
258 
259     //menu fading/scrolling effects
260     //bool doChildEffects;
261 
262     QPointer<QAction> actionAboutToTrigger;
263     QPointer<QWidget> noReplayFor;
264     //! Frame visibility
265     bool hasFrame;
266 
267     QPointer<KexiMenuWidgetAction> previousPersistentlySelectedAction;
268 
269     //! True if persistent selections are enabled. False by default.
270     //bool persistentSelectionsEnabled;
271 
272 //! @todo KEXI3 port OxygenHelper
273 #if 0
274     OxygenHelper *oxygenHelper;
275 #endif
276     bool bespin;
277     bool qtcurve;
278 
279     //! @return y coordinate of bottom margin of last menu item
280     int bottomOfLastItem() const;
281     int logoBottomMargin() const;
282     void updateLogo();
283     void updateLogoPixmap();
284     QPixmap calligraLogoPixmap;
285     ClickableLogoArea *clickableLogoArea;
286     QWidget *socialWidget;
287     QFont smallTextFont;
288 };
289 
290 #endif // KEXIMENUWIDGET_P_H
291