source: trunk/src/styles/qwarp4style.cpp@ 178

Last change on this file since 178 was 178, checked in by dmik, 18 years ago

styles/Warp4: Increased tool button size hint to avoid cutting contained icons (#9).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 150.6 KB
Line 
1/****************************************************************************
2** $Id: qwarp4style.cpp 178 2008-02-25 22:07:51Z dmik $
3**
4** Implementation of OS/2 Warp-like style class
5**
6** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
7** Copyright (C) 2007-2007 netlabs.org. OS/2 Development.
8**
9** This file is part of the widgets module of the Qt GUI Toolkit.
10**
11** This file may be distributed under the terms of the Q Public License
12** as defined by Trolltech AS of Norway and appearing in the file
13** LICENSE.QPL included in the packaging of this file.
14**
15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file.
19**
20** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
21** licenses may use this file in accordance with the Qt Commercial License
22** Agreement provided with the Software.
23**
24** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26**
27** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
28** information about Qt Commercial License Agreements.
29** See http://www.trolltech.com/qpl/ for QPL licensing information.
30** See http://www.trolltech.com/gpl/ for GPL licensing information.
31**
32** Contact info@trolltech.com if any conditions of this licensing are
33** not clear to you.
34**
35**********************************************************************/
36
37#if !defined(QT_NO_STYLE_WARP4) || defined(QT_PLUGIN)
38
39#include <limits.h>
40#include "qapplication.h"
41#include "qpainter.h"
42#include "qdrawutil.h" // for now
43#include "qlabel.h"
44#include "qimage.h"
45#include "qcombobox.h"
46#include "qlistbox.h"
47#include "qrangecontrol.h"
48#include "qscrollbar.h"
49#include "qslider.h"
50#include "qtabwidget.h"
51#include "qlistview.h"
52#include "qbitmap.h"
53#include "qcleanuphandler.h"
54#include "qdockwindow.h"
55#include "qobjectlist.h"
56#include "qmenubar.h"
57#include "qprogressbar.h"
58#include "qptrlist.h"
59#include "qvaluelist.h"
60#include "qmainwindow.h"
61#include "qdockarea.h"
62
63#include "qpixmap.h"
64#include "qmap.h"
65#include "qtabbar.h"
66#include "qwidget.h"
67#include "qwidgetstack.h"
68#include "qtoolbutton.h"
69#include "qpushbutton.h"
70#include "qpopupmenu.h"
71#include "qevent.h"
72
73#include "qwarp4style.h"
74
75#ifndef QT_NO_ICONSET
76#include "qiconset.h"
77#endif
78
79// defined in qapplication_pm.cpp
80extern QRgb qt_sysclr2qrgb(LONG sysClr);
81
82/*----------------------------------------------------------------------*\
83 * Internal pixmaps
84\*----------------------------------------------------------------------*/
85
86// Note: All these colors only serve as placeholders; they are being replaced
87// by system colors in the QWarpPixmap constructor. After that, they are being
88// cached as pixmaps (like the system bitmaps and icons)
89
90static char* arrowup_xpm[] =
91{
92/* width height ncolors chars_per_pixel */
93"12 12 4 1",
94/* colors */
95" c #0000FF", // transparent
96"! c #808080", // dark grey
97"# c #FFFFFF", // light
98"$ c #000000", // shadow
99/* pixels */
100" ",
101" ",
102" ",
103" ## ",
104" #!!# ",
105" #!!!!# ",
106" #!!!!!!# ",
107" #!!!!!!!!# ",
108"#$$$$$$$$$$#",
109" ",
110" ",
111" "
112};
113
114static char* arrowdown_xpm[] =
115{
116/* width height ncolors chars_per_pixel */
117"12 12 4 1",
118/* colors */
119" c #0000FF", // transparent
120"! c #808080", // dark grey
121"# c #FFFFFF", // light
122"$ c #000000", // shadow
123/* pixels */
124" ",
125" ",
126" ",
127"#$$$$$$$$$$#",
128" #!!!!!!!!# ",
129" #!!!!!!# ",
130" #!!!!# ",
131" #!!# ",
132" ## ",
133" ",
134" ",
135" "
136};
137
138static char* arrowright_xpm[] =
139{
140/* width height ncolors chars_per_pixel */
141"12 12 4 1",
142/* colors */
143" c #0000FF", // transparent
144"! c #808080", // dark grey
145"# c #FFFFFF", // light
146"$ c #000000", // shadow
147/* pixels */
148" # ",
149" $# ",
150" $!# ",
151" $!!# ",
152" $!!!# ",
153" $!!!!# ",
154" $!!!!# ",
155" $!!!# ",
156" $!!# ",
157" $!# ",
158" $# ",
159" # "
160};
161
162static char* arrowleft_xpm[] =
163{
164/* width height ncolors chars_per_pixel */
165"12 12 4 1",
166/* colors */
167" c #0000FF", // transparent
168"! c #808080", // dark grey
169"# c #FFFFFF", // light
170"$ c #000000", // shadow
171/* pixels */
172" # ",
173" #$ ",
174" #!$ ",
175" #!!$ ",
176" #!!!$ ",
177" #!!!!$ ",
178" #!!!!$ ",
179" #!!!$ ",
180" #!!$ ",
181" #!$ ",
182" #$ ",
183" # "
184};
185
186static char* checkmark_xpm[] =
187{
188/* width height ncolors chars_per_pixel */
189"8 8 4 1",
190/* colors */
191" c #0000FF", // transparent
192"! c #808080", // dark grey
193"# c #FFFFFF", // light
194"$ c #000000", // shadow
195/* pixels */
196" #! ",
197" ##!! ",
198" ###!!! ",
199"####!!!!",
200"!!!!$$$$",
201" !!!$$$ ",
202" !!$$ ",
203" !$ "
204};
205
206static char* tabhdrplus_xpm[] =
207{
208/* width height ncolors chars_per_pixel */
209"7 7 4 1",
210/* colors */
211" c #0000FF", // transparent
212"! c #C0C0C0", // button (lignt grey)
213"# c #808080", // dark grey
214"- c #FFFFFF", // light
215/* pixels */
216" --- ",
217" -!# ",
218"---!#--",
219"-!!!!!#",
220"-##!###",
221" -!# ",
222" -## "
223};
224
225static char* tabhdrminus_xpm[] =
226{
227/* width height ncolors chars_per_pixel */
228"7 7 4 1",
229/* colors */
230" c #0000FF", // transparent
231"! c #C0C0C0", // button (lignt grey)
232"# c #808080", // dark grey
233"- c #FFFFFF", // light
234/* pixels */
235" ",
236" ",
237"-------",
238"-!!!!!#",
239"#######",
240" ",
241" "
242};
243
244#ifndef QT_NO_ICONSET
245
246class Q_EXPORT QIconFactoryPM: public QIconFactory
247{
248public:
249 virtual QPixmap* createPixmap(QIconSet const& iconSet, QIconSet::Size size,
250 QIconSet::Mode mode, QIconSet::State state);
251};
252
253QPixmap* QIconFactoryPM::createPixmap(QIconSet const& iconSet, QIconSet::Size size,
254 QIconSet::Mode mode, QIconSet::State state)
255{
256 // we are only providing a way to "disable" icons
257 if(QIconSet::Disabled != mode)
258 return 0;
259
260 // generate "normal" pixmap, and return 0 if this fails
261 QPixmap normPixmap = iconSet.pixmap(size, QIconSet::Normal, state);
262 if(normPixmap.isNull())
263 return 0;
264
265 // For PM/Warp style, "disabling" a pixmap means overimpose a raster
266 // of transparency.
267 // Note: if possible we realize this transparency raster with a mask;
268 // only if the pixmap comes with an alpha channel already, we are making
269 // use of that one
270
271 QBitmap mask;
272 QImage alphaImg;
273 if(normPixmap.mask())
274 {
275 // if a mask exists, use it
276 mask = *normPixmap.mask();
277 }
278 else if(normPixmap.hasAlphaChannel())
279 {
280 // if an alpha channel exists, use it
281 alphaImg = normPixmap.convertToImage();
282 }
283 else
284 {
285 // if none exists, generate a mask and initialize it with "fully opaque)
286 mask = QBitmap(normPixmap.size());
287 mask.fill(Qt::color1);
288 }
289
290 QPixmap* pixmap = 0;
291 int r, c;
292
293 // alpha channel case
294 if(mask.isNull())
295 {
296 if(32 != alphaImg.depth())
297 alphaImg = alphaImg.convertDepth(32);
298 for(r = 0; c < alphaImg.height(); ++r)
299 {
300 for(c = 0; c < alphaImg.width(); ++c);
301 {
302 if(0 ==((r + c) % 2))
303 alphaImg.setPixel(c, r, 0);
304 }
305 }
306 pixmap = new QPixmap(alphaImg);
307 }
308
309 // mask case
310 else
311 {
312 QImage img = mask.convertToImage();
313 for(r = 0; r < img.height(); ++r)
314 {
315 int pix;
316 for(c = 0; c < img.width(); ++c)
317 {
318 pix = img.pixelIndex(c, r);
319 pix = ((0 == pix) || (0 == ((r + c) % 2))) ? 0 : 1;
320 img.setPixel(c, r, pix);
321 }
322 }
323 mask.convertFromImage(img);
324 pixmap = new QPixmap(normPixmap);
325 pixmap->setMask(mask);
326 }
327
328 return pixmap;
329}
330
331#endif // ifndef QT_NO_ICONSET
332
333/*! \internal
334 Helper function to make the "background" of an image transparent.
335 this is done heuristically by assuming that if all corners have the
336 same color, and if that color happens to be also the same as the
337 system dialog background color, then this color is actually intended
338 to be "transparent", and it is changed to that, starting at the
339 four corners and as far as this color is continuously there (flood fill).
340*/
341static void qFloodFill(QImage& im, int x, int y, QRgb color)
342{
343 // note: this is a primitive, completely un-optimized flood fill,
344 // but since 1) only rather small images are treated and 2) they are
345 // even cached, the overhead does not seem to be excessive!
346
347 // get current color and change to new color
348 QRgb currentCol = im.pixel(x, y);
349 im.setPixel(x, y, color);
350
351 // recursive calls in all four directions, if color is right
352 if((x > 0) && (im.pixel(x - 1, y) == currentCol))
353 qFloodFill(im, x - 1, y, color);
354 if((x < (im.width() - 1)) && (im.pixel(x + 1, y) == currentCol))
355 qFloodFill(im, x + 1, y, color);
356 if((y > 0) && (im.pixel(x, y - 1) == currentCol))
357 qFloodFill(im, x, y - 1, color);
358 if((y < (im.height() - 1)) && (im.pixel(x, y + 1) == currentCol))
359 qFloodFill(im, x, y + 1, color);
360}
361
362static void qImageBackgroundTransparent(QImage& im)
363{
364 // if colors in all four corners are equal and equal to the system
365 // standard dialog background color, we assume this color is meant to
366 // be the "background" and change that to "transparent"
367 // this makes radiobuttons look ok on other than a standard dialog
368 // background, like inside a listview control
369 int xm = im.width() - 1,
370 ym = im.height() - 1;
371 static QRgb dlgBackCol = qt_sysclr2qrgb(SYSCLR_DIALOGBACKGROUND) | 0xff000000;
372 QRgb cornerCol = im.pixel(0, 0);
373 if((cornerCol == dlgBackCol) &&
374 (cornerCol == im.pixel(0, ym)) &&
375 (cornerCol == im.pixel(xm, 0)) &&
376 (cornerCol == im.pixel(xm, ym)))
377 {
378 im.setAlphaBuffer(true);
379 qFloodFill(im, 0, 0, (QRgb)0);
380 qFloodFill(im, 0, ym, (QRgb)0);
381 qFloodFill(im, xm, 0, (QRgb)0);
382 qFloodFill(im, xm, ym, (QRgb)0);
383 }
384}
385
386/*----------------------------------------------------------------------*\
387 * QWarpPixmap class
388 * Describes a pixmap that is being read from the PM system
389\*----------------------------------------------------------------------*/
390
391/*! \internal
392 Describes a pixmap that is being read from the PM system.
393*/
394class QWarpPixmap: public QPixmap
395{
396public:
397 typedef enum
398 {
399 bmp,
400 ico,
401 internal
402 }
403 QWarpPixmapType;
404
405 typedef enum
406 {
407 arrowup,
408 arrowdown,
409 arrowleft,
410 arrowright,
411 tabheadertr,
412 tabheaderbr,
413 tabheadertl,
414 tabheaderbl,
415 tabhdrplus,
416 tabhdrminus,
417 chkboxnormal,
418 chkboxsunken,
419 chkboxchecked,
420 chkboxcheckedsunken,
421 chkboxtri,
422 chkboxtrisunken,
423 radbutnormal,
424 radbutsunken,
425 radbutchecked,
426 radbutcheckedsunken,
427 checkmark
428 }
429 QWarpInternalPixmap;
430
431 QWarpPixmap(unsigned long id, QWarpPixmapType type, long sz = -1);
432
433 bool isOk() const { return ok; }
434
435private:
436 bool ok;
437 static QMap<QString, QPixmap>* tabHeaderCorners;
438
439 bool indicatorPixmap(bool isCheckbox, uint status, bool sunken);
440 bool drawTabHeaderTopRight(int sz);
441 bool drawTabHeaderBottomRight(int sz);
442 bool drawTabHeaderTopLeft(int sz);
443 bool drawTabHeaderBottomLeft(int sz);
444};
445
446QMap<QString, QPixmap>* QWarpPixmap::tabHeaderCorners = 0;
447
448QWarpPixmap::QWarpPixmap(unsigned long id, QWarpPixmapType type, long sz)
449 : ok(false)
450{
451 QImage img;
452
453 if(internal == type)
454 {
455 switch(id)
456 {
457 case arrowleft:
458 img = QImage(arrowleft_xpm);
459 break;
460 case arrowright:
461 img = QImage(arrowright_xpm);
462 break;
463 case arrowup:
464 img = QImage(arrowup_xpm);
465 break;
466 case arrowdown:
467 img = QImage(arrowdown_xpm);
468 break;
469 case tabheadertr:
470 ok = drawTabHeaderTopRight(sz);
471 break;
472 case tabheaderbr:
473 ok = drawTabHeaderBottomRight(sz);
474 break;
475 case tabheadertl:
476 ok = drawTabHeaderTopLeft(sz);
477 break;
478 case tabheaderbl:
479 ok = drawTabHeaderBottomLeft(sz);
480 break;
481 case tabhdrplus:
482 img = QImage(tabhdrplus_xpm);
483 break;
484 case tabhdrminus:
485 img = QImage(tabhdrminus_xpm);
486 break;
487 case chkboxnormal:
488 ok = indicatorPixmap(true, 0, false);
489 break;
490 case chkboxsunken:
491 ok = indicatorPixmap(true, 0, true);
492 break;
493 case chkboxchecked:
494 ok = indicatorPixmap(true, 1, false);
495 break;
496 case chkboxcheckedsunken:
497 ok = indicatorPixmap(true, 1, true);
498 break;
499 case chkboxtri:
500 ok = indicatorPixmap(true, 2, false);
501 break;
502 case chkboxtrisunken:
503 ok = indicatorPixmap(true, 2, true);
504 break;
505 case radbutnormal:
506 ok = indicatorPixmap(false, 0, false);
507 break;
508 case radbutsunken:
509 ok = indicatorPixmap(false, 0, true);
510 break;
511 case radbutchecked:
512 ok = indicatorPixmap(false, 1, false);
513 break;
514 case radbutcheckedsunken:
515 ok = indicatorPixmap(false, 1, true);
516 break;
517 case checkmark:
518 default:
519 img = QImage(checkmark_xpm);
520 break;
521 }
522
523 img.setAlphaBuffer(true);
524
525 QColorGroup const& cg = QApplication::palette().active();
526 int col;
527 for(col = 0; col < img.numColors(); ++col)
528 {
529 switch(img.color(col))
530 {
531 case 0xff0000ff: // transparent
532 img.setColor(col, QRgb(0x00000000));
533 break;
534 case 0xffc0c0c0: // button (light grey)
535 img.setColor(col, QRgb(cg.button().rgb() | 0xff000000));
536 break;
537 case 0xff808080: // dark grey
538 img.setColor(col, QRgb(cg.dark().rgb() | 0xff000000));
539 break;
540 case 0xffffffff: // light
541 img.setColor(col, QRgb(cg.light().rgb() | 0xff000000));
542 break;
543 case 0xff000000: // shadow
544 img.setColor(col, QRgb(cg.shadow().rgb() | 0xff000000));
545 break;
546 }
547 }
548 }
549
550 else
551 {
552 HBITMAP hbits = NULLHANDLE,
553 hmask = NULLHANDLE;
554 bool color = true;
555
556 switch(type)
557 {
558 case bmp:
559 {
560 hbits = WinGetSysBitmap(HWND_DESKTOP, id);
561 break;
562 }
563
564 default: // ico
565 {
566 HPOINTER ptr = WinQuerySysPointer(HWND_DESKTOP, id, FALSE);
567 if(NULLHANDLE != ptr)
568 {
569 POINTERINFO ptrInfo;
570 WinQueryPointerInfo(ptr, (PPOINTERINFO)&ptrInfo);
571 hmask = ptrInfo.hbmPointer;
572 color = NULLHANDLE != ptrInfo.hbmColor;
573 if(color)
574 hbits = ptrInfo.hbmColor;
575 else
576 hbits = ptrInfo.hbmPointer;
577 }
578 break;
579 }
580 }
581
582 if(NULLHANDLE == hbits)
583 return;
584
585 BITMAPINFOHEADER2 bmpHdr;
586 ::memset(&bmpHdr, 0, sizeof(bmpHdr));
587 bmpHdr.cbFix = sizeof(bmpHdr);
588 GpiQueryBitmapInfoHeader(hbits, (PBITMAPINFOHEADER2)&bmpHdr);
589
590 BITMAPINFOHEADER2 maskHdr;
591 if(NULLHANDLE != hmask)
592 {
593 ::memset(&maskHdr, 0, sizeof(maskHdr));
594 maskHdr.cbFix = sizeof(maskHdr);
595 GpiQueryBitmapInfoHeader(hmask, (PBITMAPINFOHEADER2)&maskHdr);
596 }
597
598 HAB hab = WinQueryAnchorBlock(HWND_DESKTOP);
599 HDC hdc = DevOpenDC(hab, OD_MEMORY, "*", 0, NULL, NULLHANDLE);
600 if(0 == hdc)
601 return;
602
603 SIZEL size;
604 size.cx = bmpHdr.cx;
605 size.cy = bmpHdr.cy;
606 HPS hps = GpiCreatePS(hab, hdc, (PSIZEL)&size,
607 PU_PELS | GPIF_LONG | GPIT_NORMAL | GPIA_ASSOC);
608 if(0 == hps)
609 return;
610
611 if((ico == type) && !color)
612 size.cy /= 2;
613 img = QImage(size.cx, size.cy, 32);
614
615 unsigned long bmpInfoSize = sizeof(BITMAPINFO2) + 255 * sizeof(RGB2);
616 BITMAPINFO2* bmpInfo = (BITMAPINFO2*)new BYTE[bmpInfoSize];
617 int lBufSize = 4 * size.cx * size.cy;
618
619 PBYTE mBuf = 0;
620 if(NULLHANDLE != hmask)
621 {
622 GpiSetBitmap(hps, hmask);
623 img.setAlphaBuffer(true);
624
625 ::memset(bmpInfo, 0, bmpInfoSize);
626 ::memcpy(bmpInfo, &maskHdr, sizeof(BITMAPINFOHEADER2));
627 bmpInfo->cBitCount = 32; // note: this avoids padding at row ends!
628 bmpInfo->ulCompression = BCA_UNCOMP;
629
630 mBuf = new BYTE[lBufSize];
631 ::memset(mBuf, 0, lBufSize);
632
633 if(size.cy != GpiQueryBitmapBits(hps, size.cy, size.cy, mBuf, bmpInfo))
634 {
635 delete[] mBuf;
636 delete[] (PBYTE)bmpInfo;
637 return;
638 }
639 }
640
641 GpiSetBitmap(hps, hbits);
642
643 ::memset(bmpInfo, 0, bmpInfoSize);
644 ::memcpy(bmpInfo, &bmpHdr, sizeof(BITMAPINFOHEADER2));
645 bmpInfo->cBitCount = 32;
646 bmpInfo->ulCompression = BCA_UNCOMP;
647
648 PBYTE lBuf = new BYTE[lBufSize];
649 ::memset(lBuf, 0, lBufSize);
650
651 if(size.cy != GpiQueryBitmapBits(hps, 0, size.cy, lBuf, bmpInfo))
652 {
653 delete[] lBuf;
654 delete[] mBuf;
655 delete[] (PBYTE)bmpInfo;
656 return;
657 }
658
659 int r, c;
660 uint col;
661 for(r = 0; r < size.cy; ++r)
662 {
663 for(c = 0; c < size.cx; ++c)
664 {
665 col = *((uint*)&lBuf[(r * size.cx + c) * 4]);
666 uint alpha = 255;
667 if(NULLHANDLE != hmask)
668 alpha -= (uint)(unsigned char)mBuf[(r * size.cx + c) * 4];
669 col |= 0x01000000 * alpha;
670 img.setPixel(c, size.cy - r - 1, col);
671 }
672 }
673
674 delete[] mBuf;
675 delete[] lBuf;
676 delete[] (PBYTE)bmpInfo;
677 GpiSetBitmap(hps, NULLHANDLE);
678 GpiDestroyPS(hps);
679 DevCloseDC(hdc);
680 }
681
682 if(!img.isNull())
683 {
684 // images that are to be made transparent from the corners, if
685 // standard dialog background is the color there
686 // note: there seems to be nothing like the STL set<> in Qt, which
687 // would be more appropriate for the purpose here!
688 static QValueList<int> tbl;
689 if(tbl.empty())
690 {
691 tbl.push_back(52);
692 tbl.push_back(54);
693 tbl.push_back(56);
694 tbl.push_back(SBMP_RESTOREBUTTON);
695 tbl.push_back(SBMP_MINBUTTON);
696 tbl.push_back(SBMP_MAXBUTTON);
697 }
698 if((bmp == type) && (tbl.end() != tbl.find(id)))
699 qImageBackgroundTransparent(img);
700
701 ok = convertFromImage(img);
702 }
703}
704
705bool QWarpPixmap::indicatorPixmap(bool isCheckbox, uint status, bool sunken)
706{
707 QImage ii = QWarpPixmap(SBMP_CHECKBOXES, QWarpPixmap::bmp).convertToImage();
708
709 int c = 0;
710 if(sunken)
711 c += 2;
712 if(0 < status)
713 ++c;
714 int r = (isCheckbox ? 0 : 1);
715 if(2 <= status)
716 r = 2;
717
718 unsigned long w = ii.width() / 4,
719 h = ii.height() / 3;
720 QRect rect(0, 0, w, h);
721 rect.moveBy(c * w, r * h);
722
723 // cut out the right sub-image and make "background" transparent
724 ii = ii.copy(rect);
725 qImageBackgroundTransparent(ii);
726
727 // convert to pixmap
728 convertFromImage(ii);
729
730 return true;
731}
732
733bool QWarpPixmap::drawTabHeaderTopRight(int sz)
734{
735 QColorGroup const& cg = QApplication::palette().active();
736
737 resize(sz, sz);
738 fill(cg.button());
739 QPainter p(this);
740
741 // short lines in the corners
742 p.setPen(cg.dark());
743 QPoint pt(0, 0);
744 QPoint pt2(2, 0);
745 p.drawLine(pt, pt2);
746 pt2 += QPoint(1, 1);
747 p.drawLine(pt2, pt += QPoint(5, 1));
748 pt2 = pt + QPoint(sz - 7, sz - 7);
749 p.drawLine(pt2 + QPoint(0, 1), pt2 + QPoint(0, 4));
750
751 // corner
752 p.drawLine(pt, QPoint(pt.x(), pt2.y()));
753 p.drawLine(pt2, QPoint(pt.x(), pt2.y()));
754
755 // corner shadow
756 p.drawLine(pt.x() + 5, pt2.y() + 2, pt2.x() - 1, pt2.y() + 2);
757 QPoint pd(pt.x() + 6, pt2.y() + 3);
758 while(pd.x() < pt2.x())
759 {
760 p.drawPoint(pd);
761 pd += QPoint(2, 0);
762 }
763 p.setPen(cg.shadow());
764 p.drawLine(pt.x() + 5, pt2.y() + 1, pt2.x() - 1, pt2.y() + 1);
765
766 // bend
767 p.drawLine(pt += QPoint(1, 1), pt2);
768 p.setPen(cg.dark());
769 p.drawLine(pt + QPoint(2, 1), pt2 += QPoint(0, -1));
770 p.drawLine(pt += QPoint(0, 1), pt2 += QPoint(-2, 0));
771 p.drawLine(pt += QPoint(0, 1), pt2 += QPoint(-1, 0));
772 p.setPen(cg.light());
773 p.drawLine(pt + QPoint(0, 3), pt2 + QPoint(-3, 0));
774
775 return true;
776}
777
778bool QWarpPixmap::drawTabHeaderBottomRight(int sz)
779{
780 QColorGroup const& cg = QApplication::palette().active();
781
782 resize(sz, sz);
783 fill(cg.button());
784 QPainter p(this);
785
786 // short lines in the corners
787 p.setPen(cg.dark());
788 QPoint pt(0, sz - 1);
789 QPoint pt2(2, sz - 1);
790 p.drawLine(pt, pt2);
791 pt2 += QPoint(1, -1);
792 p.drawLine(pt2, pt += QPoint(5, -1));
793 pt2 = pt + QPoint(sz - 7, -sz + 7);
794 p.drawLine(pt2 + QPoint(0, -1), pt2 + QPoint(0, -4));
795
796 // corner
797 p.drawLine(pt, QPoint(pt.x(), pt2.y()));
798 p.drawLine(pt2, QPoint(pt.x(), pt2.y()));
799
800 // bend
801 p.setPen(cg.shadow());
802 p.drawLine(pt += QPoint(1, -1), pt2);
803 p.drawLine(pt += QPoint(1, 1), pt2 += QPoint(0, 2));
804 p.setPen(cg.dark());
805 p.drawLine(pt += QPoint(1, 0), pt2 += QPoint(0, 1));
806 p.drawLine(pt += QPoint(-2, 0), pt2 += QPoint(0, -2));
807 p.drawLine(pt += QPoint(0, -2), pt2 += QPoint(-2, 0));
808 p.drawLine(pt += QPoint(0, -1), pt2 += QPoint(-1, 0));
809 QPoint pd(pt + QPoint(5, 1));
810 while(pd.x() < (pt2.x() + 2))
811 {
812 p.drawPoint(pd);
813 pd += QPoint(2, -2);
814 }
815 p.setPen(cg.light());
816 p.drawLine(pt + QPoint(0, -3), pt2 + QPoint(-3, 0));
817
818 return true;
819}
820
821bool QWarpPixmap::drawTabHeaderTopLeft(int sz)
822{
823 QColorGroup const& cg = QApplication::palette().active();
824
825 resize(sz, sz);
826 fill(cg.button());
827 QPainter p(this);
828
829 // short lines in the corners
830 p.setPen(cg.dark());
831 QPoint pt(sz - 1, 0);
832 QPoint pt2(sz - 3, 0);
833 p.drawLine(pt, pt2);
834 pt2 += QPoint(-1, 1);
835 p.drawLine(pt2, pt += QPoint(-5, 1));
836 pt2 = pt + QPoint(7 - sz, sz - 7);
837
838 // corner
839 p.drawLine(pt, QPoint(pt.x(), pt2.y()));
840 p.drawLine(pt2, QPoint(pt.x(), pt2.y()));
841
842 // corner shadow
843 p.drawLine(pt.x() + 2, pt2.y() + 2, pt2.x() + 5, pt2.y() + 2);
844 p.drawLine(pt.x() + 2, pt.y() + 5, pt.x() + 2, pt2.y() + 2);
845 QPoint pd(pt2.x() + 6, pt2.y() + 3);
846 while(pd.x() < (pt.x() + 3))
847 {
848 p.drawPoint(pd);
849 pd += QPoint(2, 0);
850 }
851 pd -= QPoint(1, 1);
852 while(pd.y() > (pt.y() + 5))
853 {
854 p.drawPoint(pd);
855 pd += QPoint(0, -2);
856 }
857 p.setPen(cg.shadow());
858 p.drawLine(pt.x() + 1, pt2.y() + 1, pt2.x() + 5, pt2.y() + 1);
859 p.drawLine(pt.x() + 1, pt.y() + 5, pt.x() + 1, pt2.y() + 1);
860
861 // bend
862 p.drawLine(pt += QPoint(-1, 1), pt2 += QPoint(1, -1));
863 p.setPen(cg.dark());
864 p.drawLine(pt += QPoint(0, 1), pt2 += QPoint(1, 0));
865 p.drawLine(pt += QPoint(0, 1), pt2 += QPoint(1, 0));
866 p.setPen(cg.light());
867 p.drawLine(pt + QPoint(0, 3), pt2 + QPoint(3, 0));
868
869 return true;
870}
871
872bool QWarpPixmap::drawTabHeaderBottomLeft(int sz)
873{
874 QColorGroup const& cg = QApplication::palette().active();
875
876 resize(sz, sz);
877 fill(cg.button());
878 QPainter p(this);
879
880 // short lines in the corners
881 p.setPen(cg.dark());
882 QPoint pt(sz - 1, sz - 1);
883 QPoint pt2(sz - 3, sz - 1);
884 p.drawLine(pt, pt2);
885 pt2 += QPoint(-1, -1);
886 p.drawLine(pt2, pt += QPoint(-5, -1));
887 pt2 = pt + QPoint(7 - sz, 7 - sz);
888
889 // corner
890 p.drawLine(pt, QPoint(pt.x(), pt2.y()));
891 p.drawLine(pt2, QPoint(pt.x(), pt2.y()));
892
893 // corner shadow
894 p.drawLine(pt.x() + 2, pt.y() - 1, pt.x() + 2, pt2.y() + 5);
895 QPoint pd(pt.x() + 3, pt.y() - 2);
896 while(pd.y() > (pt2.y() + 5))
897 {
898 p.drawPoint(pd);
899 pd += QPoint(0, -2);
900 }
901 p.setPen(cg.shadow());
902 p.drawLine(pt.x() + 1, pt.y() - 1, pt.x() + 1, pt2.y() + 5);
903
904 // bend
905 p.drawLine(pt += QPoint(-1, -1), pt2 += QPoint(1, 1));
906 p.setPen(cg.dark());
907 p.drawLine(pt += QPoint(0, 1), pt2 += QPoint(-1, 0));
908 p.drawLine(pt += QPoint(0, -2), pt2 += QPoint(2, 0));
909 p.drawLine(pt += QPoint(0, -1), pt2 += QPoint(1, 0));
910 p.setPen(cg.light());
911 p.drawLine(pt + QPoint(0, -3), pt2 + QPoint(3, 0));
912
913 return true;
914}
915
916/*----------------------------------------------------------------------*\
917 * QWarpSystemPixmaps class
918\*----------------------------------------------------------------------*/
919
920/*! \internal
921 Retrieve and buffer PM system pixmaps.
922*/
923class QWarpSystemPixmaps
924{
925public:
926 QWarpSystemPixmaps() {}
927 ~QWarpSystemPixmaps();
928 QPixmap const* getPixmap(unsigned long id, QWarpPixmap::QWarpPixmapType type,
929 long sz = -1);
930
931private:
932 QMap<QString, QWarpPixmap*> pmr;
933};
934
935QWarpSystemPixmaps::~QWarpSystemPixmaps()
936{
937 QMap<QString, QWarpPixmap*>::iterator it;
938 for(it = pmr.begin(); it != pmr.end(); ++it)
939 delete *it;
940}
941
942QPixmap const* QWarpSystemPixmaps::getPixmap(unsigned long id,
943 QWarpPixmap::QWarpPixmapType type,
944 long sz /*= -1*/)
945{
946 QWarpPixmap* pix = 0;
947
948 QString key = QString("%1.%2.%3")
949 .arg((unsigned long)type, 8, 16)
950 .arg(id, 8, 16)
951 .arg(sz, 8, 16)
952 .replace(' ', '0');
953
954 QMap<QString, QWarpPixmap*>::iterator pix_it = pmr.find(key);
955 if(pmr.end() != pix_it)
956 {
957 pix = *pix_it;
958 }
959 else
960 {
961 pix = new QWarpPixmap(id, type, sz);
962 if(pix->isOk())
963 {
964 pmr.insert(key, pix);
965 }
966 else
967 {
968 delete pix;
969 pix = 0;
970 }
971 }
972
973 return (QPixmap const*)pix;
974}
975
976static QWarpSystemPixmaps qWarpSystemPixmaps;
977
978/*----------------------------------------------------------------------*\
979 * functions for drawing PM frames and pushbuttons
980\*----------------------------------------------------------------------*/
981
982static
983void qDrawWarpDefFrame(QPainter* p, QRect const& rect,
984 QColorGroup const& cg, bool def = FALSE)
985{
986 QRect rr(rect);
987
988 // outer frame of button that shows "default" state, but is unchanged
989 // if "sunken"
990
991 if(def)
992 {
993 p->setPen(cg.shadow());
994 p->drawRect(rr);
995 }
996
997 else
998 {
999 p->setPen(cg.dark());
1000 p->drawLine(rr.left(), rr.top(), rr.right() - 1, rr.top());
1001 p->drawLine(rr.left(), rr.top(), rr.left(), rr.bottom() - 1);
1002 p->setPen(cg.light());
1003 p->drawLine(rr.left() + 1, rr.bottom(), rr.right(), rr.bottom());
1004 p->drawLine(rr.right(), rr.top() + 1, rr.right(), rr.bottom());
1005 }
1006}
1007
1008static
1009void qDrawWarpFilledRect(QPainter* p, QRect const& rect,
1010 QColor dark, QColor light, QBrush const* fill,
1011 unsigned long mult, bool sunken = FALSE)
1012{
1013 QRect rr(rect);
1014
1015 // inner frame of button that shows "sunken" state, but is
1016 // unchanged if "default"
1017
1018 unsigned long l;
1019 for(l = 0; l < mult; ++l)
1020 {
1021 p->setPen(sunken ? dark : light);
1022 p->drawLine(rr.left(), rr.top(), rr.right() - 1, rr.top());
1023 p->drawLine(rr.left(), rr.top(), rr.left(), rr.bottom());
1024 p->setPen(sunken ? light : dark);
1025 p->drawLine(rr.left() + 1, rr.bottom(), rr.right(), rr.bottom());
1026 p->drawLine(rr.right(), rr.top(), rr.right(), rr.bottom());
1027 rr.addCoords(1, 1, -1, -1);
1028 }
1029
1030 if(0 != fill)
1031 {
1032 p->fillRect(rr, *fill);
1033 }
1034}
1035
1036static
1037void qDrawWarpPanel(QPainter* p, QRect const& rect,
1038 QColorGroup const& cg, int sunkenState = 1,
1039 QBrush const* fill = 0)
1040 // sunkenState: -1 = sunken
1041 // 0 = flat
1042 // 1 = raised
1043{
1044 QRect rr(rect);
1045
1046 if(0 == sunkenState) // flat
1047 {
1048 rr.addCoords(1, 1, 0, 0);
1049 p->setPen(cg.light());
1050 p->drawRect(rr);
1051 rr.addCoords(-1, -1, -1, -1);
1052 p->setPen(cg.dark());
1053 p->drawRect(rr);
1054 }
1055
1056 else if(0 > sunkenState) // sunken
1057 {
1058 qDrawWarpFilledRect(p, rect, cg.dark(), cg.light(), 0, 1, true);
1059 rr.addCoords(1, 1, -1, -1);
1060 qDrawWarpFilledRect(p, rr, cg.shadow(), cg.button(), fill, 1, true);
1061 }
1062
1063 else // raised
1064 {
1065 qDrawWarpFilledRect(p, rect, cg.shadow(), cg.dark(), 0, 1, false);
1066 rr.addCoords(1, 1, -1, -1);
1067 qDrawWarpFilledRect(p, rr, cg.dark(), cg.light(), fill, 1, false);
1068 }
1069}
1070
1071static
1072void qDrawTabBar(QPainter* p, QRect const& r,
1073 QColorGroup const& cg, QColor color,
1074 bool selected, bool bottom)
1075{
1076 QPointArray ptDark, ptColor, ptLight;
1077
1078 if(selected)
1079 {
1080 ptDark.putPoints(0, 4,
1081 r.right() - 9, r.top(),
1082 r.right() - 5, r.top() + 4,
1083 r.right(), r.bottom() - 5,
1084 r.right() - 2, r.bottom() - 5);
1085 ptColor.putPoints(0, 11,
1086 r.left(), r.bottom() - 4,
1087 r.left() + 6, r.top() + 2,
1088 r.left() + 8, r.top() + 1,
1089 r.right() - 9, r.top() + 1,
1090 r.right() - 8, r.top() + 4,
1091 r.right() - 4, r.bottom() - 9,
1092 r.right() - 2, r.bottom() - 4,
1093 r.right() - 3, r.bottom() - 2,
1094 r.right() - 5, r.bottom(),
1095 r.left() + 4, r.bottom(),
1096 r.left() + 2, r.bottom() - 2);
1097 ptLight.putPoints(0, 4,
1098 r.left(), r.bottom() - 5,
1099 r.left() + 6, r.top() + 2,
1100 r.left() + 8, r.top(),
1101 r.right() - 10, r.top());
1102 }
1103 else
1104 {
1105 ptDark.putPoints(0, 5,
1106 r.right() - 9, r.top() + 1,
1107 r.right() - 5, r.top() + 5,
1108 r.right() - 1, r.bottom() - 7,
1109 r.right() - 1, r.bottom() - 5,
1110 r.right() - 3, r.bottom() - 5);
1111 ptColor.putPoints(0, 7,
1112 r.left() + 1, r.bottom() - 5,
1113 r.left() + 6, r.top() + 4,
1114 r.left() + 8, r.top() + 2,
1115 r.right() - 9, r.top() + 2,
1116 r.right() - 8, r.top() + 5,
1117 r.right() - 5, r.bottom() - 8,
1118 r.right() - 3, r.bottom() - 5);
1119 ptLight.putPoints(0, 8,
1120 r.right(), r.bottom() - 4,
1121 r.left(), r.bottom() - 4,
1122 r.left() + 1, r.bottom() - 4,
1123 r.left() + 1, r.bottom() - 7,
1124 r.left() + 5, r.top() + 5,
1125 r.left() + 6, r.top() + 3,
1126 r.left() + 8, r.top() + 1,
1127 r.right() - 10, r.top() + 1);
1128 }
1129
1130 if(bottom)
1131 {
1132 unsigned long n;
1133 for(n = 0; n < ptDark.size(); ++n)
1134 {
1135 QPoint pt = ptDark.point(n);
1136 pt.setY(r.bottom() - pt.y());
1137 ptDark.setPoint(n, pt);
1138 }
1139 for(n = 0; n < ptColor.size(); ++n)
1140 {
1141 QPoint pt = ptColor.point(n);
1142 pt.setY(r.bottom() - pt.y());
1143 ptColor.setPoint(n, pt);
1144 }
1145 for(n = 0; n < ptLight.size(); ++n)
1146 {
1147 QPoint pt = ptLight.point(n);
1148 pt.setY(r.bottom() - pt.y());
1149 ptLight.setPoint(n, pt);
1150 }
1151 }
1152
1153 p->setBrush(cg.dark());
1154 p->setPen(QPen::NoPen);
1155 p->drawPolygon(ptDark);
1156 p->setBrush(color);
1157 p->drawPolygon(ptColor);
1158 p->setPen(cg.light());
1159 p->drawPolyline(ptLight);
1160
1161 // if bottom orientation, some "light" lines need to be "dark"
1162 if(bottom)
1163 {
1164 p->setPen(cg.dark());
1165 p->drawLine(ptLight.point(ptLight.size() - 2), ptLight.point(ptLight.size() - 1));
1166 if(!selected)
1167 p->drawLine(ptLight.point(0), ptLight.point(1));
1168 }
1169}
1170
1171// Note: This function is being copied 1:1 from QCommonStyle.cpp, only
1172// because we need to rewrite the code for drawing slider tick marks in
1173// two colors instead of only one in the "common" style! But the makers
1174// of Qt decided not to expose it or export it otherwise...
1175
1176#ifndef QT_NO_RANGECONTROL
1177// I really need this and I don't want to expose it in QRangeControl..
1178static int qPositionFromValue(QRangeControl const* rc, int logical_val,
1179 int span)
1180{
1181 if(span <= 0 ||
1182 logical_val < rc->minValue() ||
1183 rc->maxValue() <= rc->minValue())
1184 return 0;
1185 if(logical_val > rc->maxValue())
1186 return span;
1187
1188 uint range = rc->maxValue() - rc->minValue();
1189 uint p = logical_val - rc->minValue();
1190
1191 if(range > (uint)INT_MAX/4096)
1192 {
1193 const int scale = 4096 * 2;
1194 return ((p / scale) * span) / (range / scale);
1195 // ### the above line is probably not 100% correct
1196 // ### but fixing it isn't worth the extreme pain...
1197 }
1198 else if(range > (uint)span)
1199 {
1200 return (2 * p * span + range) / (2 * range);
1201 }
1202 else
1203 {
1204 uint div = span / range;
1205 uint mod = span % range;
1206 return p * div + (2 * p * mod + range) / (2 * range);
1207 }
1208 // equiv. to (p * span) / range + 0.5
1209 // no overflow because of this implicit assumption:
1210 // span <= 4096
1211}
1212#endif // QT_NO_RANGECONTROL
1213
1214/*----------------------------------------------------------------------*\
1215 * QWarpTabPanelHeader class
1216\*----------------------------------------------------------------------*/
1217
1218/*! \internal
1219 Panel header class for tab widget display and functionality in PM style
1220 (the "new" Warp4 style with the colored tabs...).
1221
1222 This is the parent/child setup of a QTabWidget:
1223 class QTabWidget
1224 class <QWidgetStack>, name <tab pages> -> panel(s) area
1225 class <QWidgetStackPrivate::Invisible>, name <qt_invisible_widgetstack>
1226 class <...panel...>
1227 class <QLabel>, name <unnamed>
1228 ...
1229 class <QWidget>, name <tab base> -> tab bar base area
1230 class <QTabBar>, name <tab control> -> tab bar
1231 class <QToolButton>, name <qt_left_btn> -> left tab bar button
1232 class <QToolButton>, name <qt_right_btn> -> right tab bar button
1233 class <QWarpTabPanelHeader>, name <qt_tabwidget_warpheader>
1234 -> this is the panel header widget that is added below, covering the
1235 tab bar base area
1236*/
1237class QWarpTabPanelHeader: public QWidget
1238{
1239 Q_OBJECT
1240
1241public:
1242 QWarpTabPanelHeader(QTabWidget* tw);
1243
1244protected:
1245 virtual bool eventFilter(QObject* watched, QEvent* ev);
1246 virtual void paintEvent(QPaintEvent* pev);
1247 virtual void mouseReleaseEvent(QMouseEvent* e);
1248
1249private:
1250 bool _bottom;
1251
1252 QTabWidget* getTabWidget();
1253 QWidgetStack* getPanel();
1254 QTabBar* getTabBar();
1255 QWidget* getTabBarBase();
1256
1257 void setupLayout(QSize sz);
1258
1259 void drawBentCornerTR(QPoint pt, int h, QPainter& p);
1260 void drawBentCornerTL(QPoint pt, int h, QPainter& p);
1261 void drawBentCornerBR(QPoint pt, int h, QPainter& p);
1262 void drawBentCornerBL(QPoint pt, int h, QPainter& p);
1263 void drawPlusButton(QPoint pt, QPainter& p);
1264 void drawMinusButton(QPoint pt, QPainter& p);
1265
1266 int currentInx();
1267
1268public:
1269 static void addIfNotPresent(QTabBar const* tb);
1270};
1271
1272QWarpTabPanelHeader::QWarpTabPanelHeader(QTabWidget* tw)
1273: QWidget(tw, "qt_warp_tabpanel_header")
1274{
1275 if(0 == tw)
1276 return;
1277
1278 // adapt the panel area size ("QWidgetStack")
1279 // note: the same effect could also be achieved by increasing the frame line
1280 // width for tab widgets, but this would also affect the tabbar layout in a
1281 // "very strange" (buggy??) way (it only works correctly for frame line widths
1282 // between 0 and 2)
1283 // also note that this reduction must be compensated when drawing the frame
1284 // (see PE_PanelTabWidget)
1285
1286 _bottom = tw->tabPosition() == QTabWidget::Bottom;
1287 QWidgetStack* tp = getPanel();
1288 if(0 != tp)
1289 {
1290 QRect r = tp->frameRect();
1291 if(_bottom)
1292 r.addCoords(11, 11, -14, 0);
1293 else
1294 r.addCoords(11, 0, -14, -11);
1295 tp->setFrameRect(r);
1296 }
1297
1298 // now we are "abusing" the otherwise unused "midLineWidth" of the tab panel
1299 // stack for signalling whether the tab bar is on top or at the bottom.
1300 // note that we can retrieve this information later in PE_PanelTabWidget from
1301 // the "opt" parameter (we don't have access to any widget from where we could
1302 // get that information "legally"!
1303
1304 tp->setMidLineWidth((int)_bottom); // now 1 is "bottom", 0 is "top"
1305
1306 // we also need to catch resize events from the tab widget, in order to adapt
1307 // the size of this panel header widget accordingly
1308
1309 tw->installEventFilter(this);
1310
1311 // note that size 0/0 means that the size is taken from that widget
1312
1313 setupLayout(QSize(0, 0));
1314
1315 // make this panel header widget visible: it displays the tab title
1316
1317#ifndef QT_PM_NO_TABWIDGET_HEADERS
1318 show();
1319#else
1320 hide();
1321#endif
1322}
1323
1324bool QWarpTabPanelHeader::eventFilter(QObject* watched, QEvent* ev)
1325{
1326 if(!watched->inherits("QTabWidget") ||
1327 (QEvent::Resize != ev->type()))
1328 return false;
1329
1330 // resize the panel header widget if the main tab widget is being resized
1331
1332 setupLayout(((QResizeEvent*)ev)->size());
1333
1334 return false;
1335}
1336
1337void QWarpTabPanelHeader::paintEvent(QPaintEvent* pev)
1338{
1339#ifndef QT_PM_NO_TABWIDGET_HEADERS
1340
1341 // draw the caption of the page in the tab bar base area
1342
1343 QRect r(geometry());
1344 QPainter p(this);
1345 bool reverse = QApplication::reverseLayout();
1346
1347 r.addCoords(-r.left(), -r.top(), -r.left(), -r.top());
1348 p.setClipRect(r);
1349 QFont f = QApplication::font();
1350 f.setBold(true);
1351 p.setFont(f);
1352 QRect fr = QFontMetrics(f).boundingRect(caption());
1353
1354 int x = (reverse ?
1355 r.right() - 5 - QFontMetrics(f).boundingRect(caption()).width() :
1356 r.left() + 5),
1357 y = (r.top() + r.bottom() + fr.height()) / 2 - 2;
1358
1359 p.drawText(x, y, caption());
1360
1361 QPoint pt1l, pt1r, pt2l, pt2r;
1362 int hh = r.height() + 1;
1363 if(_bottom)
1364 {
1365 pt1l = QPoint(1, r.bottom());
1366 pt1r = QPoint(r.width() - hh, r.bottom());
1367 pt2l = QPoint(5, r.top());
1368 pt2r = QPoint(r.width() - hh, r.top());
1369 }
1370 else
1371 {
1372 pt1l = QPoint(1, r.top());
1373 pt1r = QPoint(r.width() - hh, r.top());
1374 pt2l = QPoint(5, r.bottom() - 1);
1375 pt2r = QPoint(r.width() - hh, r.bottom() - 1);
1376 }
1377 if(reverse)
1378 {
1379 pt1l.setX(r.right() - pt1l.x());
1380 pt1r.setX(r.right() - pt1r.x());
1381 pt2l.setX(r.right() - pt2l.x());
1382 pt2r.setX(r.right() - pt2r.x());
1383 }
1384 else
1385 {
1386 pt1l.setX(r.left() + pt1l.x());
1387 pt1r.setX(r.left() + pt1r.x());
1388 pt2l.setX(r.left() + pt2l.x());
1389 pt2r.setX(r.left() + pt2r.x());
1390 }
1391 QColorGroup cg = colorGroup();
1392 p.setPen(cg.dark());
1393 p.drawLine(pt1l, pt1r);
1394 p.drawLine(pt2l, pt2r);
1395 p.setPen(cg.light());
1396 pt2l += QPoint(0, 1);
1397 pt2r += QPoint(0, 1);
1398 p.drawLine(pt2l, pt2r);
1399
1400 int inx = currentInx();
1401 QTabBar* tb = getTabBar();
1402 if(0 == tb)
1403 return; // should never happen
1404 bool noPlus = (tb->count() - 1) <= inx,
1405 noMinus = 0 >= inx;
1406
1407 QPoint cpt(pt1r);
1408 if(_bottom)
1409 {
1410 if(reverse)
1411 {
1412 cpt += QPoint(-hh, -hh + 1);
1413 drawBentCornerBL(cpt, hh, p);
1414 if(!noPlus)
1415 drawPlusButton(cpt + QPoint(5, hh - 12), p);
1416 if(!noMinus)
1417 drawMinusButton(cpt + QPoint(hh - 15, 7), p);
1418 }
1419 else
1420 {
1421 cpt += QPoint(1, -hh + 1);
1422 drawBentCornerBR(cpt, hh, p);
1423 if(!noPlus)
1424 drawPlusButton(cpt + QPoint(hh - 12, hh - 12), p);
1425 if(!noMinus)
1426 drawMinusButton(cpt + QPoint(8, 7), p);
1427 }
1428 }
1429 else
1430 {
1431 if(reverse)
1432 {
1433 cpt += QPoint(-hh, 0);
1434 drawBentCornerTL(cpt, hh, p);
1435 if(!noPlus)
1436 drawPlusButton(cpt + QPoint(5, 5), p);
1437 if(!noMinus)
1438 drawMinusButton(cpt + QPoint(hh - 15, hh - 14), p);
1439 }
1440 else
1441 {
1442 cpt += QPoint(1, 0);
1443 drawBentCornerTR(cpt, hh, p);
1444 if(!noPlus)
1445 drawPlusButton(cpt + QPoint(hh - 12, 5), p);
1446 if(!noMinus)
1447 drawMinusButton(cpt + QPoint(8, hh - 14), p);
1448 }
1449 }
1450#endif
1451}
1452
1453void QWarpTabPanelHeader::mouseReleaseEvent(QMouseEvent* e)
1454{
1455 QPoint p = e->pos();
1456 bool reverse = QApplication::reverseLayout(),
1457 corner = false;
1458 if(reverse)
1459 corner = p.x() < height();
1460 else
1461 corner = p.x() > (width() - height());
1462 if(!corner)
1463 return; // the click was outside the bent corner area
1464
1465 // calculate sum of x and y coordinates, measured from the corner
1466 // where the + button is
1467 long sum = 0;
1468 if(_bottom)
1469 {
1470 if(reverse)
1471 sum = p.x() + height() - p.y();
1472 else
1473 sum = width() - p.x() + height() - p.y();
1474 }
1475 else
1476 {
1477 if(reverse)
1478 sum = p.x() + p.y();
1479 else
1480 sum = width() - p.x() + p.y();
1481 }
1482
1483 // if this sum is less than the widget height, we are in the
1484 // + triangle of the bent corner, otherwise in the - triangle
1485 int inx = currentInx();
1486 if(height() > sum)
1487 ++inx;
1488 else
1489 --inx;
1490
1491 QTabBar* tb = getTabBar();
1492 if(0 == tb)
1493 return; // should never happen
1494 if((0 <= inx) && (tb->count() > inx))
1495 tb->setCurrentTab(tb->tabAt(inx)->identifier());
1496}
1497
1498void QWarpTabPanelHeader::drawBentCornerTR(QPoint pt, int h, QPainter& p)
1499{
1500 p.drawPixmap(pt, *qWarpSystemPixmaps.getPixmap(QWarpPixmap::tabheadertr,
1501 QWarpPixmap::internal, h));
1502}
1503
1504void QWarpTabPanelHeader::drawBentCornerTL(QPoint pt, int h, QPainter& p)
1505{
1506 p.drawPixmap(pt, *qWarpSystemPixmaps.getPixmap(QWarpPixmap::tabheadertl,
1507 QWarpPixmap::internal, h));
1508}
1509
1510void QWarpTabPanelHeader::drawBentCornerBR(QPoint pt, int h, QPainter& p)
1511{
1512 p.drawPixmap(pt, *qWarpSystemPixmaps.getPixmap(QWarpPixmap::tabheaderbr,
1513 QWarpPixmap::internal, h));
1514}
1515
1516void QWarpTabPanelHeader::drawBentCornerBL(QPoint pt, int h, QPainter& p)
1517{
1518 p.drawPixmap(pt, *qWarpSystemPixmaps.getPixmap(QWarpPixmap::tabheaderbl,
1519 QWarpPixmap::internal, h));
1520}
1521
1522void QWarpTabPanelHeader::drawPlusButton(QPoint pt, QPainter& p)
1523{
1524 p.drawPixmap(pt, *qWarpSystemPixmaps.getPixmap(QWarpPixmap::tabhdrplus,
1525 QWarpPixmap::internal));
1526}
1527
1528void QWarpTabPanelHeader::drawMinusButton(QPoint pt, QPainter& p)
1529{
1530 p.drawPixmap(pt, *qWarpSystemPixmaps.getPixmap(QWarpPixmap::tabhdrminus,
1531 QWarpPixmap::internal));
1532}
1533
1534QTabWidget* QWarpTabPanelHeader::getTabWidget()
1535{
1536 QWidget* ww = parentWidget();
1537 if((0 == ww) || !ww->inherits("QTabWidget"))
1538 return 0;
1539
1540 return (QTabWidget*)ww;
1541}
1542
1543QWidgetStack* QWarpTabPanelHeader::getPanel()
1544{
1545 QTabWidget* tw = getTabWidget();
1546 if(0 == tw)
1547 return 0;
1548
1549 return (QWidgetStack*)tw->child("tab pages", "QWidgetStack", false);
1550}
1551
1552QTabBar* QWarpTabPanelHeader::getTabBar()
1553{
1554 QTabWidget* tw = getTabWidget();
1555 if(0 == tw)
1556 return 0;
1557
1558 QObjectList* childList = tw->queryList("QTabBar", 0, false, false);
1559 if(childList->isEmpty())
1560 return 0;
1561
1562 return (QTabBar*)childList->at(0);
1563}
1564
1565QWidget* QWarpTabPanelHeader::getTabBarBase()
1566{
1567 QTabWidget* tw = getTabWidget();
1568 if(0 == tw)
1569 return 0;
1570
1571 return (QWidget*)tw->child("tab base", "QWidget", false);
1572}
1573
1574int QWarpTabPanelHeader::currentInx()
1575{
1576 QTabBar* tb = getTabBar();
1577 if(0 == tb)
1578 return 0; // should never happen
1579 int id = tb->currentTab();
1580
1581 return (id == 0) ? 0 : tb->indexOf(id);
1582}
1583
1584void QWarpTabPanelHeader::setupLayout(QSize sz)
1585{
1586 QTabWidget* tw = getTabWidget();
1587 if(0 == tw)
1588 return;
1589
1590 if(QSize(0, 0) == sz)
1591 sz = tw->size();
1592
1593 QTabBar* tb = getTabBar();
1594 if(0 == tb)
1595 return;
1596
1597 int th = tb->size().height();
1598 int fh = QFontMetrics(QApplication::font()).boundingRect("X").height();
1599
1600 QRect r(17, 0, sz.width() - 37, 0);
1601 if(_bottom)
1602 {
1603 r.setBottom(sz.height() - th - 17);
1604 r.setTop(r.bottom() - fh);
1605 r.addCoords(-5, -7, 6, 6);
1606 }
1607 else
1608 {
1609 r.setTop(th + 14);
1610 r.setBottom(r.top() + fh);
1611 r.addCoords(-5, -6, 6, 7);
1612 }
1613
1614 setGeometry(r);
1615}
1616
1617void QWarpTabPanelHeader::addIfNotPresent(QTabBar const* tb)
1618{
1619 QWidget* ww = tb->parentWidget();
1620 if((0 == ww) || !ww->inherits("QTabWidget"))
1621 return;
1622 QTabWidget* tw = (QTabWidget*)ww;
1623
1624 if(0 != tw->child("qt_warp_tabpanel_header", "QWarpTabPanelHeader", false))
1625 return; // header already there
1626
1627 // create if not yet present, with the tab widget as parent
1628 // note: deletion occurs when the tab widget is destroyed
1629
1630 new QWarpTabPanelHeader(tw);
1631}
1632
1633/*----------------------------------------------------------------------*\
1634 * QWarpMainWindowLayouter class
1635\*----------------------------------------------------------------------*/
1636
1637/*! \internal
1638 A widget that catches resize events for the main window and corrects
1639 the layout if necessary.
1640*/
1641class QWarpMainWindowLayouter: public QWidget
1642{
1643 Q_OBJECT
1644
1645public:
1646 QWarpMainWindowLayouter(QMainWindow* mw);
1647
1648protected:
1649 virtual bool eventFilter(QObject* watched, QEvent* ev);
1650 virtual bool event(QEvent* e);
1651
1652private:
1653 QMainWindow* getMainWindow();
1654
1655 void setupLayout();
1656
1657public:
1658 static void addIfNotPresent(QMainWindow* mw);
1659};
1660
1661QWarpMainWindowLayouter::QWarpMainWindowLayouter(QMainWindow* mw)
1662: QWidget(mw, "qt_warp_mainwindow_layouter")
1663{
1664 // we need to catch resize events from the main window, in order to adapt
1665 // the size of the client area to really cover the top and bottom dock
1666 // areas if they are empty
1667
1668 mw->installEventFilter(this);
1669 setupLayout();
1670}
1671
1672bool QWarpMainWindowLayouter::eventFilter(QObject* watched, QEvent* ev)
1673{
1674 if(!watched->inherits("QMainWindow") ||
1675 (QEvent::Resize != ev->type()))
1676 return false;
1677
1678 // we need to adapt the client area if the main window is being resized,
1679 // but only after the layouter has done its work, so we have to delay the
1680 // action by posting an event to ourselves
1681
1682 QApplication::postEvent(this, new QEvent((QEvent::Type)(QEvent::User + 2318)));
1683
1684 return false;
1685}
1686
1687bool QWarpMainWindowLayouter::event(QEvent* e)
1688{
1689 if(((QEvent::Type)(QEvent::User + 2318)) == e->type())
1690 setupLayout();
1691
1692 return QWidget::event(e);
1693}
1694
1695QMainWindow* QWarpMainWindowLayouter::getMainWindow()
1696{
1697 QWidget* ww = parentWidget();
1698 if((0 == ww) || !ww->inherits("QMainWindow"))
1699 return 0;
1700
1701 return (QMainWindow*)ww;
1702}
1703
1704void QWarpMainWindowLayouter::setupLayout()
1705{
1706 QMainWindow* mw = getMainWindow();
1707 if(0 == mw)
1708 return;
1709
1710 QWidget* cw = mw->centralWidget();
1711 if(0 == cw)
1712 return;
1713
1714 QDockArea* td = mw->topDock();
1715 QDockArea* bd = mw->bottomDock();
1716 QRect gg = cw->geometry();
1717 QRect gg2(gg);
1718
1719 if((0 != td) && (1 == td->height()))
1720 gg2.setTop(td->geometry().top());
1721
1722 if((0 != bd) && (1 == bd->height()))
1723 gg2.setBottom(bd->geometry().bottom());
1724
1725 if(gg != gg2)
1726 cw->setGeometry(gg2);
1727}
1728
1729void QWarpMainWindowLayouter::addIfNotPresent(QMainWindow* mw)
1730{
1731 if(0 != mw->child("qt_warp_mainwindow_layouter", "QWarpMainWindowLayouter", false))
1732 return; // layouter already there
1733
1734 // create if not yet present, with the main window as parent
1735 // note: deletion occurs when the main window is destroyed
1736
1737 new QWarpMainWindowLayouter(mw);
1738}
1739
1740/*! \internal
1741 Global function for determining whether a popup menu has submenus.
1742
1743 Note: this function is "ugly" because it is called for every menu
1744 item once, while the popup widget in turn scans through the menu
1745 items - but there is no other way to correct the problem with having
1746 at the same time an accelerator key (string after \t (tab)) and a
1747 submenu arrow displayed!
1748
1749 btw., the Windows style solves that problem by always having some space left
1750 for the arrow, and Motiv overpaints the arrow over the accelerator string,
1751 but native PM handles the case in a flexible and correct way!...
1752*/
1753static
1754bool qPopupMenuHasSub(QPopupMenu const* pm)
1755{
1756 bool hasSub = false;
1757 unsigned long ix;
1758 for(ix = 0; ix < pm->count(); ++ix)
1759 {
1760 QMenuItem const* mi = pm->findItem(pm->idAt(ix));
1761 hasSub = hasSub || (0 != mi->popup());
1762 }
1763
1764 return hasSub;
1765}
1766
1767/*----------------------------------------------------------------------*\
1768 * Auxiliary functions
1769\*----------------------------------------------------------------------*/
1770
1771/*! \internal
1772 Debug log of widget hierarchy.
1773*/
1774#if 0
1775static void qDebugLog(QWidget* widget,
1776 bool withChildren = false,
1777 unsigned long indent = 0)
1778{
1779 qDebug("%*sclass <%s>, name <%s>", (int)indent, "", widget->className(), widget->name());
1780 QRect r(widget->geometry());
1781 qDebug("%*sgeom (%d, %d) - (%d, %d) (size = %d, %d)", (int)indent, "", r.left(), r.top(), r.right(), r.bottom(), r.width(), r.height());
1782 r = widget->frameGeometry();
1783 qDebug("%*sframe (%d, %d) - (%d, %d)", (int)indent, "", r.left(), r.top(), r.right(), r.bottom());
1784
1785 if(withChildren)
1786 {
1787 QObjectList* wl = widget->queryList("QWidget", 0, false, false);
1788 QObjectListIterator wlit(*wl);
1789 QWidget* cw;
1790 while((cw = (QWidget*)wlit.current()) != 0)
1791 {
1792 ++wlit;
1793 qDebugLog(cw, true, indent + 2);
1794 }
1795 delete wl;
1796 }
1797}
1798#endif
1799
1800/*----------------------------------------------------------------------*\
1801 * QWarp4Style class
1802\*----------------------------------------------------------------------*/
1803
1804/*!
1805 \class QWarp4Style qwarp4style.h
1806 \brief The QWarp4Style class provides an OS/2 Warp 4 like look and feel.
1807
1808 \ingroup appearance
1809
1810 This style is Qt's default GUI style on OS/2 (or eComStation).
1811*/
1812
1813/*!
1814 Constructs a QWarp4Style
1815*/
1816QWarp4Style::QWarp4Style()
1817 : QCommonStyle()
1818 , oldDefIconFactory(0)
1819{
1820 pmDefIconFactory = new QIconFactoryPM();
1821}
1822
1823/*! \reimp */
1824QWarp4Style::~QWarp4Style()
1825{
1826 delete pmDefIconFactory;
1827}
1828
1829/*! \reimp */
1830void QWarp4Style::polish(QApplication* app)
1831{
1832#ifndef QT_NO_ICONSET
1833 // replace the "disabled" creation mechanism for pixmaps
1834 // and do it "the Warp way"
1835 oldDefIconFactory = QIconFactory::defaultFactory();
1836 bool oldAutoDelete = oldDefIconFactory->autoDelete();
1837 // prevent the old factory from being deleted when replacing
1838 oldDefIconFactory->setAutoDelete(FALSE);
1839 QIconFactory::installDefaultFactory(pmDefIconFactory);
1840 oldDefIconFactory->setAutoDelete(oldAutoDelete);
1841#endif
1842}
1843
1844/*! \reimp */
1845void QWarp4Style::unPolish(QApplication*)
1846{
1847#ifndef QT_NO_ICONSET
1848 // restore the original default iconfactory (unless it has been changed
1849 // externally after we were polished)
1850 if (pmDefIconFactory == QIconFactory::defaultFactory())
1851 {
1852 QIconFactory::installDefaultFactory(oldDefIconFactory);
1853 }
1854 else
1855 {
1856 // We are now responsible for deleting the old factory.
1857 // Note: the QIconFactory reference management in Qt is unreliable
1858 // (see qiconset.cpp, qcleanuphandler.h) so even after our attempt to
1859 // be tidy there is still a zillion cases for memory leaks or freed
1860 // memory access. I'm not going to fix Qt in this part.
1861 if (oldDefIconFactory->autoDelete())
1862 delete oldDefIconFactory;
1863 }
1864#endif
1865}
1866
1867/*! \reimp */
1868void QWarp4Style::polish(QWidget* widget)
1869{
1870 QCommonStyle::polish(widget);
1871}
1872
1873/*! \reimp */
1874void QWarp4Style::unPolish(QWidget* widget)
1875{
1876 QCommonStyle::polish(widget);
1877}
1878
1879/*! \reimp */
1880void QWarp4Style::polish(QPalette& pal)
1881{
1882 QCommonStyle::polish(pal);
1883}
1884
1885/*! \reimp */
1886void QWarp4Style::drawPrimitive (PrimitiveElement pe,
1887 QPainter *p,
1888 const QRect &r,
1889 const QColorGroup &cg,
1890 SFlags flags,
1891 const QStyleOption &opt) const
1892{
1893 QRect rr (r);
1894
1895 switch (pe)
1896 {
1897 case PE_ButtonCommand:
1898 case PE_ButtonTool:
1899 {
1900 bool def = flags & Style_ButtonDefault;
1901 qDrawWarpDefFrame (p, rr, cg, def);
1902 rr.addCoords (1, 1, -1, -1);
1903
1904 bool sunken = flags & (Style_Sunken | Style_Down | Style_On);
1905 QBrush fill = cg.brush (QColorGroup::Button);
1906 qDrawWarpFilledRect (p, rr, cg.dark(), cg.light(), &fill, 2, sunken);
1907 break;
1908 }
1909
1910 case PE_HeaderArrow:
1911 {
1912 p->save();
1913 while(0 != (rr.width() % 4))
1914 rr.setWidth(rr.width() - 1);
1915 rr.moveTop(rr.top() + rr.height() / 2 - rr.width() / 4 - 1);
1916 rr.setHeight(rr.width() / 2 + 1);
1917 rr.setWidth(rr.width() + 1);
1918 QPointArray pa(3);
1919 if(flags & Style_Down)
1920 {
1921 pa.setPoint(0, rr.left() + rr.width() / 2, rr.bottom());
1922 pa.setPoint(1, rr.left(), rr.top());
1923 pa.setPoint(2, rr.right(), rr.top());
1924 }
1925 else
1926 {
1927 pa.setPoint(0, rr.left(), rr.bottom());
1928 pa.setPoint(1, rr.right(), rr.bottom());
1929 pa.setPoint(2, rr.left() + rr.width() / 2, rr.top());
1930 }
1931 p->setPen(Qt::NoPen);
1932 p->setBrush(cg.shadow());
1933 p->drawPolygon(pa);
1934 p->restore();
1935 break;
1936 }
1937
1938 case PE_ButtonBevel:
1939 case PE_HeaderSection:
1940 {
1941 QBrush fill;
1942
1943 if(!(flags & Style_Down) && (flags & Style_On))
1944 fill = QBrush(cg.light(), Dense4Pattern);
1945 else
1946 fill = cg.brush(QColorGroup::Button);
1947
1948 if(flags & (Style_Raised | Style_Down | Style_On | Style_Sunken))
1949 qDrawWarpFilledRect(p, r, cg.dark(), cg.light(), &fill, 2,
1950 flags & (Style_Down | Style_On));
1951 else
1952 p->fillRect(r, fill);
1953
1954 break;
1955 }
1956
1957 case PE_ButtonDefault:
1958 {
1959 p->setPen(cg.shadow());
1960 p->drawRect(r);
1961
1962 break;
1963 }
1964
1965 case PE_Separator:
1966 {
1967 p->setPen(cg.dark());
1968 rr.addCoords(0, 0, 0, -1);
1969 p->drawLine(rr.bottomLeft(), rr.bottomRight());
1970 break;
1971 }
1972
1973 case PE_FocusRect:
1974 {
1975 if(opt.isDefault())
1976 p->drawWinFocusRect(r);
1977 else
1978 p->drawWinFocusRect(r, opt.color());
1979
1980 break;
1981 }
1982
1983 case PE_Indicator:
1984 case PE_CheckListIndicator:
1985 case PE_ExclusiveIndicator:
1986 case PE_CheckListExclusiveIndicator:
1987 {
1988 bool sunken = flags & (Style_Sunken | Style_Down);
1989 QWarpPixmap::QWarpInternalPixmap type;
1990 switch(pe)
1991 {
1992 case PE_Indicator:
1993 case PE_CheckListIndicator:
1994 {
1995 if(flags & Style_On)
1996 {
1997 if(sunken)
1998 type = QWarpPixmap::chkboxcheckedsunken;
1999 else
2000 type = QWarpPixmap::chkboxchecked;
2001 }
2002 else if(flags & Style_NoChange)
2003 {
2004 if(sunken)
2005 type = QWarpPixmap::chkboxtrisunken;
2006 else
2007 type = QWarpPixmap::chkboxtri;
2008 }
2009 else
2010 {
2011 if(sunken)
2012 type = QWarpPixmap::chkboxsunken;
2013 else
2014 type = QWarpPixmap::chkboxnormal;
2015 }
2016 break;
2017 }
2018 case PE_ExclusiveIndicator:
2019 case PE_CheckListExclusiveIndicator:
2020 default:
2021 {
2022 if(flags & Style_On)
2023 {
2024 if(sunken)
2025 type = QWarpPixmap::radbutcheckedsunken;
2026 else
2027 type = QWarpPixmap::radbutchecked;
2028 }
2029 else
2030 {
2031 if(sunken)
2032 type = QWarpPixmap::radbutsunken;
2033 else
2034 type = QWarpPixmap::radbutnormal;
2035 }
2036 }
2037 }
2038
2039 QPixmap const* pix = qWarpSystemPixmaps.getPixmap(type,
2040 QWarpPixmap::internal);
2041 p->drawPixmap(r.x(), r.y(), *pix);
2042
2043 break;
2044 }
2045
2046 case PE_IndicatorMask:
2047 {
2048 p->fillRect(r, color1);
2049 break;
2050 }
2051
2052 case PE_ExclusiveIndicatorMask:
2053 {
2054 p->setPen(color1);
2055 p->setBrush(color1);
2056 p->drawEllipse(r);
2057
2058 break;
2059 }
2060
2061 case PE_SpinWidgetPlus:
2062 case PE_SpinWidgetMinus:
2063 case PE_SpinWidgetUp:
2064 case PE_SpinWidgetDown:
2065 {
2066 p->save();
2067
2068 // button background
2069 p->setPen(cg.shadow());
2070 p->fillRect(r, QBrush(cg.button()));
2071
2072 // three possible states
2073 enum { normal, upPressed, downPressed } st;
2074 st = normal;
2075 if(flags & Style_Sunken)
2076 {
2077 if(flags & Style_On)
2078 st = upPressed;
2079 else
2080 st = downPressed;
2081 }
2082
2083 // left and top border
2084 if(upPressed == st) p->setPen(cg.dark());
2085 else p->setPen(cg.light());
2086 p->drawLine(r.topLeft(), r.topRight());
2087 p->drawLine(r.topLeft(), r.bottomLeft());
2088 p->drawLine(r.left(), r.top() + 1, r.right(), r.top() + 1);
2089 p->drawLine(r.left() + 1, r.top(), r.left() + 1, r.bottom());
2090
2091 // right and bottom border
2092 if(downPressed == st) p->setPen(cg.light());
2093 else p->setPen(cg.dark());
2094 p->drawLine(r.topRight(), r.bottomRight());
2095 p->drawLine(r.bottomLeft(), r.bottomRight());
2096 p->drawLine(r.right() - 1, r.top(), r.right() - 1, r.bottom());
2097 p->drawLine(r.left(), r.bottom() - 1, r.right(), r.bottom() - 1);
2098
2099 // diagonal
2100 if(upPressed == st) p->setPen(cg.light());
2101 else p->setPen(cg.shadow());
2102 p->drawLine(r.bottomLeft(), r.topRight());
2103 if(upPressed == st) p->setPen(cg.light());
2104 else p->setPen(cg.dark());
2105 p->drawLine(r.left(), r.bottom() - 1, r.right() - 1, r.top());
2106 if(downPressed == st) p->setPen(cg.dark());
2107 else p->setPen(cg.light());
2108 p->drawLine(r.left() + 1, r.bottom(), r.right(), r.top() + 1);
2109
2110 // rectangles for up/down symbols
2111 QRect upRect;
2112 upRect.setWidth((r.width() - 4) / 2 - 1);
2113 if(1 != (upRect.width() % 2))
2114 {
2115 // we want an odd number for the width and height, and in
2116 // order to avoid too small symbols, we add 1 in case we
2117 // already rounded off during the division by 2 above
2118 if(1 == (r.width() % 2))
2119 upRect.setWidth(upRect.width() + 1);
2120 else
2121 upRect.setWidth(upRect.width() - 1);
2122 }
2123 upRect.setHeight(upRect.width());
2124 upRect.moveTopLeft(r.topLeft() + QPoint(2, 3));
2125 QRect downRect(upRect);
2126 downRect.moveBottomRight(r.bottomRight() - QPoint(3, 3));
2127 if(upPressed == st)
2128 upRect.moveBy(1, 1);
2129 if(downPressed == st)
2130 downRect.moveBy(1, 1);
2131
2132 switch(pe)
2133 {
2134 case PE_SpinWidgetPlus:
2135 case PE_SpinWidgetMinus:
2136 {
2137 p->setPen(cg.buttonText());
2138 p->drawLine(upRect.left(), upRect.center().y(),
2139 upRect.right(), upRect.center().y());
2140 p->drawLine(upRect.center().x(), upRect.top(),
2141 upRect.center().x(), upRect.bottom());
2142 p->drawLine(downRect.left(), downRect.center().y(),
2143 downRect.right(), downRect.center().y());
2144 break;
2145 }
2146
2147 case PE_SpinWidgetUp:
2148 case PE_SpinWidgetDown:
2149 default:
2150 {
2151 p->setBrush(cg.buttonText());
2152 p->setPen(QPen::NoPen);
2153 QPointArray a;
2154 a.putPoints(0, 3,
2155 upRect.left(), upRect.center().y(),
2156 upRect.center().x(), upRect.top(),
2157 upRect.right(), upRect.center().y());
2158 p->drawPolygon(a);
2159 a.resize(0);
2160 a.putPoints(0, 3,
2161 downRect.left(), downRect.center().y(),
2162 downRect.center().x(), downRect.bottom(),
2163 downRect.right(), downRect.center().y());
2164 p->drawPolygon(a);
2165 }
2166 }
2167
2168 p->restore();
2169
2170 break;
2171 }
2172
2173 case PE_Panel:
2174 {
2175 qDrawWarpPanel(p, rr, cg, -1);
2176 break;
2177 }
2178
2179 case PE_PanelPopup:
2180 {
2181 QBrush br(cg.background());
2182 qDrawWarpPanel(p, rr, cg, 1, &br);
2183 break;
2184 }
2185
2186 case PE_PanelTabWidget:
2187 {
2188 // compensate for artificially reduced frame size
2189 // note that we get the information about "bottom" or "top" tabs
2190 // from the "mid line width" in the "opt" parameter
2191 // (see also QWarpTabPanelHeader::QWarpTabPanelHeader)
2192 bool bottom = (bool)opt.midLineWidth();
2193 QRect rr1(rr), rr2(rr);
2194 if(bottom)
2195 {
2196 rr1.addCoords(-11, -11, 14, 0);
2197 rr2.addCoords(0, 0, 3, 0);
2198 }
2199 else
2200 {
2201 rr1.addCoords(-11, 0, 14, 11);
2202 rr2.addCoords(0, 0, 3, 0);
2203 }
2204 p->setClipRect(rr1);
2205
2206 p->setPen(cg.light());
2207 if(bottom)
2208 {
2209 p->drawLine(rr1.left(), rr1.top(), rr1.left(), rr1.bottom());
2210 p->drawLine(rr1.left(), rr1.top(), rr1.right(), rr1.top());
2211 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2212 }
2213 else
2214 {
2215 p->drawLine(rr1.left(), rr1.top(), rr1.left(), rr1.bottom() - 1);
2216 p->drawLine(rr2.left(), rr2.bottom(), rr2.right(), rr2.bottom());
2217 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2218 }
2219
2220 p->setPen(cg.dark());
2221 if(bottom)
2222 {
2223 p->drawLine(rr1.right(), rr1.top(), rr1.right(), rr1.bottom());
2224 p->drawLine(rr2.left(), rr2.top(), rr2.right(), rr2.top());
2225 p->drawLine(rr2.left(), rr2.top(), rr2.left(), rr2.bottom());
2226 rr2.addCoords(0, 2, -3, 0);
2227 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2228 }
2229 else
2230 {
2231 p->drawLine(rr1.left(), rr1.bottom(), rr1.right(), rr1.bottom());
2232 p->drawLine(rr1.right(), rr1.top(), rr1.right(), rr1.bottom());
2233 p->drawLine(rr2.left(), rr2.top(), rr2.left(), rr2.bottom() - 1);
2234 rr2.addCoords(0, 0, -3, -2);
2235 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2236 }
2237
2238 break;
2239 }
2240
2241 case PE_PanelMenuBar:
2242 {
2243 // It looks like this code is never being called!
2244 break;
2245 }
2246
2247 case PE_PanelGroupBox:
2248 {
2249 qDrawWarpPanel(p, rr, cg, 0);
2250 break;
2251 }
2252
2253 case PE_TabBarBase:
2254 {
2255 bool bottom = flags & Style_Bottom;
2256 if(bottom)
2257 rr.addCoords(0, 0, 0, -1);
2258 else
2259 rr.addCoords(0, 1, 0, 0);
2260 QRect rr2(rr);
2261 if(bottom)
2262 rr2.addCoords(11, 0, -11, -11);
2263 else
2264 rr2.addCoords(11, 11, -11, 0);
2265
2266 p->setPen(cg.light());
2267 if(bottom)
2268 {
2269 p->drawLine(rr.left(), rr.top(), rr.left(), rr.bottom());
2270 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2271 p->drawLine(rr2.left(), rr2.bottom(), rr2.right(), rr2.bottom());
2272#ifndef QT_PM_NO_TABWIDGET_HEADERS
2273 p->drawLine(rr2.left() + 6, rr2.top() + 2, rr2.right() - 9, rr2.top() + 2);
2274#endif
2275 }
2276 else
2277 {
2278 p->drawLine(rr.left(), rr.top(), rr.right(), rr.top());
2279 p->drawLine(rr.left(), rr.top(), rr.left(), rr.bottom());
2280 p->drawLine(rr2.right(), rr2.top() + 1, rr2.right(), rr2.bottom());
2281#ifndef QT_PM_NO_TABWIDGET_HEADERS
2282 p->drawLine(rr2.left() + 6, rr2.bottom() - 1, rr2.right() - 9, rr2.bottom() - 1);
2283#endif
2284 }
2285
2286 p->setPen(cg.dark());
2287 if(bottom)
2288 {
2289 p->drawLine(rr.left(), rr.bottom(), rr.right(), rr.bottom());
2290 p->drawLine(rr.right(), rr.top(), rr.right(), rr.bottom());
2291 p->drawLine(rr2.left(), rr2.top(), rr2.left(), rr2.bottom() - 1);
2292#ifndef QT_PM_NO_TABWIDGET_HEADERS
2293 p->drawLine(rr2.left() + 6, rr2.top() + 1, rr2.right() - 9, rr2.top() + 1);
2294#endif
2295 rr2.addCoords(2, 0, -3, -2);
2296 p->drawLine(rr2.left(), rr2.bottom(), rr2.right(), rr2.bottom());
2297 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2298 }
2299 else
2300 {
2301 p->drawLine(rr.right(), rr.top(), rr.right(), rr.bottom());
2302 p->drawLine(rr2.left(), rr2.top(), rr2.right(), rr2.top());
2303 p->drawLine(rr2.left(), rr2.top(), rr2.left(), rr2.bottom());
2304#ifndef QT_PM_NO_TABWIDGET_HEADERS
2305 p->drawLine(rr2.left() + 6, rr2.bottom() - 2, rr2.right() - 9, rr2.bottom() - 2);
2306#endif
2307 rr2.addCoords(2, 2, -3, 0);
2308 p->drawLine(rr2.left(), rr2.top(), rr2.right(), rr2.top());
2309 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2310 }
2311
2312 break;
2313 }
2314
2315 case PE_Splitter:
2316 {
2317 QPen oldPen = p->pen();
2318 p->setPen(cg.light());
2319
2320 if(flags & Style_Horizontal)
2321 {
2322 p->drawLine(r.x() + 1, r.y(), r.x() + 1, r.height());
2323 p->setPen(cg.dark());
2324 p->drawLine(r.x(), r.y(), r.x(), r.height());
2325 p->drawLine(r.right()-1, r.y(), r.right()-1, r.height());
2326 p->setPen(cg.shadow());
2327 p->drawLine(r.right(), r.y(), r.right(), r.height());
2328 }
2329 else
2330 {
2331 p->drawLine(r.x(), r.y() + 1, r.width(), r.y() + 1);
2332 p->setPen(cg.dark());
2333 p->drawLine(r.x(), r.bottom() - 1, r.width(), r.bottom() - 1);
2334 p->setPen(cg.shadow());
2335 p->drawLine(r.x(), r.bottom(), r.width(), r.bottom());
2336 }
2337 p->setPen(oldPen);
2338
2339 break;
2340 }
2341
2342 case PE_DockWindowResizeHandle:
2343 {
2344 QPen oldPen = p->pen();
2345 p->setPen(cg.light());
2346
2347 if(flags & Style_Horizontal)
2348 {
2349 p->drawLine(r.x(), r.y(), r.width(), r.y());
2350 p->setPen(cg.dark());
2351 p->drawLine(r.x(), r.bottom() - 1, r.width(), r.bottom() - 1);
2352 p->setPen(cg.shadow());
2353 p->drawLine(r.x(), r.bottom(), r.width(), r.bottom());
2354 }
2355 else
2356 {
2357 p->drawLine(r.x(), r.y(), r.x(), r.height());
2358 p->setPen(cg.dark());
2359 p->drawLine(r.right()-1, r.y(), r.right()-1, r.height());
2360 p->setPen(cg.shadow());
2361 p->drawLine(r.right(), r.y(), r.right(), r.height());
2362 }
2363 p->setPen(oldPen);
2364
2365 break;
2366 }
2367
2368 case PE_ScrollBarSubLine:
2369 case PE_ScrollBarAddLine:
2370 {
2371 QPointArray pa;
2372 if(flags & Style_Horizontal)
2373 {
2374 int height2 = rr.height() / 2 - 4,
2375 width2 = height2 / 2;
2376 if(pe == PE_ScrollBarSubLine)
2377 {
2378 pa.putPoints(0, 4,
2379 width2, height2,
2380 width2, 1 - height2,
2381 1 - width2, 0,
2382 1 - width2, 1);
2383 }
2384 else
2385 {
2386 pa.putPoints(0, 4,
2387 1 - width2, 1 - height2,
2388 1 - width2, height2,
2389 width2, 1,
2390 width2, 0);
2391 }
2392 }
2393 else
2394 {
2395 int width2 = rr.width() / 2 - 4,
2396 height2 = width2 / 2;
2397 if(pe == PE_ScrollBarSubLine)
2398 {
2399 pa.putPoints(0, 4,
2400 1 - width2, height2,
2401 width2, height2,
2402 1, 1 - height2,
2403 0, 1 - height2);
2404 }
2405 else
2406 {
2407 pa.putPoints(0, 4,
2408 width2, 1 - height2,
2409 1 - width2, 1 - height2,
2410 0, height2,
2411 1, height2);
2412 }
2413 }
2414 pa.translate(rr.center().x(), rr.center().y());
2415
2416 p->setPen(cg.dark());
2417 if(!((flags & Style_Horizontal) && (pe == PE_ScrollBarAddLine)))
2418 {
2419 p->drawLine(rr.topLeft(), rr.bottomLeft());
2420 rr.setLeft(rr.left() + 1);
2421 }
2422 if(!(!(flags & Style_Horizontal) && (pe == PE_ScrollBarAddLine)))
2423 {
2424 p->drawLine(rr.topLeft(), rr.topRight());
2425 rr.setTop(rr.top() + 1);
2426 }
2427 p->setPen(cg.light());
2428 if(!((flags & Style_Horizontal) && (pe == PE_ScrollBarSubLine)))
2429 {
2430 p->drawLine(rr.topRight(), rr.bottomRight());
2431 rr.setRight(rr.right() - 1);
2432 }
2433 if(!(!(flags & Style_Horizontal) && (pe == PE_ScrollBarSubLine)))
2434 {
2435 p->drawLine(rr.bottomLeft(), rr.bottomRight());
2436 rr.setBottom(rr.bottom() - 1);
2437 }
2438
2439 if(!(flags & Style_Down))
2440 flags |= Style_Raised;
2441 drawPrimitive(PE_ButtonBevel, p, rr, cg, flags);
2442 p->setPen(cg.light());
2443 p->drawLine(rr.topRight(), rr.topRight() + QPoint(-1, 1));
2444
2445 QBrush::BrushStyle bs = (flags & Style_Enabled) ? Qt::SolidPattern : Qt::Dense4Pattern;
2446 p->setBrush(QBrush(cg.shadow(), bs));
2447 p->setPen(QPen(Qt::NoPen));
2448 p->drawPolygon(pa);
2449
2450 break;
2451 }
2452
2453 case PE_ScrollBarAddPage:
2454 case PE_ScrollBarSubPage:
2455 case PE_ScrollBarSlider:
2456 {
2457 if(!rr.isValid())
2458 break;
2459
2460 p->setPen(cg.light());
2461 if(flags & Style_Horizontal)
2462 {
2463 p->drawLine(rr.bottomLeft(), rr.bottomRight());
2464 rr.setBottom(rr.bottom() - 1);
2465 }
2466 else
2467 {
2468 p->drawLine(rr.topRight(), rr.bottomRight());
2469 rr.setRight(rr.right() - 1);
2470 }
2471 p->setPen(cg.dark());
2472 if(flags & Style_Horizontal)
2473 {
2474 p->drawLine(rr.topLeft(), rr.topRight());
2475 rr.setTop(rr.top() + 1);
2476 }
2477 else
2478 {
2479 p->drawLine(rr.topLeft(), rr.bottomLeft());
2480 rr.setLeft(rr.left() + 1);
2481 }
2482 p->drawLine(rr.topLeft(), rr.topRight());
2483
2484 if(pe == PE_ScrollBarSlider)
2485 {
2486 if(!(flags & Style_Down))
2487 flags |= Style_Raised;
2488 drawPrimitive(PE_ButtonBevel, p, rr, cg, flags);
2489 QPoint from, to, step;
2490 if(flags & Style_Horizontal)
2491 {
2492 from = QPoint(rr.center().x() - 5, rr.top() + 4);
2493 to = QPoint(rr.center().x() - 5, rr.bottom() - 4);
2494 step = QPoint(1, 0);
2495 }
2496 else
2497 {
2498 from = QPoint(rr.left() + 4, rr.center().y() - 5);
2499 to = QPoint(rr.right() - 4, rr.center().y() - 5);
2500 step = QPoint(0, 1);
2501 }
2502
2503 int i;
2504 for(i = 0; i < 12; ++i)
2505 {
2506 if(0 == (i % 2))
2507 p->setPen(cg.shadow());
2508 else
2509 p->setPen(cg.light());
2510 p->drawLine(from, to);
2511 from += step;
2512 to += step;
2513 }
2514 }
2515
2516 else // ..AddPage or ..SubPage
2517 {
2518 rr.setTop(rr.top() + 1);
2519 p->drawLine(rr.topLeft(), rr.bottomLeft());
2520 rr.setLeft(rr.left() + 1);
2521
2522 QBrush br;
2523 if(flags & Style_Down)
2524 br = QBrush(cg.shadow());
2525 else
2526 br = QBrush(qt_sysclr2qrgb(SYSCLR_SCROLLBAR));
2527 p->setPen(QPen(Qt::NoPen));
2528
2529 p->fillRect(rr, br);
2530 }
2531
2532 break;
2533 }
2534
2535 case PE_WindowFrame:
2536 {
2537 QColorGroup popupCG = cg;
2538 popupCG.setColor(QColorGroup::Light, cg.background());
2539 popupCG.setColor(QColorGroup::Midlight, cg.light());
2540
2541 int lw = opt.isDefault() ? pixelMetric(PM_MDIFrameWidth)
2542 : opt.lineWidth();
2543
2544 if(lw == 2)
2545 {
2546 qDrawWarpPanel(p, r, popupCG, -1);
2547 }
2548 else
2549 {
2550 QBrush fill = QBrush(cg.background());
2551 qDrawWarpPanel(p, r, popupCG, -1, &fill);
2552 }
2553
2554 break;
2555 }
2556
2557 default:
2558 {
2559 if((PE_CheckMark == pe) ||
2560 ((pe >= PE_ArrowUp) && (pe <= PE_ArrowLeft)))
2561 {
2562 QPixmap const* pm = 0;
2563
2564 switch(pe)
2565 {
2566 case PE_ArrowUp:
2567 pm = qWarpSystemPixmaps.getPixmap(QWarpPixmap::arrowup,
2568 QWarpPixmap::internal);
2569 break;
2570
2571 case PE_ArrowDown:
2572 pm = qWarpSystemPixmaps.getPixmap(QWarpPixmap::arrowdown,
2573 QWarpPixmap::internal);
2574 break;
2575
2576 case PE_ArrowRight:
2577 pm = qWarpSystemPixmaps.getPixmap(QWarpPixmap::arrowright,
2578 QWarpPixmap::internal);
2579 break;
2580
2581 case PE_ArrowLeft:
2582 pm = qWarpSystemPixmaps.getPixmap(QWarpPixmap::arrowleft,
2583 QWarpPixmap::internal);
2584 break;
2585
2586 default: // PE_CheckMark
2587 pm = qWarpSystemPixmaps.getPixmap(QWarpPixmap::checkmark,
2588 QWarpPixmap::internal);
2589 break;
2590 }
2591
2592 int x = rr.left() + (rr.width() - pm->width()) / 2,
2593 y = rr.top() + (rr.height() - pm->height()) / 2;
2594 p->drawPixmap(x, y, *pm);
2595 }
2596 else
2597 {
2598 QCommonStyle::drawPrimitive(pe, p, r, cg, flags, opt);
2599 }
2600 }
2601 }
2602}
2603
2604/*!
2605 \reimp
2606*/
2607void QWarp4Style::drawControl(ControlElement element,
2608 QPainter* p,
2609 QWidget const* widget,
2610 QRect const& r,
2611 QColorGroup const& cg,
2612 SFlags flags,
2613 QStyleOption const& opt) const
2614{
2615 switch (element)
2616 {
2617#ifndef QT_NO_TABBAR
2618 case CE_TabBarTab:
2619 {
2620 if(!widget || !widget->parentWidget() || !opt.tab())
2621 break;
2622
2623 QTabBar const* tb = (QTabBar const*)widget;
2624 QTab const* t = opt.tab();
2625 bool selected = flags & Style_Selected,
2626 bottom = (QTabBar::RoundedBelow == tb->shape()) ||
2627 (QTabBar::TriangularBelow == tb->shape());
2628 int id = tb->indexOf(t->identifier());
2629
2630 // check if the panel header widget is already present and
2631 // create them here
2632 // note that this is the only place to do it from within the
2633 // style class!
2634 QWarpTabPanelHeader::addIfNotPresent(tb);
2635
2636 static const QColor tabCols[10] =
2637 {
2638 QColor(85, 219, 255),
2639 QColor(128, 219, 170),
2640 QColor(128, 146, 255),
2641 QColor(213, 182, 170),
2642 QColor(255, 255, 170),
2643 QColor(170, 146, 170),
2644 QColor(255, 146, 85),
2645 QColor(255, 219, 85),
2646 QColor(255, 182, 170),
2647 QColor(255, 219, 170)
2648 };
2649
2650 qDrawTabBar(p, r, cg, tabCols[id % 10], selected, bottom);
2651
2652 if(QApplication::reverseLayout())
2653 {
2654 p->setPen(cg.dark());
2655 int right = tb->size().width() - 1;
2656 if(bottom)
2657 p->drawLine(right, r.top(), right, r.top() + 4);
2658 else
2659 p->drawLine(right, r.bottom(), right, r.bottom() - 4);
2660
2661 }
2662 p->setPen(cg.light());
2663 if(bottom)
2664 p->drawLine(0, r.top(), 0, r.top() + 4);
2665 else
2666 p->drawLine(0, r.bottom(), 0, r.bottom() - 4);
2667
2668 break;
2669 }
2670
2671 case CE_TabBarLabel:
2672 {
2673 if(opt.isDefault())
2674 break;
2675
2676 QTabBar const* tb = (QTabBar const*)widget;
2677 QTab const* t = opt.tab();
2678 bool selected = flags & Style_Selected,
2679 bottom = (QTabBar::RoundedBelow == tb->shape()) ||
2680 (QTabBar::TriangularBelow == tb->shape());
2681
2682 QRect tr(r);
2683 if(bottom)
2684 tr.addCoords(3, 4, 1, 0);
2685 else
2686 tr.addCoords(3, 1, 1, -3);
2687
2688 if(selected)
2689 {
2690 QFont f = p->font();
2691 QRect rold = QFontMetrics(f).boundingRect(t->text());
2692 f.setBold(true);
2693 QRect rnew = QFontMetrics(f).boundingRect(t->text());
2694 p->setFont(f);
2695 int hdiff = rnew.width() - rold.width() + 1;
2696 tr.addCoords(-hdiff / 2, 0, hdiff / 2, 0);
2697
2698 QWidget* pw = widget->parentWidget();
2699 if((0 != pw) && (pw->inherits("QTabWidget")))
2700 {
2701 QTabWidget* tw = (QTabWidget*)pw;
2702 QWarpTabPanelHeader* twh =
2703 (QWarpTabPanelHeader*)tw->child("qt_warp_tabpanel_header",
2704 "QWarpTabPanelHeader", false);
2705 if(0 != twh)
2706 {
2707 twh->setCaption(t->text());
2708 QRect r(twh->visibleRect());
2709 twh->repaint();
2710 }
2711 }
2712 }
2713
2714 int alignment = AlignCenter | ShowPrefix;
2715 if(!styleHint(SH_UnderlineAccelerator, widget, QStyleOption::Default, 0))
2716 alignment |= NoAccel;
2717 drawItem(p, tr, alignment, cg, flags & Style_Enabled, 0, t->text());
2718
2719 if((flags & Style_HasFocus) && !t->text().isEmpty())
2720 drawPrimitive(PE_FocusRect, p, tr, cg);
2721
2722 break;
2723 }
2724#endif // QT_NO_TABBAR
2725
2726 case CE_ToolBoxTab:
2727 {
2728 qDrawWarpPanel(p, r, cg, -1, &cg.brush(QColorGroup::Button));
2729 break;
2730 }
2731
2732 case CE_ProgressBarGroove:
2733 {
2734 QRect rr(r);
2735 QBrush fill = cg.brush(QColorGroup::Button);
2736 qDrawWarpFilledRect(p, rr, cg.dark(), cg.light(), &fill, 2, true);
2737 // For OS/2, this can be also cg.shadow() if the user has clicked on
2738 // the bar with the mouse, but this is only due to the fact that an "OS/2
2739 // progressbar" is actually a slider, not just a display widget
2740 p->setPen(cg.dark());
2741 rr.addCoords(2, 2, -2, -1);
2742 p->drawRect(rr);
2743 break;
2744 }
2745
2746#ifndef QT_NO_PROGRESSBAR
2747 case CE_ProgressBarContents:
2748 {
2749 QProgressBar const* progressbar = (QProgressBar const*)widget;
2750 QColorGroup cgh = cg;
2751 cgh.setColor(QColorGroup::Highlight, QColor(0, 0, 170));
2752 bool reverse = QApplication::reverseLayout();
2753 QRect br(r);
2754 br.addCoords(3, 3, -3, -2);
2755
2756 if(!progressbar->totalSteps())
2757 {
2758 // draw busy indicator
2759 static const int indWidth = 30;
2760 br.addCoords(indWidth / 2, 0, -indWidth / 2, 0);
2761 int bw = br.width();
2762 int x = progressbar->progress() % (bw * 2);
2763 if(x > bw)
2764 x = 2 * bw - x;
2765 x = reverse ? br.right() - x : br.left() + x;
2766 p->setPen(QPen(cgh.highlight(), indWidth));
2767 p->drawLine(x, br.top(), x, br.bottom());
2768 }
2769
2770 else
2771 {
2772 int pos = (progressbar->progress() * br.width()) /
2773 progressbar->totalSteps();
2774 pos = reverse ?
2775 br.right() - pos :
2776 br.left() + pos;
2777
2778 p->setPen(cgh.dark());
2779 p->drawLine(pos, br.top(), pos, br.bottom());
2780
2781 if(reverse)
2782 br.setLeft(pos + 1);
2783 else
2784 br.setRight(pos - 1);
2785
2786 p->fillRect(br, cgh.highlight());
2787 }
2788
2789 break;
2790 }
2791
2792 case CE_ProgressBarLabel:
2793 {
2794 QProgressBar const* progressbar = (QProgressBar const*)widget;
2795 if(0 == progressbar->totalSteps())
2796 break;
2797
2798 if(progressbar->indicatorFollowsStyle() ||
2799 progressbar->centerIndicator())
2800 {
2801 QRect br(r);
2802 br.addCoords(3, 3, -3, -2);
2803 int pos = (progressbar->progress() * br.width()) /
2804 progressbar->totalSteps();
2805 bool reverse = QApplication::reverseLayout();
2806 if(reverse)
2807 pos = br.right() - pos;
2808 else
2809 pos = br.left() + pos;
2810
2811 // paint label black in background area
2812 QRect clip(br);
2813 if(reverse)
2814 clip.setRight(pos);
2815 else
2816 clip.setLeft(pos);
2817 p->setClipRect(clip);
2818 drawItem(p, br, AlignCenter | SingleLine, cg, flags & Style_Enabled, 0,
2819 progressbar->progressString());
2820
2821 // paint label "light" in blue ribbonstrip area
2822 clip = br;
2823 if(reverse)
2824 clip.setLeft(pos);
2825 else
2826 clip.setRight(pos);
2827 p->setClipRect(clip);
2828 drawItem(p, br, AlignCenter | SingleLine, cg, flags & Style_Enabled, 0,
2829 progressbar->progressString(), -1, &cg.highlightedText());
2830 }
2831
2832 else
2833 {
2834 drawItem(p, r, AlignCenter | SingleLine, cg, flags & Style_Enabled, 0,
2835 progressbar->progressString(), -1, 0);
2836 }
2837
2838 break;
2839 }
2840#endif // QT_NO_PROGRESSBAR
2841
2842#ifndef QT_NO_POPUPMENU
2843 case CE_PopupMenuItem:
2844 {
2845 if(!widget || opt.isDefault())
2846 break;
2847
2848 // QPopupMenu has WResizeNoErase and WRepaintNoErase flags, so we
2849 // must erase areas not covered by menu items (this is requested by
2850 // QPopupMenu using 0 as the menu item argument).
2851 // note: we do this with the frame drawing (PE_PanelPopup)
2852
2853 QPopupMenu const* popupmenu = (QPopupMenu const*)widget;
2854 QMenuItem* mi = opt.menuItem();
2855 if(!mi)
2856 break;
2857
2858 int tabw = opt.tabWidth() + 3;
2859 int iconw = QMAX(11, opt.maxIconWidth()) + 6;
2860 bool dis = !(flags & Style_Enabled);
2861 bool act = flags & Style_Active;
2862 bool reverse = QApplication::reverseLayout();
2863 int subw = (qPopupMenuHasSub(popupmenu) ? 19 : 0);
2864
2865 // the popup menu adds 1 pixel vertically on top and bottom, but
2866 // actually needs only 2 at the bottom, so we move all items
2867 // 1 pixel up
2868
2869 QRect rr(r);
2870 rr.moveBy(0, -1);
2871
2872 int x, y, w, h;
2873 rr.rect(&x, &y, &w, &h);
2874
2875 if(mi && mi->isSeparator()) // draw separator
2876 {
2877 p->setPen(cg.dark());
2878 p->drawLine(x, y + 4, x + w, y + 4);
2879 p->setPen(cg.light());
2880 p->drawLine(x, y + 5, x + w, y + 5);
2881 return;
2882 }
2883
2884 if(act)
2885 {
2886 QRect hr(rr);
2887 hr.addCoords(3, 0, -3, 1);
2888 p->fillRect(hr, cg.highlight());
2889 p->setPen(cg.highlightedText());
2890 }
2891 else
2892 {
2893 p->setPen(cg.text());
2894 }
2895
2896 if(mi->iconSet()) // draw iconset
2897 {
2898 QIconSet::Mode mode = dis ? QIconSet::Disabled : QIconSet::Normal;
2899 if(act && !dis)
2900 mode = QIconSet::Active;
2901 QPixmap pixmap;
2902 if(popupmenu->isCheckable() && mi->isChecked())
2903 pixmap = mi->iconSet()->pixmap(QIconSet::Small, mode, QIconSet::On);
2904 else
2905 pixmap = mi->iconSet()->pixmap(QIconSet::Small, mode);
2906 int px = (reverse ? (w - pixmap.width() - 6) : 6);
2907 p->drawPixmap(px, y, pixmap);
2908 }
2909
2910 else if(popupmenu->isCheckable() && mi->isChecked()) // just "checking"...
2911 {
2912 SFlags cflags = Style_Default;
2913 if(!dis)
2914 cflags |= Style_Enabled;
2915 if(act)
2916 cflags |= Style_On;
2917
2918 int xc = (reverse ? w - iconw + 15 : iconw - 15),
2919 yc = (rr.top() + rr.bottom()) / 2 - 3;
2920 drawPrimitive(PE_CheckMark, p, QRect(xc, yc, 16, 8), cg, cflags);
2921 }
2922
2923 if(mi->custom())
2924 {
2925 mi->custom()->paint(p, cg, act, !dis, 0, 10, 8, 8);
2926 }
2927
2928 QString s = mi->text();
2929 if(!s.isNull()) // draw text
2930 {
2931 int text_flags = AlignVCenter | ShowPrefix | DontClip | SingleLine;
2932 if(!styleHint(SH_UnderlineAccelerator, widget))
2933 text_flags |= NoAccel;
2934 text_flags |= (reverse ? AlignRight : AlignLeft);
2935
2936 // tab text
2937 int t = s.find('\t');
2938 QString ts;
2939 if(t >= 0)
2940 {
2941 ts = s.mid(t + 1);
2942 s = s.left(t);
2943 int tx = (reverse ? subw : w - tabw - subw);
2944 p->drawText(tx, y + 1, tabw, h, text_flags, ts);
2945 }
2946
2947 // normal text
2948 int tx = (reverse ? tabw + subw : iconw);
2949 p->drawText(tx, y + 1, w - iconw - tabw - subw, h, text_flags, s);
2950 }
2951
2952 else if(mi->pixmap()) // draw pixmap
2953 {
2954 QPixmap* pixmap = mi->pixmap();
2955 if(pixmap->depth() == 1)
2956 p->setBackgroundMode(OpaqueMode);
2957 int px = (reverse ? (w - pixmap->width() - iconw) : iconw);
2958 if(dis)
2959 {
2960 QIconSet is(*pixmap);
2961 p->drawPixmap(px, y, is.pixmap(QIconSet::Automatic, QIconSet::Disabled));
2962 }
2963 else
2964 {
2965 p->drawPixmap(px, y, *pixmap);
2966 }
2967 if(pixmap->depth() == 1)
2968 p->setBackgroundMode(TransparentMode);
2969 }
2970
2971 if(mi->popup()) // draw sub menu arrow
2972 {
2973 PrimitiveElement arrow;
2974 arrow = (reverse ? PE_ArrowLeft : PE_ArrowRight);
2975 int xa = (reverse ? 5 : w - 15),
2976 ya = (rr.top() + rr.bottom()) / 2 - 4;
2977 drawPrimitive(arrow, p, QRect(xa, ya, 12, 12),
2978 cg, dis ? Style_Default : Style_Enabled);
2979 }
2980 break;
2981 }
2982#endif // QT_NO_POPUPMENU
2983
2984 case CE_MenuBarItem:
2985 {
2986 QWidget* w = (QWidget*)widget;
2987 while(true)
2988 {
2989 QWidget* p = w->parentWidget(true);
2990 if(0 == p)
2991 break;
2992 else
2993 w = p;
2994 }
2995
2996 // here we let the two grey lines disappear at the top and bottom of
2997 // the client area that are actually the empty top and bottom docking
2998 // areas (only as long as they are empty, of course)
2999 if(w->inherits("QMainWindow"))
3000 QWarpMainWindowLayouter::addIfNotPresent((QMainWindow*)w);
3001
3002 bool act = flags & Style_Active;
3003 QColorGroup mcg(cg);
3004
3005 if(act)
3006 {
3007 QRect hr(r);
3008 hr.addCoords(0, 2, 0, 0);
3009 p->fillRect(hr, cg.highlight());
3010 mcg.setColor(QColorGroup::ButtonText, mcg.highlightedText());
3011 }
3012 else
3013 {
3014 mcg.setColor(QColorGroup::ButtonText, mcg.text());
3015 }
3016
3017 QCommonStyle::drawControl(element, p, widget, r, mcg, flags, opt);
3018 break;
3019 }
3020
3021#ifndef QT_NO_TOOLBUTTON
3022 case CE_ToolButtonLabel:
3023 {
3024 if (!qstrcmp (widget->name(), "qt_left_btn") ||
3025 !qstrcmp (widget->name(), "qt_right_btn"))
3026 {
3027 // do nothing in this case!
3028 }
3029 else
3030 {
3031 QToolButton const *toolbutton = (QToolButton const *) widget;
3032 QRect rect = r;
3033 Qt::ArrowType arrowType = opt.isDefault() ?
3034 Qt::DownArrow : opt.arrowType();
3035
3036 if (flags & (Style_Down | Style_On))
3037 rect.moveBy (pixelMetric(PM_ButtonShiftHorizontal, widget),
3038 pixelMetric(PM_ButtonShiftVertical, widget));
3039
3040 if (!opt.isDefault())
3041 {
3042 PrimitiveElement pe;
3043 switch (arrowType)
3044 {
3045 case Qt::LeftArrow:
3046 pe = PE_ArrowLeft;
3047 break;
3048 case Qt::RightArrow:
3049 pe = PE_ArrowRight;
3050 break;
3051 case Qt::UpArrow:
3052 pe = PE_ArrowUp;
3053 break;
3054 default:
3055 case Qt::DownArrow:
3056 pe = PE_ArrowDown;
3057 break;
3058 }
3059
3060 drawPrimitive (pe, p, rect, cg, flags, opt);
3061 }
3062 else
3063 {
3064 QColor btext = toolbutton->paletteForegroundColor();
3065
3066 if (toolbutton->iconSet().isNull() &&
3067 !toolbutton->text().isNull() &&
3068 !toolbutton->usesTextLabel())
3069 {
3070 int alignment = AlignCenter | AlignVCenter | ShowPrefix;
3071
3072 if (!styleHint (SH_UnderlineAccelerator, widget,
3073 QStyleOption::Default, 0))
3074 alignment |= NoAccel;
3075
3076 drawItem (p, rect, alignment, cg,
3077 flags & Style_Enabled, 0, toolbutton->text(),
3078 toolbutton->text().length(), &btext);
3079 }
3080 else
3081 {
3082 QPixmap pm;
3083
3084 QIconSet::Size size =
3085 toolbutton->usesBigPixmap() ? QIconSet::Large : QIconSet::Small;
3086
3087 QIconSet::State state =
3088 toolbutton->isOn() ? QIconSet::On : QIconSet::Off;
3089
3090 QIconSet::Mode mode;
3091 if (!toolbutton->isEnabled())
3092 mode = QIconSet::Disabled;
3093 else if (flags & (Style_Down | Style_On | Style_Raised))
3094 mode = QIconSet::Active;
3095 else
3096 mode = QIconSet::Normal;
3097
3098 pm = toolbutton->iconSet().pixmap(size, mode, state);
3099
3100 if (toolbutton->usesTextLabel())
3101 {
3102 if (toolbutton->textPosition() == QToolButton::Under)
3103 {
3104 p->setFont(toolbutton->font());
3105
3106 QRect pr = rect, tr = rect;
3107 int fh = p->fontMetrics().height();
3108 pr.addCoords (0, 1, 0, -fh - 3);
3109 tr.addCoords (0, pr.bottom(), 0, -3);
3110 drawItem (p, pr, AlignCenter, cg, TRUE, &pm, QString::null);
3111 int alignment = AlignCenter | ShowPrefix;
3112
3113 if (!styleHint (SH_UnderlineAccelerator, widget, QStyleOption::Default, 0))
3114 alignment |= NoAccel;
3115
3116 drawItem (p, tr, alignment, cg,
3117 flags & Style_Enabled, 0, toolbutton->textLabel(),
3118 toolbutton->textLabel().length(), &btext);
3119 }
3120 else
3121 {
3122 p->setFont (toolbutton->font());
3123
3124 QRect pr = rect, tr = rect;
3125 pr.setWidth (pm.width() + 8);
3126 tr.addCoords (pr.right(), 0, 0, 0);
3127 drawItem (p, pr, AlignCenter, cg, TRUE, &pm, QString::null);
3128 int alignment = AlignLeft | AlignVCenter | ShowPrefix;
3129
3130 if (!styleHint(SH_UnderlineAccelerator, widget, QStyleOption::Default, 0))
3131 alignment |= NoAccel;
3132
3133 drawItem (p, tr, alignment, cg,
3134 flags & Style_Enabled, 0, toolbutton->textLabel(),
3135 toolbutton->textLabel().length(), &btext);
3136 }
3137 }
3138 else
3139 {
3140 drawItem (p, rect, AlignCenter, cg, TRUE, &pm, QString::null);
3141 }
3142 }
3143 }
3144 }
3145
3146 break;
3147 }
3148#endif // QT_NO_TOOLBUTTON
3149
3150 default:
3151 {
3152 QCommonStyle::drawControl(element, p, widget, r, cg, flags, opt);
3153 }
3154 }
3155}
3156
3157/*!
3158 \reimp
3159*/
3160int QWarp4Style::pixelMetric(PixelMetric metric, QWidget const* widget) const
3161{
3162 int ret;
3163
3164 switch (metric)
3165 {
3166 case PM_ButtonDefaultIndicator:
3167 case PM_ButtonShiftHorizontal:
3168 case PM_ButtonShiftVertical:
3169 {
3170 ret = 1;
3171 break;
3172 }
3173
3174 case PM_IndicatorWidth:
3175 case PM_ExclusiveIndicatorWidth:
3176 {
3177 QPixmap const* ip = qWarpSystemPixmaps.getPixmap(QWarpPixmap::chkboxnormal,
3178 QWarpPixmap::internal);
3179 ret = ip->width();
3180 break;
3181 }
3182
3183 case PM_IndicatorHeight:
3184 case PM_ExclusiveIndicatorHeight:
3185 {
3186 QPixmap const* ip = qWarpSystemPixmaps.getPixmap(QWarpPixmap::chkboxnormal,
3187 QWarpPixmap::internal);
3188 ret = ip->height();
3189 break;
3190 }
3191
3192 #ifndef QT_NO_SCROLLBAR
3193 case PM_ScrollBarExtent:
3194 {
3195 if(!widget)
3196 {
3197 ret = 16;
3198 }
3199 else
3200 {
3201 QScrollBar const* bar = (QScrollBar const*)widget;
3202 int s = (bar->orientation() == Qt::Horizontal) ?
3203 QApplication::globalStrut().height() :
3204 QApplication::globalStrut().width();
3205 ret = QMAX(16, s);
3206 }
3207
3208 break;
3209 }
3210
3211 case PM_ScrollBarSliderMin:
3212 {
3213 ret = 20;
3214 break;
3215 }
3216 #endif
3217
3218 case PM_MaximumDragDistance:
3219 {
3220 ret = -1;
3221 break;
3222 }
3223
3224 #ifndef QT_NO_SLIDER
3225 case PM_SliderThickness:
3226 {
3227 ret = 20;
3228 break;
3229 }
3230
3231 case PM_SliderLength:
3232 {
3233 // we increase the "length" by 2 x 2, but then draw the slider 2 pixels
3234 // smaller than indicated, so we get the effect of a slider that does
3235 // not fully touch the extreme ends of the "groove"
3236 ret = 12 + 4;
3237 break;
3238 }
3239
3240 // Returns the number of pixels to use for the business part of the
3241 // slider (i.e., the non-tickmark portion). The remaining space is shared
3242 // equally between the tickmark regions.
3243 case PM_SliderControlThickness:
3244 {
3245 QSlider const* sl = (QSlider const*) widget;
3246 int space = (sl->orientation() == Horizontal) ? sl->height() : sl->width();
3247 int ticks = sl->tickmarks();
3248 int n = 0;
3249 if(ticks & QSlider::Above)
3250 n++;
3251 if(ticks & QSlider::Below)
3252 n++;
3253 if(!n)
3254 {
3255 ret = space;
3256 break;
3257 }
3258
3259 int thick = 6; // Magic constant to get 5 + 16 + 5
3260 if(ticks != QSlider::Both && ticks != QSlider::NoMarks)
3261 thick += pixelMetric(PM_SliderLength, sl) / 4;
3262
3263 space -= thick;
3264 //### the two sides may be unequal in size
3265 if(space > 0)
3266 thick += (space * 2) / (n + 2);
3267 ret = thick;
3268
3269 break;
3270 }
3271 #endif // QT_NO_SLIDER
3272
3273 case PM_MenuBarFrameWidth:
3274 {
3275 ret = 0;
3276 break;
3277 }
3278
3279 case PM_MenuBarItemSpacing:
3280 {
3281 ret = 8;
3282 break;
3283 }
3284
3285 case PM_PopupMenuFrameHorizontalExtra:
3286 {
3287 ret = 0;
3288 break;
3289 }
3290
3291 case PM_PopupMenuFrameVerticalExtra:
3292 {
3293 ret = 1;
3294 break;
3295 }
3296
3297 case PM_TabBarTabOverlap:
3298 {
3299 ret = 10;
3300 break;
3301 }
3302
3303 case PM_TabBarBaseHeight:
3304 {
3305#ifndef QT_PM_NO_TABWIDGET_HEADERS
3306 ret = QFontMetrics(QApplication::font()).boundingRect("X").height() + 29;
3307#else
3308 ret = 16;
3309#endif
3310 break;
3311 }
3312
3313 case PM_TabBarBaseOverlap:
3314 {
3315 ret = 6;
3316 break;
3317 }
3318
3319 case PM_TabBarTabHSpace:
3320 {
3321 ret = 28;
3322 break;
3323 }
3324
3325 case PM_TabBarTabVSpace:
3326 {
3327 ret = 9;
3328 break;
3329 }
3330
3331 case PM_TabBarScrollButtonWidth:
3332 {
3333 ret = 25;
3334 break;
3335 }
3336
3337 case PM_TabBarTabShiftHorizontal:
3338 case PM_TabBarTabShiftVertical:
3339 {
3340 ret = 0;
3341 break;
3342 }
3343
3344 case PM_SplitterWidth:
3345 {
3346 ret = QMAX(6, QApplication::globalStrut().width());
3347 break;
3348 }
3349
3350 default:
3351 {
3352 ret = QCommonStyle::pixelMetric(metric, widget);
3353 break;
3354 }
3355 }
3356
3357 return ret;
3358}
3359
3360/*!
3361 \reimp
3362*/
3363QSize QWarp4Style::sizeFromContents(ContentsType contents,
3364 QWidget const* widget,
3365 QSize const& contentsSize,
3366 QStyleOption const& opt) const
3367{
3368 QSize sz(contentsSize);
3369
3370 switch (contents)
3371 {
3372 case CT_PushButton:
3373 {
3374#ifndef QT_NO_PUSHBUTTON
3375 const QPushButton* button = (const QPushButton*)widget;
3376 sz = QCommonStyle::sizeFromContents(contents, widget, contentsSize, opt);
3377 int w = sz.width(),
3378 h = sz.height();
3379
3380 int defwidth = 0;
3381 if(button->isDefault() || button->autoDefault())
3382 defwidth = 2 * pixelMetric(PM_ButtonDefaultIndicator, widget);
3383 if(w < 80 + defwidth && !button->pixmap())
3384 w = 80 + defwidth;
3385 if(h < 23 + defwidth)
3386 h = 23 + defwidth;
3387
3388 sz = QSize(w, h);
3389#endif // QT_NO_PUSHBUTTON
3390
3391 break;
3392 }
3393
3394 case CT_ToolButton:
3395 {
3396 // this includes 3px margin drawn for PE_ButtonTool + 1px spacing
3397 // around contents + 1px extra width/height for pressed icon shift
3398 sz = QSize (sz.width() + 9, sz.height() + 9);
3399 break;
3400 }
3401
3402 case CT_PopupMenuItem:
3403 {
3404#ifndef QT_NO_POPUPMENU
3405 if(! widget || opt.isDefault())
3406 break;
3407
3408 QPopupMenu const* popup = (QPopupMenu const*)widget;
3409 QMenuItem* mi = opt.menuItem();
3410 int iconw = QMAX(11, opt.maxIconWidth());
3411 QString s = mi->text();
3412 int w = sz.width(),
3413 h = sz.height();
3414
3415 if(mi->custom())
3416 {
3417 w = mi->custom()->sizeHint().width();
3418 h = mi->custom()->sizeHint().height();
3419 if(!mi->custom()->fullSpan())
3420 w += iconw;
3421 }
3422 else if(mi->widget())
3423 {
3424 }
3425 else if(mi->isSeparator())
3426 {
3427 w = 10; // arbitrary
3428 h = 8;
3429 }
3430 else
3431 {
3432 if(mi->pixmap())
3433 h = QMAX(h, mi->pixmap()->height() + 3);
3434 else if(!s.isNull())
3435 h = QMAX(h, popup->fontMetrics().height() + 1);
3436
3437 if(mi->iconSet())
3438 {
3439 h = QMAX(h, mi->iconSet()->
3440 pixmap(QIconSet::Small, QIconSet::Normal).height() + 3);
3441 w = QMAX(w, iconw);
3442 }
3443 }
3444
3445 if(!s.isNull())
3446 {
3447 w += 19;
3448 }
3449
3450 if(qPopupMenuHasSub(popup))
3451 {
3452 w += 19;
3453 }
3454
3455 w += 9;
3456
3457 sz = QSize(w, h);
3458#endif // QT_NO_POPUPMENU
3459
3460 break;
3461 }
3462
3463 case CT_MenuBar:
3464 {
3465 // It looks like this code is never being called!
3466 break;
3467 }
3468
3469 case CT_SpinBox:
3470 {
3471 sz.setHeight(sz.height() - 2);
3472 break;
3473 }
3474
3475 case CT_TabWidget:
3476 {
3477 sz.setWidth(sz.width() + 32); // 16, 16
3478 sz.setHeight(sz.height() + 14); // 0, 14
3479 break;
3480 }
3481
3482 case CT_LineEdit:
3483 {
3484 sz.setHeight(sz.height() - 1);
3485 break;
3486 }
3487
3488 default:
3489 {
3490 sz = QCommonStyle::sizeFromContents(contents, widget, sz, opt);
3491 break;
3492 }
3493 }
3494
3495 return sz;
3496}
3497
3498/*! \reimp
3499*/
3500void QWarp4Style::polishPopupMenu(QPopupMenu* p)
3501{
3502 #ifndef QT_NO_POPUPMENU
3503 if(!p->testWState(WState_Polished))
3504 p->setCheckable(TRUE);
3505 #endif
3506}
3507
3508/*!
3509 \reimp
3510 */
3511QPixmap QWarp4Style::stylePixmap(StylePixmap stylepixmap,
3512 QWidget const* widget,
3513 QStyleOption const& opt) const
3514{
3515 #ifndef QT_NO_IMAGEIO_XPM
3516 switch (stylepixmap)
3517 {
3518 // SP_TitleBarShadeButton - shade button on titlebars.
3519 case SP_TitleBarShadeButton:
3520 return *qWarpSystemPixmaps.getPixmap(54, // any SBMP_ value??
3521 QWarpPixmap::bmp);
3522
3523 // SP_TitleBarUnshadeButton - unshade button on titlebars.
3524 case SP_TitleBarUnshadeButton:
3525 return *qWarpSystemPixmaps.getPixmap(56, // any SBMP_ value??
3526 QWarpPixmap::bmp);
3527
3528 // SP_TitleBarNormalButton - normal (restore) button on titlebars.
3529 case SP_TitleBarNormalButton:
3530 return *qWarpSystemPixmaps.getPixmap(SBMP_RESTOREBUTTON,
3531 QWarpPixmap::bmp);
3532
3533 // SP_TitleBarMinButton - minimize button on titlebars. For example, in a QWorkspace.
3534 case SP_TitleBarMinButton:
3535 return *qWarpSystemPixmaps.getPixmap(SBMP_MINBUTTON,
3536 QWarpPixmap::bmp);
3537
3538 // SP_TitleBarMaxButton - maximize button on titlebars.
3539 case SP_TitleBarMaxButton:
3540 return *qWarpSystemPixmaps.getPixmap(SBMP_MAXBUTTON,
3541 QWarpPixmap::bmp);
3542
3543 // SP_TitleBarCloseButton - close button on titlebars.
3544 case SP_TitleBarCloseButton:
3545 return *qWarpSystemPixmaps.getPixmap(52, // any SBMP_ value??
3546 QWarpPixmap::bmp);
3547
3548 // SP_DockWindowCloseButton - close button on dock windows; see also QDockWindow.
3549 case SP_DockWindowCloseButton:
3550 return *qWarpSystemPixmaps.getPixmap(52, // should be a bit smaller!
3551 QWarpPixmap::bmp);
3552
3553 // SP_MessageBoxInformation - the 'information' icon.
3554 case SP_MessageBoxInformation:
3555 return *qWarpSystemPixmaps.getPixmap(SPTR_ICONINFORMATION,
3556 QWarpPixmap::ico);
3557
3558 // SP_MessageBoxWarning - the 'warning' icon.
3559 case SP_MessageBoxWarning:
3560 return *qWarpSystemPixmaps.getPixmap(SPTR_ICONWARNING,
3561 QWarpPixmap::ico);
3562
3563 // SP_MessageBoxCritical - the 'critical' icon.
3564 case SP_MessageBoxCritical:
3565 return *qWarpSystemPixmaps.getPixmap(SPTR_ICONERROR,
3566 QWarpPixmap::ico);
3567
3568 // SP_MessageBoxQuestion - the 'question' icon.
3569 case SP_MessageBoxQuestion:
3570 return *qWarpSystemPixmaps.getPixmap(SPTR_ICONQUESTION,
3571 QWarpPixmap::ico);
3572
3573 default:
3574 break;
3575 }
3576 #endif //QT_NO_IMAGEIO_XPM
3577
3578 return QCommonStyle::stylePixmap(stylepixmap, widget, opt);
3579}
3580
3581/*!\reimp
3582*/
3583void QWarp4Style::drawComplexControl(ComplexControl ctrl, QPainter *p,
3584 QWidget const* widget,
3585 QRect const& r,
3586 QColorGroup const& cg,
3587 SFlags flags,
3588 SCFlags sub,
3589 SCFlags subActive,
3590 QStyleOption const& opt) const
3591{
3592 switch (ctrl)
3593 {
3594 #ifndef QT_NO_SCROLLBAR
3595 case CC_ScrollBar:
3596 {
3597 QScrollBar const* scrollbar = (QScrollBar const*)widget;
3598 bool maxedOut = (scrollbar->minValue() == scrollbar->maxValue());
3599
3600 QRect subline = querySubControlMetrics(ctrl, widget, SC_ScrollBarSubLine, opt),
3601 addline = querySubControlMetrics(ctrl, widget, SC_ScrollBarAddLine, opt),
3602 subpage = querySubControlMetrics(ctrl, widget, SC_ScrollBarSubPage, opt),
3603 addpage = querySubControlMetrics(ctrl, widget, SC_ScrollBarAddPage, opt),
3604 slider = querySubControlMetrics(ctrl, widget, SC_ScrollBarSlider, opt);
3605 if(!scrollbar->isEnabled())
3606 {
3607 subpage.unite(addpage).unite(slider); // fill the whole, empty bar
3608 addpage = slider = QRect(); // invalid rectangle
3609 maxedOut = true; // to avoid setting the Style_Enabled flag
3610 }
3611 bool isMin = scrollbar->value() <= scrollbar->minValue(),
3612 isMax = scrollbar->value() >= scrollbar->maxValue();
3613
3614 if((sub & SC_ScrollBarSubLine) && subline.isValid())
3615 drawPrimitive(PE_ScrollBarSubLine, p, subline, cg,
3616 ((maxedOut || isMin) ? Style_Default : Style_Enabled) |
3617 ((!isMin && (subActive == SC_ScrollBarSubLine)) ? Style_Down : Style_Default) |
3618 ((scrollbar->orientation() == Qt::Horizontal) ? Style_Horizontal : 0));
3619 if((sub & SC_ScrollBarAddLine) && addline.isValid())
3620 drawPrimitive(PE_ScrollBarAddLine, p, addline, cg,
3621 ((maxedOut || isMax) ? Style_Default : Style_Enabled) |
3622 ((!isMax && (subActive == SC_ScrollBarAddLine)) ? Style_Down : Style_Default) |
3623 ((scrollbar->orientation() == Qt::Horizontal) ? Style_Horizontal : 0));
3624 if((sub & SC_ScrollBarSubPage) && subpage.isValid())
3625 drawPrimitive(PE_ScrollBarSubPage, p, subpage, cg,
3626 ((maxedOut) ? Style_Default : Style_Enabled) |
3627 ((subActive == SC_ScrollBarSubPage) ? Style_Down : Style_Default) |
3628 ((scrollbar->orientation() == Qt::Horizontal) ? Style_Horizontal : 0));
3629 if((sub & SC_ScrollBarAddPage) && addpage.isValid())
3630 drawPrimitive(PE_ScrollBarAddPage, p, addpage, cg,
3631 ((maxedOut) ? Style_Default : Style_Enabled) |
3632 ((subActive == SC_ScrollBarAddPage) ? Style_Down : Style_Default) |
3633 ((scrollbar->orientation() == Qt::Horizontal) ? Style_Horizontal : 0));
3634 if((sub & SC_ScrollBarSlider) && slider.isValid())
3635 drawPrimitive(PE_ScrollBarSlider, p, slider, cg,
3636 ((maxedOut) ? Style_Default : Style_Enabled) |
3637 ((subActive == SC_ScrollBarSlider) ? Style_Down : Style_Default) |
3638 ((scrollbar->orientation() == Qt::Horizontal) ? Style_Horizontal : 0));
3639
3640 break;
3641 }
3642 #endif // QT_NO_SCROLLBAR
3643
3644 case CC_SpinWidget:
3645 {
3646 #ifndef QT_NO_SPINWIDGET
3647 QSpinWidget const* sw = (QSpinWidget const*)widget;
3648 SFlags flags;
3649 PrimitiveElement pe;
3650
3651 if(sub & SC_SpinWidgetFrame)
3652 {
3653 qDrawWarpPanel(p, r, cg, -1);
3654 }
3655
3656 if((sub & SC_SpinWidgetUp) ||
3657 (sub & SC_SpinWidgetDown))
3658 {
3659 flags = Style_Enabled;
3660 if((subActive == SC_SpinWidgetUp) ||
3661 (subActive == SC_SpinWidgetDown))
3662 flags |= Style_Sunken;
3663 else
3664 flags |= Style_Raised;
3665
3666 // we "misuse" the On flag to indicate whether the
3667 // "up" part or the "down" part of the button is sunken
3668 if(subActive == SC_SpinWidgetUp)
3669 flags |= Style_On;
3670
3671 if(sub & SC_SpinWidgetUp)
3672 {
3673 if(sw->buttonSymbols() == QSpinWidget::PlusMinus)
3674 pe = PE_SpinWidgetPlus;
3675 else
3676 pe = PE_SpinWidgetUp;
3677 }
3678 else
3679 {
3680 if(sw->buttonSymbols() == QSpinWidget::PlusMinus)
3681 pe = PE_SpinWidgetMinus;
3682 else
3683 pe = PE_SpinWidgetDown;
3684 }
3685
3686 QRect re = sw->upRect();
3687 re.setWidth(re.width() - 2);
3688 bool reverse = QApplication::reverseLayout();
3689 if(!reverse)
3690 re.moveLeft(re.left() + 2);
3691 drawPrimitive(pe, p, re, cg, flags);
3692
3693 // doesn't work yet...
3694 int x = re.left() - 1;
3695 if(reverse)
3696 {
3697 x = re.right() + 2;
3698 p->setPen(cg.light());
3699 }
3700 else
3701 {
3702 p->setPen(cg.dark());
3703 }
3704 p->drawLine(x, re.top(), x, re.bottom());
3705 p->setPen(cg.button());
3706 x--;
3707 p->drawLine(x, re.top(), x, re.bottom());
3708 }
3709
3710 //if(sub & SC_SpinWidgetDown)
3711 //{
3712 // do nothing!
3713 // note: for the Warp style we put all the up/down button
3714 // functionality into the "up" button with the diagonal
3715 // separator
3716 //}
3717 #endif
3718
3719 break;
3720 }
3721
3722 #ifndef QT_NO_TOOLBUTTON
3723 case CC_ToolButton:
3724 {
3725 bool right;
3726 if((right = (QString("qt_right_btn") == widget->name())) ||
3727 (QString("qt_left_btn") == widget->name()))
3728 {
3729 QToolButton* tb = (QToolButton*)widget;
3730 QTabBar* ptb = (QTabBar*)tb->parentWidget();
3731 if((0 == ptb) || !ptb->inherits("QTabBar"))
3732 return;
3733 bool bottom = (QTabBar::RoundedBelow == ptb->shape()) ||
3734 (QTabBar::TriangularBelow == ptb->shape());
3735
3736 QRect r(visualRect(querySubControlMetrics(ctrl, widget, SC_ToolButton, opt), widget));
3737 if(right)
3738 r.addCoords(-3, 0, 0, 0);
3739 else
3740 r.addCoords(0, 0, 3, 0);
3741 p->setClipRect(r);
3742
3743 p->setPen(cg.dark());
3744 if(right)
3745 {
3746 if(bottom)
3747 p->drawLine(r.right(), r.top(), r.right(), r.top() + 3);
3748 else
3749 p->drawLine(r.right(), r.bottom(), r.right(), r.bottom() - 3);
3750 }
3751
3752 QRect tr1(r), tr2(r);
3753 if(right)
3754 {
3755 tr1.addCoords(-1, 0, 1, 0);
3756 tr2.addCoords(-21, 0, -21, 0);
3757 }
3758 else
3759 {
3760 tr1.addCoords(21, 0, 21, 0);
3761 tr2.addCoords(-1, 0, 1, 0);
3762 }
3763
3764 QColorGroup const& cg(tb->colorGroup());
3765 qDrawTabBar(p, tr1, cg, cg.background(), false, bottom);
3766 qDrawTabBar(p, tr2, cg, cg.background(), false, bottom);
3767
3768 if(bottom)
3769 r.addCoords(0, 2, 0, 2);
3770 QPointArray triang;
3771 if(right)
3772 {
3773 triang.putPoints(0, 3,
3774 r.left() + 8, r.top() + 6,
3775 r.left() + 19, r.top() + 12,
3776 r.left() + 8, r.top() + 18);
3777 }
3778 else
3779 {
3780 triang.putPoints(0, 3,
3781 r.right() - 10, r.top() + 6,
3782 r.right() - 21, r.top() + 12,
3783 r.right() - 10, r.top() + 18);
3784 }
3785 p->setBrush(QColor(0, 0, 255));
3786 p->setPen(QPen::NoPen);
3787 p->drawPolygon(triang);
3788 }
3789
3790 else
3791 {
3792 QCommonStyle::drawComplexControl(ctrl, p, widget, r, cg, flags, sub,
3793 subActive, opt);
3794 }
3795
3796 break;
3797 }
3798 #endif // QT_NO_TOOLBUTTON
3799
3800 #ifndef QT_NO_LISTVIEW
3801 case CC_ListView:
3802 {
3803 if(sub & SC_ListView)
3804 {
3805 QCommonStyle::drawComplexControl(ctrl, p, widget, r, cg, flags, sub, subActive, opt);
3806 }
3807
3808 if(sub & (SC_ListViewBranch | SC_ListViewExpand))
3809 {
3810 QListViewItem *item = opt.listViewItem(),
3811 *child = item->firstChild();
3812 QListView* v = item->listView();
3813 int y = r.y();
3814 int bx = r.width() / 2;
3815 int // linetop = 0,
3816 linebot = 0;
3817
3818 // skip the stuff above the exposed rectangle
3819 while(child && ((y + child->height()) <= 0))
3820 {
3821 y += child->totalHeight();
3822 child = child->nextSibling();
3823 }
3824
3825 // notes about drawing lines for Warp:
3826 // 1. Warp type lines follow a different logic than the "normal" lines
3827 // for "tree views" in Qt (which follows more or less Windows)
3828 // 2. In order to ensure partial repaints, it looks like we have to
3829 // draw some lines twice: once with the parent and once with the
3830 // child (and hopefully to the same place...)
3831
3832 while(child && (y < r.height()))
3833 {
3834 if(child->isVisible())
3835 {
3836 int lh;
3837 if(!item->multiLinesEnabled())
3838 lh = child->height();
3839 else
3840 lh = p->fontMetrics().height() + 2 * v->itemMargin();
3841 lh = QMAX(lh, QApplication::globalStrut().height());
3842 if((lh % 2) > 0)
3843 lh++;
3844 linebot = y + lh / 2;
3845 p->setPen(cg.shadow());
3846
3847 // parents and grandparents
3848 int vlx = bx - v->treeStepSize() + 2,
3849 vlyt = linebot - child->height() + 8,
3850 vlyb = linebot - child->height() + 9 + child->totalHeight();
3851 if(0 <= item->depth())
3852 {
3853 // vertical line for parent
3854 if(item->isOpen())
3855 {
3856 if(0 == child->nextSibling())
3857 p->drawLine(vlx, vlyt, vlx, linebot - 2);
3858 else
3859 p->drawLine(vlx, vlyt, vlx, vlyb);
3860 }
3861
3862 // vertical lines for grandparents and "older"
3863 QListViewItem* gp = item;
3864 while(0 < gp->depth())
3865 {
3866 gp = gp->parent();
3867 vlx -= v->treeStepSize();
3868 if(0 != gp->nextSibling())
3869 p->drawLine(vlx, vlyt, vlx, vlyb);
3870 }
3871 }
3872
3873 // draw child itself
3874 if((child->isExpandable() || child->childCount()) &&
3875 (child->height() > 0))
3876 {
3877 // horizontal line up to button
3878 if((0 <= item->depth()) && item->isOpen())
3879 {
3880 p->drawLine(bx - v->treeStepSize() + 3, linebot - 2,
3881 bx - 6, linebot - 2);
3882 }
3883
3884 // button
3885 QRect rr(bx - 6, linebot - 9, 16, 16);
3886 drawPrimitive(PE_ButtonCommand, p, rr, cg,
3887 Style_Raised | Style_ButtonDefault);
3888
3889 // plus or minus
3890 p->setPen(cg.light());
3891 p->drawLine(bx, linebot - 1, bx + 6, linebot - 1);
3892 if(!child->isOpen())
3893 p->drawLine(bx + 3, linebot + 2, bx + 3, linebot - 4);
3894 p->setPen(cg.shadow());
3895 p->drawLine(bx - 1, linebot - 2, bx + 5, linebot - 2);
3896 if(!child->isOpen())
3897 p->drawLine(bx + 2, linebot + 1, bx + 2, linebot - 5);
3898
3899 // lines below expanded child
3900 if(child->isOpen())
3901 {
3902 // vertical line
3903 p->drawLine(bx + 2,
3904 linebot + child->height() - 15,
3905 bx + 2,
3906 linebot + child->totalHeight() - child->height() - 2);
3907
3908 // horizontal lines at child's children
3909 QListViewItem* child2 = child->firstChild();
3910 int y2 = linebot + child->height() - 2;
3911 while(child2 && (y2 < r.height()))
3912 {
3913 if(child2->isVisible())
3914 {
3915 p->drawLine(bx + 2, y2,
3916 bx + v->treeStepSize() - 12, y2);
3917 y2 += child2->totalHeight();
3918 }
3919 child2 = child2->nextSibling();
3920 }
3921 }
3922 }
3923 else if((0 <= item->depth()) && item->isOpen())
3924 {
3925 // horizontal line without button
3926 p->setPen(cg.shadow());
3927 p->drawLine(bx - v->treeStepSize() + 3, linebot - 2,
3928 bx + 8, linebot - 2);
3929 }
3930
3931 y += child->totalHeight();
3932 }
3933 child = child->nextSibling();
3934 }
3935 }
3936
3937 break;
3938 }
3939 #endif //QT_NO_LISTVIEW
3940
3941 #ifndef QT_NO_COMBOBOX
3942 case CC_ComboBox:
3943 {
3944 if(sub & SC_ComboBoxFrame)
3945 {
3946 qDrawWarpPanel(p, r, cg, -1);
3947 p->setPen(cg.dark());
3948 int x = r.right() - 2 - 16;
3949 p->drawLine(x, r.top() + 2, x, r.bottom() - 2);
3950 }
3951
3952 if(sub & SC_ComboBoxArrow)
3953 {
3954 QRect ar = visualRect(querySubControlMetrics(CC_ComboBox, widget,
3955 SC_ComboBoxArrow),
3956 widget);
3957 QBrush fill = cg.brush(QColorGroup::Button);
3958 bool sunken = subActive == SC_ComboBoxArrow;
3959 qDrawWarpFilledRect(p, ar, cg.dark(), cg.light(), &fill, 2, sunken);
3960 p->setPen(cg.button());
3961 p->drawLine(ar.bottomLeft(), ar.topRight());
3962 QPixmap const* pm = qWarpSystemPixmaps.getPixmap(SBMP_COMBODOWN,
3963 QWarpPixmap::bmp);
3964 QPoint ppt = ar.topLeft() +
3965 QPoint((ar.width() - pm->width()) / 2,
3966 (ar.height() - pm->height()) / 2);
3967 p->drawPixmap(ppt, *pm);
3968 }
3969
3970 if(sub & SC_ComboBoxEditField)
3971 {
3972 QComboBox const* cb = (QComboBox const*)widget;
3973 QRect re = QStyle::visualRect(querySubControlMetrics(CC_ComboBox, widget,
3974 SC_ComboBoxEditField),
3975 widget);
3976 p->fillRect(re, cg.brush(QColorGroup::Base));
3977
3978 if(cb->hasFocus())
3979 {
3980 p->setPen(cg.highlightedText());
3981 p->setBackgroundColor(cg.highlight());
3982 }
3983 else
3984 {
3985 p->setPen(cg.text());
3986 p->setBackgroundColor(cg.background());
3987 }
3988
3989 if(cb->hasFocus() && !cb->editable())
3990 {
3991 re = QStyle::visualRect(subRect(SR_ComboBoxFocusRect, cb), widget);
3992 p->fillRect(re, cg.brush(QColorGroup::Highlight));
3993 }
3994 }
3995
3996 break;
3997 }
3998 #endif // QT_NO_COMBOBOX
3999
4000 #ifndef QT_NO_SLIDER
4001 case CC_Slider:
4002 {
4003 QSlider const* sl = (QSlider const*)widget;
4004 QRect groove = querySubControlMetrics(CC_Slider, widget, SC_SliderGroove, opt),
4005 handle = querySubControlMetrics(CC_Slider, widget, SC_SliderHandle, opt);
4006
4007 // reducing the handle length by 2 on each side
4008 if(sl->orientation() == Horizontal)
4009 {
4010 handle.setLeft(handle.left() + 2);
4011 handle.setRight(handle.right() - 2);
4012 }
4013 else
4014 {
4015 handle.setTop(handle.top() + 2);
4016 handle.setBottom(handle.bottom() - 2);
4017 }
4018
4019 if((sub & SC_SliderGroove) && groove.isValid())
4020 {
4021 if(sl->orientation() == Horizontal)
4022 {
4023 groove.setTop(groove.top() + 4);
4024 groove.setBottom(groove.bottom() - 4);
4025 }
4026 else
4027 {
4028 groove.setLeft(groove.left() + 4);
4029 groove.setRight(groove.right() - 4);
4030 }
4031
4032 qDrawWarpFilledRect(p, groove, cg.dark(), cg.light(),
4033 &cg.brush(QColorGroup::Button), 2, true);
4034
4035 groove.setTop(groove.top() + 2);
4036 groove.setLeft(groove.left() + 2);
4037 if(sl->orientation() == Horizontal)
4038 {
4039 groove.setRight(groove.right() - 2);
4040 groove.setBottom(groove.bottom() - 1);
4041 }
4042 else
4043 {
4044 groove.setRight(groove.right() - 1);
4045 groove.setBottom(groove.bottom() - 2);
4046 }
4047
4048 if(flags & Style_HasFocus)
4049 p->setPen(cg.shadow());
4050 else
4051 p->setPen(cg.dark());
4052
4053 p->drawRect(groove);
4054 }
4055
4056 if(sub & SC_SliderTickmarks)
4057 {
4058 int tickOffset = pixelMetric(PM_SliderTickmarkOffset, sl);
4059 int thickness = pixelMetric(PM_SliderControlThickness, sl);
4060 int len = pixelMetric(PM_SliderLength, sl);
4061 int ticks = sl->tickmarks();
4062 int available = pixelMetric(PM_SliderSpaceAvailable, sl);
4063 int interval = sl->tickInterval();
4064
4065 if(interval <= 0 )
4066 {
4067 interval = sl->lineStep();
4068 if((qPositionFromValue(sl, interval, available) -
4069 qPositionFromValue(sl, 0, available)) < 3)
4070 interval = sl->pageStep();
4071 }
4072
4073 int fudge = len / 2;
4074 int pos;
4075
4076 if(ticks & QSlider::Above)
4077 {
4078 if(sl->orientation() == Horizontal)
4079 p->fillRect(0, 0, sl->width(), tickOffset,
4080 cg.brush(QColorGroup::Background));
4081 else
4082 p->fillRect(0, 0, tickOffset, sl->width(),
4083 cg.brush(QColorGroup::Background));
4084 int v = sl->minValue();
4085 if (!interval)
4086 interval = 1;
4087 while(v <= sl->maxValue() + 1)
4088 {
4089 pos = qPositionFromValue(sl, v, available) + fudge;
4090 if(sl->orientation() == Horizontal)
4091 {
4092 p->setPen(cg.dark());
4093 p->drawLine(pos - 1, 0, pos - 1, tickOffset - 1);
4094 p->setPen(cg.light());
4095 p->drawLine(pos, 0, pos, tickOffset - 1);
4096 }
4097 else
4098 {
4099 p->setPen(cg.dark());
4100 p->drawLine(0, pos - 1, tickOffset - 1, pos - 1);
4101 p->setPen(cg.light());
4102 p->drawLine(0, pos, tickOffset - 1, pos);
4103 }
4104 v += interval;
4105 }
4106 }
4107
4108 if(ticks & QSlider::Below)
4109 {
4110 if(sl->orientation() == Horizontal)
4111 p->fillRect(0, tickOffset + thickness, sl->width(), tickOffset,
4112 cg.brush(QColorGroup::Background));
4113 else
4114 p->fillRect(tickOffset + thickness, 0, tickOffset, sl->height(),
4115 cg.brush(QColorGroup::Background));
4116 int v = sl->minValue();
4117 if(!interval)
4118 interval = 1;
4119 while(v <= sl->maxValue() + 1)
4120 {
4121 pos = qPositionFromValue(sl, v, available) + fudge;
4122 if(sl->orientation() == Horizontal)
4123 {
4124 p->setPen(cg.dark());
4125 p->drawLine(pos - 1, tickOffset + thickness + 1,
4126 pos - 1, tickOffset + thickness + 1 + available - 1);
4127 p->setPen(cg.light());
4128 p->drawLine(pos, tickOffset + thickness + 1,
4129 pos, tickOffset + thickness + 1 + available - 1);
4130 }
4131 else
4132 {
4133 p->setPen(cg.dark());
4134 p->drawLine(tickOffset + thickness + 1, pos - 1,
4135 tickOffset + thickness + 1 + available - 1, pos - 1);
4136 p->setPen(cg.light());
4137 p->drawLine(tickOffset + thickness + 1, pos,
4138 tickOffset + thickness + 1 + available - 1, pos);
4139 }
4140 v += interval;
4141 }
4142 }
4143 }
4144
4145 if(sub & SC_SliderHandle)
4146 {
4147 qDrawWarpFilledRect(p, handle, cg.dark(), cg.light(),
4148 &cg.brush(QColorGroup::Button), 2, false);
4149
4150 if(flags & Style_HasFocus)
4151 p->setPen(cg.shadow());
4152 else
4153 p->setPen(cg.dark());
4154
4155 if(sl->orientation() == Horizontal)
4156 p->drawLine(handle.topLeft() + QPoint(5, 2),
4157 handle.bottomLeft() + QPoint(5, -2));
4158 else
4159 p->drawLine(handle.topLeft() + QPoint(2, 5),
4160 handle.topRight() + QPoint(-2, 5));
4161
4162 p->setPen(cg.light());
4163
4164 if(sl->orientation() == Horizontal)
4165 p->drawLine(handle.topLeft() + QPoint(6, 2),
4166 handle.bottomLeft() + QPoint(6, -2));
4167 else
4168 p->drawLine(handle.topLeft() + QPoint(2, 6),
4169 handle.topRight() + QPoint(-2, 6));
4170 }
4171
4172 break;
4173 }
4174 #endif // QT_NO_SLIDER
4175
4176 default:
4177 {
4178 QCommonStyle::drawComplexControl(ctrl, p, widget, r, cg, flags, sub,
4179 subActive, opt);
4180 break;
4181 }
4182 }
4183}
4184
4185/*! \reimp */
4186QRect QWarp4Style::querySubControlMetrics(ComplexControl control,
4187 QWidget const* widget,
4188 SubControl sc,
4189 QStyleOption const& opt) const
4190{
4191 switch(control)
4192 {
4193 #ifndef QT_NO_SCROLLBAR
4194 case CC_ScrollBar:
4195 {
4196 QScrollBar const* scrollbar = (QScrollBar const*)widget;
4197 int sbextent = pixelMetric(PM_ScrollBarExtent, widget);
4198 int maxlen = ((scrollbar->orientation() == Qt::Horizontal) ?
4199 scrollbar->width() : scrollbar->height()) -
4200 (2 * 21); // 2 buttons incl. lines
4201 int sliderstart = scrollbar->sliderStart();
4202
4203 // calculate slider length
4204 int sliderlen;
4205 if(scrollbar->maxValue() != scrollbar->minValue())
4206 {
4207 uint range = scrollbar->maxValue() - scrollbar->minValue();
4208 sliderlen = (scrollbar->pageStep() * maxlen) /
4209 (range + scrollbar->pageStep());
4210 int slidermin = pixelMetric(PM_ScrollBarSliderMin, widget);
4211 if((sliderlen < slidermin) || (range > INT_MAX / 2))
4212 sliderlen = slidermin;
4213 if(sliderlen > maxlen)
4214 sliderlen = maxlen;
4215 }
4216 else
4217 {
4218 sliderlen = maxlen;
4219 }
4220
4221 // calculate button width (for vertical scroll bars this is the height)
4222 // note: the "button" includes the lines at the extreme ends of the sb
4223 int buttonWidth;
4224 if(scrollbar->orientation() == Qt::Horizontal)
4225 buttonWidth = QMIN(scrollbar->width() / 2, 21);
4226 else
4227 buttonWidth = QMIN(scrollbar->height() / 2, 21);
4228
4229 switch(sc)
4230 {
4231 case SC_ScrollBarSubLine: // top/left button
4232 {
4233 if(scrollbar->orientation() == Qt::Horizontal)
4234 return QRect(0, 0, buttonWidth, sbextent);
4235 else
4236 return QRect(0, 0, sbextent, buttonWidth);
4237 }
4238
4239 case SC_ScrollBarAddLine: // bottom/right button
4240 {
4241 if(scrollbar->orientation() == Qt::Horizontal)
4242 return QRect(scrollbar->width() - buttonWidth, 0,
4243 buttonWidth, sbextent);
4244 else
4245 return QRect(0, scrollbar->height() - buttonWidth,
4246 sbextent, buttonWidth);
4247 }
4248
4249 case SC_ScrollBarSubPage: // between top/left button and slider
4250 {
4251 if(scrollbar->orientation() == Qt::Horizontal)
4252 return QRect(buttonWidth, 0,
4253 sliderstart - buttonWidth, sbextent);
4254 else
4255 return QRect(0, buttonWidth,
4256 sbextent, sliderstart - buttonWidth);
4257 }
4258
4259 case SC_ScrollBarAddPage: // between bottom/right button and slider
4260 {
4261 if(scrollbar->orientation() == Qt::Horizontal)
4262 return QRect(sliderstart + sliderlen, 0,
4263 maxlen + buttonWidth - sliderstart - sliderlen, sbextent);
4264 else
4265 return QRect(0, sliderstart + sliderlen,
4266 sbextent, maxlen + buttonWidth - sliderstart - sliderlen);
4267 }
4268
4269 case SC_ScrollBarGroove:
4270 {
4271 if(scrollbar->orientation() == Qt::Horizontal)
4272 return QRect(buttonWidth, 0,
4273 scrollbar->width() - buttonWidth * 2, sbextent);
4274 else
4275 return QRect(0, buttonWidth,
4276 sbextent, scrollbar->height() - buttonWidth * 2);
4277 }
4278
4279 case SC_ScrollBarSlider:
4280 {
4281 if(scrollbar->orientation() == Qt::Horizontal)
4282 return QRect(sliderstart, 0, sliderlen, sbextent);
4283 else
4284 return QRect(0, sliderstart, sbextent, sliderlen);
4285 }
4286 }
4287
4288 break;
4289 }
4290 #endif // QT_NO_SCROLLBAR
4291
4292 case CC_SpinWidget:
4293 {
4294 int fw = pixelMetric(PM_SpinBoxFrameWidth, widget);
4295 QSize bs;
4296 bs.setHeight(widget->height() - 2 * fw);
4297 if(bs.height() < 16)
4298 bs.setHeight(16);
4299 bs.setWidth(bs.height() + 2);
4300 bs = bs.expandedTo(QApplication::globalStrut());
4301 int bx = widget->width() - bs.width() - fw,
4302 by = fw;
4303
4304 switch(sc)
4305 {
4306 case SC_SpinWidgetUp:
4307 return QRect(bx, by, bs.width(), bs.height());
4308 case SC_SpinWidgetDown:
4309 return QRect(bx, by + bs.height(), bs.width(), 0);
4310 case SC_SpinWidgetButtonField:
4311 return QRect(bx, by, bs.width(), widget->height() - 2 * fw);
4312 case SC_SpinWidgetEditField:
4313 return QRect(fw, fw,
4314 widget->width() - bs.width() - 2 * fw,
4315 widget->height() - 2 * fw);
4316 case SC_SpinWidgetFrame:
4317 return widget->rect();
4318 default:
4319 break;
4320 }
4321
4322 break;
4323 }
4324
4325 case CC_ComboBox:
4326 {
4327 QRect r(widget->rect());
4328 int x = r.left(),
4329 y = r.top(),
4330 wi = r.width(),
4331 he = r.height();
4332 int xpos = x;
4333 xpos += wi - 2 - 16;
4334
4335 switch(sc)
4336 {
4337 case SC_ComboBoxFrame:
4338 return widget->rect();
4339 case SC_ComboBoxArrow:
4340 return QRect(xpos, y + 2, 16, he - 4);
4341 case SC_ComboBoxEditField:
4342 return QRect(x + 2, y + 2, wi - 5 - 16, he - 4);
4343 case SC_ComboBoxListBoxPopup:
4344 return opt.rect();
4345 default:
4346 break;
4347 }
4348 break;
4349 }
4350
4351 default:
4352 {
4353 return QCommonStyle::querySubControlMetrics(control, widget, sc, opt);
4354 }
4355 }
4356
4357 return QRect();
4358}
4359
4360/*! \reimp */
4361int QWarp4Style::styleHint(StyleHint hint,
4362 QWidget const* widget,
4363 QStyleOption const& opt,
4364 QStyleHintReturn *returnData) const
4365{
4366 int ret;
4367
4368 switch (hint)
4369 {
4370 case SH_EtchDisabledText:
4371 case SH_Slider_SnapToValue:
4372 case SH_PrintDialog_RightAlignButtons:
4373 case SH_FontDialog_SelectAssociatedText:
4374 case SH_MenuBar_AltKeyNavigation:
4375 case SH_MainWindow_SpaceBelowMenuBar:
4376 case SH_ScrollBar_StopMouseOverSlider:
4377 {
4378 ret = 1;
4379 break;
4380 }
4381
4382 case SH_MenuBar_MouseTracking:
4383 case SH_PopupMenu_MouseTracking:
4384 case SH_PopupMenu_AllowActiveAndDisabled:
4385 case SH_PopupMenu_SpaceActivatesItem:
4386 case SH_PopupMenu_Scrollable:
4387 case SH_PopupMenu_SloppySubMenus:
4388 case SH_PopupMenu_SubMenuPopupDelay:
4389 case SH_ComboBox_ListMouseTracking:
4390 case SH_ItemView_ChangeHighlightOnFocus:
4391 case SH_ToolBox_SelectedPageTitleBold:
4392 {
4393 ret = 0;
4394 break;
4395 }
4396
4397 case SH_GUIStyle:
4398 {
4399 // This value still exists from Qt 1.0 (as it seems), but is never
4400 // ever used in the current code! So the function of setting it
4401 // here is only to avoid using one of the other GUI styles still
4402 // being used (i.e., WindowsStyle and MotifStyle - which in turn are
4403 // also due to being removed entirely with some new Qt version...)
4404 // Note: currently it is being used to add some space to the left of
4405 // the menubar - as that space (another amount...) is also added
4406 // for other OS styles in QMenuBar.cpp (looks like an 1.0 inheritance!)
4407 ret = PMStyle;
4408 break;
4409 }
4410
4411 default:
4412 {
4413 ret = QCommonStyle::styleHint(hint, widget, opt, returnData);
4414 break;
4415 }
4416 }
4417
4418 return ret;
4419}
4420
4421/*! \reimp */
4422QRect QWarp4Style::subRect(SubRect r, QWidget const* widget) const
4423{
4424 QRect rect;
4425
4426 switch(r)
4427 {
4428 case SR_PushButtonFocusRect:
4429 case SR_CheckBoxFocusRect:
4430 case SR_RadioButtonFocusRect:
4431 {
4432 QButton const* button = (QButton const*)widget;
4433 if(!button->pixmap() && button->text().isEmpty())
4434 {
4435 switch(r)
4436 {
4437 case SR_PushButtonFocusRect:
4438 rect = QRect(widget->rect().center(), QSize(0, 0));
4439 break;
4440 case SR_CheckBoxFocusRect:
4441 rect = subRect(SR_CheckBoxIndicator, widget);
4442 break;
4443 case SR_RadioButtonFocusRect:
4444 rect = subRect(SR_RadioButtonIndicator, widget);
4445 break;
4446 }
4447 rect.addCoords(1, 1, -1, -1);
4448 break;
4449 }
4450 QPainter* p = new QPainter(button);
4451 QRect cr;
4452 switch(r)
4453 {
4454 case SR_PushButtonFocusRect:
4455 cr = subRect(SR_PushButtonContents, widget);
4456 break;
4457 case SR_CheckBoxFocusRect:
4458 cr = subRect(SR_CheckBoxContents, widget);
4459 break;
4460 case SR_RadioButtonFocusRect:
4461 cr = subRect(SR_RadioButtonContents, widget);
4462 break;
4463 }
4464 int align = ((SR_PushButtonFocusRect == r) ?
4465 Qt::AlignCenter | Qt::AlignVCenter :
4466 Qt::AlignLeft | Qt::AlignVCenter | Qt::ShowPrefix);
4467 rect = itemRect(p, cr, align,
4468 button->isEnabled(), button->pixmap(), button->text());
4469 delete p;
4470 rect.addCoords(-1, -1, 1, 1);
4471 rect = rect.intersect(widget->rect());
4472 break;
4473 }
4474
4475 #ifndef QT_NO_SLIDER
4476 case SR_SliderFocusRect:
4477 {
4478 rect = widget->rect();
4479 break;
4480 }
4481 #endif // QT_NO_SLIDER
4482
4483 #ifndef QT_NO_PROGRESSBAR
4484 case SR_ProgressBarGroove:
4485 case SR_ProgressBarContents:
4486 {
4487 QFontMetrics fm((widget ? widget->fontMetrics() :
4488 QApplication::fontMetrics()));
4489 QProgressBar const* progressbar = (QProgressBar const*)widget;
4490 int textw = 0;
4491 if(progressbar->percentageVisible())
4492 textw = fm.width("100%") + 6;
4493
4494 // only change for Warp4 compared to "common": the style default
4495 // is "centered"
4496 QRect wrect(widget->rect());
4497 if(!progressbar->indicatorFollowsStyle() &&
4498 !progressbar->centerIndicator())
4499 rect.setCoords(wrect.left(), wrect.top(),
4500 wrect.right() - textw, wrect.bottom());
4501 else
4502 rect = wrect;
4503 break;
4504 }
4505
4506 case SR_ProgressBarLabel:
4507 {
4508 QFontMetrics fm((widget ? widget->fontMetrics() :
4509 QApplication::fontMetrics()));
4510 QProgressBar const* progressbar = (QProgressBar const*)widget;
4511 int textw = 0;
4512 if(progressbar->percentageVisible())
4513 textw = fm.width("100%") + 6;
4514
4515 // only change for Warp4 compared to "common": the style default
4516 // is "centered"
4517 QRect wrect(widget->rect());
4518 if(!progressbar->indicatorFollowsStyle() &&
4519 !progressbar->centerIndicator())
4520 rect.setCoords(wrect.right() - textw, wrect.top(),
4521 wrect.right(), wrect.bottom());
4522 else
4523 rect = wrect;
4524 break;
4525 }
4526 #endif
4527
4528 case SR_ToolBoxTabContents:
4529 {
4530 rect = widget->rect();
4531 break;
4532 }
4533
4534 default:
4535 {
4536 rect = QCommonStyle::subRect(r, widget);
4537 break;
4538 }
4539 }
4540
4541 return rect;
4542}
4543
4544#include "qwarp4style.moc"
4545
4546#endif
Note: See TracBrowser for help on using the repository browser.