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

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

Styles: Implemented the first version of the Warp4 style (contributed by Cornelis Bockemuehl).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 150.6 KB
Line 
1/****************************************************************************
2** $Id: qwarp4style.cpp 175 2007-11-06 23:17:04Z 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 QRect const& r,
1889 QColorGroup const& cg,
1890 SFlags flags,
1891 QStyleOption const& opt) const
1892{
1893 QRect rr(r);
1894
1895 switch (pe)
1896 {
1897 case PE_ButtonCommand:
1898 case PE_ButtonTool:
1899 {
1900 bool sunken = flags & (Style_Sunken | Style_Down | Style_On),
1901 def = flags & Style_ButtonDefault;
1902 qDrawWarpDefFrame(p, rr, cg, def);
1903 QBrush fill = cg.brush(QColorGroup::Button);
1904 rr.addCoords(1, 1, -1, -1);
1905 qDrawWarpFilledRect(p, rr, cg.dark(), cg.light(), &fill, 2, sunken);
1906 break;
1907 }
1908
1909 case PE_HeaderArrow:
1910 {
1911 p->save();
1912 while(0 != (rr.width() % 4))
1913 rr.setWidth(rr.width() - 1);
1914 rr.moveTop(rr.top() + rr.height() / 2 - rr.width() / 4 - 1);
1915 rr.setHeight(rr.width() / 2 + 1);
1916 rr.setWidth(rr.width() + 1);
1917 QPointArray pa(3);
1918 if(flags & Style_Down)
1919 {
1920 pa.setPoint(0, rr.left() + rr.width() / 2, rr.bottom());
1921 pa.setPoint(1, rr.left(), rr.top());
1922 pa.setPoint(2, rr.right(), rr.top());
1923 }
1924 else
1925 {
1926 pa.setPoint(0, rr.left(), rr.bottom());
1927 pa.setPoint(1, rr.right(), rr.bottom());
1928 pa.setPoint(2, rr.left() + rr.width() / 2, rr.top());
1929 }
1930 p->setPen(Qt::NoPen);
1931 p->setBrush(cg.shadow());
1932 p->drawPolygon(pa);
1933 p->restore();
1934 break;
1935 }
1936
1937 case PE_ButtonBevel:
1938 case PE_HeaderSection:
1939 {
1940 QBrush fill;
1941
1942 if(!(flags & Style_Down) && (flags & Style_On))
1943 fill = QBrush(cg.light(), Dense4Pattern);
1944 else
1945 fill = cg.brush(QColorGroup::Button);
1946
1947 if(flags & (Style_Raised | Style_Down | Style_On | Style_Sunken))
1948 qDrawWarpFilledRect(p, r, cg.dark(), cg.light(), &fill, 2,
1949 flags & (Style_Down | Style_On));
1950 else
1951 p->fillRect(r, fill);
1952
1953 break;
1954 }
1955
1956 case PE_ButtonDefault:
1957 {
1958 p->setPen(cg.shadow());
1959 p->drawRect(r);
1960
1961 break;
1962 }
1963
1964 case PE_Separator:
1965 {
1966 p->setPen(cg.dark());
1967 rr.addCoords(0, 0, 0, -1);
1968 p->drawLine(rr.bottomLeft(), rr.bottomRight());
1969 break;
1970 }
1971
1972 case PE_FocusRect:
1973 {
1974 if(opt.isDefault())
1975 p->drawWinFocusRect(r);
1976 else
1977 p->drawWinFocusRect(r, opt.color());
1978
1979 break;
1980 }
1981
1982 case PE_Indicator:
1983 case PE_CheckListIndicator:
1984 case PE_ExclusiveIndicator:
1985 case PE_CheckListExclusiveIndicator:
1986 {
1987 bool sunken = flags & (Style_Sunken | Style_Down);
1988 QWarpPixmap::QWarpInternalPixmap type;
1989 switch(pe)
1990 {
1991 case PE_Indicator:
1992 case PE_CheckListIndicator:
1993 {
1994 if(flags & Style_On)
1995 {
1996 if(sunken)
1997 type = QWarpPixmap::chkboxcheckedsunken;
1998 else
1999 type = QWarpPixmap::chkboxchecked;
2000 }
2001 else if(flags & Style_NoChange)
2002 {
2003 if(sunken)
2004 type = QWarpPixmap::chkboxtrisunken;
2005 else
2006 type = QWarpPixmap::chkboxtri;
2007 }
2008 else
2009 {
2010 if(sunken)
2011 type = QWarpPixmap::chkboxsunken;
2012 else
2013 type = QWarpPixmap::chkboxnormal;
2014 }
2015 break;
2016 }
2017 case PE_ExclusiveIndicator:
2018 case PE_CheckListExclusiveIndicator:
2019 default:
2020 {
2021 if(flags & Style_On)
2022 {
2023 if(sunken)
2024 type = QWarpPixmap::radbutcheckedsunken;
2025 else
2026 type = QWarpPixmap::radbutchecked;
2027 }
2028 else
2029 {
2030 if(sunken)
2031 type = QWarpPixmap::radbutsunken;
2032 else
2033 type = QWarpPixmap::radbutnormal;
2034 }
2035 }
2036 }
2037
2038 QPixmap const* pix = qWarpSystemPixmaps.getPixmap(type,
2039 QWarpPixmap::internal);
2040 p->drawPixmap(r.x(), r.y(), *pix);
2041
2042 break;
2043 }
2044
2045 case PE_IndicatorMask:
2046 {
2047 p->fillRect(r, color1);
2048 break;
2049 }
2050
2051 case PE_ExclusiveIndicatorMask:
2052 {
2053 p->setPen(color1);
2054 p->setBrush(color1);
2055 p->drawEllipse(r);
2056
2057 break;
2058 }
2059
2060 case PE_SpinWidgetPlus:
2061 case PE_SpinWidgetMinus:
2062 case PE_SpinWidgetUp:
2063 case PE_SpinWidgetDown:
2064 {
2065 p->save();
2066
2067 // button background
2068 p->setPen(cg.shadow());
2069 p->fillRect(r, QBrush(cg.button()));
2070
2071 // three possible states
2072 enum { normal, upPressed, downPressed } st;
2073 st = normal;
2074 if(flags & Style_Sunken)
2075 {
2076 if(flags & Style_On)
2077 st = upPressed;
2078 else
2079 st = downPressed;
2080 }
2081
2082 // left and top border
2083 if(upPressed == st) p->setPen(cg.dark());
2084 else p->setPen(cg.light());
2085 p->drawLine(r.topLeft(), r.topRight());
2086 p->drawLine(r.topLeft(), r.bottomLeft());
2087 p->drawLine(r.left(), r.top() + 1, r.right(), r.top() + 1);
2088 p->drawLine(r.left() + 1, r.top(), r.left() + 1, r.bottom());
2089
2090 // right and bottom border
2091 if(downPressed == st) p->setPen(cg.light());
2092 else p->setPen(cg.dark());
2093 p->drawLine(r.topRight(), r.bottomRight());
2094 p->drawLine(r.bottomLeft(), r.bottomRight());
2095 p->drawLine(r.right() - 1, r.top(), r.right() - 1, r.bottom());
2096 p->drawLine(r.left(), r.bottom() - 1, r.right(), r.bottom() - 1);
2097
2098 // diagonal
2099 if(upPressed == st) p->setPen(cg.light());
2100 else p->setPen(cg.shadow());
2101 p->drawLine(r.bottomLeft(), r.topRight());
2102 if(upPressed == st) p->setPen(cg.light());
2103 else p->setPen(cg.dark());
2104 p->drawLine(r.left(), r.bottom() - 1, r.right() - 1, r.top());
2105 if(downPressed == st) p->setPen(cg.dark());
2106 else p->setPen(cg.light());
2107 p->drawLine(r.left() + 1, r.bottom(), r.right(), r.top() + 1);
2108
2109 // rectangles for up/down symbols
2110 QRect upRect;
2111 upRect.setWidth((r.width() - 4) / 2 - 1);
2112 if(1 != (upRect.width() % 2))
2113 {
2114 // we want an odd number for the width and height, and in
2115 // order to avoid too small symbols, we add 1 in case we
2116 // already rounded off during the division by 2 above
2117 if(1 == (r.width() % 2))
2118 upRect.setWidth(upRect.width() + 1);
2119 else
2120 upRect.setWidth(upRect.width() - 1);
2121 }
2122 upRect.setHeight(upRect.width());
2123 upRect.moveTopLeft(r.topLeft() + QPoint(2, 3));
2124 QRect downRect(upRect);
2125 downRect.moveBottomRight(r.bottomRight() - QPoint(3, 3));
2126 if(upPressed == st)
2127 upRect.moveBy(1, 1);
2128 if(downPressed == st)
2129 downRect.moveBy(1, 1);
2130
2131 switch(pe)
2132 {
2133 case PE_SpinWidgetPlus:
2134 case PE_SpinWidgetMinus:
2135 {
2136 p->setPen(cg.buttonText());
2137 p->drawLine(upRect.left(), upRect.center().y(),
2138 upRect.right(), upRect.center().y());
2139 p->drawLine(upRect.center().x(), upRect.top(),
2140 upRect.center().x(), upRect.bottom());
2141 p->drawLine(downRect.left(), downRect.center().y(),
2142 downRect.right(), downRect.center().y());
2143 break;
2144 }
2145
2146 case PE_SpinWidgetUp:
2147 case PE_SpinWidgetDown:
2148 default:
2149 {
2150 p->setBrush(cg.buttonText());
2151 p->setPen(QPen::NoPen);
2152 QPointArray a;
2153 a.putPoints(0, 3,
2154 upRect.left(), upRect.center().y(),
2155 upRect.center().x(), upRect.top(),
2156 upRect.right(), upRect.center().y());
2157 p->drawPolygon(a);
2158 a.resize(0);
2159 a.putPoints(0, 3,
2160 downRect.left(), downRect.center().y(),
2161 downRect.center().x(), downRect.bottom(),
2162 downRect.right(), downRect.center().y());
2163 p->drawPolygon(a);
2164 }
2165 }
2166
2167 p->restore();
2168
2169 break;
2170 }
2171
2172 case PE_Panel:
2173 {
2174 qDrawWarpPanel(p, rr, cg, -1);
2175 break;
2176 }
2177
2178 case PE_PanelPopup:
2179 {
2180 QBrush br(cg.background());
2181 qDrawWarpPanel(p, rr, cg, 1, &br);
2182 break;
2183 }
2184
2185 case PE_PanelTabWidget:
2186 {
2187 // compensate for artificially reduced frame size
2188 // note that we get the information about "bottom" or "top" tabs
2189 // from the "mid line width" in the "opt" parameter
2190 // (see also QWarpTabPanelHeader::QWarpTabPanelHeader)
2191 bool bottom = (bool)opt.midLineWidth();
2192 QRect rr1(rr), rr2(rr);
2193 if(bottom)
2194 {
2195 rr1.addCoords(-11, -11, 14, 0);
2196 rr2.addCoords(0, 0, 3, 0);
2197 }
2198 else
2199 {
2200 rr1.addCoords(-11, 0, 14, 11);
2201 rr2.addCoords(0, 0, 3, 0);
2202 }
2203 p->setClipRect(rr1);
2204
2205 p->setPen(cg.light());
2206 if(bottom)
2207 {
2208 p->drawLine(rr1.left(), rr1.top(), rr1.left(), rr1.bottom());
2209 p->drawLine(rr1.left(), rr1.top(), rr1.right(), rr1.top());
2210 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2211 }
2212 else
2213 {
2214 p->drawLine(rr1.left(), rr1.top(), rr1.left(), rr1.bottom() - 1);
2215 p->drawLine(rr2.left(), rr2.bottom(), rr2.right(), rr2.bottom());
2216 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2217 }
2218
2219 p->setPen(cg.dark());
2220 if(bottom)
2221 {
2222 p->drawLine(rr1.right(), rr1.top(), rr1.right(), rr1.bottom());
2223 p->drawLine(rr2.left(), rr2.top(), rr2.right(), rr2.top());
2224 p->drawLine(rr2.left(), rr2.top(), rr2.left(), rr2.bottom());
2225 rr2.addCoords(0, 2, -3, 0);
2226 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2227 }
2228 else
2229 {
2230 p->drawLine(rr1.left(), rr1.bottom(), rr1.right(), rr1.bottom());
2231 p->drawLine(rr1.right(), rr1.top(), rr1.right(), rr1.bottom());
2232 p->drawLine(rr2.left(), rr2.top(), rr2.left(), rr2.bottom() - 1);
2233 rr2.addCoords(0, 0, -3, -2);
2234 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2235 }
2236
2237 break;
2238 }
2239
2240 case PE_PanelMenuBar:
2241 {
2242 // It looks like this code is never being called!
2243 break;
2244 }
2245
2246 case PE_PanelGroupBox:
2247 {
2248 qDrawWarpPanel(p, rr, cg, 0);
2249 break;
2250 }
2251
2252 case PE_TabBarBase:
2253 {
2254 bool bottom = flags & Style_Bottom;
2255 if(bottom)
2256 rr.addCoords(0, 0, 0, -1);
2257 else
2258 rr.addCoords(0, 1, 0, 0);
2259 QRect rr2(rr);
2260 if(bottom)
2261 rr2.addCoords(11, 0, -11, -11);
2262 else
2263 rr2.addCoords(11, 11, -11, 0);
2264
2265 p->setPen(cg.light());
2266 if(bottom)
2267 {
2268 p->drawLine(rr.left(), rr.top(), rr.left(), rr.bottom());
2269 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2270 p->drawLine(rr2.left(), rr2.bottom(), rr2.right(), rr2.bottom());
2271#ifndef QT_PM_NO_TABWIDGET_HEADERS
2272 p->drawLine(rr2.left() + 6, rr2.top() + 2, rr2.right() - 9, rr2.top() + 2);
2273#endif
2274 }
2275 else
2276 {
2277 p->drawLine(rr.left(), rr.top(), rr.right(), rr.top());
2278 p->drawLine(rr.left(), rr.top(), rr.left(), rr.bottom());
2279 p->drawLine(rr2.right(), rr2.top() + 1, rr2.right(), rr2.bottom());
2280#ifndef QT_PM_NO_TABWIDGET_HEADERS
2281 p->drawLine(rr2.left() + 6, rr2.bottom() - 1, rr2.right() - 9, rr2.bottom() - 1);
2282#endif
2283 }
2284
2285 p->setPen(cg.dark());
2286 if(bottom)
2287 {
2288 p->drawLine(rr.left(), rr.bottom(), rr.right(), rr.bottom());
2289 p->drawLine(rr.right(), rr.top(), rr.right(), rr.bottom());
2290 p->drawLine(rr2.left(), rr2.top(), rr2.left(), rr2.bottom() - 1);
2291#ifndef QT_PM_NO_TABWIDGET_HEADERS
2292 p->drawLine(rr2.left() + 6, rr2.top() + 1, rr2.right() - 9, rr2.top() + 1);
2293#endif
2294 rr2.addCoords(2, 0, -3, -2);
2295 p->drawLine(rr2.left(), rr2.bottom(), rr2.right(), rr2.bottom());
2296 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2297 }
2298 else
2299 {
2300 p->drawLine(rr.right(), rr.top(), rr.right(), rr.bottom());
2301 p->drawLine(rr2.left(), rr2.top(), rr2.right(), rr2.top());
2302 p->drawLine(rr2.left(), rr2.top(), rr2.left(), rr2.bottom());
2303#ifndef QT_PM_NO_TABWIDGET_HEADERS
2304 p->drawLine(rr2.left() + 6, rr2.bottom() - 2, rr2.right() - 9, rr2.bottom() - 2);
2305#endif
2306 rr2.addCoords(2, 2, -3, 0);
2307 p->drawLine(rr2.left(), rr2.top(), rr2.right(), rr2.top());
2308 p->drawLine(rr2.right(), rr2.top(), rr2.right(), rr2.bottom());
2309 }
2310
2311 break;
2312 }
2313
2314 case PE_Splitter:
2315 {
2316 QPen oldPen = p->pen();
2317 p->setPen(cg.light());
2318
2319 if(flags & Style_Horizontal)
2320 {
2321 p->drawLine(r.x() + 1, r.y(), r.x() + 1, r.height());
2322 p->setPen(cg.dark());
2323 p->drawLine(r.x(), r.y(), r.x(), r.height());
2324 p->drawLine(r.right()-1, r.y(), r.right()-1, r.height());
2325 p->setPen(cg.shadow());
2326 p->drawLine(r.right(), r.y(), r.right(), r.height());
2327 }
2328 else
2329 {
2330 p->drawLine(r.x(), r.y() + 1, r.width(), r.y() + 1);
2331 p->setPen(cg.dark());
2332 p->drawLine(r.x(), r.bottom() - 1, r.width(), r.bottom() - 1);
2333 p->setPen(cg.shadow());
2334 p->drawLine(r.x(), r.bottom(), r.width(), r.bottom());
2335 }
2336 p->setPen(oldPen);
2337
2338 break;
2339 }
2340
2341 case PE_DockWindowResizeHandle:
2342 {
2343 QPen oldPen = p->pen();
2344 p->setPen(cg.light());
2345
2346 if(flags & Style_Horizontal)
2347 {
2348 p->drawLine(r.x(), r.y(), r.width(), r.y());
2349 p->setPen(cg.dark());
2350 p->drawLine(r.x(), r.bottom() - 1, r.width(), r.bottom() - 1);
2351 p->setPen(cg.shadow());
2352 p->drawLine(r.x(), r.bottom(), r.width(), r.bottom());
2353 }
2354 else
2355 {
2356 p->drawLine(r.x(), r.y(), r.x(), r.height());
2357 p->setPen(cg.dark());
2358 p->drawLine(r.right()-1, r.y(), r.right()-1, r.height());
2359 p->setPen(cg.shadow());
2360 p->drawLine(r.right(), r.y(), r.right(), r.height());
2361 }
2362 p->setPen(oldPen);
2363
2364 break;
2365 }
2366
2367 case PE_ScrollBarSubLine:
2368 case PE_ScrollBarAddLine:
2369 {
2370 QPointArray pa;
2371 if(flags & Style_Horizontal)
2372 {
2373 int height2 = rr.height() / 2 - 4,
2374 width2 = height2 / 2;
2375 if(pe == PE_ScrollBarSubLine)
2376 {
2377 pa.putPoints(0, 4,
2378 width2, height2,
2379 width2, 1 - height2,
2380 1 - width2, 0,
2381 1 - width2, 1);
2382 }
2383 else
2384 {
2385 pa.putPoints(0, 4,
2386 1 - width2, 1 - height2,
2387 1 - width2, height2,
2388 width2, 1,
2389 width2, 0);
2390 }
2391 }
2392 else
2393 {
2394 int width2 = rr.width() / 2 - 4,
2395 height2 = width2 / 2;
2396 if(pe == PE_ScrollBarSubLine)
2397 {
2398 pa.putPoints(0, 4,
2399 1 - width2, height2,
2400 width2, height2,
2401 1, 1 - height2,
2402 0, 1 - height2);
2403 }
2404 else
2405 {
2406 pa.putPoints(0, 4,
2407 width2, 1 - height2,
2408 1 - width2, 1 - height2,
2409 0, height2,
2410 1, height2);
2411 }
2412 }
2413 pa.translate(rr.center().x(), rr.center().y());
2414
2415 p->setPen(cg.dark());
2416 if(!((flags & Style_Horizontal) && (pe == PE_ScrollBarAddLine)))
2417 {
2418 p->drawLine(rr.topLeft(), rr.bottomLeft());
2419 rr.setLeft(rr.left() + 1);
2420 }
2421 if(!(!(flags & Style_Horizontal) && (pe == PE_ScrollBarAddLine)))
2422 {
2423 p->drawLine(rr.topLeft(), rr.topRight());
2424 rr.setTop(rr.top() + 1);
2425 }
2426 p->setPen(cg.light());
2427 if(!((flags & Style_Horizontal) && (pe == PE_ScrollBarSubLine)))
2428 {
2429 p->drawLine(rr.topRight(), rr.bottomRight());
2430 rr.setRight(rr.right() - 1);
2431 }
2432 if(!(!(flags & Style_Horizontal) && (pe == PE_ScrollBarSubLine)))
2433 {
2434 p->drawLine(rr.bottomLeft(), rr.bottomRight());
2435 rr.setBottom(rr.bottom() - 1);
2436 }
2437
2438 if(!(flags & Style_Down))
2439 flags |= Style_Raised;
2440 drawPrimitive(PE_ButtonBevel, p, rr, cg, flags);
2441 p->setPen(cg.light());
2442 p->drawLine(rr.topRight(), rr.topRight() + QPoint(-1, 1));
2443
2444 QBrush::BrushStyle bs = (flags & Style_Enabled) ? Qt::SolidPattern : Qt::Dense4Pattern;
2445 p->setBrush(QBrush(cg.shadow(), bs));
2446 p->setPen(QPen(Qt::NoPen));
2447 p->drawPolygon(pa);
2448
2449 break;
2450 }
2451
2452 case PE_ScrollBarAddPage:
2453 case PE_ScrollBarSubPage:
2454 case PE_ScrollBarSlider:
2455 {
2456 if(!rr.isValid())
2457 break;
2458
2459 p->setPen(cg.light());
2460 if(flags & Style_Horizontal)
2461 {
2462 p->drawLine(rr.bottomLeft(), rr.bottomRight());
2463 rr.setBottom(rr.bottom() - 1);
2464 }
2465 else
2466 {
2467 p->drawLine(rr.topRight(), rr.bottomRight());
2468 rr.setRight(rr.right() - 1);
2469 }
2470 p->setPen(cg.dark());
2471 if(flags & Style_Horizontal)
2472 {
2473 p->drawLine(rr.topLeft(), rr.topRight());
2474 rr.setTop(rr.top() + 1);
2475 }
2476 else
2477 {
2478 p->drawLine(rr.topLeft(), rr.bottomLeft());
2479 rr.setLeft(rr.left() + 1);
2480 }
2481 p->drawLine(rr.topLeft(), rr.topRight());
2482
2483 if(pe == PE_ScrollBarSlider)
2484 {
2485 if(!(flags & Style_Down))
2486 flags |= Style_Raised;
2487 drawPrimitive(PE_ButtonBevel, p, rr, cg, flags);
2488 QPoint from, to, step;
2489 if(flags & Style_Horizontal)
2490 {
2491 from = QPoint(rr.center().x() - 5, rr.top() + 4);
2492 to = QPoint(rr.center().x() - 5, rr.bottom() - 4);
2493 step = QPoint(1, 0);
2494 }
2495 else
2496 {
2497 from = QPoint(rr.left() + 4, rr.center().y() - 5);
2498 to = QPoint(rr.right() - 4, rr.center().y() - 5);
2499 step = QPoint(0, 1);
2500 }
2501
2502 int i;
2503 for(i = 0; i < 12; ++i)
2504 {
2505 if(0 == (i % 2))
2506 p->setPen(cg.shadow());
2507 else
2508 p->setPen(cg.light());
2509 p->drawLine(from, to);
2510 from += step;
2511 to += step;
2512 }
2513 }
2514
2515 else // ..AddPage or ..SubPage
2516 {
2517 rr.setTop(rr.top() + 1);
2518 p->drawLine(rr.topLeft(), rr.bottomLeft());
2519 rr.setLeft(rr.left() + 1);
2520
2521 QBrush br;
2522 if(flags & Style_Down)
2523 br = QBrush(cg.shadow());
2524 else
2525 br = QBrush(qt_sysclr2qrgb(SYSCLR_SCROLLBAR));
2526 p->setPen(QPen(Qt::NoPen));
2527
2528 p->fillRect(rr, br);
2529 }
2530
2531 break;
2532 }
2533
2534 case PE_WindowFrame:
2535 {
2536 QColorGroup popupCG = cg;
2537 popupCG.setColor(QColorGroup::Light, cg.background());
2538 popupCG.setColor(QColorGroup::Midlight, cg.light());
2539
2540 int lw = opt.isDefault() ? pixelMetric(PM_MDIFrameWidth)
2541 : opt.lineWidth();
2542
2543 if(lw == 2)
2544 {
2545 qDrawWarpPanel(p, r, popupCG, -1);
2546 }
2547 else
2548 {
2549 QBrush fill = QBrush(cg.background());
2550 qDrawWarpPanel(p, r, popupCG, -1, &fill);
2551 }
2552
2553 break;
2554 }
2555
2556 default:
2557 {
2558 if((PE_CheckMark == pe) ||
2559 ((pe >= PE_ArrowUp) && (pe <= PE_ArrowLeft)))
2560 {
2561 QPixmap const* pm = 0;
2562
2563 switch(pe)
2564 {
2565 case PE_ArrowUp:
2566 pm = qWarpSystemPixmaps.getPixmap(QWarpPixmap::arrowup,
2567 QWarpPixmap::internal);
2568 break;
2569
2570 case PE_ArrowDown:
2571 pm = qWarpSystemPixmaps.getPixmap(QWarpPixmap::arrowdown,
2572 QWarpPixmap::internal);
2573 break;
2574
2575 case PE_ArrowRight:
2576 pm = qWarpSystemPixmaps.getPixmap(QWarpPixmap::arrowright,
2577 QWarpPixmap::internal);
2578 break;
2579
2580 case PE_ArrowLeft:
2581 pm = qWarpSystemPixmaps.getPixmap(QWarpPixmap::arrowleft,
2582 QWarpPixmap::internal);
2583 break;
2584
2585 default: // PE_CheckMark
2586 pm = qWarpSystemPixmaps.getPixmap(QWarpPixmap::checkmark,
2587 QWarpPixmap::internal);
2588 break;
2589 }
2590
2591 int x = rr.left() + (rr.width() - pm->width()) / 2,
2592 y = rr.top() + (rr.height() - pm->height()) / 2;
2593 p->drawPixmap(x, y, *pm);
2594 }
2595 else
2596 {
2597 QCommonStyle::drawPrimitive(pe, p, r, cg, flags, opt);
2598 }
2599 }
2600 }
2601}
2602
2603/*!
2604 \reimp
2605*/
2606void QWarp4Style::drawControl(ControlElement element,
2607 QPainter* p,
2608 QWidget const* widget,
2609 QRect const& r,
2610 QColorGroup const& cg,
2611 SFlags flags,
2612 QStyleOption const& opt) const
2613{
2614 switch (element)
2615 {
2616 #ifndef QT_NO_TABBAR
2617 case CE_TabBarTab:
2618 {
2619 if(!widget || !widget->parentWidget() || !opt.tab())
2620 break;
2621
2622 QTabBar const* tb = (QTabBar const*)widget;
2623 QTab const* t = opt.tab();
2624 bool selected = flags & Style_Selected,
2625 bottom = (QTabBar::RoundedBelow == tb->shape()) ||
2626 (QTabBar::TriangularBelow == tb->shape());
2627 int id = tb->indexOf(t->identifier());
2628
2629 // check if the panel header widget is already present and
2630 // create them here
2631 // note that this is the only place to do it from within the
2632 // style class!
2633 QWarpTabPanelHeader::addIfNotPresent(tb);
2634
2635 static const QColor tabCols[10] =
2636 {
2637 QColor(85, 219, 255),
2638 QColor(128, 219, 170),
2639 QColor(128, 146, 255),
2640 QColor(213, 182, 170),
2641 QColor(255, 255, 170),
2642 QColor(170, 146, 170),
2643 QColor(255, 146, 85),
2644 QColor(255, 219, 85),
2645 QColor(255, 182, 170),
2646 QColor(255, 219, 170)
2647 };
2648
2649 qDrawTabBar(p, r, cg, tabCols[id % 10], selected, bottom);
2650
2651 if(QApplication::reverseLayout())
2652 {
2653 p->setPen(cg.dark());
2654 int right = tb->size().width() - 1;
2655 if(bottom)
2656 p->drawLine(right, r.top(), right, r.top() + 4);
2657 else
2658 p->drawLine(right, r.bottom(), right, r.bottom() - 4);
2659
2660 }
2661 p->setPen(cg.light());
2662 if(bottom)
2663 p->drawLine(0, r.top(), 0, r.top() + 4);
2664 else
2665 p->drawLine(0, r.bottom(), 0, r.bottom() - 4);
2666
2667 break;
2668 }
2669
2670 case CE_TabBarLabel:
2671 {
2672 if(opt.isDefault())
2673 break;
2674
2675 QTabBar const* tb = (QTabBar const*)widget;
2676 QTab const* t = opt.tab();
2677 bool selected = flags & Style_Selected,
2678 bottom = (QTabBar::RoundedBelow == tb->shape()) ||
2679 (QTabBar::TriangularBelow == tb->shape());
2680
2681 QRect tr(r);
2682 if(bottom)
2683 tr.addCoords(3, 4, 1, 0);
2684 else
2685 tr.addCoords(3, 1, 1, -3);
2686
2687 if(selected)
2688 {
2689 QFont f = p->font();
2690 QRect rold = QFontMetrics(f).boundingRect(t->text());
2691 f.setBold(true);
2692 QRect rnew = QFontMetrics(f).boundingRect(t->text());
2693 p->setFont(f);
2694 int hdiff = rnew.width() - rold.width() + 1;
2695 tr.addCoords(-hdiff / 2, 0, hdiff / 2, 0);
2696
2697 QWidget* pw = widget->parentWidget();
2698 if((0 != pw) && (pw->inherits("QTabWidget")))
2699 {
2700 QTabWidget* tw = (QTabWidget*)pw;
2701 QWarpTabPanelHeader* twh =
2702 (QWarpTabPanelHeader*)tw->child("qt_warp_tabpanel_header",
2703 "QWarpTabPanelHeader", false);
2704 if(0 != twh)
2705 {
2706 twh->setCaption(t->text());
2707 QRect r(twh->visibleRect());
2708 twh->repaint();
2709 }
2710 }
2711 }
2712
2713 int alignment = AlignCenter | ShowPrefix;
2714 if(!styleHint(SH_UnderlineAccelerator, widget, QStyleOption::Default, 0))
2715 alignment |= NoAccel;
2716 drawItem(p, tr, alignment, cg, flags & Style_Enabled, 0, t->text());
2717
2718 if((flags & Style_HasFocus) && !t->text().isEmpty())
2719 drawPrimitive(PE_FocusRect, p, tr, cg);
2720
2721 break;
2722 }
2723 #endif // QT_NO_TABBAR
2724
2725 case CE_ToolBoxTab:
2726 {
2727 qDrawWarpPanel(p, r, cg, -1, &cg.brush(QColorGroup::Button));
2728 break;
2729 }
2730
2731 case CE_ProgressBarGroove:
2732 {
2733 QRect rr(r);
2734 QBrush fill = cg.brush(QColorGroup::Button);
2735 qDrawWarpFilledRect(p, rr, cg.dark(), cg.light(), &fill, 2, true);
2736 // For OS/2, this can be also cg.shadow() if the user has clicked on
2737 // the bar with the mouse, but this is only due to the fact that an "OS/2
2738 // progressbar" is actually a slider, not just a display widget
2739 p->setPen(cg.dark());
2740 rr.addCoords(2, 2, -2, -1);
2741 p->drawRect(rr);
2742 break;
2743 }
2744
2745 #ifndef QT_NO_PROGRESSBAR
2746 case CE_ProgressBarContents:
2747 {
2748 QProgressBar const* progressbar = (QProgressBar const*)widget;
2749 QColorGroup cgh = cg;
2750 cgh.setColor(QColorGroup::Highlight, QColor(0, 0, 170));
2751 bool reverse = QApplication::reverseLayout();
2752 QRect br(r);
2753 br.addCoords(3, 3, -3, -2);
2754
2755 if(!progressbar->totalSteps())
2756 {
2757 // draw busy indicator
2758 static const int indWidth = 30;
2759 br.addCoords(indWidth / 2, 0, -indWidth / 2, 0);
2760 int bw = br.width();
2761 int x = progressbar->progress() % (bw * 2);
2762 if(x > bw)
2763 x = 2 * bw - x;
2764 x = reverse ? br.right() - x : br.left() + x;
2765 p->setPen(QPen(cgh.highlight(), indWidth));
2766 p->drawLine(x, br.top(), x, br.bottom());
2767 }
2768
2769 else
2770 {
2771 int pos = (progressbar->progress() * br.width()) /
2772 progressbar->totalSteps();
2773 pos = reverse ?
2774 br.right() - pos :
2775 br.left() + pos;
2776
2777 p->setPen(cgh.dark());
2778 p->drawLine(pos, br.top(), pos, br.bottom());
2779
2780 if(reverse)
2781 br.setLeft(pos + 1);
2782 else
2783 br.setRight(pos - 1);
2784
2785 p->fillRect(br, cgh.highlight());
2786 }
2787
2788 break;
2789 }
2790
2791 case CE_ProgressBarLabel:
2792 {
2793 QProgressBar const* progressbar = (QProgressBar const*)widget;
2794 if(0 == progressbar->totalSteps())
2795 break;
2796
2797 if(progressbar->indicatorFollowsStyle() ||
2798 progressbar->centerIndicator())
2799 {
2800 QRect br(r);
2801 br.addCoords(3, 3, -3, -2);
2802 int pos = (progressbar->progress() * br.width()) /
2803 progressbar->totalSteps();
2804 bool reverse = QApplication::reverseLayout();
2805 if(reverse)
2806 pos = br.right() - pos;
2807 else
2808 pos = br.left() + pos;
2809
2810 // paint label black in background area
2811 QRect clip(br);
2812 if(reverse)
2813 clip.setRight(pos);
2814 else
2815 clip.setLeft(pos);
2816 p->setClipRect(clip);
2817 drawItem(p, br, AlignCenter | SingleLine, cg, flags & Style_Enabled, 0,
2818 progressbar->progressString());
2819
2820 // paint label "light" in blue ribbonstrip area
2821 clip = br;
2822 if(reverse)
2823 clip.setLeft(pos);
2824 else
2825 clip.setRight(pos);
2826 p->setClipRect(clip);
2827 drawItem(p, br, AlignCenter | SingleLine, cg, flags & Style_Enabled, 0,
2828 progressbar->progressString(), -1, &cg.highlightedText());
2829 }
2830
2831 else
2832 {
2833 drawItem(p, r, AlignCenter | SingleLine, cg, flags & Style_Enabled, 0,
2834 progressbar->progressString(), -1, 0);
2835 }
2836
2837 break;
2838 }
2839 #endif
2840
2841 #ifndef QT_NO_POPUPMENU
2842 case CE_PopupMenuItem:
2843 {
2844 if(!widget || opt.isDefault())
2845 break;
2846
2847 // QPopupMenu has WResizeNoErase and WRepaintNoErase flags, so we
2848 // must erase areas not covered by menu items (this is requested by
2849 // QPopupMenu using 0 as the menu item argument).
2850 // note: we do this with the frame drawing (PE_PanelPopup)
2851
2852 QPopupMenu const* popupmenu = (QPopupMenu const*)widget;
2853 QMenuItem* mi = opt.menuItem();
2854 if(!mi)
2855 break;
2856
2857 int tabw = opt.tabWidth() + 3;
2858 int iconw = QMAX(11, opt.maxIconWidth()) + 6;
2859 bool dis = !(flags & Style_Enabled);
2860 bool act = flags & Style_Active;
2861 bool reverse = QApplication::reverseLayout();
2862 int subw = (qPopupMenuHasSub(popupmenu) ? 19 : 0);
2863
2864 // the popup menu adds 1 pixel vertically on top and bottom, but
2865 // actually needs only 2 at the bottom, so we move all items
2866 // 1 pixel up
2867
2868 QRect rr(r);
2869 rr.moveBy(0, -1);
2870
2871 int x, y, w, h;
2872 rr.rect(&x, &y, &w, &h);
2873
2874 if(mi && mi->isSeparator()) // draw separator
2875 {
2876 p->setPen(cg.dark());
2877 p->drawLine(x, y + 4, x + w, y + 4);
2878 p->setPen(cg.light());
2879 p->drawLine(x, y + 5, x + w, y + 5);
2880 return;
2881 }
2882
2883 if(act)
2884 {
2885 QRect hr(rr);
2886 hr.addCoords(3, 0, -3, 1);
2887 p->fillRect(hr, cg.highlight());
2888 p->setPen(cg.highlightedText());
2889 }
2890 else
2891 {
2892 p->setPen(cg.text());
2893 }
2894
2895 if(mi->iconSet()) // draw iconset
2896 {
2897 QIconSet::Mode mode = dis ? QIconSet::Disabled : QIconSet::Normal;
2898 if(act && !dis)
2899 mode = QIconSet::Active;
2900 QPixmap pixmap;
2901 if(popupmenu->isCheckable() && mi->isChecked())
2902 pixmap = mi->iconSet()->pixmap(QIconSet::Small, mode, QIconSet::On);
2903 else
2904 pixmap = mi->iconSet()->pixmap(QIconSet::Small, mode);
2905 int px = (reverse ? (w - pixmap.width() - 6) : 6);
2906 p->drawPixmap(px, y, pixmap);
2907 }
2908
2909 else if(popupmenu->isCheckable() && mi->isChecked()) // just "checking"...
2910 {
2911 SFlags cflags = Style_Default;
2912 if(!dis)
2913 cflags |= Style_Enabled;
2914 if(act)
2915 cflags |= Style_On;
2916
2917 int xc = (reverse ? w - iconw + 15 : iconw - 15),
2918 yc = (rr.top() + rr.bottom()) / 2 - 3;
2919 drawPrimitive(PE_CheckMark, p, QRect(xc, yc, 16, 8), cg, cflags);
2920 }
2921
2922 if(mi->custom())
2923 {
2924 mi->custom()->paint(p, cg, act, !dis, 0, 10, 8, 8);
2925 }
2926
2927 QString s = mi->text();
2928 if(!s.isNull()) // draw text
2929 {
2930 int text_flags = AlignVCenter | ShowPrefix | DontClip | SingleLine;
2931 if(!styleHint(SH_UnderlineAccelerator, widget))
2932 text_flags |= NoAccel;
2933 text_flags |= (reverse ? AlignRight : AlignLeft);
2934
2935 // tab text
2936 int t = s.find('\t');
2937 QString ts;
2938 if(t >= 0)
2939 {
2940 ts = s.mid(t + 1);
2941 s = s.left(t);
2942 int tx = (reverse ? subw : w - tabw - subw);
2943 p->drawText(tx, y + 1, tabw, h, text_flags, ts);
2944 }
2945
2946 // normal text
2947 int tx = (reverse ? tabw + subw : iconw);
2948 p->drawText(tx, y + 1, w - iconw - tabw - subw, h, text_flags, s);
2949 }
2950
2951 else if(mi->pixmap()) // draw pixmap
2952 {
2953 QPixmap* pixmap = mi->pixmap();
2954 if(pixmap->depth() == 1)
2955 p->setBackgroundMode(OpaqueMode);
2956 int px = (reverse ? (w - pixmap->width() - iconw) : iconw);
2957 if(dis)
2958 {
2959 QIconSet is(*pixmap);
2960 p->drawPixmap(px, y, is.pixmap(QIconSet::Automatic, QIconSet::Disabled));
2961 }
2962 else
2963 {
2964 p->drawPixmap(px, y, *pixmap);
2965 }
2966 if(pixmap->depth() == 1)
2967 p->setBackgroundMode(TransparentMode);
2968 }
2969
2970 if(mi->popup()) // draw sub menu arrow
2971 {
2972 PrimitiveElement arrow;
2973 arrow = (reverse ? PE_ArrowLeft : PE_ArrowRight);
2974 int xa = (reverse ? 5 : w - 15),
2975 ya = (rr.top() + rr.bottom()) / 2 - 4;
2976 drawPrimitive(arrow, p, QRect(xa, ya, 12, 12),
2977 cg, dis ? Style_Default : Style_Enabled);
2978 }
2979 break;
2980 }
2981 #endif
2982
2983 case CE_MenuBarItem:
2984 {
2985 QWidget* w = (QWidget*)widget;
2986 while(true)
2987 {
2988 QWidget* p = w->parentWidget(true);
2989 if(0 == p)
2990 break;
2991 else
2992 w = p;
2993 }
2994
2995 // here we let the two grey lines disappear at the top and bottom of
2996 // the client area that are actually the empty top and bottom docking
2997 // areas (only as long as they are empty, of course)
2998 if(w->inherits("QMainWindow"))
2999 QWarpMainWindowLayouter::addIfNotPresent((QMainWindow*)w);
3000
3001 bool act = flags & Style_Active;
3002 QColorGroup mcg(cg);
3003
3004 if(act)
3005 {
3006 QRect hr(r);
3007 hr.addCoords(0, 2, 0, 0);
3008 p->fillRect(hr, cg.highlight());
3009 mcg.setColor(QColorGroup::ButtonText, mcg.highlightedText());
3010 }
3011 else
3012 {
3013 mcg.setColor(QColorGroup::ButtonText, mcg.text());
3014 }
3015
3016 QCommonStyle::drawControl(element, p, widget, r, mcg, flags, opt);
3017 break;
3018 }
3019
3020 #ifndef QT_NO_TOOLBUTTON
3021 case CE_ToolButtonLabel:
3022 {
3023 if((QString("qt_left_btn") == widget->name()) ||
3024 (QString("qt_right_btn") == widget->name()))
3025 {
3026 // do nothing in this case!
3027 }
3028 else
3029 {
3030 QToolButton const* toolbutton = (QToolButton const*)widget;
3031 QRect rect = r;
3032 // the following line is the only difference to the "commonstyle":
3033 // it makes sure that the bitmap and/or label does not overpaint
3034 // the button frame
3035 rect.addCoords(3, 3, -3, -3);
3036 Qt::ArrowType arrowType = opt.isDefault() ?
3037 Qt::DownArrow : opt.arrowType();
3038
3039 if(flags & (Style_Down | Style_On))
3040 rect.moveBy(pixelMetric(PM_ButtonShiftHorizontal, widget),
3041 pixelMetric(PM_ButtonShiftVertical, widget));
3042
3043 if(!opt.isDefault())
3044 {
3045 PrimitiveElement pe;
3046 switch (arrowType)
3047 {
3048 case Qt::LeftArrow:
3049 pe = PE_ArrowLeft;
3050 break;
3051 case Qt::RightArrow:
3052 pe = PE_ArrowRight;
3053 break;
3054 case Qt::UpArrow:
3055 pe = PE_ArrowUp;
3056 break;
3057 default:
3058 case Qt::DownArrow:
3059 pe = PE_ArrowDown;
3060 break;
3061 }
3062
3063 drawPrimitive(pe, p, rect, cg, flags, opt);
3064 }
3065
3066 else
3067 {
3068 QColor btext = toolbutton->paletteForegroundColor();
3069
3070 if(toolbutton->iconSet().isNull() &&
3071 !toolbutton->text().isNull() &&
3072 !toolbutton->usesTextLabel())
3073 {
3074 int alignment = AlignCenter | AlignVCenter | ShowPrefix;
3075
3076 if(!styleHint(SH_UnderlineAccelerator, widget,
3077 QStyleOption::Default, 0))
3078 alignment |= NoAccel;
3079
3080 drawItem(p, rect, alignment, cg,
3081 flags & Style_Enabled, 0, toolbutton->text(),
3082 toolbutton->text().length(), &btext);
3083 }
3084
3085 else
3086 {
3087 QPixmap pm;
3088
3089 QIconSet::Size size =
3090 toolbutton->usesBigPixmap() ? QIconSet::Large : QIconSet::Small;
3091
3092 QIconSet::State state =
3093 toolbutton->isOn() ? QIconSet::On : QIconSet::Off;
3094
3095 QIconSet::Mode mode;
3096 if(!toolbutton->isEnabled())
3097 mode = QIconSet::Disabled;
3098 else if(flags & (Style_Down | Style_On | Style_Raised))
3099 mode = QIconSet::Active;
3100 else
3101 mode = QIconSet::Normal;
3102
3103 pm = toolbutton->iconSet().pixmap(size, mode, state);
3104
3105 if(toolbutton->usesTextLabel())
3106 {
3107 if(toolbutton->textPosition() == QToolButton::Under)
3108 {
3109 p->setFont(toolbutton->font());
3110
3111 QRect pr = rect, tr = rect;
3112 int fh = p->fontMetrics().height();
3113 pr.addCoords(0, 1, 0, -fh - 3);
3114 tr.addCoords(0, pr.bottom(), 0, -3);
3115 drawItem(p, pr, AlignCenter, cg, TRUE, &pm, QString::null);
3116 int alignment = AlignCenter | ShowPrefix;
3117
3118 if(!styleHint(SH_UnderlineAccelerator, widget, QStyleOption::Default, 0))
3119 alignment |= NoAccel;
3120
3121 drawItem(p, tr, alignment, cg,
3122 flags & Style_Enabled, 0, toolbutton->textLabel(),
3123 toolbutton->textLabel().length(), &btext);
3124 }
3125 else
3126 {
3127 p->setFont(toolbutton->font());
3128
3129 QRect pr = rect, tr = rect;
3130 pr.setWidth(pm.width() + 8);
3131 tr.addCoords(pr.right(), 0, 0, 0);
3132 drawItem(p, pr, AlignCenter, cg, TRUE, &pm, QString::null);
3133 int alignment = AlignLeft | AlignVCenter | ShowPrefix;
3134
3135 if(!styleHint(SH_UnderlineAccelerator, widget, QStyleOption::Default, 0))
3136 alignment |= NoAccel;
3137
3138 drawItem(p, tr, alignment, cg,
3139 flags & Style_Enabled, 0, toolbutton->textLabel(),
3140 toolbutton->textLabel().length(), &btext);
3141 }
3142 }
3143 else
3144 {
3145 drawItem(p, rect, AlignCenter, cg, TRUE, &pm, QString::null);
3146 }
3147 }
3148 }
3149 }
3150
3151 break;
3152 }
3153 #endif
3154
3155 default:
3156 {
3157 QCommonStyle::drawControl(element, p, widget, r, cg, flags, opt);
3158 }
3159 }
3160}
3161
3162/*!
3163 \reimp
3164*/
3165int QWarp4Style::pixelMetric(PixelMetric metric, QWidget const* widget) const
3166{
3167 int ret;
3168
3169 switch (metric)
3170 {
3171 case PM_ButtonDefaultIndicator:
3172 case PM_ButtonShiftHorizontal:
3173 case PM_ButtonShiftVertical:
3174 {
3175 ret = 1;
3176 break;
3177 }
3178
3179 case PM_IndicatorWidth:
3180 case PM_ExclusiveIndicatorWidth:
3181 {
3182 QPixmap const* ip = qWarpSystemPixmaps.getPixmap(QWarpPixmap::chkboxnormal,
3183 QWarpPixmap::internal);
3184 ret = ip->width();
3185 break;
3186 }
3187
3188 case PM_IndicatorHeight:
3189 case PM_ExclusiveIndicatorHeight:
3190 {
3191 QPixmap const* ip = qWarpSystemPixmaps.getPixmap(QWarpPixmap::chkboxnormal,
3192 QWarpPixmap::internal);
3193 ret = ip->height();
3194 break;
3195 }
3196
3197 #ifndef QT_NO_SCROLLBAR
3198 case PM_ScrollBarExtent:
3199 {
3200 if(!widget)
3201 {
3202 ret = 16;
3203 }
3204 else
3205 {
3206 QScrollBar const* bar = (QScrollBar const*)widget;
3207 int s = (bar->orientation() == Qt::Horizontal) ?
3208 QApplication::globalStrut().height() :
3209 QApplication::globalStrut().width();
3210 ret = QMAX(16, s);
3211 }
3212
3213 break;
3214 }
3215
3216 case PM_ScrollBarSliderMin:
3217 {
3218 ret = 20;
3219 break;
3220 }
3221 #endif
3222
3223 case PM_MaximumDragDistance:
3224 {
3225 ret = -1;
3226 break;
3227 }
3228
3229 #ifndef QT_NO_SLIDER
3230 case PM_SliderThickness:
3231 {
3232 ret = 20;
3233 break;
3234 }
3235
3236 case PM_SliderLength:
3237 {
3238 // we increase the "length" by 2 x 2, but then draw the slider 2 pixels
3239 // smaller than indicated, so we get the effect of a slider that does
3240 // not fully touch the extreme ends of the "groove"
3241 ret = 12 + 4;
3242 break;
3243 }
3244
3245 // Returns the number of pixels to use for the business part of the
3246 // slider (i.e., the non-tickmark portion). The remaining space is shared
3247 // equally between the tickmark regions.
3248 case PM_SliderControlThickness:
3249 {
3250 QSlider const* sl = (QSlider const*) widget;
3251 int space = (sl->orientation() == Horizontal) ? sl->height() : sl->width();
3252 int ticks = sl->tickmarks();
3253 int n = 0;
3254 if(ticks & QSlider::Above)
3255 n++;
3256 if(ticks & QSlider::Below)
3257 n++;
3258 if(!n)
3259 {
3260 ret = space;
3261 break;
3262 }
3263
3264 int thick = 6; // Magic constant to get 5 + 16 + 5
3265 if(ticks != QSlider::Both && ticks != QSlider::NoMarks)
3266 thick += pixelMetric(PM_SliderLength, sl) / 4;
3267
3268 space -= thick;
3269 //### the two sides may be unequal in size
3270 if(space > 0)
3271 thick += (space * 2) / (n + 2);
3272 ret = thick;
3273
3274 break;
3275 }
3276 #endif // QT_NO_SLIDER
3277
3278 case PM_MenuBarFrameWidth:
3279 {
3280 ret = 0;
3281 break;
3282 }
3283
3284 case PM_MenuBarItemSpacing:
3285 {
3286 ret = 8;
3287 break;
3288 }
3289
3290 case PM_PopupMenuFrameHorizontalExtra:
3291 {
3292 ret = 0;
3293 break;
3294 }
3295
3296 case PM_PopupMenuFrameVerticalExtra:
3297 {
3298 ret = 1;
3299 break;
3300 }
3301
3302 case PM_TabBarTabOverlap:
3303 {
3304 ret = 10;
3305 break;
3306 }
3307
3308 case PM_TabBarBaseHeight:
3309 {
3310#ifndef QT_PM_NO_TABWIDGET_HEADERS
3311 ret = QFontMetrics(QApplication::font()).boundingRect("X").height() + 29;
3312#else
3313 ret = 16;
3314#endif
3315 break;
3316 }
3317
3318 case PM_TabBarBaseOverlap:
3319 {
3320 ret = 6;
3321 break;
3322 }
3323
3324 case PM_TabBarTabHSpace:
3325 {
3326 ret = 28;
3327 break;
3328 }
3329
3330 case PM_TabBarTabVSpace:
3331 {
3332 ret = 9;
3333 break;
3334 }
3335
3336 case PM_TabBarScrollButtonWidth:
3337 {
3338 ret = 25;
3339 break;
3340 }
3341
3342 case PM_TabBarTabShiftHorizontal:
3343 case PM_TabBarTabShiftVertical:
3344 {
3345 ret = 0;
3346 break;
3347 }
3348
3349 case PM_SplitterWidth:
3350 {
3351 ret = QMAX(6, QApplication::globalStrut().width());
3352 break;
3353 }
3354
3355 default:
3356 {
3357 ret = QCommonStyle::pixelMetric(metric, widget);
3358 break;
3359 }
3360 }
3361
3362 return ret;
3363}
3364
3365/*!
3366 \reimp
3367*/
3368QSize QWarp4Style::sizeFromContents(ContentsType contents,
3369 QWidget const* widget,
3370 QSize const& contentsSize,
3371 QStyleOption const& opt) const
3372{
3373 QSize sz(contentsSize);
3374
3375 switch (contents)
3376 {
3377 case CT_PushButton:
3378 {
3379 #ifndef QT_NO_PUSHBUTTON
3380 const QPushButton* button = (const QPushButton*)widget;
3381 sz = QCommonStyle::sizeFromContents(contents, widget, contentsSize, opt);
3382 int w = sz.width(),
3383 h = sz.height();
3384
3385 int defwidth = 0;
3386 if(button->isDefault() || button->autoDefault())
3387 defwidth = 2 * pixelMetric(PM_ButtonDefaultIndicator, widget);
3388 if(w < 80 + defwidth && !button->pixmap())
3389 w = 80 + defwidth;
3390 if(h < 23 + defwidth)
3391 h = 23 + defwidth;
3392
3393 sz = QSize(w, h);
3394 #endif
3395
3396 break;
3397 }
3398
3399 case CT_ToolButton:
3400 {
3401 sz = QSize(sz.width() + 6, sz.height() + 5);
3402 break;
3403 }
3404
3405 case CT_PopupMenuItem:
3406 {
3407 #ifndef QT_NO_POPUPMENU
3408 if(! widget || opt.isDefault())
3409 break;
3410
3411 QPopupMenu const* popup = (QPopupMenu const*)widget;
3412 QMenuItem* mi = opt.menuItem();
3413 int iconw = QMAX(11, opt.maxIconWidth());
3414 QString s = mi->text();
3415 int w = sz.width(),
3416 h = sz.height();
3417
3418 if(mi->custom())
3419 {
3420 w = mi->custom()->sizeHint().width();
3421 h = mi->custom()->sizeHint().height();
3422 if(!mi->custom()->fullSpan())
3423 w += iconw;
3424 }
3425 else if(mi->widget())
3426 {
3427 }
3428 else if(mi->isSeparator())
3429 {
3430 w = 10; // arbitrary
3431 h = 8;
3432 }
3433 else
3434 {
3435 if(mi->pixmap())
3436 h = QMAX(h, mi->pixmap()->height() + 3);
3437 else if(!s.isNull())
3438 h = QMAX(h, popup->fontMetrics().height() + 1);
3439
3440 if(mi->iconSet())
3441 {
3442 h = QMAX(h, mi->iconSet()->
3443 pixmap(QIconSet::Small, QIconSet::Normal).height() + 3);
3444 w = QMAX(w, iconw);
3445 }
3446 }
3447
3448 if(!s.isNull())
3449 {
3450 w += 19;
3451 }
3452
3453 if(qPopupMenuHasSub(popup))
3454 {
3455 w += 19;
3456 }
3457
3458 w += 9;
3459
3460 sz = QSize(w, h);
3461 #endif
3462
3463 break;
3464 }
3465
3466 case CT_MenuBar:
3467 {
3468 // It looks like this code is never being called!
3469 break;
3470 }
3471
3472 case CT_SpinBox:
3473 {
3474 sz.setHeight(sz.height() - 2);
3475 break;
3476 }
3477
3478 case CT_TabWidget:
3479 {
3480 sz.setWidth(sz.width() + 32); // 16, 16
3481 sz.setHeight(sz.height() + 14); // 0, 14
3482 break;
3483 }
3484
3485 case CT_LineEdit:
3486 {
3487 sz.setHeight(sz.height() - 1);
3488 break;
3489 }
3490
3491 default:
3492 {
3493 sz = QCommonStyle::sizeFromContents(contents, widget, sz, opt);
3494 break;
3495 }
3496 }
3497
3498 return sz;
3499}
3500
3501/*! \reimp
3502*/
3503void QWarp4Style::polishPopupMenu(QPopupMenu* p)
3504{
3505 #ifndef QT_NO_POPUPMENU
3506 if(!p->testWState(WState_Polished))
3507 p->setCheckable(TRUE);
3508 #endif
3509}
3510
3511/*!
3512 \reimp
3513 */
3514QPixmap QWarp4Style::stylePixmap(StylePixmap stylepixmap,
3515 QWidget const* widget,
3516 QStyleOption const& opt) const
3517{
3518 #ifndef QT_NO_IMAGEIO_XPM
3519 switch (stylepixmap)
3520 {
3521 // SP_TitleBarShadeButton - shade button on titlebars.
3522 case SP_TitleBarShadeButton:
3523 return *qWarpSystemPixmaps.getPixmap(54, // any SBMP_ value??
3524 QWarpPixmap::bmp);
3525
3526 // SP_TitleBarUnshadeButton - unshade button on titlebars.
3527 case SP_TitleBarUnshadeButton:
3528 return *qWarpSystemPixmaps.getPixmap(56, // any SBMP_ value??
3529 QWarpPixmap::bmp);
3530
3531 // SP_TitleBarNormalButton - normal (restore) button on titlebars.
3532 case SP_TitleBarNormalButton:
3533 return *qWarpSystemPixmaps.getPixmap(SBMP_RESTOREBUTTON,
3534 QWarpPixmap::bmp);
3535
3536 // SP_TitleBarMinButton - minimize button on titlebars. For example, in a QWorkspace.
3537 case SP_TitleBarMinButton:
3538 return *qWarpSystemPixmaps.getPixmap(SBMP_MINBUTTON,
3539 QWarpPixmap::bmp);
3540
3541 // SP_TitleBarMaxButton - maximize button on titlebars.
3542 case SP_TitleBarMaxButton:
3543 return *qWarpSystemPixmaps.getPixmap(SBMP_MAXBUTTON,
3544 QWarpPixmap::bmp);
3545
3546 // SP_TitleBarCloseButton - close button on titlebars.
3547 case SP_TitleBarCloseButton:
3548 return *qWarpSystemPixmaps.getPixmap(52, // any SBMP_ value??
3549 QWarpPixmap::bmp);
3550
3551 // SP_DockWindowCloseButton - close button on dock windows; see also QDockWindow.
3552 case SP_DockWindowCloseButton:
3553 return *qWarpSystemPixmaps.getPixmap(52, // should be a bit smaller!
3554 QWarpPixmap::bmp);
3555
3556 // SP_MessageBoxInformation - the 'information' icon.
3557 case SP_MessageBoxInformation:
3558 return *qWarpSystemPixmaps.getPixmap(SPTR_ICONINFORMATION,
3559 QWarpPixmap::ico);
3560
3561 // SP_MessageBoxWarning - the 'warning' icon.
3562 case SP_MessageBoxWarning:
3563 return *qWarpSystemPixmaps.getPixmap(SPTR_ICONWARNING,
3564 QWarpPixmap::ico);
3565
3566 // SP_MessageBoxCritical - the 'critical' icon.
3567 case SP_MessageBoxCritical:
3568 return *qWarpSystemPixmaps.getPixmap(SPTR_ICONERROR,
3569 QWarpPixmap::ico);
3570
3571 // SP_MessageBoxQuestion - the 'question' icon.
3572 case SP_MessageBoxQuestion:
3573 return *qWarpSystemPixmaps.getPixmap(SPTR_ICONQUESTION,
3574 QWarpPixmap::ico);
3575
3576 default:
3577 break;
3578 }
3579 #endif //QT_NO_IMAGEIO_XPM
3580
3581 return QCommonStyle::stylePixmap(stylepixmap, widget, opt);
3582}
3583
3584/*!\reimp
3585*/
3586void QWarp4Style::drawComplexControl(ComplexControl ctrl, QPainter *p,
3587 QWidget const* widget,
3588 QRect const& r,
3589 QColorGroup const& cg,
3590 SFlags flags,
3591 SCFlags sub,
3592 SCFlags subActive,
3593 QStyleOption const& opt) const
3594{
3595 switch (ctrl)
3596 {
3597 #ifndef QT_NO_SCROLLBAR
3598 case CC_ScrollBar:
3599 {
3600 QScrollBar const* scrollbar = (QScrollBar const*)widget;
3601 bool maxedOut = (scrollbar->minValue() == scrollbar->maxValue());
3602
3603 QRect subline = querySubControlMetrics(ctrl, widget, SC_ScrollBarSubLine, opt),
3604 addline = querySubControlMetrics(ctrl, widget, SC_ScrollBarAddLine, opt),
3605 subpage = querySubControlMetrics(ctrl, widget, SC_ScrollBarSubPage, opt),
3606 addpage = querySubControlMetrics(ctrl, widget, SC_ScrollBarAddPage, opt),
3607 slider = querySubControlMetrics(ctrl, widget, SC_ScrollBarSlider, opt);
3608 if(!scrollbar->isEnabled())
3609 {
3610 subpage.unite(addpage).unite(slider); // fill the whole, empty bar
3611 addpage = slider = QRect(); // invalid rectangle
3612 maxedOut = true; // to avoid setting the Style_Enabled flag
3613 }
3614 bool isMin = scrollbar->value() <= scrollbar->minValue(),
3615 isMax = scrollbar->value() >= scrollbar->maxValue();
3616
3617 if((sub & SC_ScrollBarSubLine) && subline.isValid())
3618 drawPrimitive(PE_ScrollBarSubLine, p, subline, cg,
3619 ((maxedOut || isMin) ? Style_Default : Style_Enabled) |
3620 ((!isMin && (subActive == SC_ScrollBarSubLine)) ? Style_Down : Style_Default) |
3621 ((scrollbar->orientation() == Qt::Horizontal) ? Style_Horizontal : 0));
3622 if((sub & SC_ScrollBarAddLine) && addline.isValid())
3623 drawPrimitive(PE_ScrollBarAddLine, p, addline, cg,
3624 ((maxedOut || isMax) ? Style_Default : Style_Enabled) |
3625 ((!isMax && (subActive == SC_ScrollBarAddLine)) ? Style_Down : Style_Default) |
3626 ((scrollbar->orientation() == Qt::Horizontal) ? Style_Horizontal : 0));
3627 if((sub & SC_ScrollBarSubPage) && subpage.isValid())
3628 drawPrimitive(PE_ScrollBarSubPage, p, subpage, cg,
3629 ((maxedOut) ? Style_Default : Style_Enabled) |
3630 ((subActive == SC_ScrollBarSubPage) ? Style_Down : Style_Default) |
3631 ((scrollbar->orientation() == Qt::Horizontal) ? Style_Horizontal : 0));
3632 if((sub & SC_ScrollBarAddPage) && addpage.isValid())
3633 drawPrimitive(PE_ScrollBarAddPage, p, addpage, cg,
3634 ((maxedOut) ? Style_Default : Style_Enabled) |
3635 ((subActive == SC_ScrollBarAddPage) ? Style_Down : Style_Default) |
3636 ((scrollbar->orientation() == Qt::Horizontal) ? Style_Horizontal : 0));
3637 if((sub & SC_ScrollBarSlider) && slider.isValid())
3638 drawPrimitive(PE_ScrollBarSlider, p, slider, cg,
3639 ((maxedOut) ? Style_Default : Style_Enabled) |
3640 ((subActive == SC_ScrollBarSlider) ? Style_Down : Style_Default) |
3641 ((scrollbar->orientation() == Qt::Horizontal) ? Style_Horizontal : 0));
3642
3643 break;
3644 }
3645 #endif // QT_NO_SCROLLBAR
3646
3647 case CC_SpinWidget:
3648 {
3649 #ifndef QT_NO_SPINWIDGET
3650 QSpinWidget const* sw = (QSpinWidget const*)widget;
3651 SFlags flags;
3652 PrimitiveElement pe;
3653
3654 if(sub & SC_SpinWidgetFrame)
3655 {
3656 qDrawWarpPanel(p, r, cg, -1);
3657 }
3658
3659 if((sub & SC_SpinWidgetUp) ||
3660 (sub & SC_SpinWidgetDown))
3661 {
3662 flags = Style_Enabled;
3663 if((subActive == SC_SpinWidgetUp) ||
3664 (subActive == SC_SpinWidgetDown))
3665 flags |= Style_Sunken;
3666 else
3667 flags |= Style_Raised;
3668
3669 // we "misuse" the On flag to indicate whether the
3670 // "up" part or the "down" part of the button is sunken
3671 if(subActive == SC_SpinWidgetUp)
3672 flags |= Style_On;
3673
3674 if(sub & SC_SpinWidgetUp)
3675 {
3676 if(sw->buttonSymbols() == QSpinWidget::PlusMinus)
3677 pe = PE_SpinWidgetPlus;
3678 else
3679 pe = PE_SpinWidgetUp;
3680 }
3681 else
3682 {
3683 if(sw->buttonSymbols() == QSpinWidget::PlusMinus)
3684 pe = PE_SpinWidgetMinus;
3685 else
3686 pe = PE_SpinWidgetDown;
3687 }
3688
3689 QRect re = sw->upRect();
3690 re.setWidth(re.width() - 2);
3691 bool reverse = QApplication::reverseLayout();
3692 if(!reverse)
3693 re.moveLeft(re.left() + 2);
3694 drawPrimitive(pe, p, re, cg, flags);
3695
3696 // doesn't work yet...
3697 int x = re.left() - 1;
3698 if(reverse)
3699 {
3700 x = re.right() + 2;
3701 p->setPen(cg.light());
3702 }
3703 else
3704 {
3705 p->setPen(cg.dark());
3706 }
3707 p->drawLine(x, re.top(), x, re.bottom());
3708 p->setPen(cg.button());
3709 x--;
3710 p->drawLine(x, re.top(), x, re.bottom());
3711 }
3712
3713 //if(sub & SC_SpinWidgetDown)
3714 //{
3715 // do nothing!
3716 // note: for the Warp style we put all the up/down button
3717 // functionality into the "up" button with the diagonal
3718 // separator
3719 //}
3720 #endif
3721
3722 break;
3723 }
3724
3725 #ifndef QT_NO_TOOLBUTTON
3726 case CC_ToolButton:
3727 {
3728 bool right;
3729 if((right = (QString("qt_right_btn") == widget->name())) ||
3730 (QString("qt_left_btn") == widget->name()))
3731 {
3732 QToolButton* tb = (QToolButton*)widget;
3733 QTabBar* ptb = (QTabBar*)tb->parentWidget();
3734 if((0 == ptb) || !ptb->inherits("QTabBar"))
3735 return;
3736 bool bottom = (QTabBar::RoundedBelow == ptb->shape()) ||
3737 (QTabBar::TriangularBelow == ptb->shape());
3738
3739 QRect r(visualRect(querySubControlMetrics(ctrl, widget, SC_ToolButton, opt), widget));
3740 if(right)
3741 r.addCoords(-3, 0, 0, 0);
3742 else
3743 r.addCoords(0, 0, 3, 0);
3744 p->setClipRect(r);
3745
3746 p->setPen(cg.dark());
3747 if(right)
3748 {
3749 if(bottom)
3750 p->drawLine(r.right(), r.top(), r.right(), r.top() + 3);
3751 else
3752 p->drawLine(r.right(), r.bottom(), r.right(), r.bottom() - 3);
3753 }
3754
3755 QRect tr1(r), tr2(r);
3756 if(right)
3757 {
3758 tr1.addCoords(-1, 0, 1, 0);
3759 tr2.addCoords(-21, 0, -21, 0);
3760 }
3761 else
3762 {
3763 tr1.addCoords(21, 0, 21, 0);
3764 tr2.addCoords(-1, 0, 1, 0);
3765 }
3766
3767 QColorGroup const& cg(tb->colorGroup());
3768 qDrawTabBar(p, tr1, cg, cg.background(), false, bottom);
3769 qDrawTabBar(p, tr2, cg, cg.background(), false, bottom);
3770
3771 if(bottom)
3772 r.addCoords(0, 2, 0, 2);
3773 QPointArray triang;
3774 if(right)
3775 {
3776 triang.putPoints(0, 3,
3777 r.left() + 8, r.top() + 6,
3778 r.left() + 19, r.top() + 12,
3779 r.left() + 8, r.top() + 18);
3780 }
3781 else
3782 {
3783 triang.putPoints(0, 3,
3784 r.right() - 10, r.top() + 6,
3785 r.right() - 21, r.top() + 12,
3786 r.right() - 10, r.top() + 18);
3787 }
3788 p->setBrush(QColor(0, 0, 255));
3789 p->setPen(QPen::NoPen);
3790 p->drawPolygon(triang);
3791 }
3792
3793 else
3794 {
3795 QCommonStyle::drawComplexControl(ctrl, p, widget, r, cg, flags, sub,
3796 subActive, opt);
3797 }
3798
3799 break;
3800 }
3801 #endif // QT_NO_TOOLBUTTON
3802
3803 #ifndef QT_NO_LISTVIEW
3804 case CC_ListView:
3805 {
3806 if(sub & SC_ListView)
3807 {
3808 QCommonStyle::drawComplexControl(ctrl, p, widget, r, cg, flags, sub, subActive, opt);
3809 }
3810
3811 if(sub & (SC_ListViewBranch | SC_ListViewExpand))
3812 {
3813 QListViewItem *item = opt.listViewItem(),
3814 *child = item->firstChild();
3815 QListView* v = item->listView();
3816 int y = r.y();
3817 int bx = r.width() / 2;
3818 int // linetop = 0,
3819 linebot = 0;
3820
3821 // skip the stuff above the exposed rectangle
3822 while(child && ((y + child->height()) <= 0))
3823 {
3824 y += child->totalHeight();
3825 child = child->nextSibling();
3826 }
3827
3828 // notes about drawing lines for Warp:
3829 // 1. Warp type lines follow a different logic than the "normal" lines
3830 // for "tree views" in Qt (which follows more or less Windows)
3831 // 2. In order to ensure partial repaints, it looks like we have to
3832 // draw some lines twice: once with the parent and once with the
3833 // child (and hopefully to the same place...)
3834
3835 while(child && (y < r.height()))
3836 {
3837 if(child->isVisible())
3838 {
3839 int lh;
3840 if(!item->multiLinesEnabled())
3841 lh = child->height();
3842 else
3843 lh = p->fontMetrics().height() + 2 * v->itemMargin();
3844 lh = QMAX(lh, QApplication::globalStrut().height());
3845 if((lh % 2) > 0)
3846 lh++;
3847 linebot = y + lh / 2;
3848 p->setPen(cg.shadow());
3849
3850 // parents and grandparents
3851 int vlx = bx - v->treeStepSize() + 2,
3852 vlyt = linebot - child->height() + 8,
3853 vlyb = linebot - child->height() + 9 + child->totalHeight();
3854 if(0 <= item->depth())
3855 {
3856 // vertical line for parent
3857 if(item->isOpen())
3858 {
3859 if(0 == child->nextSibling())
3860 p->drawLine(vlx, vlyt, vlx, linebot - 2);
3861 else
3862 p->drawLine(vlx, vlyt, vlx, vlyb);
3863 }
3864
3865 // vertical lines for grandparents and "older"
3866 QListViewItem* gp = item;
3867 while(0 < gp->depth())
3868 {
3869 gp = gp->parent();
3870 vlx -= v->treeStepSize();
3871 if(0 != gp->nextSibling())
3872 p->drawLine(vlx, vlyt, vlx, vlyb);
3873 }
3874 }
3875
3876 // draw child itself
3877 if((child->isExpandable() || child->childCount()) &&
3878 (child->height() > 0))
3879 {
3880 // horizontal line up to button
3881 if((0 <= item->depth()) && item->isOpen())
3882 {
3883 p->drawLine(bx - v->treeStepSize() + 3, linebot - 2,
3884 bx - 6, linebot - 2);
3885 }
3886
3887 // button
3888 QRect rr(bx - 6, linebot - 9, 16, 16);
3889 drawPrimitive(PE_ButtonCommand, p, rr, cg,
3890 Style_Raised | Style_ButtonDefault);
3891
3892 // plus or minus
3893 p->setPen(cg.light());
3894 p->drawLine(bx, linebot - 1, bx + 6, linebot - 1);
3895 if(!child->isOpen())
3896 p->drawLine(bx + 3, linebot + 2, bx + 3, linebot - 4);
3897 p->setPen(cg.shadow());
3898 p->drawLine(bx - 1, linebot - 2, bx + 5, linebot - 2);
3899 if(!child->isOpen())
3900 p->drawLine(bx + 2, linebot + 1, bx + 2, linebot - 5);
3901
3902 // lines below expanded child
3903 if(child->isOpen())
3904 {
3905 // vertical line
3906 p->drawLine(bx + 2,
3907 linebot + child->height() - 15,
3908 bx + 2,
3909 linebot + child->totalHeight() - child->height() - 2);
3910
3911 // horizontal lines at child's children
3912 QListViewItem* child2 = child->firstChild();
3913 int y2 = linebot + child->height() - 2;
3914 while(child2 && (y2 < r.height()))
3915 {
3916 if(child2->isVisible())
3917 {
3918 p->drawLine(bx + 2, y2,
3919 bx + v->treeStepSize() - 12, y2);
3920 y2 += child2->totalHeight();
3921 }
3922 child2 = child2->nextSibling();
3923 }
3924 }
3925 }
3926 else if((0 <= item->depth()) && item->isOpen())
3927 {
3928 // horizontal line without button
3929 p->setPen(cg.shadow());
3930 p->drawLine(bx - v->treeStepSize() + 3, linebot - 2,
3931 bx + 8, linebot - 2);
3932 }
3933
3934 y += child->totalHeight();
3935 }
3936 child = child->nextSibling();
3937 }
3938 }
3939
3940 break;
3941 }
3942 #endif //QT_NO_LISTVIEW
3943
3944 #ifndef QT_NO_COMBOBOX
3945 case CC_ComboBox:
3946 {
3947 if(sub & SC_ComboBoxFrame)
3948 {
3949 qDrawWarpPanel(p, r, cg, -1);
3950 p->setPen(cg.dark());
3951 int x = r.right() - 2 - 16;
3952 p->drawLine(x, r.top() + 2, x, r.bottom() - 2);
3953 }
3954
3955 if(sub & SC_ComboBoxArrow)
3956 {
3957 QRect ar = visualRect(querySubControlMetrics(CC_ComboBox, widget,
3958 SC_ComboBoxArrow),
3959 widget);
3960 QBrush fill = cg.brush(QColorGroup::Button);
3961 bool sunken = subActive == SC_ComboBoxArrow;
3962 qDrawWarpFilledRect(p, ar, cg.dark(), cg.light(), &fill, 2, sunken);
3963 p->setPen(cg.button());
3964 p->drawLine(ar.bottomLeft(), ar.topRight());
3965 QPixmap const* pm = qWarpSystemPixmaps.getPixmap(SBMP_COMBODOWN,
3966 QWarpPixmap::bmp);
3967 QPoint ppt = ar.topLeft() +
3968 QPoint((ar.width() - pm->width()) / 2,
3969 (ar.height() - pm->height()) / 2);
3970 p->drawPixmap(ppt, *pm);
3971 }
3972
3973 if(sub & SC_ComboBoxEditField)
3974 {
3975 QComboBox const* cb = (QComboBox const*)widget;
3976 QRect re = QStyle::visualRect(querySubControlMetrics(CC_ComboBox, widget,
3977 SC_ComboBoxEditField),
3978 widget);
3979 p->fillRect(re, cg.brush(QColorGroup::Base));
3980
3981 if(cb->hasFocus())
3982 {
3983 p->setPen(cg.highlightedText());
3984 p->setBackgroundColor(cg.highlight());
3985 }
3986 else
3987 {
3988 p->setPen(cg.text());
3989 p->setBackgroundColor(cg.background());
3990 }
3991
3992 if(cb->hasFocus() && !cb->editable())
3993 {
3994 re = QStyle::visualRect(subRect(SR_ComboBoxFocusRect, cb), widget);
3995 p->fillRect(re, cg.brush(QColorGroup::Highlight));
3996 }
3997 }
3998
3999 break;
4000 }
4001 #endif // QT_NO_COMBOBOX
4002
4003 #ifndef QT_NO_SLIDER
4004 case CC_Slider:
4005 {
4006 QSlider const* sl = (QSlider const*)widget;
4007 QRect groove = querySubControlMetrics(CC_Slider, widget, SC_SliderGroove, opt),
4008 handle = querySubControlMetrics(CC_Slider, widget, SC_SliderHandle, opt);
4009
4010 // reducing the handle length by 2 on each side
4011 if(sl->orientation() == Horizontal)
4012 {
4013 handle.setLeft(handle.left() + 2);
4014 handle.setRight(handle.right() - 2);
4015 }
4016 else
4017 {
4018 handle.setTop(handle.top() + 2);
4019 handle.setBottom(handle.bottom() - 2);
4020 }
4021
4022 if((sub & SC_SliderGroove) && groove.isValid())
4023 {
4024 if(sl->orientation() == Horizontal)
4025 {
4026 groove.setTop(groove.top() + 4);
4027 groove.setBottom(groove.bottom() - 4);
4028 }
4029 else
4030 {
4031 groove.setLeft(groove.left() + 4);
4032 groove.setRight(groove.right() - 4);
4033 }
4034
4035 qDrawWarpFilledRect(p, groove, cg.dark(), cg.light(),
4036 &cg.brush(QColorGroup::Button), 2, true);
4037
4038 groove.setTop(groove.top() + 2);
4039 groove.setLeft(groove.left() + 2);
4040 if(sl->orientation() == Horizontal)
4041 {
4042 groove.setRight(groove.right() - 2);
4043 groove.setBottom(groove.bottom() - 1);
4044 }
4045 else
4046 {
4047 groove.setRight(groove.right() - 1);
4048 groove.setBottom(groove.bottom() - 2);
4049 }
4050
4051 if(flags & Style_HasFocus)
4052 p->setPen(cg.shadow());
4053 else
4054 p->setPen(cg.dark());
4055
4056 p->drawRect(groove);
4057 }
4058
4059 if(sub & SC_SliderTickmarks)
4060 {
4061 int tickOffset = pixelMetric(PM_SliderTickmarkOffset, sl);
4062 int thickness = pixelMetric(PM_SliderControlThickness, sl);
4063 int len = pixelMetric(PM_SliderLength, sl);
4064 int ticks = sl->tickmarks();
4065 int available = pixelMetric(PM_SliderSpaceAvailable, sl);
4066 int interval = sl->tickInterval();
4067
4068 if(interval <= 0 )
4069 {
4070 interval = sl->lineStep();
4071 if((qPositionFromValue(sl, interval, available) -
4072 qPositionFromValue(sl, 0, available)) < 3)
4073 interval = sl->pageStep();
4074 }
4075
4076 int fudge = len / 2;
4077 int pos;
4078
4079 if(ticks & QSlider::Above)
4080 {
4081 if(sl->orientation() == Horizontal)
4082 p->fillRect(0, 0, sl->width(), tickOffset,
4083 cg.brush(QColorGroup::Background));
4084 else
4085 p->fillRect(0, 0, tickOffset, sl->width(),
4086 cg.brush(QColorGroup::Background));
4087 int v = sl->minValue();
4088 if (!interval)
4089 interval = 1;
4090 while(v <= sl->maxValue() + 1)
4091 {
4092 pos = qPositionFromValue(sl, v, available) + fudge;
4093 if(sl->orientation() == Horizontal)
4094 {
4095 p->setPen(cg.dark());
4096 p->drawLine(pos - 1, 0, pos - 1, tickOffset - 1);
4097 p->setPen(cg.light());
4098 p->drawLine(pos, 0, pos, tickOffset - 1);
4099 }
4100 else
4101 {
4102 p->setPen(cg.dark());
4103 p->drawLine(0, pos - 1, tickOffset - 1, pos - 1);
4104 p->setPen(cg.light());
4105 p->drawLine(0, pos, tickOffset - 1, pos);
4106 }
4107 v += interval;
4108 }
4109 }
4110
4111 if(ticks & QSlider::Below)
4112 {
4113 if(sl->orientation() == Horizontal)
4114 p->fillRect(0, tickOffset + thickness, sl->width(), tickOffset,
4115 cg.brush(QColorGroup::Background));
4116 else
4117 p->fillRect(tickOffset + thickness, 0, tickOffset, sl->height(),
4118 cg.brush(QColorGroup::Background));
4119 int v = sl->minValue();
4120 if(!interval)
4121 interval = 1;
4122 while(v <= sl->maxValue() + 1)
4123 {
4124 pos = qPositionFromValue(sl, v, available) + fudge;
4125 if(sl->orientation() == Horizontal)
4126 {
4127 p->setPen(cg.dark());
4128 p->drawLine(pos - 1, tickOffset + thickness + 1,
4129 pos - 1, tickOffset + thickness + 1 + available - 1);
4130 p->setPen(cg.light());
4131 p->drawLine(pos, tickOffset + thickness + 1,
4132 pos, tickOffset + thickness + 1 + available - 1);
4133 }
4134 else
4135 {
4136 p->setPen(cg.dark());
4137 p->drawLine(tickOffset + thickness + 1, pos - 1,
4138 tickOffset + thickness + 1 + available - 1, pos - 1);
4139 p->setPen(cg.light());
4140 p->drawLine(tickOffset + thickness + 1, pos,
4141 tickOffset + thickness + 1 + available - 1, pos);
4142 }
4143 v += interval;
4144 }
4145 }
4146 }
4147
4148 if(sub & SC_SliderHandle)
4149 {
4150 qDrawWarpFilledRect(p, handle, cg.dark(), cg.light(),
4151 &cg.brush(QColorGroup::Button), 2, false);
4152
4153 if(flags & Style_HasFocus)
4154 p->setPen(cg.shadow());
4155 else
4156 p->setPen(cg.dark());
4157
4158 if(sl->orientation() == Horizontal)
4159 p->drawLine(handle.topLeft() + QPoint(5, 2),
4160 handle.bottomLeft() + QPoint(5, -2));
4161 else
4162 p->drawLine(handle.topLeft() + QPoint(2, 5),
4163 handle.topRight() + QPoint(-2, 5));
4164
4165 p->setPen(cg.light());
4166
4167 if(sl->orientation() == Horizontal)
4168 p->drawLine(handle.topLeft() + QPoint(6, 2),
4169 handle.bottomLeft() + QPoint(6, -2));
4170 else
4171 p->drawLine(handle.topLeft() + QPoint(2, 6),
4172 handle.topRight() + QPoint(-2, 6));
4173 }
4174
4175 break;
4176 }
4177 #endif // QT_NO_SLIDER
4178
4179 default:
4180 {
4181 QCommonStyle::drawComplexControl(ctrl, p, widget, r, cg, flags, sub,
4182 subActive, opt);
4183 break;
4184 }
4185 }
4186}
4187
4188/*! \reimp */
4189QRect QWarp4Style::querySubControlMetrics(ComplexControl control,
4190 QWidget const* widget,
4191 SubControl sc,
4192 QStyleOption const& opt) const
4193{
4194 switch(control)
4195 {
4196 #ifndef QT_NO_SCROLLBAR
4197 case CC_ScrollBar:
4198 {
4199 QScrollBar const* scrollbar = (QScrollBar const*)widget;
4200 int sbextent = pixelMetric(PM_ScrollBarExtent, widget);
4201 int maxlen = ((scrollbar->orientation() == Qt::Horizontal) ?
4202 scrollbar->width() : scrollbar->height()) -
4203 (2 * 21); // 2 buttons incl. lines
4204 int sliderstart = scrollbar->sliderStart();
4205
4206 // calculate slider length
4207 int sliderlen;
4208 if(scrollbar->maxValue() != scrollbar->minValue())
4209 {
4210 uint range = scrollbar->maxValue() - scrollbar->minValue();
4211 sliderlen = (scrollbar->pageStep() * maxlen) /
4212 (range + scrollbar->pageStep());
4213 int slidermin = pixelMetric(PM_ScrollBarSliderMin, widget);
4214 if((sliderlen < slidermin) || (range > INT_MAX / 2))
4215 sliderlen = slidermin;
4216 if(sliderlen > maxlen)
4217 sliderlen = maxlen;
4218 }
4219 else
4220 {
4221 sliderlen = maxlen;
4222 }
4223
4224 // calculate button width (for vertical scroll bars this is the height)
4225 // note: the "button" includes the lines at the extreme ends of the sb
4226 int buttonWidth;
4227 if(scrollbar->orientation() == Qt::Horizontal)
4228 buttonWidth = QMIN(scrollbar->width() / 2, 21);
4229 else
4230 buttonWidth = QMIN(scrollbar->height() / 2, 21);
4231
4232 switch(sc)
4233 {
4234 case SC_ScrollBarSubLine: // top/left button
4235 {
4236 if(scrollbar->orientation() == Qt::Horizontal)
4237 return QRect(0, 0, buttonWidth, sbextent);
4238 else
4239 return QRect(0, 0, sbextent, buttonWidth);
4240 }
4241
4242 case SC_ScrollBarAddLine: // bottom/right button
4243 {
4244 if(scrollbar->orientation() == Qt::Horizontal)
4245 return QRect(scrollbar->width() - buttonWidth, 0,
4246 buttonWidth, sbextent);
4247 else
4248 return QRect(0, scrollbar->height() - buttonWidth,
4249 sbextent, buttonWidth);
4250 }
4251
4252 case SC_ScrollBarSubPage: // between top/left button and slider
4253 {
4254 if(scrollbar->orientation() == Qt::Horizontal)
4255 return QRect(buttonWidth, 0,
4256 sliderstart - buttonWidth, sbextent);
4257 else
4258 return QRect(0, buttonWidth,
4259 sbextent, sliderstart - buttonWidth);
4260 }
4261
4262 case SC_ScrollBarAddPage: // between bottom/right button and slider
4263 {
4264 if(scrollbar->orientation() == Qt::Horizontal)
4265 return QRect(sliderstart + sliderlen, 0,
4266 maxlen + buttonWidth - sliderstart - sliderlen, sbextent);
4267 else
4268 return QRect(0, sliderstart + sliderlen,
4269 sbextent, maxlen + buttonWidth - sliderstart - sliderlen);
4270 }
4271
4272 case SC_ScrollBarGroove:
4273 {
4274 if(scrollbar->orientation() == Qt::Horizontal)
4275 return QRect(buttonWidth, 0,
4276 scrollbar->width() - buttonWidth * 2, sbextent);
4277 else
4278 return QRect(0, buttonWidth,
4279 sbextent, scrollbar->height() - buttonWidth * 2);
4280 }
4281
4282 case SC_ScrollBarSlider:
4283 {
4284 if(scrollbar->orientation() == Qt::Horizontal)
4285 return QRect(sliderstart, 0, sliderlen, sbextent);
4286 else
4287 return QRect(0, sliderstart, sbextent, sliderlen);
4288 }
4289 }
4290
4291 break;
4292 }
4293 #endif // QT_NO_SCROLLBAR
4294
4295 case CC_SpinWidget:
4296 {
4297 int fw = pixelMetric(PM_SpinBoxFrameWidth, widget);
4298 QSize bs;
4299 bs.setHeight(widget->height() - 2 * fw);
4300 if(bs.height() < 16)
4301 bs.setHeight(16);
4302 bs.setWidth(bs.height() + 2);
4303 bs = bs.expandedTo(QApplication::globalStrut());
4304 int bx = widget->width() - bs.width() - fw,
4305 by = fw;
4306
4307 switch(sc)
4308 {
4309 case SC_SpinWidgetUp:
4310 return QRect(bx, by, bs.width(), bs.height());
4311 case SC_SpinWidgetDown:
4312 return QRect(bx, by + bs.height(), bs.width(), 0);
4313 case SC_SpinWidgetButtonField:
4314 return QRect(bx, by, bs.width(), widget->height() - 2 * fw);
4315 case SC_SpinWidgetEditField:
4316 return QRect(fw, fw,
4317 widget->width() - bs.width() - 2 * fw,
4318 widget->height() - 2 * fw);
4319 case SC_SpinWidgetFrame:
4320 return widget->rect();
4321 default:
4322 break;
4323 }
4324
4325 break;
4326 }
4327
4328 case CC_ComboBox:
4329 {
4330 QRect r(widget->rect());
4331 int x = r.left(),
4332 y = r.top(),
4333 wi = r.width(),
4334 he = r.height();
4335 int xpos = x;
4336 xpos += wi - 2 - 16;
4337
4338 switch(sc)
4339 {
4340 case SC_ComboBoxFrame:
4341 return widget->rect();
4342 case SC_ComboBoxArrow:
4343 return QRect(xpos, y + 2, 16, he - 4);
4344 case SC_ComboBoxEditField:
4345 return QRect(x + 2, y + 2, wi - 5 - 16, he - 4);
4346 case SC_ComboBoxListBoxPopup:
4347 return opt.rect();
4348 default:
4349 break;
4350 }
4351 break;
4352 }
4353
4354 default:
4355 {
4356 return QCommonStyle::querySubControlMetrics(control, widget, sc, opt);
4357 }
4358 }
4359
4360 return QRect();
4361}
4362
4363/*! \reimp */
4364int QWarp4Style::styleHint(StyleHint hint,
4365 QWidget const* widget,
4366 QStyleOption const& opt,
4367 QStyleHintReturn *returnData) const
4368{
4369 int ret;
4370
4371 switch (hint)
4372 {
4373 case SH_EtchDisabledText:
4374 case SH_Slider_SnapToValue:
4375 case SH_PrintDialog_RightAlignButtons:
4376 case SH_FontDialog_SelectAssociatedText:
4377 case SH_MenuBar_AltKeyNavigation:
4378 case SH_MainWindow_SpaceBelowMenuBar:
4379 case SH_ScrollBar_StopMouseOverSlider:
4380 {
4381 ret = 1;
4382 break;
4383 }
4384
4385 case SH_MenuBar_MouseTracking:
4386 case SH_PopupMenu_MouseTracking:
4387 case SH_PopupMenu_AllowActiveAndDisabled:
4388 case SH_PopupMenu_SpaceActivatesItem:
4389 case SH_PopupMenu_Scrollable:
4390 case SH_PopupMenu_SloppySubMenus:
4391 case SH_PopupMenu_SubMenuPopupDelay:
4392 case SH_ComboBox_ListMouseTracking:
4393 case SH_ItemView_ChangeHighlightOnFocus:
4394 case SH_ToolBox_SelectedPageTitleBold:
4395 {
4396 ret = 0;
4397 break;
4398 }
4399
4400 case SH_GUIStyle:
4401 {
4402 // This value still exists from Qt 1.0 (as it seems), but is never
4403 // ever used in the current code! So the function of setting it
4404 // here is only to avoid using one of the other GUI styles still
4405 // being used (i.e., WindowsStyle and MotifStyle - which in turn are
4406 // also due to being removed entirely with some new Qt version...)
4407 // Note: currently it is being used to add some space to the left of
4408 // the menubar - as that space (another amount...) is also added
4409 // for other OS styles in QMenuBar.cpp (looks like an 1.0 inheritance!)
4410 ret = PMStyle;
4411 break;
4412 }
4413
4414 default:
4415 {
4416 ret = QCommonStyle::styleHint(hint, widget, opt, returnData);
4417 break;
4418 }
4419 }
4420
4421 return ret;
4422}
4423
4424/*! \reimp */
4425QRect QWarp4Style::subRect(SubRect r, QWidget const* widget) const
4426{
4427 QRect rect;
4428
4429 switch(r)
4430 {
4431 case SR_PushButtonFocusRect:
4432 case SR_CheckBoxFocusRect:
4433 case SR_RadioButtonFocusRect:
4434 {
4435 QButton const* button = (QButton const*)widget;
4436 if(!button->pixmap() && button->text().isEmpty())
4437 {
4438 switch(r)
4439 {
4440 case SR_PushButtonFocusRect:
4441 rect = QRect(widget->rect().center(), QSize(0, 0));
4442 break;
4443 case SR_CheckBoxFocusRect:
4444 rect = subRect(SR_CheckBoxIndicator, widget);
4445 break;
4446 case SR_RadioButtonFocusRect:
4447 rect = subRect(SR_RadioButtonIndicator, widget);
4448 break;
4449 }
4450 rect.addCoords(1, 1, -1, -1);
4451 break;
4452 }
4453 QPainter* p = new QPainter(button);
4454 QRect cr;
4455 switch(r)
4456 {
4457 case SR_PushButtonFocusRect:
4458 cr = subRect(SR_PushButtonContents, widget);
4459 break;
4460 case SR_CheckBoxFocusRect:
4461 cr = subRect(SR_CheckBoxContents, widget);
4462 break;
4463 case SR_RadioButtonFocusRect:
4464 cr = subRect(SR_RadioButtonContents, widget);
4465 break;
4466 }
4467 int align = ((SR_PushButtonFocusRect == r) ?
4468 Qt::AlignCenter | Qt::AlignVCenter :
4469 Qt::AlignLeft | Qt::AlignVCenter | Qt::ShowPrefix);
4470 rect = itemRect(p, cr, align,
4471 button->isEnabled(), button->pixmap(), button->text());
4472 delete p;
4473 rect.addCoords(-1, -1, 1, 1);
4474 rect = rect.intersect(widget->rect());
4475 break;
4476 }
4477
4478 #ifndef QT_NO_SLIDER
4479 case SR_SliderFocusRect:
4480 {
4481 rect = widget->rect();
4482 break;
4483 }
4484 #endif // QT_NO_SLIDER
4485
4486 #ifndef QT_NO_PROGRESSBAR
4487 case SR_ProgressBarGroove:
4488 case SR_ProgressBarContents:
4489 {
4490 QFontMetrics fm((widget ? widget->fontMetrics() :
4491 QApplication::fontMetrics()));
4492 QProgressBar const* progressbar = (QProgressBar const*)widget;
4493 int textw = 0;
4494 if(progressbar->percentageVisible())
4495 textw = fm.width("100%") + 6;
4496
4497 // only change for Warp4 compared to "common": the style default
4498 // is "centered"
4499 QRect wrect(widget->rect());
4500 if(!progressbar->indicatorFollowsStyle() &&
4501 !progressbar->centerIndicator())
4502 rect.setCoords(wrect.left(), wrect.top(),
4503 wrect.right() - textw, wrect.bottom());
4504 else
4505 rect = wrect;
4506 break;
4507 }
4508
4509 case SR_ProgressBarLabel:
4510 {
4511 QFontMetrics fm((widget ? widget->fontMetrics() :
4512 QApplication::fontMetrics()));
4513 QProgressBar const* progressbar = (QProgressBar const*)widget;
4514 int textw = 0;
4515 if(progressbar->percentageVisible())
4516 textw = fm.width("100%") + 6;
4517
4518 // only change for Warp4 compared to "common": the style default
4519 // is "centered"
4520 QRect wrect(widget->rect());
4521 if(!progressbar->indicatorFollowsStyle() &&
4522 !progressbar->centerIndicator())
4523 rect.setCoords(wrect.right() - textw, wrect.top(),
4524 wrect.right(), wrect.bottom());
4525 else
4526 rect = wrect;
4527 break;
4528 }
4529 #endif
4530
4531 case SR_ToolBoxTabContents:
4532 {
4533 rect = widget->rect();
4534 break;
4535 }
4536
4537 default:
4538 {
4539 rect = QCommonStyle::subRect(r, widget);
4540 break;
4541 }
4542 }
4543
4544 return rect;
4545}
4546
4547#include "qwarp4style.moc"
4548
4549#endif
Note: See TracBrowser for help on using the repository browser.