1 /*****************************************************************************
2  *   Copyright 2007 - 2010 Craig Drummond <craig.p.drummond@gmail.com>       *
3  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
4  *                                                                           *
5  *   This program is free software; you can redistribute it and/or modify    *
6  *   it under the terms of the GNU Lesser General Public License as          *
7  *   published by the Free Software Foundation; either version 2.1 of the    *
8  *   License, or (at your option) version 3, or any later version accepted   *
9  *   by the membership of KDE e.V. (or its successor approved by the         *
10  *   membership of KDE e.V.), which shall act as a proxy defined in          *
11  *   Section 6 of version 3 of the license.                                  *
12  *                                                                           *
13  *   This program is distributed in the hope that it will be useful,         *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
16  *   Lesser General Public License for more details.                         *
17  *                                                                           *
18  *   You should have received a copy of the GNU Lesser General Public        *
19  *   License along with this library. If not,                                *
20  *   see <http://www.gnu.org/licenses/>.                                     *
21  *****************************************************************************/
22 /*
23   based on the window decoration "Plastik":
24   Copyright (C) 2003-2005 Sandro Giessl <sandro@giessl.com>
25 
26   based on the window decoration "Web":
27   Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
28 */
29 
30 #include "qtcurvebutton.h"
31 #include <QAbstractButton>
32 #include <QStyle>
33 #include <QStyleOption>
34 #include <QBitmap>
35 #include <QPainter>
36 #include <QPixmap>
37 #include <QTimer>
38 #include "qtcurveclient.h"
39 #include <common/common.h>
40 
41 namespace QtCurve {
42 namespace KWin {
43 
QtCurveButton(ButtonType type,QtCurveClient * parent)44 QtCurveButton::QtCurveButton(ButtonType type, QtCurveClient *parent)
45     : KCommonDecorationButton(type, parent),
46       m_client(parent),
47       m_iconType(NumButtonIcons),
48       m_hover(false)
49 {
50     // setAttribute(Qt::WA_PaintOnScreen, false);
51     setAttribute(Qt::WA_NoSystemBackground, true);
52     setAutoFillBackground(false);
53     // setFocusPolicy(Qt::NoFocus);
54     // setAttribute(Qt::WA_OpaquePaintEvent, false);
55     // setAttribute(Qt::WA_Hover, true);
56     setCursor(Qt::ArrowCursor);
57     reset(DecorationReset);
58 }
59 
reset(unsigned long changed)60 void QtCurveButton::reset(unsigned long changed)
61 {
62     if (changed & DecorationReset || changed & ManualReset ||
63         changed & SizeChange || changed & StateChange) {
64         switch (type()) {
65 #if KDE_IS_VERSION(4, 9, 85)
66         case AppMenuButton:
67             m_iconType = MenuIcon;
68             break;
69 #endif
70             // TODO ItemMenuButton?
71         case ItemCloseButton:
72             m_iconType = CloseTabIcon;
73             break;
74         case CloseButton:
75             m_iconType = CloseIcon;
76             break;
77         case HelpButton:
78             m_iconType = HelpIcon;
79             break;
80         case MinButton:
81             m_iconType = MinIcon;
82             break;
83         case MaxButton:
84             m_iconType = isChecked() ? MaxRestoreIcon : MaxIcon;
85             break;
86         case OnAllDesktopsButton:
87             m_iconType = isChecked() ? NotOnAllDesktopsIcon : OnAllDesktopsIcon;
88             break;
89         case ShadeButton:
90             m_iconType = isChecked() ? UnShadeIcon : ShadeIcon;
91             break;
92         case AboveButton:
93             m_iconType = isChecked() ? NoKeepAboveIcon : KeepAboveIcon;
94             break;
95         case BelowButton:
96             m_iconType = isChecked() ? NoKeepBelowIcon : KeepBelowIcon;
97             break;
98         case MenuButton:
99             m_iconType = MenuIcon;
100             break;
101         default:
102             m_iconType = NumButtonIcons; // empty...
103             break;
104         }
105 
106         this->update();
107     }
108 }
109 
enterEvent(QEvent * e)110 void QtCurveButton::enterEvent(QEvent *e)
111 {
112     m_hover = true;
113     KCommonDecorationButton::enterEvent(e);
114     update();
115     // Hacky NVIDIA fix - sometimes mouseover state gets 'stuck' -
116     // but only for some windows!!!
117     QTimer::singleShot(50, this, SLOT(update()));
118 }
119 
leaveEvent(QEvent * e)120 void QtCurveButton::leaveEvent(QEvent *e)
121 {
122     m_hover = false;
123     KCommonDecorationButton::leaveEvent(e);
124     update();
125     // Hacky NVIDIA fix - sometimes mouseover state gets 'stuck' -
126     // but only for some windows!!!
127     QTimer::singleShot(50, this, SLOT(update()));
128 }
129 
paintEvent(QPaintEvent * ev)130 void QtCurveButton::paintEvent(QPaintEvent *ev)
131 {
132     if (m_client->compositingActive()) {
133         QPainter p(this);
134         p.setClipRect(rect().intersected(ev->rect()));
135         drawButton(&p);
136     } else {
137         QPixmap pixmap(size());
138         {
139             QPainter p(&pixmap);
140             p.setRenderHints(QPainter::Antialiasing);
141             parentWidget()->render(&p, QPoint(), geometry(),
142                                    QWidget::DrawWindowBackground);
143             drawButton(&p);
144         }
145         QPainter p(this);
146         p.setClipRect(ev->rect());
147         p.drawPixmap(QPoint(), pixmap);
148     }
149 }
150 
drawButton(QPainter * painter)151 void QtCurveButton::drawButton(QPainter *painter)
152 {
153     int flags = Handler()->wStyle()->pixelMetric(
154         (QStyle::PixelMetric)QtC_TitleBarButtons, 0L, 0L);
155     bool active(m_client->isActive());
156 
157     if (!active && !m_hover && flags & TITLEBAR_BUTTOM_HIDE_ON_INACTIVE_WINDOW)
158         return;
159 
160     QRect r(0, 0, width(), height());
161     int versionHack = 0;
162     bool sunken(isDown());
163     bool drawFrame(!(flags & TITLEBAR_BUTTON_NO_FRAME) &&
164                    (m_hover || sunken ||
165                     !(flags & TITLEBAR_BUTTON_HOVER_FRAME)));
166     bool drewFrame(false);
167     bool iconForMenu(TITLEBAR_ICON_MENU_BUTTON ==
168                      Handler()->wStyle()->pixelMetric(
169                          (QStyle::PixelMetric)QtC_TitleBarIcon, 0L, 0L));
170     QColor buttonColor(KDecoration::options()->color(KDecoration::ColorTitleBar,
171                                                      active));
172     QPixmap buffer(width(), height());
173     buffer.fill(Qt::transparent);
174     QPainter bP(&buffer);
175     bool isTabClose(ItemCloseButton == type());
176 
177     // isItemMenu?
178     if (isTabClose && drawFrame && !(sunken || m_hover))
179         drawFrame = false;
180     // if(CloseButton == type())
181     //     buttonColor = midColor(QColor(180,64,32), buttonColor);
182 
183     switch (type()) {
184     case HelpButton:
185         versionHack = TBAR_VERSION_HACK + TITLEBAR_HELP;
186         break;
187     case MaxButton:
188         versionHack = TBAR_VERSION_HACK + TITLEBAR_MAX;
189         break;
190     case MinButton:
191         versionHack = TBAR_VERSION_HACK + TITLEBAR_MIN;
192         break;
193     case ItemCloseButton:
194     case CloseButton:
195         versionHack = TBAR_VERSION_HACK + TITLEBAR_CLOSE;
196         break;
197 #if KDE_IS_VERSION(4, 9, 85)
198     case AppMenuButton:
199 #endif
200     case MenuButton:
201         versionHack = TBAR_VERSION_HACK + TITLEBAR_MENU;
202         break;
203     case OnAllDesktopsButton:
204         versionHack = TBAR_VERSION_HACK + TITLEBAR_ALL_DESKTOPS;
205         break;
206     case AboveButton:
207         versionHack = TBAR_VERSION_HACK + TITLEBAR_KEEP_ABOVE;
208         break;
209     case BelowButton:
210         versionHack = TBAR_VERSION_HACK + TITLEBAR_KEEP_BELOW;
211         break;
212     case ShadeButton:
213         versionHack = TBAR_VERSION_HACK + TITLEBAR_SHADE;
214     default:
215         break;
216     }
217 
218     if (drawFrame &&
219         (/*!(flags&TITLEBAR_BUTTON_ROUND) || */
220             MenuButton != type() || !iconForMenu)) {
221         QStyleOption opt;
222         int offset = flags & TITLEBAR_BUTTON_ROUND &&
223             !m_client->isToolWindow() ? 1 : 0;
224 
225         if (flags & TITLEBAR_BUTTON_SUNKEN_BACKGROUND)
226             // && flags & TITLEBAR_BUTTON_ROUND)
227             offset++;
228         opt.init(this);
229         opt.rect = QRect(offset, offset, width() - (2 * offset),
230                          height() - (2 * offset));
231         opt.state |= (isDown() ? QStyle::State_Sunken : QStyle::State_Raised) |
232             (active ? QStyle::State_Active : QStyle::State_None) |
233             (m_hover ? QStyle::State_MouseOver : QStyle::State_None) |
234             QStyle::State_Horizontal | QtC_StateKWin;
235         opt.state &= ~QStyle::State_HasFocus;
236         if (!isEnabled()) {
237             opt.palette.setColor(QPalette::Button, buttonColor);
238         } else {
239             if (!(flags & TITLEBAR_BUTTON_STD_COLOR) ||
240                 (flags & TITLEBAR_BUTTON_COLOR_MOUSE_OVER && !m_hover &&
241                  !(flags&TITLEBAR_BUTTON_COLOR)))
242                 opt.palette.setColor(QPalette::Button, buttonColor);
243             if (flags & TITLEBAR_BUTTON_COLOR &&
244                 !(flags & TITLEBAR_BUTTON_COLOR_SYMBOL))
245                 opt.version = versionHack;
246         }
247         Handler()->wStyle()->drawPrimitive(QStyle::PE_PanelButtonCommand,
248                                            &opt, &bP, 0L);
249         drewFrame = true;
250     }
251 
252     if (MenuButton == type() && iconForMenu) {
253         QPixmap menuIcon(m_client->icon().pixmap(
254                              style()->pixelMetric(QStyle::PM_SmallIconSize)));
255         if (width() < menuIcon.width() || height() < menuIcon.height())
256             menuIcon = menuIcon.scaled(width(), height());
257 
258         int dX(((width() - menuIcon.width()) / 2.0) + 0.5),
259                       dY(((height() - menuIcon.height()) / 2.0) + 0.5);
260 
261         if (sunken) {
262             dY++;
263             dX++;
264         }
265         bP.drawPixmap(dX, dY, menuIcon);
266     } else if (isEnabled() && (!(flags & TITLEBAR_BUTTON_HOVER_SYMBOL_FULL) ||
267                                sunken || m_hover)) {
268         const QBitmap &icon =
269             Handler()->buttonBitmap(m_iconType, size(),
270                                     decoration()->isToolWindow());
271         bool customCol(false);
272         bool faded(!m_hover && flags & TITLEBAR_BUTTON_HOVER_SYMBOL);
273         QColor col(KDecoration::options()->color(KDecoration::ColorFont, active/* || faded*/));
274         int dX(r.x()+(r.width() - icon.width())/2);
275         int dY(r.y()+(r.height() - icon.height())/2);
276         EEffect effect((EEffect)(style()->pixelMetric((QStyle::PixelMetric)QtC_TitleBarEffect)));
277 
278         if(EFFECT_ETCH==effect && drewFrame)
279             effect=EFFECT_SHADOW;
280 
281         if(m_hover || !(flags&TITLEBAR_BUTTON_HOVER_SYMBOL))
282         {
283             bool userDefined=flags&TITLEBAR_BUTTON_ICON_COLOR;
284 
285             if(userDefined || (flags&TITLEBAR_BUTTON_COLOR && flags&TITLEBAR_BUTTON_COLOR_SYMBOL))
286             {
287                 QStyleOption opt;
288 
289                 opt.init(this);
290                 if(userDefined)
291                 {
292                     versionHack+=NUM_TITLEBAR_BUTTONS;
293                     if(!active)
294                         versionHack+=NUM_TITLEBAR_BUTTONS;
295                 }
296                 opt.version=versionHack;
297                 col=QColor(QRgb(Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_TitleBarIconColor, &opt, 0L)));
298                 customCol=true;
299             }
300         }
301 
302         if (sunken) {
303             dY++;
304             dX++;
305         } else if (!faded && EFFECT_NONE != effect) {
306             QColor shadow(WINDOW_SHADOW_COLOR(effect));
307 
308             shadow.setAlphaF(WINDOW_TEXT_SHADOW_ALPHA(effect));
309             bP.setPen(shadow);
310             bP.drawPixmap(EFFECT_SHADOW==effect ? dX+1 : dX, dY+1, icon);
311         }
312 
313         if (m_hover && !sunken && !(flags&TITLEBAR_BUTTON_COLOR) && !customCol) {
314             if (CloseButton == type() || isTabClose) {
315                 col = CLOSE_COLOR;
316             } else if(flags&TITLEBAR_BUTTON_USE_HOVER_COLOR) {
317                 col = Handler()->hoverCol(active);
318             }
319         }
320 
321         if (faded) {
322             col.setAlphaF(HOVER_BUTTON_ALPHA(col));
323         } else {
324             // If dont set an alpha level here, then (at least on intel)
325             // the background colour is used!
326             col.setAlpha(254);
327         }
328 
329         bP.setPen(col);
330         bP.drawPixmap(dX, dY, icon);
331     }
332 
333     bP.end();
334     painter->drawPixmap(0, 0, buffer);
335 }
336 
icon(ButtonIcon icon,int size,QStyle * style)337 QBitmap IconEngine::icon(ButtonIcon icon, int size, QStyle *style)
338 {
339     if (size%2 == 0)
340         --size;
341 
342     QBitmap bitmap(size, size);
343     bitmap.fill(Qt::color0);
344     QPainter p(&bitmap);
345 
346     p.setPen(Qt::color1);
347 
348     QRect r = bitmap.rect();
349 
350     // line widths
351     int lwTitleBar = 1;
352     if (r.width() > 16)
353         lwTitleBar = 4;
354     else if (r.width() > 4)
355         lwTitleBar = 2;
356 
357     switch (icon) {
358     case CloseTabIcon:
359         r.adjust(1, 1, -1, -1);
360     case CloseIcon: {
361         int lineWidth = 1;
362         if (r.width() > 16) {
363             lineWidth = 3;
364         } else if (r.width() > 4) {
365             lineWidth = 2;
366         }
367 
368         drawObject(p, DiagonalLine, r.x(), r.y(), r.width(), lineWidth);
369         drawObject(p, CrossDiagonalLine, r.x(), r.bottom(),
370                    r.width(), lineWidth);
371         break;
372     }
373     case MaxIcon:
374         if (Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_TitleBarButtons, 0L, 0L) & TITLEBAR_BUTTOM_ARROW_MIN_MAX) {
375             QStyleOption opt;
376             opt.rect = r;
377             opt.state = QStyle::State_Enabled | QtC_StateKWin;
378             style->drawPrimitive(QStyle::PE_IndicatorArrowUp, &opt, &p, 0L);
379         } else {
380             int lineWidth2 = 1; // frame
381             if (r.width() > 16) {
382                 lineWidth2 = 2;
383             } else if (r.width() > 4) {
384                 lineWidth2 = 1;
385             }
386             drawObject(p, HorizontalLine, r.x(), r.top(),
387                        r.width(), lwTitleBar);
388             drawObject(p, HorizontalLine, r.x(), r.bottom() - (lineWidth2 - 1),
389                        r.width(), lineWidth2);
390             drawObject(p, VerticalLine, r.x(), r.top(), r.height(), lineWidth2);
391             drawObject(p, VerticalLine, r.right() - (lineWidth2 - 1),
392                        r.top(), r.height(), lineWidth2);
393         }
394         break;
395     case MaxRestoreIcon:
396         if (Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_TitleBarButtons, 0L, 0L) & TITLEBAR_BUTTOM_ARROW_MIN_MAX) {
397             p.drawLine(r.x() + 1, r.y(), r.x() + r.width() - 2, r.y());
398             p.drawLine(r.x() + 1, r.y() + r.height() - 1,
399                        r.x() + r.width() - 2, r.y() + r.height() - 1);
400             p.drawLine(r.x(), r.y() + 1, r.x(), r.y() + r.height() - 2);
401             p.drawLine(r.x() + r.width() - 1, r.y() + 1,
402                        r.x() + r.width() - 1, r.y() + r.height() - 2);
403             p.drawRect(r.x() + 1, r.y() + 1, r.width() - 3, r.height() - 3);
404         } else {
405             int lineWidth2 = 1; // frame
406             if (r.width() > 16) {
407                 lineWidth2 = 2;
408             } else if (r.width() > 4) {
409                 lineWidth2 = 1;
410             }
411             int margin1, margin2;
412             margin1 = margin2 = lineWidth2 * 2 + 1;
413             if (r.width() < 8)
414                 margin1 = 1;
415             int margin1h = margin1 - 1;
416             int margin2h = margin2 - 1;
417 
418             // background window
419             drawObject(p, HorizontalLine, r.x() + margin1h, r.top(),
420                        r.width() - margin1, lwTitleBar);
421             drawObject(p, HorizontalLine, r.right() - margin2h,
422                        r.bottom() - (lineWidth2 - 1) - margin1, margin2h,
423                        lineWidth2);
424             drawObject(p, VerticalLine, r.x() + margin1h, r.top(), margin2,
425                        lineWidth2);
426             drawObject(p, VerticalLine, r.right() - (lineWidth2 - 1),
427                        r.top(), r.height() - margin1, lineWidth2);
428 
429             // foreground window
430             drawObject(p, HorizontalLine, r.x(), r.top() + margin2,
431                        r.width() - margin2h, lwTitleBar);
432             drawObject(p, HorizontalLine, r.x(),
433                        r.bottom() - (lineWidth2 - 1), r.width() - margin2h,
434                        lineWidth2);
435             drawObject(p, VerticalLine, r.x(), r.top() + margin2, r.height(),
436                        lineWidth2);
437             drawObject(p, VerticalLine, r.right() - (lineWidth2 - 1) - margin2h,
438                        r.top() + margin2, r.height(), lineWidth2);
439         }
440         break;
441     case MinIcon:
442         if (Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_TitleBarButtons, 0L, 0L)&TITLEBAR_BUTTOM_ARROW_MIN_MAX) {
443             QStyleOption opt;
444 
445             opt.rect = r;
446             opt.state = QStyle::State_Enabled | QtC_StateKWin;
447             style->drawPrimitive(QStyle::PE_IndicatorArrowDown, &opt, &p, 0L);
448         } else {
449             drawObject(p, HorizontalLine, r.x(), r.bottom() - (lwTitleBar - 1),
450                        r.width(), lwTitleBar);
451         }
452         break;
453     case HelpIcon: {
454         int center = r.x()+r.width()/2; // -1;
455         int side = r.width()/4;
456 
457         // paint a question mark... code is quite messy,
458         // to be cleaned up later...! :o
459         if (r.width() > 16) {
460             int lineWidth = 3;
461 
462             // top bar
463             drawObject(p, HorizontalLine, center - side + 3, r.y(),
464                        2 * side - 3 - 1, lineWidth);
465             // top bar rounding
466             drawObject(p, CrossDiagonalLine, center - side - 1, r.y() + 5,
467                        6, lineWidth);
468             drawObject(p, DiagonalLine, center + side - 3, r.y(), 5, lineWidth);
469             // right bar
470             drawObject(p, VerticalLine, center + side + 2 - lineWidth,
471                        r.y() + 3, r.height() - (2 * lineWidth + side + 2 + 1),
472                        lineWidth);
473             // bottom bar
474             drawObject(p, CrossDiagonalLine, center, r.bottom() - 2 * lineWidth,
475                        side + 2, lineWidth);
476             drawObject(p, HorizontalLine, center,
477                        r.bottom() - 3 * lineWidth + 2, lineWidth, lineWidth);
478             // the dot
479             drawObject(p, HorizontalLine, center, r.bottom() - (lineWidth - 1),
480                        lineWidth, lineWidth);
481         } else if (r.width() > 8) {
482             int lineWidth = 2;
483 
484             // top bar
485             drawObject(p, HorizontalLine, center - (side - 1), r.y(),
486                        2 * side - 1, lineWidth);
487             // top bar rounding
488             if (r.width() > 9)
489                 drawObject(p, CrossDiagonalLine, center - side - 1, r.y() + 3, 3, lineWidth);
490             else
491                 drawObject(p, CrossDiagonalLine, center - side - 1, r.y() + 2, 3, lineWidth);
492             drawObject(p, DiagonalLine, center + side - 1, r.y(), 3, lineWidth);
493             // right bar
494             drawObject(p, VerticalLine, center + side + 2 - lineWidth, r.y() + 2, r.height() - (2*lineWidth + side + 1), lineWidth);
495             // bottom bar
496             drawObject(p, CrossDiagonalLine, center, r.bottom() - 2*lineWidth + 1, side + 2, lineWidth);
497             // the dot
498             drawObject(p, HorizontalLine, center, r.bottom() - (lineWidth - 1), lineWidth, lineWidth);
499         }
500         else
501         {
502             int lineWidth = 1;
503 
504             // top bar
505             drawObject(p, HorizontalLine, center - (side - 1), r.y(), 2*side, lineWidth);
506             // top bar rounding
507             drawObject(p, CrossDiagonalLine, center - side - 1, r.y() + 1, 2, lineWidth);
508             // right bar
509             drawObject(p, VerticalLine, center + side + 1, r.y(), r.height() - (side + 2 + 1), lineWidth);
510             // bottom bar
511             drawObject(p, CrossDiagonalLine, center, r.bottom() - 2, side + 2, lineWidth);
512             // the dot
513             drawObject(p, HorizontalLine, center, r.bottom(), 1, 1);
514         }
515 
516         break;
517     }
518     case NotOnAllDesktopsIcon:
519     {
520         r.adjust(1, 1, -1, -1);
521 
522         int lwMark = (r.width() - 1)/2;
523         if (lwMark < 1)
524             lwMark = 3;
525 
526         drawObject(p, HorizontalLine, r.x(), r.y(), lwMark, lwMark);
527         drawObject(p, HorizontalLine, r.x() + (r.width() - lwMark), r.y(), lwMark, lwMark);
528         drawObject(p, HorizontalLine, r.x() + (r.width() - lwMark), r.y() + (r.height() - lwMark), lwMark, lwMark);
529         drawObject(p, HorizontalLine, r.x(), r.y() + (r.height() - lwMark), lwMark, lwMark);
530         break;
531     }
532     case OnAllDesktopsIcon:
533     {
534         int lwMark = r.width() - lwTitleBar*2 - 2;
535         if (lwMark < 1)
536             lwMark = 3;
537 
538         drawObject(p, HorizontalLine, r.x() + (r.width() - lwMark)/2, r.y() + (r.height() - lwMark)/2, lwMark, lwMark);
539         break;
540     }
541     case NoKeepAboveIcon:
542     case KeepAboveIcon:
543     {
544         QStyleOption opt;
545 
546         opt.rect=r.adjusted(0, -(1 + lwTitleBar), 0, 0);
547         opt.rect.adjust(2, 2, -2, -2);
548         opt.state=QStyle::State_Enabled|QtC_StateKWin;
549 
550         opt.rect.adjust(0, -1, 0, -1);
551         if(NoKeepAboveIcon==icon)
552         {
553             int w=r.width()/3;
554             if(0==w%2)
555                 w++;
556             drawObject(p, HorizontalLine, r.x() + (r.width() - w)/2, r.y() + 1, w, 2);
557         }
558         else
559             style->drawPrimitive(QStyle::PE_IndicatorArrowUp, &opt, &p, 0L);
560         opt.rect.adjust(0, 4, 0, 4);
561         style->drawPrimitive(QStyle::PE_IndicatorArrowUp, &opt, &p, 0L);
562         break;
563     }
564     case NoKeepBelowIcon:
565     case KeepBelowIcon:
566     {
567         QStyleOption opt;
568 
569         opt.rect=r.adjusted(0, -(1 + lwTitleBar), 0, 0);
570         opt.rect.adjust(2, 2, -2, -2);
571         opt.state=QStyle::State_Enabled|QtC_StateKWin;
572         opt.rect.adjust(0, -1, 0, -1);
573         style->drawPrimitive(QStyle::PE_IndicatorArrowDown, &opt, &p, 0L);
574         opt.rect.adjust(0, 4, 0, 4);
575         if(NoKeepBelowIcon==icon)
576         {
577             int w=r.width()/3;
578             if(0==w%2)
579                 w++;
580             drawObject(p, HorizontalLine, r.x() + (r.width() - w)/2, r.y() + r.height() - 3, w, 2);
581         }
582         else
583             style->drawPrimitive(QStyle::PE_IndicatorArrowDown, &opt, &p, 0L);
584         break;
585     }
586     case UnShadeIcon:
587     case ShadeIcon: {
588         QStyleOption opt;
589 
590         //opt.init(btn);
591         opt.rect=r.adjusted(0, -(1 + lwTitleBar), 0, 0);
592         opt.rect.adjust(2, 2, -2, -2);
593         if(UnShadeIcon==icon)
594             opt.rect.adjust(0, -1, 0, -1);
595         opt.state=QStyle::State_Enabled|QtC_StateKWin;
596 
597         //opt.palette.setColor(QPalette::Button, Qt::red);
598         style->drawPrimitive(ShadeIcon==icon ? QStyle::PE_IndicatorArrowDown
599                              : QStyle::PE_IndicatorArrowUp,
600                              &opt, &p, 0L);
601         drawObject(p, HorizontalLine, r.x() + 1, r.bottom() - (lwTitleBar - 1), r.width() - 2, lwTitleBar);
602         break;
603     }
604     case MenuIcon: {
605         int offset=(r.height() - 7)/2;
606         for (int i = 0;i < 3;i++)
607             drawObject(p, HorizontalLine, r.x() + 1, r.y() + offset + (i*3), r.width() - 2, 1);
608         break;
609     }
610     default:
611         break;
612     }
613 
614     p.end();
615     bitmap.setMask(bitmap);
616 
617     return bitmap;
618 }
619 
620 void
drawObject(QPainter & p,Object object,int x,int y,int length,int lineWidth)621 IconEngine::drawObject(QPainter &p, Object object, int x, int y,
622                        int length, int lineWidth)
623 {
624     switch(object) {
625     case DiagonalLine:
626         if (lineWidth <= 1) {
627             for (int i = 0;i < length;i++) {
628                 p.drawPoint(x + i, y + i);
629             }
630         } else if (lineWidth <= 2) {
631             for (int i = 0;i < length;i++) {
632                 p.drawPoint(x + i, y + i);
633             }
634             for (int i = 0;i < length - 1;i++) {
635                 p.drawPoint(x + 1 + i, y + i);
636                 p.drawPoint(x + i, y + 1 + i);
637             }
638         } else {
639             for (int i = 1;i < length - 1;i++) {
640                 p.drawPoint(x + i, y + i);
641             }
642             for (int i = 0;i < length - 1;i++) {
643                 p.drawPoint(x + 1 + i, y + i);
644                 p.drawPoint(x + i, y + 1 + i);
645             }
646             for (int i = 0;i < (length - 2);i++) {
647                 p.drawPoint(x + 2 + i, y + i);
648                 p.drawPoint(x + i, y + 2 + i);
649             }
650         }
651         break;
652     case CrossDiagonalLine:
653         if (lineWidth <= 1) {
654             for (int i = 0;i < length;i++) {
655                 p.drawPoint(x + i, y - i);
656             }
657         } else if (lineWidth <= 2) {
658             for (int i = 0;i < length;i++) {
659                 p.drawPoint(x + i, y - i);
660             }
661             for (int i = 0;i < length - 1;i++) {
662                 p.drawPoint(x + 1 + i, y - i);
663                 p.drawPoint(x + i, y - 1 - i);
664             }
665         } else {
666             for (int i = 1;i < length - 1;i++) {
667                 p.drawPoint(x + i, y - i);
668             }
669             for (int i = 0;i < length - 1;i++) {
670                 p.drawPoint(x + 1 + i, y - i);
671                 p.drawPoint(x + i, y - 1 - i);
672             }
673             for (int i = 0;i < length - 2;i++) {
674                 p.drawPoint(x + 2 + i, y - i);
675                 p.drawPoint(x + i, y - 2 - i);
676             }
677         }
678         break;
679     case HorizontalLine:
680         for (int i = 0;i < lineWidth;i++) {
681             p.drawLine(x, y + i, x + length - 1, y + i);
682         }
683         break;
684     case VerticalLine:
685         for (int i = 0;i < lineWidth;i++) {
686             p.drawLine(x + i, y, x + i, y + length - 1);
687         }
688     default:
689         break;
690     }
691 }
692 
693 }
694 }
695