From f67b8df3ebdba2d398b9cce686b7c644adffff08 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 7 May 2011 00:02:01 +0200 Subject: library split --- src/widgets/styles/images/cdr-128.png | Bin 0 -> 16418 bytes src/widgets/styles/images/cdr-16.png | Bin 0 -> 845 bytes src/widgets/styles/images/cdr-32.png | Bin 0 -> 2016 bytes src/widgets/styles/images/closedock-16.png | Bin 0 -> 516 bytes src/widgets/styles/images/closedock-down-16.png | Bin 0 -> 578 bytes src/widgets/styles/images/computer-16.png | Bin 0 -> 782 bytes src/widgets/styles/images/computer-32.png | Bin 0 -> 1807 bytes src/widgets/styles/images/defaults60theme.blob | Bin 0 -> 74127 bytes src/widgets/styles/images/desktop-16.png | Bin 0 -> 773 bytes src/widgets/styles/images/desktop-32.png | Bin 0 -> 1103 bytes src/widgets/styles/images/dirclosed-128.png | Bin 0 -> 1386 bytes src/widgets/styles/images/dirclosed-16.png | Bin 0 -> 231 bytes src/widgets/styles/images/dirclosed-32.png | Bin 0 -> 474 bytes src/widgets/styles/images/dirlink-128.png | Bin 0 -> 5155 bytes src/widgets/styles/images/dirlink-16.png | Bin 0 -> 416 bytes src/widgets/styles/images/dirlink-32.png | Bin 0 -> 1046 bytes src/widgets/styles/images/diropen-128.png | Bin 0 -> 2075 bytes src/widgets/styles/images/diropen-16.png | Bin 0 -> 248 bytes src/widgets/styles/images/diropen-32.png | Bin 0 -> 633 bytes src/widgets/styles/images/dockdock-16.png | Bin 0 -> 438 bytes src/widgets/styles/images/dockdock-down-16.png | Bin 0 -> 406 bytes src/widgets/styles/images/down-128.png | Bin 0 -> 9550 bytes src/widgets/styles/images/down-16.png | Bin 0 -> 817 bytes src/widgets/styles/images/down-32.png | Bin 0 -> 1820 bytes src/widgets/styles/images/dvd-128.png | Bin 0 -> 14941 bytes src/widgets/styles/images/dvd-16.png | Bin 0 -> 892 bytes src/widgets/styles/images/dvd-32.png | Bin 0 -> 2205 bytes src/widgets/styles/images/file-128.png | Bin 0 -> 3997 bytes src/widgets/styles/images/file-16.png | Bin 0 -> 423 bytes src/widgets/styles/images/file-32.png | Bin 0 -> 713 bytes src/widgets/styles/images/filecontents-128.png | Bin 0 -> 8109 bytes src/widgets/styles/images/filecontents-16.png | Bin 0 -> 766 bytes src/widgets/styles/images/filecontents-32.png | Bin 0 -> 1712 bytes src/widgets/styles/images/fileinfo-128.png | Bin 0 -> 12002 bytes src/widgets/styles/images/fileinfo-16.png | Bin 0 -> 849 bytes src/widgets/styles/images/fileinfo-32.png | Bin 0 -> 2010 bytes src/widgets/styles/images/filelink-128.png | Bin 0 -> 5601 bytes src/widgets/styles/images/filelink-16.png | Bin 0 -> 566 bytes src/widgets/styles/images/filelink-32.png | Bin 0 -> 1192 bytes src/widgets/styles/images/floppy-128.png | Bin 0 -> 5074 bytes src/widgets/styles/images/floppy-16.png | Bin 0 -> 602 bytes src/widgets/styles/images/floppy-32.png | Bin 0 -> 1019 bytes src/widgets/styles/images/fontbitmap-16.png | Bin 0 -> 537 bytes src/widgets/styles/images/fonttruetype-16.png | Bin 0 -> 442 bytes src/widgets/styles/images/harddrive-128.png | Bin 0 -> 11250 bytes src/widgets/styles/images/harddrive-16.png | Bin 0 -> 802 bytes src/widgets/styles/images/harddrive-32.png | Bin 0 -> 1751 bytes src/widgets/styles/images/left-128.png | Bin 0 -> 9432 bytes src/widgets/styles/images/left-16.png | Bin 0 -> 826 bytes src/widgets/styles/images/left-32.png | Bin 0 -> 1799 bytes src/widgets/styles/images/media-pause-16.png | Bin 0 -> 229 bytes src/widgets/styles/images/media-pause-32.png | Bin 0 -> 185 bytes src/widgets/styles/images/media-play-16.png | Bin 0 -> 262 bytes src/widgets/styles/images/media-play-32.png | Bin 0 -> 413 bytes .../styles/images/media-seek-backward-16.png | Bin 0 -> 384 bytes .../styles/images/media-seek-backward-32.png | Bin 0 -> 548 bytes .../styles/images/media-seek-forward-16.png | Bin 0 -> 370 bytes .../styles/images/media-seek-forward-32.png | Bin 0 -> 524 bytes .../styles/images/media-skip-backward-16.png | Bin 0 -> 396 bytes .../styles/images/media-skip-backward-32.png | Bin 0 -> 570 bytes .../styles/images/media-skip-forward-16.png | Bin 0 -> 384 bytes .../styles/images/media-skip-forward-32.png | Bin 0 -> 549 bytes src/widgets/styles/images/media-stop-16.png | Bin 0 -> 166 bytes src/widgets/styles/images/media-stop-32.png | Bin 0 -> 176 bytes src/widgets/styles/images/media-volume-16.png | Bin 0 -> 799 bytes .../styles/images/media-volume-muted-16.png | Bin 0 -> 668 bytes src/widgets/styles/images/networkdrive-128.png | Bin 0 -> 18075 bytes src/widgets/styles/images/networkdrive-16.png | Bin 0 -> 885 bytes src/widgets/styles/images/networkdrive-32.png | Bin 0 -> 2245 bytes src/widgets/styles/images/newdirectory-128.png | Bin 0 -> 7503 bytes src/widgets/styles/images/newdirectory-16.png | Bin 0 -> 870 bytes src/widgets/styles/images/newdirectory-32.png | Bin 0 -> 1590 bytes src/widgets/styles/images/parentdir-128.png | Bin 0 -> 8093 bytes src/widgets/styles/images/parentdir-16.png | Bin 0 -> 938 bytes src/widgets/styles/images/parentdir-32.png | Bin 0 -> 1603 bytes src/widgets/styles/images/refresh-24.png | Bin 0 -> 1654 bytes src/widgets/styles/images/refresh-32.png | Bin 0 -> 2431 bytes src/widgets/styles/images/right-128.png | Bin 0 -> 9367 bytes src/widgets/styles/images/right-16.png | Bin 0 -> 811 bytes src/widgets/styles/images/right-32.png | Bin 0 -> 1804 bytes .../styles/images/standardbutton-apply-128.png | Bin 0 -> 5395 bytes .../styles/images/standardbutton-apply-16.png | Bin 0 -> 611 bytes .../styles/images/standardbutton-apply-32.png | Bin 0 -> 1279 bytes .../styles/images/standardbutton-cancel-128.png | Bin 0 -> 7039 bytes .../styles/images/standardbutton-cancel-16.png | Bin 0 -> 689 bytes .../styles/images/standardbutton-cancel-32.png | Bin 0 -> 1573 bytes .../styles/images/standardbutton-clear-128.png | Bin 0 -> 3094 bytes .../styles/images/standardbutton-clear-16.png | Bin 0 -> 456 bytes .../styles/images/standardbutton-clear-32.png | Bin 0 -> 866 bytes .../styles/images/standardbutton-close-128.png | Bin 0 -> 4512 bytes .../styles/images/standardbutton-close-16.png | Bin 0 -> 366 bytes .../styles/images/standardbutton-close-32.png | Bin 0 -> 780 bytes .../styles/images/standardbutton-closetab-16.png | Bin 0 -> 406 bytes .../images/standardbutton-closetab-down-16.png | Bin 0 -> 481 bytes .../images/standardbutton-closetab-hover-16.png | Bin 0 -> 570 bytes .../styles/images/standardbutton-delete-128.png | Bin 0 -> 5414 bytes .../styles/images/standardbutton-delete-16.png | Bin 0 -> 722 bytes .../styles/images/standardbutton-delete-32.png | Bin 0 -> 1541 bytes .../styles/images/standardbutton-help-128.png | Bin 0 -> 10765 bytes .../styles/images/standardbutton-help-16.png | Bin 0 -> 840 bytes .../styles/images/standardbutton-help-32.png | Bin 0 -> 2066 bytes .../styles/images/standardbutton-no-128.png | Bin 0 -> 6520 bytes src/widgets/styles/images/standardbutton-no-16.png | Bin 0 -> 701 bytes src/widgets/styles/images/standardbutton-no-32.png | Bin 0 -> 1445 bytes .../styles/images/standardbutton-ok-128.png | Bin 0 -> 4232 bytes src/widgets/styles/images/standardbutton-ok-16.png | Bin 0 -> 584 bytes src/widgets/styles/images/standardbutton-ok-32.png | Bin 0 -> 1246 bytes .../styles/images/standardbutton-open-128.png | Bin 0 -> 5415 bytes .../styles/images/standardbutton-open-16.png | Bin 0 -> 629 bytes .../styles/images/standardbutton-open-32.png | Bin 0 -> 1154 bytes .../styles/images/standardbutton-save-128.png | Bin 0 -> 4398 bytes .../styles/images/standardbutton-save-16.png | Bin 0 -> 583 bytes .../styles/images/standardbutton-save-32.png | Bin 0 -> 1092 bytes .../styles/images/standardbutton-yes-128.png | Bin 0 -> 6554 bytes .../styles/images/standardbutton-yes-16.png | Bin 0 -> 687 bytes .../styles/images/standardbutton-yes-32.png | Bin 0 -> 1504 bytes src/widgets/styles/images/stop-24.png | Bin 0 -> 1267 bytes src/widgets/styles/images/stop-32.png | Bin 0 -> 1878 bytes src/widgets/styles/images/trash-128.png | Bin 0 -> 3296 bytes src/widgets/styles/images/trash-16.png | Bin 0 -> 419 bytes src/widgets/styles/images/trash-32.png | Bin 0 -> 883 bytes src/widgets/styles/images/up-128.png | Bin 0 -> 9363 bytes src/widgets/styles/images/up-16.png | Bin 0 -> 814 bytes src/widgets/styles/images/up-32.png | Bin 0 -> 1798 bytes src/widgets/styles/images/viewdetailed-128.png | Bin 0 -> 4743 bytes src/widgets/styles/images/viewdetailed-16.png | Bin 0 -> 499 bytes src/widgets/styles/images/viewdetailed-32.png | Bin 0 -> 1092 bytes src/widgets/styles/images/viewlist-128.png | Bin 0 -> 4069 bytes src/widgets/styles/images/viewlist-16.png | Bin 0 -> 490 bytes src/widgets/styles/images/viewlist-32.png | Bin 0 -> 1006 bytes src/widgets/styles/qcdestyle.cpp | 305 + src/widgets/styles/qcdestyle.h | 82 + src/widgets/styles/qcleanlooksstyle.cpp | 4466 ++++++++++++ src/widgets/styles/qcleanlooksstyle.h | 114 + src/widgets/styles/qcleanlooksstyle_p.h | 80 + src/widgets/styles/qcommonstyle.cpp | 6085 ++++++++++++++++ src/widgets/styles/qcommonstyle.h | 109 + src/widgets/styles/qcommonstyle_p.h | 113 + src/widgets/styles/qcommonstylepixmaps_p.h | 186 + src/widgets/styles/qdrawutil.cpp | 1053 +++ src/widgets/styles/qdrawutil.h | 175 + src/widgets/styles/qgtkpainter.cpp | 721 ++ src/widgets/styles/qgtkpainter_p.h | 129 + src/widgets/styles/qgtkstyle.cpp | 3563 ++++++++++ src/widgets/styles/qgtkstyle.h | 128 + src/widgets/styles/qgtkstyle_p.cpp | 1146 +++ src/widgets/styles/qgtkstyle_p.h | 531 ++ src/widgets/styles/qmacstyle.qdoc | 247 + src/widgets/styles/qmacstyle_mac.h | 148 + src/widgets/styles/qmacstyle_mac.mm | 6042 ++++++++++++++++ src/widgets/styles/qmacstyle_mac_p.h | 241 + src/widgets/styles/qmacstylepixmaps_mac_p.h | 72 + src/widgets/styles/qmotifstyle.cpp | 2721 ++++++++ src/widgets/styles/qmotifstyle.h | 128 + src/widgets/styles/qmotifstyle_p.h | 82 + src/widgets/styles/qplastiquestyle.cpp | 6011 ++++++++++++++++ src/widgets/styles/qplastiquestyle.h | 119 + src/widgets/styles/qproxystyle.cpp | 420 ++ src/widgets/styles/qproxystyle.h | 114 + src/widgets/styles/qproxystyle_p.h | 79 + src/widgets/styles/qs60style.cpp | 3618 ++++++++++ src/widgets/styles/qs60style.h | 118 + src/widgets/styles/qs60style_p.h | 638 ++ src/widgets/styles/qs60style_s60.cpp | 1591 +++++ src/widgets/styles/qs60style_simulated.cpp | 457 ++ src/widgets/styles/qs60style_stub.cpp | 131 + src/widgets/styles/qstyle.cpp | 2459 +++++++ src/widgets/styles/qstyle.h | 889 +++ src/widgets/styles/qstyle.qrc | 135 + src/widgets/styles/qstyle_p.h | 108 + src/widgets/styles/qstyle_s60.qrc | 137 + src/widgets/styles/qstyle_s60_simulated.qrc | 6 + src/widgets/styles/qstyle_wince.qrc | 97 + src/widgets/styles/qstylefactory.cpp | 271 + src/widgets/styles/qstylefactory.h | 66 + src/widgets/styles/qstylehelper.cpp | 378 + src/widgets/styles/qstylehelper_p.h | 89 + src/widgets/styles/qstyleoption.cpp | 5508 +++++++++++++++ src/widgets/styles/qstyleoption.h | 970 +++ src/widgets/styles/qstylepainter.cpp | 176 + src/widgets/styles/qstylepainter.h | 112 + src/widgets/styles/qstyleplugin.cpp | 115 + src/widgets/styles/qstyleplugin.h | 81 + src/widgets/styles/qstylesheetstyle.cpp | 5898 ++++++++++++++++ src/widgets/styles/qstylesheetstyle_default.cpp | 512 ++ src/widgets/styles/qstylesheetstyle_p.h | 204 + src/widgets/styles/qwindowscestyle.cpp | 2429 +++++++ src/widgets/styles/qwindowscestyle.h | 103 + src/widgets/styles/qwindowscestyle_p.h | 118 + src/widgets/styles/qwindowsmobilestyle.cpp | 7283 ++++++++++++++++++++ src/widgets/styles/qwindowsmobilestyle.h | 116 + src/widgets/styles/qwindowsmobilestyle_p.h | 136 + src/widgets/styles/qwindowsstyle.cpp | 3392 +++++++++ src/widgets/styles/qwindowsstyle.h | 111 + src/widgets/styles/qwindowsstyle_p.h | 106 + src/widgets/styles/qwindowsvistastyle.cpp | 2670 +++++++ src/widgets/styles/qwindowsvistastyle.h | 108 + src/widgets/styles/qwindowsvistastyle_p.h | 220 + src/widgets/styles/qwindowsxpstyle.cpp | 4271 ++++++++++++ src/widgets/styles/qwindowsxpstyle.h | 107 + src/widgets/styles/qwindowsxpstyle_p.h | 356 + src/widgets/styles/styles.pri | 194 + 202 files changed, 81894 insertions(+) create mode 100644 src/widgets/styles/images/cdr-128.png create mode 100644 src/widgets/styles/images/cdr-16.png create mode 100644 src/widgets/styles/images/cdr-32.png create mode 100644 src/widgets/styles/images/closedock-16.png create mode 100644 src/widgets/styles/images/closedock-down-16.png create mode 100644 src/widgets/styles/images/computer-16.png create mode 100644 src/widgets/styles/images/computer-32.png create mode 100644 src/widgets/styles/images/defaults60theme.blob create mode 100644 src/widgets/styles/images/desktop-16.png create mode 100644 src/widgets/styles/images/desktop-32.png create mode 100644 src/widgets/styles/images/dirclosed-128.png create mode 100644 src/widgets/styles/images/dirclosed-16.png create mode 100644 src/widgets/styles/images/dirclosed-32.png create mode 100644 src/widgets/styles/images/dirlink-128.png create mode 100644 src/widgets/styles/images/dirlink-16.png create mode 100644 src/widgets/styles/images/dirlink-32.png create mode 100644 src/widgets/styles/images/diropen-128.png create mode 100644 src/widgets/styles/images/diropen-16.png create mode 100644 src/widgets/styles/images/diropen-32.png create mode 100644 src/widgets/styles/images/dockdock-16.png create mode 100644 src/widgets/styles/images/dockdock-down-16.png create mode 100644 src/widgets/styles/images/down-128.png create mode 100644 src/widgets/styles/images/down-16.png create mode 100644 src/widgets/styles/images/down-32.png create mode 100644 src/widgets/styles/images/dvd-128.png create mode 100644 src/widgets/styles/images/dvd-16.png create mode 100644 src/widgets/styles/images/dvd-32.png create mode 100644 src/widgets/styles/images/file-128.png create mode 100644 src/widgets/styles/images/file-16.png create mode 100644 src/widgets/styles/images/file-32.png create mode 100644 src/widgets/styles/images/filecontents-128.png create mode 100644 src/widgets/styles/images/filecontents-16.png create mode 100644 src/widgets/styles/images/filecontents-32.png create mode 100644 src/widgets/styles/images/fileinfo-128.png create mode 100644 src/widgets/styles/images/fileinfo-16.png create mode 100644 src/widgets/styles/images/fileinfo-32.png create mode 100644 src/widgets/styles/images/filelink-128.png create mode 100644 src/widgets/styles/images/filelink-16.png create mode 100644 src/widgets/styles/images/filelink-32.png create mode 100644 src/widgets/styles/images/floppy-128.png create mode 100644 src/widgets/styles/images/floppy-16.png create mode 100644 src/widgets/styles/images/floppy-32.png create mode 100644 src/widgets/styles/images/fontbitmap-16.png create mode 100644 src/widgets/styles/images/fonttruetype-16.png create mode 100644 src/widgets/styles/images/harddrive-128.png create mode 100644 src/widgets/styles/images/harddrive-16.png create mode 100644 src/widgets/styles/images/harddrive-32.png create mode 100644 src/widgets/styles/images/left-128.png create mode 100644 src/widgets/styles/images/left-16.png create mode 100644 src/widgets/styles/images/left-32.png create mode 100644 src/widgets/styles/images/media-pause-16.png create mode 100644 src/widgets/styles/images/media-pause-32.png create mode 100644 src/widgets/styles/images/media-play-16.png create mode 100644 src/widgets/styles/images/media-play-32.png create mode 100644 src/widgets/styles/images/media-seek-backward-16.png create mode 100644 src/widgets/styles/images/media-seek-backward-32.png create mode 100644 src/widgets/styles/images/media-seek-forward-16.png create mode 100644 src/widgets/styles/images/media-seek-forward-32.png create mode 100644 src/widgets/styles/images/media-skip-backward-16.png create mode 100644 src/widgets/styles/images/media-skip-backward-32.png create mode 100644 src/widgets/styles/images/media-skip-forward-16.png create mode 100644 src/widgets/styles/images/media-skip-forward-32.png create mode 100644 src/widgets/styles/images/media-stop-16.png create mode 100644 src/widgets/styles/images/media-stop-32.png create mode 100644 src/widgets/styles/images/media-volume-16.png create mode 100644 src/widgets/styles/images/media-volume-muted-16.png create mode 100644 src/widgets/styles/images/networkdrive-128.png create mode 100644 src/widgets/styles/images/networkdrive-16.png create mode 100644 src/widgets/styles/images/networkdrive-32.png create mode 100644 src/widgets/styles/images/newdirectory-128.png create mode 100644 src/widgets/styles/images/newdirectory-16.png create mode 100644 src/widgets/styles/images/newdirectory-32.png create mode 100644 src/widgets/styles/images/parentdir-128.png create mode 100644 src/widgets/styles/images/parentdir-16.png create mode 100644 src/widgets/styles/images/parentdir-32.png create mode 100644 src/widgets/styles/images/refresh-24.png create mode 100644 src/widgets/styles/images/refresh-32.png create mode 100644 src/widgets/styles/images/right-128.png create mode 100644 src/widgets/styles/images/right-16.png create mode 100644 src/widgets/styles/images/right-32.png create mode 100644 src/widgets/styles/images/standardbutton-apply-128.png create mode 100644 src/widgets/styles/images/standardbutton-apply-16.png create mode 100644 src/widgets/styles/images/standardbutton-apply-32.png create mode 100644 src/widgets/styles/images/standardbutton-cancel-128.png create mode 100644 src/widgets/styles/images/standardbutton-cancel-16.png create mode 100644 src/widgets/styles/images/standardbutton-cancel-32.png create mode 100644 src/widgets/styles/images/standardbutton-clear-128.png create mode 100644 src/widgets/styles/images/standardbutton-clear-16.png create mode 100644 src/widgets/styles/images/standardbutton-clear-32.png create mode 100644 src/widgets/styles/images/standardbutton-close-128.png create mode 100644 src/widgets/styles/images/standardbutton-close-16.png create mode 100644 src/widgets/styles/images/standardbutton-close-32.png create mode 100644 src/widgets/styles/images/standardbutton-closetab-16.png create mode 100644 src/widgets/styles/images/standardbutton-closetab-down-16.png create mode 100644 src/widgets/styles/images/standardbutton-closetab-hover-16.png create mode 100644 src/widgets/styles/images/standardbutton-delete-128.png create mode 100644 src/widgets/styles/images/standardbutton-delete-16.png create mode 100644 src/widgets/styles/images/standardbutton-delete-32.png create mode 100644 src/widgets/styles/images/standardbutton-help-128.png create mode 100644 src/widgets/styles/images/standardbutton-help-16.png create mode 100644 src/widgets/styles/images/standardbutton-help-32.png create mode 100644 src/widgets/styles/images/standardbutton-no-128.png create mode 100644 src/widgets/styles/images/standardbutton-no-16.png create mode 100644 src/widgets/styles/images/standardbutton-no-32.png create mode 100644 src/widgets/styles/images/standardbutton-ok-128.png create mode 100644 src/widgets/styles/images/standardbutton-ok-16.png create mode 100644 src/widgets/styles/images/standardbutton-ok-32.png create mode 100644 src/widgets/styles/images/standardbutton-open-128.png create mode 100644 src/widgets/styles/images/standardbutton-open-16.png create mode 100644 src/widgets/styles/images/standardbutton-open-32.png create mode 100644 src/widgets/styles/images/standardbutton-save-128.png create mode 100644 src/widgets/styles/images/standardbutton-save-16.png create mode 100644 src/widgets/styles/images/standardbutton-save-32.png create mode 100644 src/widgets/styles/images/standardbutton-yes-128.png create mode 100644 src/widgets/styles/images/standardbutton-yes-16.png create mode 100644 src/widgets/styles/images/standardbutton-yes-32.png create mode 100644 src/widgets/styles/images/stop-24.png create mode 100644 src/widgets/styles/images/stop-32.png create mode 100644 src/widgets/styles/images/trash-128.png create mode 100644 src/widgets/styles/images/trash-16.png create mode 100644 src/widgets/styles/images/trash-32.png create mode 100644 src/widgets/styles/images/up-128.png create mode 100644 src/widgets/styles/images/up-16.png create mode 100644 src/widgets/styles/images/up-32.png create mode 100644 src/widgets/styles/images/viewdetailed-128.png create mode 100644 src/widgets/styles/images/viewdetailed-16.png create mode 100644 src/widgets/styles/images/viewdetailed-32.png create mode 100644 src/widgets/styles/images/viewlist-128.png create mode 100644 src/widgets/styles/images/viewlist-16.png create mode 100644 src/widgets/styles/images/viewlist-32.png create mode 100644 src/widgets/styles/qcdestyle.cpp create mode 100644 src/widgets/styles/qcdestyle.h create mode 100644 src/widgets/styles/qcleanlooksstyle.cpp create mode 100644 src/widgets/styles/qcleanlooksstyle.h create mode 100644 src/widgets/styles/qcleanlooksstyle_p.h create mode 100644 src/widgets/styles/qcommonstyle.cpp create mode 100644 src/widgets/styles/qcommonstyle.h create mode 100644 src/widgets/styles/qcommonstyle_p.h create mode 100644 src/widgets/styles/qcommonstylepixmaps_p.h create mode 100644 src/widgets/styles/qdrawutil.cpp create mode 100644 src/widgets/styles/qdrawutil.h create mode 100644 src/widgets/styles/qgtkpainter.cpp create mode 100644 src/widgets/styles/qgtkpainter_p.h create mode 100644 src/widgets/styles/qgtkstyle.cpp create mode 100644 src/widgets/styles/qgtkstyle.h create mode 100644 src/widgets/styles/qgtkstyle_p.cpp create mode 100644 src/widgets/styles/qgtkstyle_p.h create mode 100644 src/widgets/styles/qmacstyle.qdoc create mode 100644 src/widgets/styles/qmacstyle_mac.h create mode 100644 src/widgets/styles/qmacstyle_mac.mm create mode 100644 src/widgets/styles/qmacstyle_mac_p.h create mode 100644 src/widgets/styles/qmacstylepixmaps_mac_p.h create mode 100644 src/widgets/styles/qmotifstyle.cpp create mode 100644 src/widgets/styles/qmotifstyle.h create mode 100644 src/widgets/styles/qmotifstyle_p.h create mode 100644 src/widgets/styles/qplastiquestyle.cpp create mode 100644 src/widgets/styles/qplastiquestyle.h create mode 100644 src/widgets/styles/qproxystyle.cpp create mode 100644 src/widgets/styles/qproxystyle.h create mode 100644 src/widgets/styles/qproxystyle_p.h create mode 100644 src/widgets/styles/qs60style.cpp create mode 100644 src/widgets/styles/qs60style.h create mode 100644 src/widgets/styles/qs60style_p.h create mode 100644 src/widgets/styles/qs60style_s60.cpp create mode 100644 src/widgets/styles/qs60style_simulated.cpp create mode 100644 src/widgets/styles/qs60style_stub.cpp create mode 100644 src/widgets/styles/qstyle.cpp create mode 100644 src/widgets/styles/qstyle.h create mode 100644 src/widgets/styles/qstyle.qrc create mode 100644 src/widgets/styles/qstyle_p.h create mode 100644 src/widgets/styles/qstyle_s60.qrc create mode 100644 src/widgets/styles/qstyle_s60_simulated.qrc create mode 100644 src/widgets/styles/qstyle_wince.qrc create mode 100644 src/widgets/styles/qstylefactory.cpp create mode 100644 src/widgets/styles/qstylefactory.h create mode 100644 src/widgets/styles/qstylehelper.cpp create mode 100644 src/widgets/styles/qstylehelper_p.h create mode 100644 src/widgets/styles/qstyleoption.cpp create mode 100644 src/widgets/styles/qstyleoption.h create mode 100644 src/widgets/styles/qstylepainter.cpp create mode 100644 src/widgets/styles/qstylepainter.h create mode 100644 src/widgets/styles/qstyleplugin.cpp create mode 100644 src/widgets/styles/qstyleplugin.h create mode 100644 src/widgets/styles/qstylesheetstyle.cpp create mode 100644 src/widgets/styles/qstylesheetstyle_default.cpp create mode 100644 src/widgets/styles/qstylesheetstyle_p.h create mode 100644 src/widgets/styles/qwindowscestyle.cpp create mode 100644 src/widgets/styles/qwindowscestyle.h create mode 100644 src/widgets/styles/qwindowscestyle_p.h create mode 100644 src/widgets/styles/qwindowsmobilestyle.cpp create mode 100644 src/widgets/styles/qwindowsmobilestyle.h create mode 100644 src/widgets/styles/qwindowsmobilestyle_p.h create mode 100644 src/widgets/styles/qwindowsstyle.cpp create mode 100644 src/widgets/styles/qwindowsstyle.h create mode 100644 src/widgets/styles/qwindowsstyle_p.h create mode 100644 src/widgets/styles/qwindowsvistastyle.cpp create mode 100644 src/widgets/styles/qwindowsvistastyle.h create mode 100644 src/widgets/styles/qwindowsvistastyle_p.h create mode 100644 src/widgets/styles/qwindowsxpstyle.cpp create mode 100644 src/widgets/styles/qwindowsxpstyle.h create mode 100644 src/widgets/styles/qwindowsxpstyle_p.h create mode 100644 src/widgets/styles/styles.pri (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/images/cdr-128.png b/src/widgets/styles/images/cdr-128.png new file mode 100644 index 0000000000..c5daa15fc8 Binary files /dev/null and b/src/widgets/styles/images/cdr-128.png differ diff --git a/src/widgets/styles/images/cdr-16.png b/src/widgets/styles/images/cdr-16.png new file mode 100644 index 0000000000..82d7533bd1 Binary files /dev/null and b/src/widgets/styles/images/cdr-16.png differ diff --git a/src/widgets/styles/images/cdr-32.png b/src/widgets/styles/images/cdr-32.png new file mode 100644 index 0000000000..dcfb085da5 Binary files /dev/null and b/src/widgets/styles/images/cdr-32.png differ diff --git a/src/widgets/styles/images/closedock-16.png b/src/widgets/styles/images/closedock-16.png new file mode 100644 index 0000000000..ab9d669eee Binary files /dev/null and b/src/widgets/styles/images/closedock-16.png differ diff --git a/src/widgets/styles/images/closedock-down-16.png b/src/widgets/styles/images/closedock-down-16.png new file mode 100644 index 0000000000..c1791dd2cc Binary files /dev/null and b/src/widgets/styles/images/closedock-down-16.png differ diff --git a/src/widgets/styles/images/computer-16.png b/src/widgets/styles/images/computer-16.png new file mode 100644 index 0000000000..43fb0bb581 Binary files /dev/null and b/src/widgets/styles/images/computer-16.png differ diff --git a/src/widgets/styles/images/computer-32.png b/src/widgets/styles/images/computer-32.png new file mode 100644 index 0000000000..6d750ce89b Binary files /dev/null and b/src/widgets/styles/images/computer-32.png differ diff --git a/src/widgets/styles/images/defaults60theme.blob b/src/widgets/styles/images/defaults60theme.blob new file mode 100644 index 0000000000..f3a59528d6 Binary files /dev/null and b/src/widgets/styles/images/defaults60theme.blob differ diff --git a/src/widgets/styles/images/desktop-16.png b/src/widgets/styles/images/desktop-16.png new file mode 100644 index 0000000000..d612dfb0fc Binary files /dev/null and b/src/widgets/styles/images/desktop-16.png differ diff --git a/src/widgets/styles/images/desktop-32.png b/src/widgets/styles/images/desktop-32.png new file mode 100644 index 0000000000..ad85b48d3a Binary files /dev/null and b/src/widgets/styles/images/desktop-32.png differ diff --git a/src/widgets/styles/images/dirclosed-128.png b/src/widgets/styles/images/dirclosed-128.png new file mode 100644 index 0000000000..e4fa843162 Binary files /dev/null and b/src/widgets/styles/images/dirclosed-128.png differ diff --git a/src/widgets/styles/images/dirclosed-16.png b/src/widgets/styles/images/dirclosed-16.png new file mode 100644 index 0000000000..333fe8eaac Binary files /dev/null and b/src/widgets/styles/images/dirclosed-16.png differ diff --git a/src/widgets/styles/images/dirclosed-32.png b/src/widgets/styles/images/dirclosed-32.png new file mode 100644 index 0000000000..3add907ed5 Binary files /dev/null and b/src/widgets/styles/images/dirclosed-32.png differ diff --git a/src/widgets/styles/images/dirlink-128.png b/src/widgets/styles/images/dirlink-128.png new file mode 100644 index 0000000000..ec299f8e52 Binary files /dev/null and b/src/widgets/styles/images/dirlink-128.png differ diff --git a/src/widgets/styles/images/dirlink-16.png b/src/widgets/styles/images/dirlink-16.png new file mode 100644 index 0000000000..9f16cd3520 Binary files /dev/null and b/src/widgets/styles/images/dirlink-16.png differ diff --git a/src/widgets/styles/images/dirlink-32.png b/src/widgets/styles/images/dirlink-32.png new file mode 100644 index 0000000000..776536d131 Binary files /dev/null and b/src/widgets/styles/images/dirlink-32.png differ diff --git a/src/widgets/styles/images/diropen-128.png b/src/widgets/styles/images/diropen-128.png new file mode 100644 index 0000000000..b91c4af72a Binary files /dev/null and b/src/widgets/styles/images/diropen-128.png differ diff --git a/src/widgets/styles/images/diropen-16.png b/src/widgets/styles/images/diropen-16.png new file mode 100644 index 0000000000..95f0771d06 Binary files /dev/null and b/src/widgets/styles/images/diropen-16.png differ diff --git a/src/widgets/styles/images/diropen-32.png b/src/widgets/styles/images/diropen-32.png new file mode 100644 index 0000000000..af5f7e7e81 Binary files /dev/null and b/src/widgets/styles/images/diropen-32.png differ diff --git a/src/widgets/styles/images/dockdock-16.png b/src/widgets/styles/images/dockdock-16.png new file mode 100644 index 0000000000..4ac9483176 Binary files /dev/null and b/src/widgets/styles/images/dockdock-16.png differ diff --git a/src/widgets/styles/images/dockdock-down-16.png b/src/widgets/styles/images/dockdock-down-16.png new file mode 100644 index 0000000000..2e85a679be Binary files /dev/null and b/src/widgets/styles/images/dockdock-down-16.png differ diff --git a/src/widgets/styles/images/down-128.png b/src/widgets/styles/images/down-128.png new file mode 100644 index 0000000000..09dfe43a93 Binary files /dev/null and b/src/widgets/styles/images/down-128.png differ diff --git a/src/widgets/styles/images/down-16.png b/src/widgets/styles/images/down-16.png new file mode 100644 index 0000000000..c60a174e25 Binary files /dev/null and b/src/widgets/styles/images/down-16.png differ diff --git a/src/widgets/styles/images/down-32.png b/src/widgets/styles/images/down-32.png new file mode 100644 index 0000000000..46eadb8e12 Binary files /dev/null and b/src/widgets/styles/images/down-32.png differ diff --git a/src/widgets/styles/images/dvd-128.png b/src/widgets/styles/images/dvd-128.png new file mode 100644 index 0000000000..9ed9dc1e55 Binary files /dev/null and b/src/widgets/styles/images/dvd-128.png differ diff --git a/src/widgets/styles/images/dvd-16.png b/src/widgets/styles/images/dvd-16.png new file mode 100644 index 0000000000..623386d4ca Binary files /dev/null and b/src/widgets/styles/images/dvd-16.png differ diff --git a/src/widgets/styles/images/dvd-32.png b/src/widgets/styles/images/dvd-32.png new file mode 100644 index 0000000000..089b72accb Binary files /dev/null and b/src/widgets/styles/images/dvd-32.png differ diff --git a/src/widgets/styles/images/file-128.png b/src/widgets/styles/images/file-128.png new file mode 100644 index 0000000000..46e6ceb49a Binary files /dev/null and b/src/widgets/styles/images/file-128.png differ diff --git a/src/widgets/styles/images/file-16.png b/src/widgets/styles/images/file-16.png new file mode 100644 index 0000000000..664b56356b Binary files /dev/null and b/src/widgets/styles/images/file-16.png differ diff --git a/src/widgets/styles/images/file-32.png b/src/widgets/styles/images/file-32.png new file mode 100644 index 0000000000..83e5c3d311 Binary files /dev/null and b/src/widgets/styles/images/file-32.png differ diff --git a/src/widgets/styles/images/filecontents-128.png b/src/widgets/styles/images/filecontents-128.png new file mode 100644 index 0000000000..50e0a838e2 Binary files /dev/null and b/src/widgets/styles/images/filecontents-128.png differ diff --git a/src/widgets/styles/images/filecontents-16.png b/src/widgets/styles/images/filecontents-16.png new file mode 100644 index 0000000000..b9399ccf2e Binary files /dev/null and b/src/widgets/styles/images/filecontents-16.png differ diff --git a/src/widgets/styles/images/filecontents-32.png b/src/widgets/styles/images/filecontents-32.png new file mode 100644 index 0000000000..3761f70690 Binary files /dev/null and b/src/widgets/styles/images/filecontents-32.png differ diff --git a/src/widgets/styles/images/fileinfo-128.png b/src/widgets/styles/images/fileinfo-128.png new file mode 100644 index 0000000000..8c5b331876 Binary files /dev/null and b/src/widgets/styles/images/fileinfo-128.png differ diff --git a/src/widgets/styles/images/fileinfo-16.png b/src/widgets/styles/images/fileinfo-16.png new file mode 100644 index 0000000000..729be4d5f2 Binary files /dev/null and b/src/widgets/styles/images/fileinfo-16.png differ diff --git a/src/widgets/styles/images/fileinfo-32.png b/src/widgets/styles/images/fileinfo-32.png new file mode 100644 index 0000000000..ca795aa49b Binary files /dev/null and b/src/widgets/styles/images/fileinfo-32.png differ diff --git a/src/widgets/styles/images/filelink-128.png b/src/widgets/styles/images/filelink-128.png new file mode 100644 index 0000000000..be86a82901 Binary files /dev/null and b/src/widgets/styles/images/filelink-128.png differ diff --git a/src/widgets/styles/images/filelink-16.png b/src/widgets/styles/images/filelink-16.png new file mode 100644 index 0000000000..6643f2c428 Binary files /dev/null and b/src/widgets/styles/images/filelink-16.png differ diff --git a/src/widgets/styles/images/filelink-32.png b/src/widgets/styles/images/filelink-32.png new file mode 100644 index 0000000000..1e46fdc13c Binary files /dev/null and b/src/widgets/styles/images/filelink-32.png differ diff --git a/src/widgets/styles/images/floppy-128.png b/src/widgets/styles/images/floppy-128.png new file mode 100644 index 0000000000..fa7a3e1334 Binary files /dev/null and b/src/widgets/styles/images/floppy-128.png differ diff --git a/src/widgets/styles/images/floppy-16.png b/src/widgets/styles/images/floppy-16.png new file mode 100644 index 0000000000..91c59c567d Binary files /dev/null and b/src/widgets/styles/images/floppy-16.png differ diff --git a/src/widgets/styles/images/floppy-32.png b/src/widgets/styles/images/floppy-32.png new file mode 100644 index 0000000000..e63b3213bf Binary files /dev/null and b/src/widgets/styles/images/floppy-32.png differ diff --git a/src/widgets/styles/images/fontbitmap-16.png b/src/widgets/styles/images/fontbitmap-16.png new file mode 100644 index 0000000000..03efc9cbab Binary files /dev/null and b/src/widgets/styles/images/fontbitmap-16.png differ diff --git a/src/widgets/styles/images/fonttruetype-16.png b/src/widgets/styles/images/fonttruetype-16.png new file mode 100644 index 0000000000..25205021e9 Binary files /dev/null and b/src/widgets/styles/images/fonttruetype-16.png differ diff --git a/src/widgets/styles/images/harddrive-128.png b/src/widgets/styles/images/harddrive-128.png new file mode 100644 index 0000000000..0b73d9de1e Binary files /dev/null and b/src/widgets/styles/images/harddrive-128.png differ diff --git a/src/widgets/styles/images/harddrive-16.png b/src/widgets/styles/images/harddrive-16.png new file mode 100644 index 0000000000..45d592baa3 Binary files /dev/null and b/src/widgets/styles/images/harddrive-16.png differ diff --git a/src/widgets/styles/images/harddrive-32.png b/src/widgets/styles/images/harddrive-32.png new file mode 100644 index 0000000000..7041452b68 Binary files /dev/null and b/src/widgets/styles/images/harddrive-32.png differ diff --git a/src/widgets/styles/images/left-128.png b/src/widgets/styles/images/left-128.png new file mode 100644 index 0000000000..a26a5195f8 Binary files /dev/null and b/src/widgets/styles/images/left-128.png differ diff --git a/src/widgets/styles/images/left-16.png b/src/widgets/styles/images/left-16.png new file mode 100644 index 0000000000..110dd90f2d Binary files /dev/null and b/src/widgets/styles/images/left-16.png differ diff --git a/src/widgets/styles/images/left-32.png b/src/widgets/styles/images/left-32.png new file mode 100644 index 0000000000..ec4107b372 Binary files /dev/null and b/src/widgets/styles/images/left-32.png differ diff --git a/src/widgets/styles/images/media-pause-16.png b/src/widgets/styles/images/media-pause-16.png new file mode 100644 index 0000000000..6cb1fd7f63 Binary files /dev/null and b/src/widgets/styles/images/media-pause-16.png differ diff --git a/src/widgets/styles/images/media-pause-32.png b/src/widgets/styles/images/media-pause-32.png new file mode 100644 index 0000000000..3f172a04d6 Binary files /dev/null and b/src/widgets/styles/images/media-pause-32.png differ diff --git a/src/widgets/styles/images/media-play-16.png b/src/widgets/styles/images/media-play-16.png new file mode 100644 index 0000000000..d7ee3ccbe3 Binary files /dev/null and b/src/widgets/styles/images/media-play-16.png differ diff --git a/src/widgets/styles/images/media-play-32.png b/src/widgets/styles/images/media-play-32.png new file mode 100644 index 0000000000..af8d2f7ba5 Binary files /dev/null and b/src/widgets/styles/images/media-play-32.png differ diff --git a/src/widgets/styles/images/media-seek-backward-16.png b/src/widgets/styles/images/media-seek-backward-16.png new file mode 100644 index 0000000000..b8a8ea42d1 Binary files /dev/null and b/src/widgets/styles/images/media-seek-backward-16.png differ diff --git a/src/widgets/styles/images/media-seek-backward-32.png b/src/widgets/styles/images/media-seek-backward-32.png new file mode 100644 index 0000000000..a21d1372fe Binary files /dev/null and b/src/widgets/styles/images/media-seek-backward-32.png differ diff --git a/src/widgets/styles/images/media-seek-forward-16.png b/src/widgets/styles/images/media-seek-forward-16.png new file mode 100644 index 0000000000..3c900dcb62 Binary files /dev/null and b/src/widgets/styles/images/media-seek-forward-16.png differ diff --git a/src/widgets/styles/images/media-seek-forward-32.png b/src/widgets/styles/images/media-seek-forward-32.png new file mode 100644 index 0000000000..4f8d370fa1 Binary files /dev/null and b/src/widgets/styles/images/media-seek-forward-32.png differ diff --git a/src/widgets/styles/images/media-skip-backward-16.png b/src/widgets/styles/images/media-skip-backward-16.png new file mode 100644 index 0000000000..f5b3f4f56d Binary files /dev/null and b/src/widgets/styles/images/media-skip-backward-16.png differ diff --git a/src/widgets/styles/images/media-skip-backward-32.png b/src/widgets/styles/images/media-skip-backward-32.png new file mode 100644 index 0000000000..1d338035ef Binary files /dev/null and b/src/widgets/styles/images/media-skip-backward-32.png differ diff --git a/src/widgets/styles/images/media-skip-forward-16.png b/src/widgets/styles/images/media-skip-forward-16.png new file mode 100644 index 0000000000..27e205b02f Binary files /dev/null and b/src/widgets/styles/images/media-skip-forward-16.png differ diff --git a/src/widgets/styles/images/media-skip-forward-32.png b/src/widgets/styles/images/media-skip-forward-32.png new file mode 100644 index 0000000000..a583fa1b11 Binary files /dev/null and b/src/widgets/styles/images/media-skip-forward-32.png differ diff --git a/src/widgets/styles/images/media-stop-16.png b/src/widgets/styles/images/media-stop-16.png new file mode 100644 index 0000000000..9ce035d696 Binary files /dev/null and b/src/widgets/styles/images/media-stop-16.png differ diff --git a/src/widgets/styles/images/media-stop-32.png b/src/widgets/styles/images/media-stop-32.png new file mode 100644 index 0000000000..aae24ba925 Binary files /dev/null and b/src/widgets/styles/images/media-stop-32.png differ diff --git a/src/widgets/styles/images/media-volume-16.png b/src/widgets/styles/images/media-volume-16.png new file mode 100644 index 0000000000..ad258340f2 Binary files /dev/null and b/src/widgets/styles/images/media-volume-16.png differ diff --git a/src/widgets/styles/images/media-volume-muted-16.png b/src/widgets/styles/images/media-volume-muted-16.png new file mode 100644 index 0000000000..06bded21e7 Binary files /dev/null and b/src/widgets/styles/images/media-volume-muted-16.png differ diff --git a/src/widgets/styles/images/networkdrive-128.png b/src/widgets/styles/images/networkdrive-128.png new file mode 100644 index 0000000000..fd4a59c6bd Binary files /dev/null and b/src/widgets/styles/images/networkdrive-128.png differ diff --git a/src/widgets/styles/images/networkdrive-16.png b/src/widgets/styles/images/networkdrive-16.png new file mode 100644 index 0000000000..1bc62f766a Binary files /dev/null and b/src/widgets/styles/images/networkdrive-16.png differ diff --git a/src/widgets/styles/images/networkdrive-32.png b/src/widgets/styles/images/networkdrive-32.png new file mode 100644 index 0000000000..6a389dcae4 Binary files /dev/null and b/src/widgets/styles/images/networkdrive-32.png differ diff --git a/src/widgets/styles/images/newdirectory-128.png b/src/widgets/styles/images/newdirectory-128.png new file mode 100644 index 0000000000..fdbee27688 Binary files /dev/null and b/src/widgets/styles/images/newdirectory-128.png differ diff --git a/src/widgets/styles/images/newdirectory-16.png b/src/widgets/styles/images/newdirectory-16.png new file mode 100644 index 0000000000..6c9f80318b Binary files /dev/null and b/src/widgets/styles/images/newdirectory-16.png differ diff --git a/src/widgets/styles/images/newdirectory-32.png b/src/widgets/styles/images/newdirectory-32.png new file mode 100644 index 0000000000..4fd0329216 Binary files /dev/null and b/src/widgets/styles/images/newdirectory-32.png differ diff --git a/src/widgets/styles/images/parentdir-128.png b/src/widgets/styles/images/parentdir-128.png new file mode 100644 index 0000000000..84d14ab079 Binary files /dev/null and b/src/widgets/styles/images/parentdir-128.png differ diff --git a/src/widgets/styles/images/parentdir-16.png b/src/widgets/styles/images/parentdir-16.png new file mode 100644 index 0000000000..665f8280f2 Binary files /dev/null and b/src/widgets/styles/images/parentdir-16.png differ diff --git a/src/widgets/styles/images/parentdir-32.png b/src/widgets/styles/images/parentdir-32.png new file mode 100644 index 0000000000..44f3c4876d Binary files /dev/null and b/src/widgets/styles/images/parentdir-32.png differ diff --git a/src/widgets/styles/images/refresh-24.png b/src/widgets/styles/images/refresh-24.png new file mode 100644 index 0000000000..4c9b72c489 Binary files /dev/null and b/src/widgets/styles/images/refresh-24.png differ diff --git a/src/widgets/styles/images/refresh-32.png b/src/widgets/styles/images/refresh-32.png new file mode 100644 index 0000000000..eecde4b8f9 Binary files /dev/null and b/src/widgets/styles/images/refresh-32.png differ diff --git a/src/widgets/styles/images/right-128.png b/src/widgets/styles/images/right-128.png new file mode 100644 index 0000000000..14b1cfd8eb Binary files /dev/null and b/src/widgets/styles/images/right-128.png differ diff --git a/src/widgets/styles/images/right-16.png b/src/widgets/styles/images/right-16.png new file mode 100644 index 0000000000..81ca628ff6 Binary files /dev/null and b/src/widgets/styles/images/right-16.png differ diff --git a/src/widgets/styles/images/right-32.png b/src/widgets/styles/images/right-32.png new file mode 100644 index 0000000000..0f6ba8608b Binary files /dev/null and b/src/widgets/styles/images/right-32.png differ diff --git a/src/widgets/styles/images/standardbutton-apply-128.png b/src/widgets/styles/images/standardbutton-apply-128.png new file mode 100644 index 0000000000..85f07a57ef Binary files /dev/null and b/src/widgets/styles/images/standardbutton-apply-128.png differ diff --git a/src/widgets/styles/images/standardbutton-apply-16.png b/src/widgets/styles/images/standardbutton-apply-16.png new file mode 100644 index 0000000000..8f11ce6504 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-apply-16.png differ diff --git a/src/widgets/styles/images/standardbutton-apply-32.png b/src/widgets/styles/images/standardbutton-apply-32.png new file mode 100644 index 0000000000..e8f7853a1e Binary files /dev/null and b/src/widgets/styles/images/standardbutton-apply-32.png differ diff --git a/src/widgets/styles/images/standardbutton-cancel-128.png b/src/widgets/styles/images/standardbutton-cancel-128.png new file mode 100644 index 0000000000..16d857030f Binary files /dev/null and b/src/widgets/styles/images/standardbutton-cancel-128.png differ diff --git a/src/widgets/styles/images/standardbutton-cancel-16.png b/src/widgets/styles/images/standardbutton-cancel-16.png new file mode 100644 index 0000000000..7bd25bd7c7 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-cancel-16.png differ diff --git a/src/widgets/styles/images/standardbutton-cancel-32.png b/src/widgets/styles/images/standardbutton-cancel-32.png new file mode 100644 index 0000000000..64a78727a1 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-cancel-32.png differ diff --git a/src/widgets/styles/images/standardbutton-clear-128.png b/src/widgets/styles/images/standardbutton-clear-128.png new file mode 100644 index 0000000000..107aea2234 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-clear-128.png differ diff --git a/src/widgets/styles/images/standardbutton-clear-16.png b/src/widgets/styles/images/standardbutton-clear-16.png new file mode 100644 index 0000000000..5359134c72 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-clear-16.png differ diff --git a/src/widgets/styles/images/standardbutton-clear-32.png b/src/widgets/styles/images/standardbutton-clear-32.png new file mode 100644 index 0000000000..8b85d6b7b3 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-clear-32.png differ diff --git a/src/widgets/styles/images/standardbutton-close-128.png b/src/widgets/styles/images/standardbutton-close-128.png new file mode 100644 index 0000000000..571aeae2bd Binary files /dev/null and b/src/widgets/styles/images/standardbutton-close-128.png differ diff --git a/src/widgets/styles/images/standardbutton-close-16.png b/src/widgets/styles/images/standardbutton-close-16.png new file mode 100644 index 0000000000..e9e481987a Binary files /dev/null and b/src/widgets/styles/images/standardbutton-close-16.png differ diff --git a/src/widgets/styles/images/standardbutton-close-32.png b/src/widgets/styles/images/standardbutton-close-32.png new file mode 100644 index 0000000000..47e5733062 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-close-32.png differ diff --git a/src/widgets/styles/images/standardbutton-closetab-16.png b/src/widgets/styles/images/standardbutton-closetab-16.png new file mode 100644 index 0000000000..540694eae3 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-closetab-16.png differ diff --git a/src/widgets/styles/images/standardbutton-closetab-down-16.png b/src/widgets/styles/images/standardbutton-closetab-down-16.png new file mode 100644 index 0000000000..ccec241652 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-closetab-down-16.png differ diff --git a/src/widgets/styles/images/standardbutton-closetab-hover-16.png b/src/widgets/styles/images/standardbutton-closetab-hover-16.png new file mode 100644 index 0000000000..b22a0ffaf0 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-closetab-hover-16.png differ diff --git a/src/widgets/styles/images/standardbutton-delete-128.png b/src/widgets/styles/images/standardbutton-delete-128.png new file mode 100644 index 0000000000..11947ba681 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-delete-128.png differ diff --git a/src/widgets/styles/images/standardbutton-delete-16.png b/src/widgets/styles/images/standardbutton-delete-16.png new file mode 100644 index 0000000000..63fe93fe98 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-delete-16.png differ diff --git a/src/widgets/styles/images/standardbutton-delete-32.png b/src/widgets/styles/images/standardbutton-delete-32.png new file mode 100644 index 0000000000..336d965d1c Binary files /dev/null and b/src/widgets/styles/images/standardbutton-delete-32.png differ diff --git a/src/widgets/styles/images/standardbutton-help-128.png b/src/widgets/styles/images/standardbutton-help-128.png new file mode 100644 index 0000000000..aa38e6fdfb Binary files /dev/null and b/src/widgets/styles/images/standardbutton-help-128.png differ diff --git a/src/widgets/styles/images/standardbutton-help-16.png b/src/widgets/styles/images/standardbutton-help-16.png new file mode 100644 index 0000000000..e8299418da Binary files /dev/null and b/src/widgets/styles/images/standardbutton-help-16.png differ diff --git a/src/widgets/styles/images/standardbutton-help-32.png b/src/widgets/styles/images/standardbutton-help-32.png new file mode 100644 index 0000000000..310056a632 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-help-32.png differ diff --git a/src/widgets/styles/images/standardbutton-no-128.png b/src/widgets/styles/images/standardbutton-no-128.png new file mode 100644 index 0000000000..491c048ebd Binary files /dev/null and b/src/widgets/styles/images/standardbutton-no-128.png differ diff --git a/src/widgets/styles/images/standardbutton-no-16.png b/src/widgets/styles/images/standardbutton-no-16.png new file mode 100644 index 0000000000..812d3f57dd Binary files /dev/null and b/src/widgets/styles/images/standardbutton-no-16.png differ diff --git a/src/widgets/styles/images/standardbutton-no-32.png b/src/widgets/styles/images/standardbutton-no-32.png new file mode 100644 index 0000000000..9548d59196 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-no-32.png differ diff --git a/src/widgets/styles/images/standardbutton-ok-128.png b/src/widgets/styles/images/standardbutton-ok-128.png new file mode 100644 index 0000000000..63cc5279ae Binary files /dev/null and b/src/widgets/styles/images/standardbutton-ok-128.png differ diff --git a/src/widgets/styles/images/standardbutton-ok-16.png b/src/widgets/styles/images/standardbutton-ok-16.png new file mode 100644 index 0000000000..fb4b4dbf96 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-ok-16.png differ diff --git a/src/widgets/styles/images/standardbutton-ok-32.png b/src/widgets/styles/images/standardbutton-ok-32.png new file mode 100644 index 0000000000..2dadd7a690 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-ok-32.png differ diff --git a/src/widgets/styles/images/standardbutton-open-128.png b/src/widgets/styles/images/standardbutton-open-128.png new file mode 100644 index 0000000000..8a052e829d Binary files /dev/null and b/src/widgets/styles/images/standardbutton-open-128.png differ diff --git a/src/widgets/styles/images/standardbutton-open-16.png b/src/widgets/styles/images/standardbutton-open-16.png new file mode 100644 index 0000000000..08cdc2b91f Binary files /dev/null and b/src/widgets/styles/images/standardbutton-open-16.png differ diff --git a/src/widgets/styles/images/standardbutton-open-32.png b/src/widgets/styles/images/standardbutton-open-32.png new file mode 100644 index 0000000000..db33c79852 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-open-32.png differ diff --git a/src/widgets/styles/images/standardbutton-save-128.png b/src/widgets/styles/images/standardbutton-save-128.png new file mode 100644 index 0000000000..fc6fd7ce1d Binary files /dev/null and b/src/widgets/styles/images/standardbutton-save-128.png differ diff --git a/src/widgets/styles/images/standardbutton-save-16.png b/src/widgets/styles/images/standardbutton-save-16.png new file mode 100644 index 0000000000..dd4e228280 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-save-16.png differ diff --git a/src/widgets/styles/images/standardbutton-save-32.png b/src/widgets/styles/images/standardbutton-save-32.png new file mode 100644 index 0000000000..177678c963 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-save-32.png differ diff --git a/src/widgets/styles/images/standardbutton-yes-128.png b/src/widgets/styles/images/standardbutton-yes-128.png new file mode 100644 index 0000000000..79c8296016 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-yes-128.png differ diff --git a/src/widgets/styles/images/standardbutton-yes-16.png b/src/widgets/styles/images/standardbutton-yes-16.png new file mode 100644 index 0000000000..cc16dbbec3 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-yes-16.png differ diff --git a/src/widgets/styles/images/standardbutton-yes-32.png b/src/widgets/styles/images/standardbutton-yes-32.png new file mode 100644 index 0000000000..e3340c6453 Binary files /dev/null and b/src/widgets/styles/images/standardbutton-yes-32.png differ diff --git a/src/widgets/styles/images/stop-24.png b/src/widgets/styles/images/stop-24.png new file mode 100644 index 0000000000..99856e9640 Binary files /dev/null and b/src/widgets/styles/images/stop-24.png differ diff --git a/src/widgets/styles/images/stop-32.png b/src/widgets/styles/images/stop-32.png new file mode 100644 index 0000000000..4f4952bb2a Binary files /dev/null and b/src/widgets/styles/images/stop-32.png differ diff --git a/src/widgets/styles/images/trash-128.png b/src/widgets/styles/images/trash-128.png new file mode 100644 index 0000000000..334fe5b6f3 Binary files /dev/null and b/src/widgets/styles/images/trash-128.png differ diff --git a/src/widgets/styles/images/trash-16.png b/src/widgets/styles/images/trash-16.png new file mode 100644 index 0000000000..c471791ee8 Binary files /dev/null and b/src/widgets/styles/images/trash-16.png differ diff --git a/src/widgets/styles/images/trash-32.png b/src/widgets/styles/images/trash-32.png new file mode 100644 index 0000000000..68625cf698 Binary files /dev/null and b/src/widgets/styles/images/trash-32.png differ diff --git a/src/widgets/styles/images/up-128.png b/src/widgets/styles/images/up-128.png new file mode 100644 index 0000000000..c10df10677 Binary files /dev/null and b/src/widgets/styles/images/up-128.png differ diff --git a/src/widgets/styles/images/up-16.png b/src/widgets/styles/images/up-16.png new file mode 100644 index 0000000000..33e939db8f Binary files /dev/null and b/src/widgets/styles/images/up-16.png differ diff --git a/src/widgets/styles/images/up-32.png b/src/widgets/styles/images/up-32.png new file mode 100644 index 0000000000..d7157c9476 Binary files /dev/null and b/src/widgets/styles/images/up-32.png differ diff --git a/src/widgets/styles/images/viewdetailed-128.png b/src/widgets/styles/images/viewdetailed-128.png new file mode 100644 index 0000000000..363937a857 Binary files /dev/null and b/src/widgets/styles/images/viewdetailed-128.png differ diff --git a/src/widgets/styles/images/viewdetailed-16.png b/src/widgets/styles/images/viewdetailed-16.png new file mode 100644 index 0000000000..44a14b923a Binary files /dev/null and b/src/widgets/styles/images/viewdetailed-16.png differ diff --git a/src/widgets/styles/images/viewdetailed-32.png b/src/widgets/styles/images/viewdetailed-32.png new file mode 100644 index 0000000000..fac1a3e683 Binary files /dev/null and b/src/widgets/styles/images/viewdetailed-32.png differ diff --git a/src/widgets/styles/images/viewlist-128.png b/src/widgets/styles/images/viewlist-128.png new file mode 100644 index 0000000000..cc301059c1 Binary files /dev/null and b/src/widgets/styles/images/viewlist-128.png differ diff --git a/src/widgets/styles/images/viewlist-16.png b/src/widgets/styles/images/viewlist-16.png new file mode 100644 index 0000000000..9132877ff6 Binary files /dev/null and b/src/widgets/styles/images/viewlist-16.png differ diff --git a/src/widgets/styles/images/viewlist-32.png b/src/widgets/styles/images/viewlist-32.png new file mode 100644 index 0000000000..fae3c24536 Binary files /dev/null and b/src/widgets/styles/images/viewlist-32.png differ diff --git a/src/widgets/styles/qcdestyle.cpp b/src/widgets/styles/qcdestyle.cpp new file mode 100644 index 0000000000..5acf399396 --- /dev/null +++ b/src/widgets/styles/qcdestyle.cpp @@ -0,0 +1,305 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcdestyle.h" + +#if !defined(QT_NO_STYLE_CDE) || defined(QT_PLUGIN) + +#include "qmenu.h" +#include "qapplication.h" +#include "qpainter.h" +#include "qdrawutil.h" +#include "qpixmap.h" +#include "qpalette.h" +#include "qwidget.h" +#include "qpushbutton.h" +#include "qscrollbar.h" +#include "qtabbar.h" +#include "qtabwidget.h" +#include "qlistview.h" +#include "qsplitter.h" +#include "qslider.h" +#include "qcombobox.h" +#include "qlineedit.h" +#include "qprogressbar.h" +#include "qimage.h" +#include "qfocusframe.h" +#include "qpainterpath.h" +#include "qdebug.h" +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QCDEStyle + \brief The QCDEStyle class provides a CDE look and feel. + + \ingroup appearance + + This style provides a slightly improved Motif look similar to some + versions of the Common Desktop Environment (CDE). The main + differences are thinner frames and more modern radio buttons and + checkboxes. Together with a dark background and a bright + text/foreground color, the style looks quite attractive (at least + for Motif fans). + + Note that most of the functions provided by QCDEStyle are + reimplementations of QStyle functions; see QStyle for their + documentation. QCDEStyle provides overloads for drawControl() and + drawPrimitive() which are documented here. + + \img qcdestyle.png + \sa QWindowsXPStyle, QMacStyle, QWindowsStyle, QPlastiqueStyle, QMotifStyle +*/ + +/*! + Constructs a QCDEStyle. + + If \a useHighlightCols is false (the default), then the style will + polish the application's color palette to emulate the Motif way of + highlighting, which is a simple inversion between the base and the + text color. +*/ +QCDEStyle::QCDEStyle(bool useHighlightCols) + : QMotifStyle(useHighlightCols) +{ +} + +/*! + Destroys the style. +*/ +QCDEStyle::~QCDEStyle() +{ +} + + +/*!\reimp +*/ +int QCDEStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, + const QWidget *widget) const +/* +int QCDEStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, + const QWidget *widget) const + */ +{ + int ret = 0; + + switch(metric) { + case PM_MenuBarPanelWidth: + case PM_DefaultFrameWidth: + case PM_FocusFrameVMargin: + case PM_FocusFrameHMargin: + case PM_MenuPanelWidth: + case PM_SpinBoxFrameWidth: + case PM_MenuBarVMargin: + case PM_MenuBarHMargin: + case PM_DockWidgetFrameWidth: + ret = 1; + break; + case PM_ScrollBarExtent: + ret = 13; + break; + default: + ret = QMotifStyle::pixelMetric(metric, option, widget); + break; + } + return ret; +} + +/*! + \reimp +*/ +void QCDEStyle::drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, + const QWidget *widget) const +{ + + switch(element) { + case CE_MenuBarItem: { + if (opt->state & State_Selected) // active item + qDrawShadePanel(p, opt->rect, opt->palette, true, 1, + &opt->palette.brush(QPalette::Button)); + else // other item + p->fillRect(opt->rect, opt->palette.brush(QPalette::Button)); + QCommonStyle::drawControl(element, opt, p, widget); + break; } + case CE_RubberBand: { + p->save(); + p->setClipping(false); + QPainterPath path; + path.addRect(opt->rect); + path.addRect(opt->rect.adjusted(2, 2, -2, -2)); + p->fillPath(path, opt->palette.color(QPalette::Active, QPalette::Text)); + p->restore(); + break; } + default: + QMotifStyle::drawControl(element, opt, p, widget); + break; + } +} + +/*! + \reimp +*/ +void QCDEStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *widget) const +{ + switch(pe) { + case PE_IndicatorCheckBox: { + bool down = opt->state & State_Sunken; + bool on = opt->state & State_On; + bool showUp = !(down ^ on); + QBrush fill = (showUp || (opt->state & State_NoChange)) ? opt->palette.brush(QPalette::Button) : opt->palette.brush(QPalette::Mid); + qDrawShadePanel(p, opt->rect, opt->palette, !showUp, pixelMetric(PM_DefaultFrameWidth), &opt->palette.brush(QPalette::Button)); + + if (on || (opt->state & State_NoChange)) { + QRect r = opt->rect; + QPolygon a(7 * 2); + int i, xx, yy; + xx = r.x() + 3; + yy = r.y() + 5; + if (opt->rect.width() <= 9) { + // When called from CE_MenuItem in QMotifStyle + xx -= 2; + yy -= 2; + } + + for (i = 0; i < 3; i++) { + a.setPoint(2 * i, xx, yy); + a.setPoint(2 * i + 1, xx, yy + 2); + xx++; yy++; + } + yy -= 2; + for (i = 3; i < 7; i++) { + a.setPoint(2 * i, xx, yy); + a.setPoint(2 * i + 1, xx, yy + 2); + xx++; yy--; + } + if (opt->state & State_NoChange) + p->setPen(opt->palette.dark().color()); + else + p->setPen(opt->palette.foreground().color()); + p->drawPolyline(a); + } + if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText)) + p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern)); + } break; + case PE_IndicatorRadioButton: + { + QRect r = opt->rect; +#define INTARRLEN(x) sizeof(x)/(sizeof(int)*2) + static const int pts1[] = { // up left lines + 1,9, 1,8, 0,7, 0,4, 1,3, 1,2, 2,1, 3,1, 4,0, 7,0, 8,1, 9,1 }; + static const int pts4[] = { // bottom right lines + 2,10, 3,10, 4,11, 7,11, 8,10, 9,10, 10,9, 10,8, 11,7, + 11,4, 10,3, 10,2 }; + static const int pts5[] = { // inner fill + 4,2, 7,2, 9,4, 9,7, 7,9, 4,9, 2,7, 2,4 }; + bool down = opt->state & State_Sunken; + bool on = opt->state & State_On; + QPolygon a(INTARRLEN(pts1), pts1); + + //center when rect is larger than indicator size + int xOffset = 0; + int yOffset = 0; + int indicatorWidth = pixelMetric(PM_ExclusiveIndicatorWidth); + int indicatorHeight = pixelMetric(PM_ExclusiveIndicatorWidth); + if (r.width() > indicatorWidth) + xOffset += (r.width() - indicatorWidth)/2; + if (r.height() > indicatorHeight) + yOffset += (r.height() - indicatorHeight)/2; + p->translate(xOffset, yOffset); + + a.translate(r.x(), r.y()); + QPen oldPen = p->pen(); + QBrush oldBrush = p->brush(); + p->setPen((down || on) ? opt->palette.dark().color() : opt->palette.light().color()); + p->drawPolyline(a); + a.setPoints(INTARRLEN(pts4), pts4); + a.translate(r.x(), r.y()); + p->setPen((down || on) ? opt->palette.light().color() : opt->palette.dark().color()); + p->drawPolyline(a); + a.setPoints(INTARRLEN(pts5), pts5); + a.translate(r.x(), r.y()); + QColor fillColor = on ? opt->palette.dark().color() : opt->palette.background().color(); + p->setPen(fillColor); + p->setBrush(on ? opt->palette.brush(QPalette::Dark) : + opt->palette.brush(QPalette::Window)); + p->drawPolygon(a); + if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText)) + p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern)); + p->setPen(oldPen); + p->setBrush(oldBrush); + + p->translate(-xOffset, -yOffset); + + } break; + default: + QMotifStyle::drawPrimitive(pe, opt, p, widget); + } +} + +/*!\reimp*/ +QPalette QCDEStyle::standardPalette() const +{ + QColor background(0xb6, 0xb6, 0xcf); + QColor light = background.lighter(); + QColor mid = background.darker(150); + QColor dark = background.darker(); + QPalette palette(Qt::black, background, light, dark, mid, Qt::black, Qt::white); + palette.setBrush(QPalette::Disabled, QPalette::WindowText, dark); + palette.setBrush(QPalette::Disabled, QPalette::Text, dark); + palette.setBrush(QPalette::Disabled, QPalette::ButtonText, dark); + palette.setBrush(QPalette::Disabled, QPalette::Base, background); + return palette; +} + +/*! + \internal +*/ +QIcon QCDEStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt, + const QWidget *widget) const +{ + return QMotifStyle::standardIconImplementation(standardIcon, opt, widget); +} + +QT_END_NAMESPACE + +#endif diff --git a/src/widgets/styles/qcdestyle.h b/src/widgets/styles/qcdestyle.h new file mode 100644 index 0000000000..ca43b6a530 --- /dev/null +++ b/src/widgets/styles/qcdestyle.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QCDESTYLE_H +#define QCDESTYLE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_STYLE_CDE) + +class Q_GUI_EXPORT QCDEStyle : public QMotifStyle +{ + Q_OBJECT +public: + explicit QCDEStyle(bool useHighlightCols = false); + virtual ~QCDEStyle(); + + int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, + const QWidget *widget = 0) const; + void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const; + void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const; + QPalette standardPalette() const; + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt = 0, + const QWidget *widget = 0) const; +}; + +#endif // QT_NO_STYLE_CDE + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QCDESTYLE_H diff --git a/src/widgets/styles/qcleanlooksstyle.cpp b/src/widgets/styles/qcleanlooksstyle.cpp new file mode 100644 index 0000000000..cc5fe10692 --- /dev/null +++ b/src/widgets/styles/qcleanlooksstyle.cpp @@ -0,0 +1,4466 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcleanlooksstyle.h" +#include "qcleanlooksstyle_p.h" + +#if !defined(QT_NO_STYLE_CLEANLOOKS) || defined(QT_PLUGIN) + +#include "qwindowsstyle_p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QStyleHelper; + +enum Direction { + TopDown, + FromLeft, + BottomUp, + FromRight +}; + +// from windows style +static const int windowsItemFrame = 2; // menu item frame width +static const int windowsItemHMargin = 3; // menu item hor text margin +static const int windowsItemVMargin = 8; // menu item ver text margin +static const int windowsRightBorder = 15; // right border on windows + +/* XPM */ +static const char * const dock_widget_close_xpm[] = { + "11 13 7 1", + " c None", + ". c #D5CFCB", + "+ c #8F8B88", + "@ c #6C6A67", + "# c #ABA6A3", + "$ c #B5B0AC", + "% c #A4A09D", + " ", + " +@@@@@@@+ ", + "+# #+", + "@ $@ @$ @", + "@ @@@ @@@ @", + "@ @@@@@ @", + "@ @@@ @", + "@ @@@@@ @", + "@ @@@ @@@ @", + "@ $@ @$ @", + "+% #+", + " +@@@@@@@+ ", + " "}; + +static const char * const qt_cleanlooks_arrow_down_xpm[] = { + "11 7 2 1", + " c None", + "x c #000000", + " ", + " x x ", + " xxx xxx ", + " xxxxxxx ", + " xxxxx ", + " xxx ", + " x "}; + +static const char * const qt_cleanlooks_arrow_up_xpm[] = { + "11 7 2 1", + " c None", + "x c #000000", + " x ", + " xxx ", + " xxxxx ", + " xxxxxxx ", + " xxx xxx ", + " x x ", + " "}; + +static const char * const dock_widget_restore_xpm[] = { + "11 13 7 1", + " c None", + ". c #D5CFCB", + "+ c #8F8B88", + "@ c #6C6A67", + "# c #ABA6A3", + "$ c #B5B0AC", + "% c #A4A09D", + " ", + " +@@@@@@@+ ", + "+# #+", + "@ #@@@# @", + "@ @ @ @", + "@ #@@@# @ @", + "@ @ @ @ @", + "@ @ @@@ @", + "@ @ @ @", + "@ #@@@# @", + "+% #+", + " +@@@@@@@+ ", + " "}; + +static const char * const workspace_minimize[] = { + "11 13 7 1", + " c None", + ". c #D5CFCB", + "+ c #8F8B88", + "@ c #6C6A67", + "# c #ABA6A3", + "$ c #B5B0AC", + "% c #A4A09D", + " ", + " +@@@@@@@+ ", + "+# #+", + "@ @", + "@ @", + "@ @", + "@ @@@@@@@ @", + "@ @@@@@@@ @", + "@ @", + "@ @", + "+% #+", + " +@@@@@@@+ ", + " "}; + + +static const char * const qt_titlebar_context_help[] = { + "10 10 3 1", + " c None", + "# c #000000", + "+ c #444444", + " +####+ ", + " ### ### ", + " ## ## ", + " +##+ ", + " +## ", + " ## ", + " ## ", + " ", + " ## ", + " ## "}; + +static const char * const qt_cleanlooks_radiobutton[] = { + "13 13 9 1", + " c None", + ". c #ABA094", + "+ c #B7ADA0", + "@ c #C4BBB2", + "# c #DDD4CD", + "$ c #E7E1E0", + "% c #F4EFED", + "& c #FFFAF9", + "* c #FCFEFB", + " #@...@# ", + " @+@#$$#+@ ", + " @+$%%***&@@ ", + "#+$%**&&**&+#", + "@@$&&******#@", + ".#**********.", + ".$&******&*&.", + ".$*&******&*.", + "+#********&#@", + "#+*********+#", + " @@*******@@ ", + " @+#%*%#+@ ", + " #@...+# "}; + +static const char * const qt_cleanlooks_radiobutton_checked[] = { + "13 13 20 1", + " c None", + ". c #A8ABAE", + "+ c #596066", + "@ c #283138", + "# c #A9ACAF", + "$ c #A6A9AB", + "% c #6B7378", + "& c #8C9296", + "* c #A2A6AA", + "= c #61696F", + "- c #596065", + "; c #93989C", + "> c #777E83", + ", c #60686E", + "' c #252D33", + ") c #535B62", + "! c #21292E", + "~ c #242B31", + "{ c #1F262B", + "] c #41484E", + " ", + " ", + " ", + " .+@+# ", + " $%&*&=# ", + " -&;>,'+ ", + " @*>,)!@ ", + " +&,)~{+ ", + " #='!{]# ", + " #+@+# ", + " ", + " ", + " "}; + + +static const char * const qt_scrollbar_button_arrow_left[] = { + "4 7 2 1", + " c None", + "* c #BFBFBF", + " *", + " **", + " ***", + "****", + " ***", + " **", + " *"}; + +static const char * const qt_scrollbar_button_arrow_right[] = { + "4 7 2 1", + " c None", + "* c #BFBFBF", + "* ", + "** ", + "*** ", + "****", + "*** ", + "** ", + "* "}; + +static const char * const qt_scrollbar_button_arrow_up[] = { + "7 4 2 1", + " c None", + "* c #BFBFBF", + " * ", + " *** ", + " ***** ", + "*******"}; + +static const char * const qt_scrollbar_button_arrow_down[] = { + "7 4 2 1", + " c None", + "* c #BFBFBF", + "*******", + " ***** ", + " *** ", + " * "}; + +static const char * const qt_spinbox_button_arrow_down[] = { + "7 4 2 1", + " c None", + "* c #BFBFBF", + "*******", + " ***** ", + " *** ", + " * "}; + +static const char * const qt_spinbox_button_arrow_up[] = { + "7 4 2 1", + " c None", + "* c #BFBFBF", + " * ", + " *** ", + " ***** ", + "*******"}; + +static const char * const qt_scrollbar_button_left[] = { + "16 16 6 1", + " c None", + ". c #BFBFBF", + "+ c #979797", + "# c #FAFAFA", + "< c #FAFAFA", + "* c #FAFAFA", + " .++++++++++++++", + ".+#############+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + ".+<<<<<<<<<<<<<+", + " .++++++++++++++"}; + +static const char * const qt_scrollbar_button_right[] = { + "16 16 6 1", + " c None", + ". c #BFBFBF", + "+ c #979797", + "# c #FAFAFA", + "< c #FAFAFA", + "* c #FAFAFA", + "++++++++++++++. ", + "+#############+.", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+<<<<<<<<<<<<<+.", + "++++++++++++++. "}; + +static const char * const qt_scrollbar_button_up[] = { + "16 16 6 1", + " c None", + ". c #BFBFBF", + "+ c #979797", + "# c #FAFAFA", + "< c #FAFAFA", + "* c #FAFAFA", + " .++++++++++++. ", + ".+############+.", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+<<<<<<<<<<<<<<+", + "++++++++++++++++"}; + +static const char * const qt_scrollbar_button_down[] = { + "16 16 6 1", + " c None", + ". c #BFBFBF", + "+ c #979797", + "# c #FAFAFA", + "< c #FAFAFA", + "* c #FAFAFA", + "++++++++++++++++", + "+##############+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + ".+<<<<<<<<<<<<+.", + " .++++++++++++. "}; + +static const char * const qt_cleanlooks_menuitem_checkbox_checked[] = { + "8 7 6 1", + " g None", + ". g #959595", + "+ g #676767", + "@ g #454545", + "# g #1D1D1D", + "0 g #101010", + " ..", + " .+ ", + " .+ ", + "0 .@ ", + "@#++. ", + " @# ", + " . "}; + +static const char * const qt_cleanlooks_checkbox_checked[] = { + "13 13 3 1", + " c None", + ". c #272D33", + "% c #666666", + + " ", + " % ", + " %. ", + " %.% ", + " %.. ", + " %.% %.. ", + " %..%..% ", + " %...% ", + " %..% ", + " %.% ", + " % ", + " ", + " "}; + +static void qt_cleanlooks_draw_gradient(QPainter *painter, const QRect &rect, const QColor &gradientStart, + const QColor &gradientStop, Direction direction = TopDown, QBrush bgBrush = QBrush()) +{ + int x = rect.center().x(); + int y = rect.center().y(); + QLinearGradient *gradient; + switch(direction) { + case FromLeft: + gradient = new QLinearGradient(rect.left(), y, rect.right(), y); + break; + case FromRight: + gradient = new QLinearGradient(rect.right(), y, rect.left(), y); + break; + case BottomUp: + gradient = new QLinearGradient(x, rect.bottom(), x, rect.top()); + break; + case TopDown: + default: + gradient = new QLinearGradient(x, rect.top(), x, rect.bottom()); + break; + } + if (bgBrush.gradient()) + gradient->setStops(bgBrush.gradient()->stops()); + else { + gradient->setColorAt(0, gradientStart); + gradient->setColorAt(1, gradientStop); + } + painter->fillRect(rect, *gradient); + delete gradient; +} + +static void qt_cleanlooks_draw_buttongradient(QPainter *painter, const QRect &rect, const QColor &gradientStart, + const QColor &gradientMid, const QColor &gradientStop, Direction direction = TopDown, + QBrush bgBrush = QBrush()) +{ + int x = rect.center().x(); + int y = rect.center().y(); + QLinearGradient *gradient; + bool horizontal = false; + switch(direction) { + case FromLeft: + horizontal = true; + gradient = new QLinearGradient(rect.left(), y, rect.right(), y); + break; + case FromRight: + horizontal = true; + gradient = new QLinearGradient(rect.right(), y, rect.left(), y); + break; + case BottomUp: + gradient = new QLinearGradient(x, rect.bottom(), x, rect.top()); + break; + case TopDown: + default: + gradient = new QLinearGradient(x, rect.top(), x, rect.bottom()); + break; + } + if (bgBrush.gradient()) + gradient->setStops(bgBrush.gradient()->stops()); + else { + int size = horizontal ? rect.width() : rect.height() ; + if (size > 4) { + float edge = 4.0/(float)size; + gradient->setColorAt(0, gradientStart); + gradient->setColorAt(edge, gradientMid.lighter(104)); + gradient->setColorAt(1.0 - edge, gradientMid.darker(100)); + gradient->setColorAt(1.0, gradientStop); + } + } + painter->fillRect(rect, *gradient); + delete gradient; +} + +static void qt_cleanlooks_draw_mdibutton(QPainter *painter, const QStyleOptionTitleBar *option, const QRect &tmp, bool hover, bool sunken) +{ + QColor dark; + dark.setHsv(option->palette.button().color().hue(), + qMin(255, (int)(option->palette.button().color().saturation()*1.9)), + qMin(255, (int)(option->palette.button().color().value()*0.7))); + + QColor highlight = option->palette.highlight().color(); + + bool active = (option->titleBarState & QStyle::State_Active); + QColor titleBarHighlight(255, 255, 255, 60); + + if (sunken) + painter->fillRect(tmp.adjusted(1, 1, -1, -1), option->palette.highlight().color().darker(120)); + else if (hover) + painter->fillRect(tmp.adjusted(1, 1, -1, -1), QColor(255, 255, 255, 20)); + + QColor mdiButtonGradientStartColor; + QColor mdiButtonGradientStopColor; + + mdiButtonGradientStartColor = QColor(0, 0, 0, 40); + mdiButtonGradientStopColor = QColor(255, 255, 255, 60); + + if (sunken) + titleBarHighlight = highlight.darker(130); + + QLinearGradient gradient(tmp.center().x(), tmp.top(), tmp.center().x(), tmp.bottom()); + gradient.setColorAt(0, mdiButtonGradientStartColor); + gradient.setColorAt(1, mdiButtonGradientStopColor); + QColor mdiButtonBorderColor(active ? option->palette.highlight().color().darker(180): dark.darker(110)); + + painter->setPen(QPen(mdiButtonBorderColor, 1)); + const QLine lines[4] = { + QLine(tmp.left() + 2, tmp.top(), tmp.right() - 2, tmp.top()), + QLine(tmp.left() + 2, tmp.bottom(), tmp.right() - 2, tmp.bottom()), + QLine(tmp.left(), tmp.top() + 2, tmp.left(), tmp.bottom() - 2), + QLine(tmp.right(), tmp.top() + 2, tmp.right(), tmp.bottom() - 2) + }; + painter->drawLines(lines, 4); + const QPoint points[4] = { + QPoint(tmp.left() + 1, tmp.top() + 1), + QPoint(tmp.right() - 1, tmp.top() + 1), + QPoint(tmp.left() + 1, tmp.bottom() - 1), + QPoint(tmp.right() - 1, tmp.bottom() - 1) + }; + painter->drawPoints(points, 4); + + painter->setPen(titleBarHighlight); + painter->drawLine(tmp.left() + 2, tmp.top() + 1, tmp.right() - 2, tmp.top() + 1); + painter->drawLine(tmp.left() + 1, tmp.top() + 2, tmp.left() + 1, tmp.bottom() - 2); + + painter->setPen(QPen(gradient, 1)); + painter->drawLine(tmp.right() + 1, tmp.top() + 2, tmp.right() + 1, tmp.bottom() - 2); + painter->drawPoint(tmp.right() , tmp.top() + 1); + + painter->drawLine(tmp.left() + 2, tmp.bottom() + 1, tmp.right() - 2, tmp.bottom() + 1); + painter->drawPoint(tmp.left() + 1, tmp.bottom()); + painter->drawPoint(tmp.right() - 1, tmp.bottom()); + painter->drawPoint(tmp.right() , tmp.bottom() - 1); +} + +/*! + \class QCleanlooksStyle + \brief The QCleanlooksStyle class provides a widget style similar to the + Clearlooks style available in GNOME. + \since 4.2 + + The Cleanlooks style provides a look and feel for widgets + that closely resembles the Clearlooks style, introduced by Richard + Stellingwerff and Daniel Borgmann. + + \sa {Cleanlooks Style Widget Gallery}, QWindowsXPStyle, QMacStyle, QWindowsStyle, + QCDEStyle, QMotifStyle, QPlastiqueStyle +*/ + +/*! + Constructs a QCleanlooksStyle object. +*/ +QCleanlooksStyle::QCleanlooksStyle() : QWindowsStyle(*new QCleanlooksStylePrivate) +{ + setObjectName(QLatin1String("CleanLooks")); +} + +/*! + \internal + + Constructs a QCleanlooksStyle object. +*/ +QCleanlooksStyle::QCleanlooksStyle(QCleanlooksStylePrivate &dd) : QWindowsStyle(dd) +{ +} + +/*! + Destroys the QCleanlooksStyle object. +*/ +QCleanlooksStyle::~QCleanlooksStyle() +{ +} + +/*! + \fn void QCleanlooksStyle::drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, + bool enabled, const QString& text, QPalette::ColorRole textRole) const + + Draws the given \a text in the specified \a rectangle using the + provided \a painter and \a palette. + + Text is drawn using the painter's pen. If an explicit \a textRole + is specified, then the text is drawn using the \a palette's color + for the specified role. The \a enabled value indicates whether or + not the item is enabled; when reimplementing, this value should + influence how the item is drawn. + + The text is aligned and wrapped according to the specified \a + alignment. + + \sa Qt::Alignment +*/ +void QCleanlooksStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal, + bool enabled, const QString& text, QPalette::ColorRole textRole) const +{ + if (text.isEmpty()) + return; + + QPen savedPen = painter->pen(); + if (textRole != QPalette::NoRole) { + painter->setPen(QPen(pal.brush(textRole), savedPen.widthF())); + } + if (!enabled) { + QPen pen = painter->pen(); + painter->setPen(pen); + } + painter->drawText(rect, alignment, text); + painter->setPen(savedPen); +} + +static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50) +{ + const int maxFactor = 100; + QColor tmp = colorA; + tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor); + tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor); + tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor); + return tmp; +} + +/*! + \reimp +*/ +void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem, + const QStyleOption *option, + QPainter *painter, const QWidget *widget) const +{ + Q_ASSERT(option); + QRect rect = option->rect; + int state = option->state; + QColor button = option->palette.button().color(); + QColor buttonShadow = option->palette.button().color().darker(110); + QColor buttonShadowAlpha = buttonShadow; + buttonShadowAlpha.setAlpha(128); + QColor darkOutline; + QColor dark; + darkOutline.setHsv(button.hue(), + qMin(255, (int)(button.saturation()*3.0)), + qMin(255, (int)(button.value()*0.6))); + dark.setHsv(button.hue(), + qMin(255, (int)(button.saturation()*1.9)), + qMin(255, (int)(button.value()*0.7))); + QColor tabFrameColor = mergedColors(option->palette.background().color(), + dark.lighter(135), 60); + + switch(elem) { +#ifndef QT_NO_TABBAR + case PE_FrameTabBarBase: + if (const QStyleOptionTabBarBase *tbb + = qstyleoption_cast(option)) { + painter->save(); + painter->setPen(QPen(darkOutline.lighter(110), 0)); + switch (tbb->shape) { + case QTabBar::RoundedNorth: { + QRegion region(tbb->rect); + region -= tbb->selectedTabRect; + painter->drawLine(tbb->rect.topLeft(), tbb->rect.topRight()); + painter->setClipRegion(region); + painter->setPen(option->palette.light().color()); + painter->drawLine(tbb->rect.topLeft() + QPoint(0, 1), + tbb->rect.topRight() + QPoint(0, 1)); + } + break; + case QTabBar::RoundedWest: + painter->drawLine(tbb->rect.left(), tbb->rect.top(), tbb->rect.left(), tbb->rect.bottom()); + break; + case QTabBar::RoundedSouth: + painter->drawLine(tbb->rect.left(), tbb->rect.bottom(), + tbb->rect.right(), tbb->rect.bottom()); + break; + case QTabBar::RoundedEast: + painter->drawLine(tbb->rect.topRight(), tbb->rect.bottomRight()); + break; + case QTabBar::TriangularNorth: + case QTabBar::TriangularEast: + case QTabBar::TriangularWest: + case QTabBar::TriangularSouth: + painter->restore(); + QWindowsStyle::drawPrimitive(elem, option, painter, widget); + return; + } + painter->restore(); + } + return; +#endif // QT_NO_TABBAR + case PE_IndicatorViewItemCheck: + { + QStyleOptionButton button; + button.QStyleOption::operator=(*option); + button.state &= ~State_MouseOver; + proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget); + } + return; + case PE_IndicatorHeaderArrow: + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + QRect r = header->rect; + QImage arrow; + if (header->sortIndicator & QStyleOptionHeader::SortUp) + arrow = QImage(qt_cleanlooks_arrow_up_xpm); + else if (header->sortIndicator & QStyleOptionHeader::SortDown) + arrow = QImage(qt_cleanlooks_arrow_down_xpm); + if (!arrow.isNull()) { + r.setSize(arrow.size()); + r.moveCenter(header->rect.center()); + arrow.setColor(1, header->palette.foreground().color().rgba()); + painter->drawImage(r, arrow); + } + } + break; + case PE_IndicatorButtonDropDown: + proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); + break; + case PE_IndicatorToolBarSeparator: + { + QRect rect = option->rect; + const int margin = 6; + if (option->state & State_Horizontal) { + const int offset = rect.width()/2; + painter->setPen(QPen(option->palette.background().color().darker(110))); + painter->drawLine(rect.bottomLeft().x() + offset, + rect.bottomLeft().y() - margin, + rect.topLeft().x() + offset, + rect.topLeft().y() + margin); + painter->setPen(QPen(option->palette.background().color().lighter(110))); + painter->drawLine(rect.bottomLeft().x() + offset + 1, + rect.bottomLeft().y() - margin, + rect.topLeft().x() + offset + 1, + rect.topLeft().y() + margin); + } else { //Draw vertical separator + const int offset = rect.height()/2; + painter->setPen(QPen(option->palette.background().color().darker(110))); + painter->drawLine(rect.topLeft().x() + margin , + rect.topLeft().y() + offset, + rect.topRight().x() - margin, + rect.topRight().y() + offset); + painter->setPen(QPen(option->palette.background().color().lighter(110))); + painter->drawLine(rect.topLeft().x() + margin , + rect.topLeft().y() + offset + 1, + rect.topRight().x() - margin, + rect.topRight().y() + offset + 1); + } + } + break; + case PE_Frame: + painter->save(); + painter->setPen(dark.lighter(108)); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + painter->restore(); + break; + case PE_FrameMenu: + painter->save(); + { + painter->setPen(QPen(darkOutline, 1)); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + QColor frameLight = option->palette.background().color().lighter(160); + QColor frameShadow = option->palette.background().color().darker(110); + + //paint beveleffect + QRect frame = option->rect.adjusted(1, 1, -1, -1); + painter->setPen(frameLight); + painter->drawLine(frame.topLeft(), frame.bottomLeft()); + painter->drawLine(frame.topLeft(), frame.topRight()); + + painter->setPen(frameShadow); + painter->drawLine(frame.topRight(), frame.bottomRight()); + painter->drawLine(frame.bottomLeft(), frame.bottomRight()); + } + painter->restore(); + break; + case PE_FrameDockWidget: + + painter->save(); + { + QColor softshadow = option->palette.background().color().darker(120); + + QRect rect= option->rect; + painter->setPen(softshadow); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + painter->setPen(QPen(option->palette.light(), 0)); + painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), QPoint(rect.left() + 1, rect.bottom() - 1)); + painter->setPen(QPen(option->palette.background().color().darker(120), 0)); + painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), QPoint(rect.right() - 2, rect.bottom() - 1)); + painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), QPoint(rect.right() - 1, rect.bottom() - 1)); + + } + painter->restore(); + break; + case PE_PanelButtonTool: + painter->save(); + if ((option->state & State_Enabled || option->state & State_On) || !(option->state & State_AutoRaise)) { + QRect rect = option->rect; + QPen oldPen = painter->pen(); + + if (widget && widget->inherits("QDockWidgetTitleButton")) { + if (option->state & State_MouseOver) + proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); + } else { + proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); + } + } + painter->restore(); + break; + case PE_IndicatorDockWidgetResizeHandle: + { + QStyleOption dockWidgetHandle = *option; + bool horizontal = option->state & State_Horizontal; + if (horizontal) + dockWidgetHandle.state &= ~State_Horizontal; + else + dockWidgetHandle.state |= State_Horizontal; + proxy()->drawControl(CE_Splitter, &dockWidgetHandle, painter, widget); + } + break; + case PE_FrameWindow: + painter->save(); + { + QRect rect= option->rect; + painter->setPen(QPen(dark.darker(150), 0)); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + painter->setPen(QPen(option->palette.light(), 0)); + painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), + QPoint(rect.left() + 1, rect.bottom() - 1)); + painter->setPen(QPen(option->palette.background().color().darker(120), 0)); + painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), + QPoint(rect.right() - 2, rect.bottom() - 1)); + painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), + QPoint(rect.right() - 1, rect.bottom() - 1)); + } + painter->restore(); + break; +#ifndef QT_NO_LINEEDIT + case PE_FrameLineEdit: + // fall through +#endif // QT_NO_LINEEDIT +#ifdef QT3_SUPPORT + if (widget && widget->inherits("Q3ToolBar")) { + proxy()->drawPrimitive(PE_Q3Separator, option, painter, widget); + break; + } +#endif + { + QPen oldPen = painter->pen(); + if (option->state & State_Enabled) { + painter->setPen(QPen(option->palette.background(), 0)); + painter->drawRect(rect.adjusted(0, 0, 0, 0)); + painter->drawRect(rect.adjusted(1, 1, -1, -1)); + } else { + painter->fillRect(rect, option->palette.background()); + } + QRect r = rect.adjusted(0, 1, 0, -1); + painter->setPen(buttonShadowAlpha); + painter->drawLine(QPoint(r.left() + 2, r.top() - 1), QPoint(r.right() - 2, r.top() - 1)); + const QPoint points[8] = { + QPoint(r.right() - 1, r.top()), + QPoint(r.right(), r.top() + 1), + QPoint(r.right() - 1, r.bottom()), + QPoint(r.right(), r.bottom() - 1), + QPoint(r.left() + 1, r.top() ), + QPoint(r.left(), r.top() + 1), + QPoint(r.left() + 1, r.bottom() ), + QPoint(r.left(), r.bottom() - 1) + }; + painter->drawPoints(points, 8); + painter->setPen(QPen(option->palette.background().color(), 1)); + painter->drawLine(QPoint(r.left() + 2, r.top() + 1), QPoint(r.right() - 2, r.top() + 1)); + + if (option->state & State_HasFocus) { + QColor darkoutline = option->palette.highlight().color().darker(150); + QColor innerline = mergedColors(option->palette.highlight().color(), Qt::white); + painter->setPen(QPen(innerline, 0)); + painter->drawRect(rect.adjusted(1, 2, -2, -3)); + painter->setPen(QPen(darkoutline, 0)); + } + else { + QColor highlight = Qt::white; + highlight.setAlpha(130); + painter->setPen(option->palette.base().color().darker(120)); + painter->drawLine(QPoint(r.left() + 1, r.top() + 1), + QPoint(r.right() - 1, r.top() + 1)); + painter->drawLine(QPoint(r.left() + 1, r.top() + 1), + QPoint(r.left() + 1, r.bottom() - 1)); + painter->setPen(option->palette.base().color()); + painter->drawLine(QPoint(r.right() - 1, r.top() + 1), + QPoint(r.right() - 1, r.bottom() - 1)); + painter->setPen(highlight); + painter->drawLine(QPoint(r.left() + 1, r.bottom() + 1), + QPoint(r.right() - 1, r.bottom() + 1)); + painter->drawPoint(QPoint(r.left(), r.bottom())); + painter->drawPoint(QPoint(r.right(), r.bottom() )); + painter->setPen(QPen(darkOutline.lighter(115), 1)); + } + painter->drawLine(QPoint(r.left(), r.top() + 2), QPoint(r.left(), r.bottom() - 2)); + painter->drawLine(QPoint(r.right(), r.top() + 2), QPoint(r.right(), r.bottom() - 2)); + painter->drawLine(QPoint(r.left() + 2, r.bottom()), QPoint(r.right() - 2, r.bottom())); + const QPoint points2[4] = { + QPoint(r.right() - 1, r.bottom() - 1), + QPoint(r.right() - 1, r.top() + 1), + QPoint(r.left() + 1, r.bottom() - 1), + QPoint(r.left() + 1, r.top() + 1) + }; + painter->drawPoints(points2, 4); + painter->drawLine(QPoint(r.left() + 2, r.top()), QPoint(r.right() - 2, r.top())); + painter->setPen(oldPen); + } + break; + case PE_IndicatorCheckBox: + painter->save(); + if (const QStyleOptionButton *checkbox = qstyleoption_cast(option)) { + QRect checkRect; + checkRect.setX(rect.left() ); + checkRect.setY(rect.top() ); + checkRect.setWidth(rect.width() - 1); + checkRect.setHeight(rect.height() - 1); + if (state & State_Sunken) + painter->setBrush(dark.lighter(130)); + else + painter->setBrush(option->palette.base()); + painter->setPen(QPen(dark.lighter(110), 0)); + painter->drawRect(checkRect); + if (checkbox->state & (State_On | State_Sunken | State_NoChange)) { + QImage image(qt_cleanlooks_checkbox_checked); + QColor fillColor = option->palette.text().color(); + image.setColor(1, fillColor.rgba()); + fillColor.setAlpha(100); + image.setColor(2, fillColor.rgba()); + painter->drawImage(rect, image); + if (checkbox->state & State_NoChange) { + QColor bgc = option->palette.background().color(); + bgc.setAlpha(127); + painter->fillRect(checkRect.adjusted(1, 1, -1, -1), bgc); + } + } + } + painter->restore(); + break; + case PE_IndicatorRadioButton: + painter->save(); + { + painter->setRenderHint(QPainter::SmoothPixmapTransform); + QRect checkRect = rect.adjusted(0, 0, 0, 0); + if (state & (State_On )) { + painter->drawImage(rect, QImage(qt_cleanlooks_radiobutton)); + painter->drawImage(checkRect, QImage(qt_cleanlooks_radiobutton_checked)); + } + else if (state & State_Sunken) { + painter->drawImage(rect, QImage(qt_cleanlooks_radiobutton)); + QColor bgc = buttonShadow; + painter->setRenderHint(QPainter::Antialiasing); + painter->setBrush(bgc); + painter->setPen(Qt::NoPen); + painter->drawEllipse(rect.adjusted(1, 1, -1, -1)); } + else { + painter->drawImage(rect, QImage(qt_cleanlooks_radiobutton)); + } + } + painter->restore(); + break; + case PE_IndicatorToolBarHandle: + painter->save(); + if (option->state & State_Horizontal) { + for (int i = rect.height()/5; i <= 4*(rect.height()/5) ; ++i) { + int y = rect.topLeft().y() + i + 1; + int x1 = rect.topLeft().x() + 3; + int x2 = rect.topRight().x() - 2; + + if (i % 2 == 0) + painter->setPen(QPen(option->palette.light(), 0)); + else + painter->setPen(QPen(dark.lighter(110), 0)); + painter->drawLine(x1, y, x2, y); + } + } + else { //vertical toolbar + for (int i = rect.width()/5; i <= 4*(rect.width()/5) ; ++i) { + int x = rect.topLeft().x() + i + 1; + int y1 = rect.topLeft().y() + 3; + int y2 = rect.topLeft().y() + 5; + + if (i % 2 == 0) + painter->setPen(QPen(option->palette.light(), 0)); + else + painter->setPen(QPen(dark.lighter(110), 0)); + painter->drawLine(x, y1, x, y2); + } + } + painter->restore(); + break; + case PE_FrameDefaultButton: + case PE_FrameFocusRect: + if (const QStyleOptionFocusRect *focusFrame = qstyleoption_cast(option)) { + if (!(focusFrame->state & State_KeyboardFocusChange)) + return; + QRect rect = focusFrame->rect; + painter->save(); + painter->setBackgroundMode(Qt::TransparentMode); + painter->setBrush(QBrush(dark.darker(120), Qt::Dense4Pattern)); + painter->setBrushOrigin(rect.topLeft()); + painter->setPen(Qt::NoPen); + const QRect rects[4] = { + QRect(rect.left(), rect.top(), rect.width(), 1), // Top + QRect(rect.left(), rect.bottom(), rect.width(), 1), // Bottom + QRect(rect.left(), rect.top(), 1, rect.height()), // Left + QRect(rect.right(), rect.top(), 1, rect.height()) // Right + }; + painter->drawRects(rects, 4); + painter->restore(); + } + break; + case PE_PanelButtonCommand: + { + bool isDefault = false; + bool isFlat = false; + bool isDown = (option->state & State_Sunken) || (option->state & State_On); + QPen oldPen = painter->pen(); + QBrush oldBrush = painter->brush(); + QRect r; + + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + isDefault = (button->features & QStyleOptionButton::DefaultButton) && (button->state & State_Enabled); + isFlat = (button->features & QStyleOptionButton::Flat); + } + + if (isFlat && !isDown) { + if (isDefault) { + r = option->rect.adjusted(0, 1, 0, -1); + painter->setPen(QPen(Qt::black, 0)); + const QLine lines[4] = { + QLine(QPoint(r.left() + 2, r.top()), + QPoint(r.right() - 2, r.top())), + QLine(QPoint(r.left(), r.top() + 2), + QPoint(r.left(), r.bottom() - 2)), + QLine(QPoint(r.right(), r.top() + 2), + QPoint(r.right(), r.bottom() - 2)), + QLine(QPoint(r.left() + 2, r.bottom()), + QPoint(r.right() - 2, r.bottom())) + }; + painter->drawLines(lines, 4); + const QPoint points[4] = { + QPoint(r.right() - 1, r.bottom() - 1), + QPoint(r.right() - 1, r.top() + 1), + QPoint(r.left() + 1, r.bottom() - 1), + QPoint(r.left() + 1, r.top() + 1) + }; + painter->drawPoints(points, 4); + painter->setPen(oldPen); + } + return; + } + + BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("pushbutton-%1").arg(isDefault)) + r = rect.adjusted(0, 1, 0, -1); + + bool isEnabled = (option->state & State_Enabled); + + QColor highlightedGradientStartColor = option->palette.button().color().lighter(107); + QColor highlightedGradientMidColor = option->palette.button().color().lighter(105); + QColor highlightedGradientStopColor = buttonShadow.lighter(107); + QColor gradientStartColor = option->palette.button().color().lighter(108); + + QColor buttonColor = option->palette.button().color(); + QColor gradientMidColor = option->palette.button().color(); + QColor gradientStopColor; + gradientStopColor.setHsv(buttonColor.hue(), + qMin(255, (int)(buttonColor.saturation()*1.9)), + qMin(255, (int)(buttonColor.value()*0.96))); + + QRect gradRect = rect.adjusted(1, 2, -1, -2); + // gradient fill + QRect innerBorder = r.adjusted(1, 1, -1, 0); + + if (isDown) { + QBrush fillColor = gradientStopColor.darker(110); + if (option->palette.button().gradient()) + fillColor = option->palette.button(); + p->fillRect(gradRect, fillColor); + p->setPen(gradientStopColor.darker(125)); + p->drawLine(innerBorder.topLeft(), innerBorder.topRight()); + p->drawLine(innerBorder.topLeft(), innerBorder.bottomLeft()); + } else { + if (isEnabled && option->state & State_MouseOver ) { + qt_cleanlooks_draw_buttongradient(p, gradRect, + highlightedGradientStartColor, + highlightedGradientMidColor, + highlightedGradientStopColor, TopDown, option->palette.button()); + } else { + qt_cleanlooks_draw_buttongradient(p, gradRect, + gradientStartColor, + gradientMidColor, + gradientStopColor, TopDown, option->palette.button()); + } + } + + bool hasFocus = option->state & State_HasFocus; + + if (!isEnabled) + p->setPen(QPen(dark.lighter(115))); + else if (isDefault) + p->setPen(QPen(Qt::black, 1)); + else + p->setPen(QPen(darkOutline, 1)); + + p->drawLine(QPoint(r.left(), r.top() + 2), + QPoint(r.left(), r.bottom() - 2)); + p->drawLine(QPoint(r.right(), r.top() + 2), + QPoint(r.right(), r.bottom() - 2)); + p->drawLine(QPoint(r.left() + 2, r.bottom()), + QPoint(r.right() - 2, r.bottom())); + const QPoint points[4] = { + QPoint(r.right() - 1, r.bottom() - 1), + QPoint(r.right() - 1, r.top() + 1), + QPoint(r.left() + 1, r.bottom() - 1), + QPoint(r.left() + 1, r.top() + 1) + }; + p->drawPoints(points, 4); + + if (!isDefault && !hasFocus && isEnabled) + p->setPen(QPen(darkOutline.darker(110), 0)); + + p->drawLine(QPoint(r.left() + 2, r.top()), + QPoint(r.right() - 2, r.top())); + + QColor highlight = Qt::white; + highlight.setAlpha(110); + p->setPen(highlight); + p->drawLine(QPoint(r.left() + 1, r.top() + 2), + QPoint(r.left() + 1, r.bottom() - 2)); + p->drawLine(QPoint(r.left() + 3, r.bottom() + 1), + QPoint(r.right() - 3, r.bottom() + 1)); + + QColor topShadow = darkOutline; + topShadow.setAlpha(60); + + p->setPen(topShadow); + const QPoint points2[8] = { + QPoint(r.right(), r.top() + 1), + QPoint(r.right() - 1, r.top() ), + QPoint(r.right(), r.bottom() - 1), + QPoint(r.right() - 1, r.bottom() ), + QPoint(r.left() + 1, r.bottom()), + QPoint(r.left(), r.bottom() - 1), + QPoint(r.left() + 1, r.top()), + QPoint(r.left(), r.top() + 1) + }; + p->drawPoints(points2, 8); + + topShadow.setAlpha(30); + p->setPen(topShadow); + + p->drawLine(QPoint(r.right() - 1, r.top() + 2), + QPoint(r.right() - 1, r.bottom() - 2)); + p->drawLine(QPoint(r.left() + 2, r.top() - 1), + QPoint(r.right() - 2, r.top() - 1)); + + if (isDefault) { + r.adjust(-1, -1, 1, 1); + p->setPen(buttonShadowAlpha.darker(120)); + const QLine lines[4] = { + QLine(r.topLeft() + QPoint(3, 0), r.topRight() - QPoint(3, 0)), + QLine(r.bottomLeft() + QPoint(3, 0), r.bottomRight() - QPoint(3, 0)), + QLine(r.topLeft() + QPoint(0, 3), r.bottomLeft() - QPoint(0, 3)), + QLine(r.topRight() + QPoint(0, 3), r.bottomRight() - QPoint(0, 3)) + }; + p->drawLines(lines, 4); + const QPoint points3[8] = { + r.topRight() + QPoint(-2, 1), + r.topRight() + QPoint(-1, 2), + r.bottomRight() + QPoint(-1, -2), + r.bottomRight() + QPoint(-2, -1), + r.topLeft() + QPoint(1, 2), + r.topLeft() + QPoint(2, 1), + r.bottomLeft() + QPoint(1, -2), + r.bottomLeft() + QPoint(2, -1) + }; + p->drawPoints(points3, 8); + } + painter->setPen(oldPen); + painter->setBrush(oldBrush); + END_STYLE_PIXMAPCACHE + } + break; +#ifndef QT_NO_TABBAR + case PE_FrameTabWidget: + painter->save(); + { + painter->fillRect(option->rect, tabFrameColor); + } +#ifndef QT_NO_TABWIDGET + if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast(option)) { + QColor borderColor = darkOutline.lighter(110); + QColor alphaCornerColor = mergedColors(borderColor, option->palette.background().color()); + QColor innerShadow = mergedColors(borderColor, option->palette.base().color()); + + int borderThickness = proxy()->pixelMetric(PM_TabBarBaseOverlap, twf, widget); + bool reverse = (twf->direction == Qt::RightToLeft); + QRect tabBarRect; + + switch (twf->shape) { + case QTabBar::RoundedNorth: + if (reverse) { + tabBarRect = QRect(twf->rect.right() - twf->leftCornerWidgetSize.width() + - twf->tabBarSize.width() + 1, + twf->rect.top(), + twf->tabBarSize.width(), borderThickness); + } else { + tabBarRect = QRect(twf->rect.left() + twf->leftCornerWidgetSize.width(), + twf->rect.top(), + twf->tabBarSize.width(), borderThickness); + } + break ; + case QTabBar::RoundedWest: + tabBarRect = QRect(twf->rect.left(), + twf->rect.top() + twf->leftCornerWidgetSize.height(), + borderThickness, + twf->tabBarSize.height()); + tabBarRect = tabBarRect; //adjust + break ; + case QTabBar::RoundedEast: + tabBarRect = QRect(twf->rect.right() - borderThickness + 1, + twf->rect.top() + twf->leftCornerWidgetSize.height(), + 0, + twf->tabBarSize.height()); + break ; + case QTabBar::RoundedSouth: + if (reverse) { + tabBarRect = QRect(twf->rect.right() - twf->leftCornerWidgetSize.width() - twf->tabBarSize.width() + 1, + twf->rect.bottom() + 1, + twf->tabBarSize.width(), + borderThickness); + } else { + tabBarRect = QRect(twf->rect.left() + twf->leftCornerWidgetSize.width(), + twf->rect.bottom() + 1, + twf->tabBarSize.width(), + borderThickness); + } + break; + default: + break; + } + + QRegion region(twf->rect); + region -= tabBarRect; + painter->setClipRegion(region); + + // Outer border + QLine leftLine = QLine(twf->rect.topLeft() + QPoint(0, 2), twf->rect.bottomLeft() - QPoint(0, 2)); + QLine rightLine = QLine(twf->rect.topRight(), twf->rect.bottomRight() - QPoint(0, 2)); + QLine bottomLine = QLine(twf->rect.bottomLeft() + QPoint(2, 0), twf->rect.bottomRight() - QPoint(2, 0)); + QLine topLine = QLine(twf->rect.topLeft(), twf->rect.topRight()); + + painter->setPen(borderColor); + painter->drawLine(topLine); + + // Inner border + QLine innerLeftLine = QLine(leftLine.p1() + QPoint(1, 0), leftLine.p2() + QPoint(1, 0)); + QLine innerRightLine = QLine(rightLine.p1() - QPoint(1, -1), rightLine.p2() - QPoint(1, 0)); + QLine innerBottomLine = QLine(bottomLine.p1() - QPoint(0, 1), bottomLine.p2() - QPoint(0, 1)); + QLine innerTopLine = QLine(topLine.p1() + QPoint(0, 1), topLine.p2() + QPoint(-1, 1)); + + // Rounded Corner + QPoint leftBottomOuterCorner = QPoint(innerLeftLine.p2() + QPoint(0, 1)); + QPoint leftBottomInnerCorner1 = QPoint(leftLine.p2() + QPoint(0, 1)); + QPoint leftBottomInnerCorner2 = QPoint(bottomLine.p1() - QPoint(1, 0)); + QPoint rightBottomOuterCorner = QPoint(innerRightLine.p2() + QPoint(0, 1)); + QPoint rightBottomInnerCorner1 = QPoint(rightLine.p2() + QPoint(0, 1)); + QPoint rightBottomInnerCorner2 = QPoint(bottomLine.p2() + QPoint(1, 0)); + QPoint leftTopOuterCorner = QPoint(innerLeftLine.p1() - QPoint(0, 1)); + QPoint leftTopInnerCorner1 = QPoint(leftLine.p1() - QPoint(0, 1)); + QPoint leftTopInnerCorner2 = QPoint(topLine.p1() - QPoint(1, 0)); + + painter->setPen(borderColor); + painter->drawLine(leftLine); + painter->drawLine(rightLine); + painter->drawLine(bottomLine); + painter->drawPoint(leftBottomOuterCorner); + painter->drawPoint(rightBottomOuterCorner); + painter->drawPoint(leftTopOuterCorner); + + painter->setPen(option->palette.light().color()); + painter->drawLine(innerLeftLine); + painter->drawLine(innerTopLine); + + painter->setPen(buttonShadowAlpha); + painter->drawLine(innerRightLine); + painter->drawLine(innerBottomLine); + + painter->setPen(alphaCornerColor); + const QPoint points[6] = { + leftBottomInnerCorner1, + leftBottomInnerCorner2, + rightBottomInnerCorner1, + rightBottomInnerCorner2, + leftTopInnerCorner1, + leftTopInnerCorner2 + }; + painter->drawPoints(points, 6); + } +#endif // QT_NO_TABWIDGET + painter->restore(); + break ; + + case PE_FrameStatusBarItem: + break; + case PE_IndicatorTabClose: + { + Q_D(const QCleanlooksStyle); + if (d->tabBarcloseButtonIcon.isNull()) + d->tabBarcloseButtonIcon = standardIcon(SP_DialogCloseButton, option, widget); + if ((option->state & State_Enabled) && (option->state & State_MouseOver)) + proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); + QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On); + proxy()->drawItemPixmap(painter, option->rect, Qt::AlignCenter, pixmap); + } + break; + +#endif // QT_NO_TABBAR + default: + QWindowsStyle::drawPrimitive(elem, option, painter, widget); + break; + } +} + +/*! + \reimp +*/ +void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, + const QWidget *widget) const +{ + QColor button = option->palette.button().color(); + QColor dark; + dark.setHsv(button.hue(), + qMin(255, (int)(button.saturation()*1.9)), + qMin(255, (int)(button.value()*0.7))); + QColor darkOutline; + darkOutline.setHsv(button.hue(), + qMin(255, (int)(button.saturation()*2.0)), + qMin(255, (int)(button.value()*0.6))); + QRect rect = option->rect; + QColor shadow = mergedColors(option->palette.background().color().darker(120), + dark.lighter(130), 60); + QColor tabFrameColor = mergedColors(option->palette.background().color(), + dark.lighter(135), 60); + + QColor highlight = option->palette.highlight().color(); + + switch(element) { + case CE_RadioButton: //fall through + case CE_CheckBox: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + bool hover = (btn->state & State_MouseOver && btn->state & State_Enabled); + if (hover) + painter->fillRect(rect, btn->palette.background().color().lighter(104)); + QStyleOptionButton copy = *btn; + copy.rect.adjust(2, 0, -2, 0); + QWindowsStyle::drawControl(element, ©, painter, widget); + } + break; + case CE_Splitter: + painter->save(); + { + // hover appearance + QBrush fillColor = option->palette.background().color(); + if (option->state & State_MouseOver && option->state & State_Enabled) + fillColor = fillColor.color().lighter(106); + + painter->fillRect(option->rect, fillColor); + + QColor grooveColor = mergedColors(dark.lighter(110), option->palette.button().color(),40); + QColor gripShadow = grooveColor.darker(110); + QPalette palette = option->palette; + bool vertical = !(option->state & State_Horizontal); + QRect scrollBarSlider = option->rect; + int gripMargin = 4; + //draw grips + if (vertical) { + for( int i = -20; i< 20 ; i += 2) { + painter->setPen(QPen(gripShadow, 1)); + painter->drawLine( + QPoint(scrollBarSlider.center().x() + i , + scrollBarSlider.top() + gripMargin), + QPoint(scrollBarSlider.center().x() + i, + scrollBarSlider.bottom() - gripMargin)); + painter->setPen(QPen(palette.light(), 1)); + painter->drawLine( + QPoint(scrollBarSlider.center().x() + i + 1, + scrollBarSlider.top() + gripMargin ), + QPoint(scrollBarSlider.center().x() + i + 1, + scrollBarSlider.bottom() - gripMargin)); + } + } else { + for (int i = -20; i < 20 ; i += 2) { + painter->setPen(QPen(gripShadow, 1)); + painter->drawLine( + QPoint(scrollBarSlider.left() + gripMargin , + scrollBarSlider.center().y()+ i), + QPoint(scrollBarSlider.right() - gripMargin, + scrollBarSlider.center().y()+ i)); + painter->setPen(QPen(palette.light(), 1)); + painter->drawLine( + QPoint(scrollBarSlider.left() + gripMargin, + scrollBarSlider.center().y() + 1 + i), + QPoint(scrollBarSlider.right() - gripMargin, + scrollBarSlider.center().y() + 1 + i)); + + } + } + } + painter->restore(); + break; +#ifndef QT_NO_SIZEGRIP + case CE_SizeGrip: + painter->save(); + { + int x, y, w, h; + option->rect.getRect(&x, &y, &w, &h); + int sw = qMin(h, w); + if (h > w) + painter->translate(0, h - w); + else + painter->translate(w - h, 0); + + int sx = x; + int sy = y; + int s = 4; + if (option->direction == Qt::RightToLeft) { + sx = x + sw; + for (int i = 0; i < 4; ++i) { + painter->setPen(QPen(option->palette.light().color(), 1)); + painter->drawLine(x, sy - 1 , sx + 1, sw); + painter->setPen(QPen(dark.lighter(120), 1)); + painter->drawLine(x, sy, sx, sw); + sx -= s; + sy += s; + } + } else { + for (int i = 0; i < 4; ++i) { + painter->setPen(QPen(option->palette.light().color(), 1)); + painter->drawLine(sx - 1, sw, sw, sy - 1); + painter->setPen(QPen(dark.lighter(120), 1)); + painter->drawLine(sx, sw, sw, sy); + sx += s; + sy += s; + } + } + } + painter->restore(); + break; +#endif // QT_NO_SIZEGRIP +#ifndef QT_NO_TOOLBAR + case CE_ToolBar: + painter->save(); + if (const QStyleOptionToolBar *toolbar = qstyleoption_cast(option)) { + QRect rect = option->rect; + + bool paintLeftBorder = true; + bool paintRightBorder = true; + bool paintBottomBorder = true; + + switch (toolbar->toolBarArea) { + case Qt::BottomToolBarArea: + switch(toolbar->positionOfLine) { + case QStyleOptionToolBar::Beginning: + case QStyleOptionToolBar::OnlyOne: + paintBottomBorder = false; + default: + break; + } + case Qt::TopToolBarArea: + switch (toolbar->positionWithinLine) { + case QStyleOptionToolBar::Beginning: + paintLeftBorder = false; + break; + case QStyleOptionToolBar::End: + paintRightBorder = false; + break; + case QStyleOptionToolBar::OnlyOne: + paintRightBorder = false; + paintLeftBorder = false; + default: + break; + } + if (toolbar->direction == Qt::RightToLeft) { //reverse layout changes the order of Beginning/end + bool tmp = paintLeftBorder; + paintRightBorder=paintLeftBorder; + paintLeftBorder=tmp; + } + break; + case Qt::RightToolBarArea: + switch (toolbar->positionOfLine) { + case QStyleOptionToolBar::Beginning: + case QStyleOptionToolBar::OnlyOne: + paintRightBorder = false; + break; + default: + break; + } + break; + case Qt::LeftToolBarArea: + switch (toolbar->positionOfLine) { + case QStyleOptionToolBar::Beginning: + case QStyleOptionToolBar::OnlyOne: + paintLeftBorder = false; + break; + default: + break; + } + break; + default: + break; + } + + QColor light = option->palette.background().color().lighter(110); + + //draw top border + painter->setPen(QPen(light)); + painter->drawLine(rect.topLeft().x(), + rect.topLeft().y(), + rect.topRight().x(), + rect.topRight().y()); + + if (paintLeftBorder) { + painter->setPen(QPen(light)); + painter->drawLine(rect.topLeft().x(), + rect.topLeft().y(), + rect.bottomLeft().x(), + rect.bottomLeft().y()); + } + + if (paintRightBorder) { + painter->setPen(QPen(shadow)); + painter->drawLine(rect.topRight().x(), + rect.topRight().y(), + rect.bottomRight().x(), + rect.bottomRight().y()); + } + + if (paintBottomBorder) { + painter->setPen(QPen(shadow)); + painter->drawLine(rect.bottomLeft().x(), + rect.bottomLeft().y(), + rect.bottomRight().x(), + rect.bottomRight().y()); + } + } + painter->restore(); + break; +#endif // QT_NO_TOOLBAR +#ifndef QT_NO_DOCKWIDGET + case CE_DockWidgetTitle: + painter->save(); + if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast(option)) { + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(dwOpt); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + + QRect rect = dwOpt->rect; + QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, option, widget); + QRect r = rect.adjusted(0, 0, -1, 0); + if (verticalTitleBar) + r.adjust(0, 0, 0, -1); + painter->setPen(option->palette.light().color()); + painter->drawRect(r.adjusted(1, 1, 1, 1)); + painter->setPen(shadow); + painter->drawRect(r); + + if (verticalTitleBar) { + QRect r = rect; + QSize s = r.size(); + s.transpose(); + r.setSize(s); + + titleRect = QRect(r.left() + rect.bottom() + - titleRect.bottom(), + r.top() + titleRect.left() - rect.left(), + titleRect.height(), titleRect.width()); + + painter->translate(r.left(), r.top() + r.width()); + painter->rotate(-90); + painter->translate(-r.left(), -r.top()); + + rect = r; + } + + if (!dwOpt->title.isEmpty()) { + QString titleText + = painter->fontMetrics().elidedText(dwOpt->title, + Qt::ElideRight, titleRect.width()); + proxy()->drawItemText(painter, + titleRect, + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette, + dwOpt->state & State_Enabled, titleText, + QPalette::WindowText); + } + } + painter->restore(); + break; +#endif // QT_NO_DOCKWIDGET + case CE_HeaderSection: + painter->save(); + // Draws the header in tables. + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + QPixmap cache; + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("headersection"), option, option->rect.size()); + pixmapName += QString::number(- int(header->position)); + pixmapName += QString::number(- int(header->orientation)); + QRect r = option->rect; + QColor gradientStopColor; + QColor gradientStartColor = option->palette.button().color(); + gradientStopColor.setHsv(gradientStartColor.hue(), + qMin(255, (int)(gradientStartColor.saturation()*2)), + qMin(255, (int)(gradientStartColor.value()*0.96))); + QLinearGradient gradient(rect.topLeft(), rect.bottomLeft()); + if (option->palette.background().gradient()) { + gradient.setStops(option->palette.background().gradient()->stops()); + } else { + gradient.setColorAt(0, gradientStartColor); + gradient.setColorAt(0.8, gradientStartColor); + gradient.setColorAt(1, gradientStopColor); + } + painter->fillRect(r, gradient); + + if (!QPixmapCache::find(pixmapName, cache)) { + cache = QPixmap(r.size()); + cache.fill(Qt::transparent); + QRect pixmapRect(0, 0, r.width(), r.height()); + QPainter cachePainter(&cache); + if (header->orientation == Qt::Vertical) { + cachePainter.setPen(QPen(dark)); + cachePainter.drawLine(pixmapRect.topRight(), pixmapRect.bottomRight()); + if (header->position != QStyleOptionHeader::End) { + cachePainter.setPen(QPen(shadow)); + cachePainter.drawLine(pixmapRect.bottomLeft() + QPoint(3, -1), pixmapRect.bottomRight() + QPoint(-3, -1)); cachePainter.setPen(QPen(option->palette.light().color())); + cachePainter.drawLine(pixmapRect.bottomLeft() + QPoint(3, 0), pixmapRect.bottomRight() + QPoint(-3, 0)); } + } else { + cachePainter.setPen(QPen(dark)); + cachePainter.drawLine(pixmapRect.bottomLeft(), pixmapRect.bottomRight()); + cachePainter.setPen(QPen(shadow)); + cachePainter.drawLine(pixmapRect.topRight() + QPoint(-1, 3), pixmapRect.bottomRight() + QPoint(-1, -3)); cachePainter.setPen(QPen(option->palette.light().color())); + cachePainter.drawLine(pixmapRect.topRight() + QPoint(0, 3), pixmapRect.bottomRight() + QPoint(0, -3)); } + cachePainter.end(); + QPixmapCache::insert(pixmapName, cache); + } + painter->drawPixmap(r.topLeft(), cache); + } + painter->restore(); + break; + case CE_ProgressBarGroove: + painter->save(); + { + painter->fillRect(rect, option->palette.base()); + QColor borderColor = dark.lighter(110); + painter->setPen(QPen(borderColor, 0)); + const QLine lines[4] = { + QLine(QPoint(rect.left() + 1, rect.top()), QPoint(rect.right() - 1, rect.top())), + QLine(QPoint(rect.left() + 1, rect.bottom()), QPoint(rect.right() - 1, rect.bottom())), + QLine(QPoint(rect.left(), rect.top() + 1), QPoint(rect.left(), rect.bottom() - 1)), + QLine(QPoint(rect.right(), rect.top() + 1), QPoint(rect.right(), rect.bottom() - 1)) + }; + painter->drawLines(lines, 4); + QColor alphaCorner = mergedColors(borderColor, option->palette.background().color()); + QColor innerShadow = mergedColors(borderColor, option->palette.base().color()); + + //corner smoothing + painter->setPen(alphaCorner); + const QPoint points[4] = { + rect.topRight(), + rect.topLeft(), + rect.bottomRight(), + rect.bottomLeft() + }; + painter->drawPoints(points, 4); + + //inner shadow + painter->setPen(innerShadow); + painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), + QPoint(rect.right() - 1, rect.top() + 1)); + painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), + QPoint(rect.left() + 1, rect.bottom() + 1)); + + } + painter->restore(); + break; + case CE_ProgressBarContents: + painter->save(); + if (const QStyleOptionProgressBar *bar = qstyleoption_cast(option)) { + QRect rect = bar->rect; + bool vertical = false; + bool inverted = false; + bool indeterminate = (bar->minimum == 0 && bar->maximum == 0); + + // Get extra style options if version 2 + if (const QStyleOptionProgressBarV2 *bar2 = qstyleoption_cast(option)) { + vertical = (bar2->orientation == Qt::Vertical); + inverted = bar2->invertedAppearance; + } + + // If the orientation is vertical, we use a transform to rotate + // the progress bar 90 degrees clockwise. This way we can use the + // same rendering code for both orientations. + if (vertical) { + rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height + QTransform m = QTransform::fromTranslate(rect.height()-1, -1.0); + m.rotate(90.0); + painter->setTransform(m, true); + } + + int maxWidth = rect.width() - 4; + int minWidth = 4; + qreal progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar + int progressBarWidth = (progress - bar->minimum) * qreal(maxWidth) / qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum); + int width = indeterminate ? maxWidth : qMax(minWidth, progressBarWidth); + + bool reverse = (!vertical && (bar->direction == Qt::RightToLeft)) || vertical; + if (inverted) + reverse = !reverse; + + QRect progressBar; + if (!indeterminate) { + if (!reverse) { + progressBar.setRect(rect.left() + 1, rect.top() + 1, width + 1, rect.height() - 3); + } else { + progressBar.setRect(rect.right() - 1 - width, rect.top() + 1, width + 1, rect.height() - 3); + } + } else { + Q_D(const QCleanlooksStyle); + int slideWidth = ((rect.width() - 4) * 2) / 3; + int step = ((d->animateStep * slideWidth) / d->animationFps) % slideWidth; + if ((((d->animateStep * slideWidth) / d->animationFps) % (2 * slideWidth)) >= slideWidth) + step = slideWidth - step; + progressBar.setRect(rect.left() + 1 + step, rect.top() + 1, + slideWidth / 2, rect.height() - 3); + } + QColor highlight = option->palette.color(QPalette::Normal, QPalette::Highlight); + painter->setPen(QPen(highlight.darker(140), 0)); + + QColor highlightedGradientStartColor = highlight.lighter(100); + QColor highlightedGradientStopColor = highlight.lighter(130); + + QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), + rect.bottomLeft().y()*2)); + + gradient.setColorAt(0, highlightedGradientStartColor); + gradient.setColorAt(1, highlightedGradientStopColor); + + painter->setBrush(gradient); + painter->drawRect(progressBar); + + painter->setPen(QPen(highlight.lighter(120), 0)); + painter->drawLine(QPoint(progressBar.left() + 1, progressBar.top() + 1), + QPoint(progressBar.right(), progressBar.top() + 1)); + painter->drawLine(QPoint(progressBar.left() + 1, progressBar.top() + 1), + QPoint(progressBar.left() + 1, progressBar.bottom() - 1)); + + painter->setPen(QPen(highlightedGradientStartColor, 7.0));//QPen(option->palette.highlight(), 3)); + + painter->save(); + painter->setClipRect(progressBar.adjusted(2, 2, -1, -1)); + for (int x = progressBar.left() - 32; x < rect.right() ; x+=18) { + painter->drawLine(x, progressBar.bottom() + 1, x + 23, progressBar.top() - 2); + } + painter->restore(); + + } + painter->restore(); + break; + case CE_MenuBarItem: + painter->save(); + if (const QStyleOptionMenuItem *mbi = qstyleoption_cast(option)) + { + QStyleOptionMenuItem item = *mbi; + item.rect = mbi->rect.adjusted(0, 3, 0, -1); + QColor highlightOutline = highlight.darker(125); + QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y()*2)); + + if (option->palette.button().gradient()) { + gradient.setStops(option->palette.button().gradient()->stops()); + } else { + gradient.setColorAt(0, option->palette.button().color()); + gradient.setColorAt(1, option->palette.button().color().darker(110)); + } + painter->fillRect(rect, gradient); + + QCommonStyle::drawControl(element, &item, painter, widget); + + bool act = mbi->state & State_Selected && mbi->state & State_Sunken; + bool dis = !(mbi->state & State_Enabled); + + QRect r = option->rect; + if (act) { + qt_cleanlooks_draw_gradient(painter, r.adjusted(1, 1, -1, -1), + highlight, + highlightOutline, TopDown, + option->palette.highlight()); + + painter->setPen(QPen(highlightOutline, 0)); + const QLine lines[4] = { + QLine(QPoint(r.left(), r.top() + 1), QPoint(r.left(), r.bottom())), + QLine(QPoint(r.right(), r.top() + 1), QPoint(r.right(), r.bottom())), + QLine(QPoint(r.left() + 1, r.bottom()), QPoint(r.right() - 1, r.bottom())), + QLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top())) + }; + painter->drawLines(lines, 4); + + //draw text + QPalette::ColorRole textRole = dis ? QPalette::Text : QPalette::HighlightedText; + uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!styleHint(SH_UnderlineShortcut, mbi, widget)) + alignment |= Qt::TextHideMnemonic; + proxy()->drawItemText(painter, item.rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole); + } + + } + painter->restore(); + break; + case CE_MenuItem: + painter->save(); + // Draws one item in a popup menu. + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast(option)) { + QColor highlightOutline = highlight.darker(125); + QColor menuBackground = option->palette.background().color().lighter(104); + QColor borderColor = option->palette.background().color().darker(160); + QColor alphaCornerColor; + + if (widget) { + // ### backgroundrole/foregroundrole should be part of the style option + alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), borderColor); + } else { + alphaCornerColor = mergedColors(option->palette.background().color(), borderColor); + } + QColor alphaTextColor = mergedColors(option->palette.background().color(), option->palette.text().color()); + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + painter->fillRect(menuItem->rect, menuBackground); + int w = 0; + if (!menuItem->text.isEmpty()) { + painter->setFont(menuItem->font); + proxy()->drawItemText(painter, menuItem->rect.adjusted(5, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter, + menuItem->palette, menuItem->state & State_Enabled, menuItem->text, + QPalette::Text); + w = menuItem->fontMetrics.width(menuItem->text) + 5; + } + painter->setPen(shadow.lighter(106)); + bool reverse = menuItem->direction == Qt::RightToLeft; + painter->drawLine(menuItem->rect.left() + 5 + (reverse ? 0 : w), menuItem->rect.center().y(), + menuItem->rect.right() - 5 - (reverse ? w : 0), menuItem->rect.center().y()); + painter->restore(); + break; + } + bool selected = menuItem->state & State_Selected && menuItem->state & State_Enabled; + if (selected) { + QRect r = option->rect.adjusted(1, 0, -2, -1); + qt_cleanlooks_draw_gradient(painter, r, highlight, + highlightOutline, TopDown, + highlight); + r = r.adjusted(-1, 0, 1, 0); + painter->setPen(QPen(highlightOutline, 0)); + const QLine lines[4] = { + QLine(QPoint(r.left(), r.top() + 1), QPoint(r.left(), r.bottom() - 1)), + QLine(QPoint(r.right(), r.top() + 1), QPoint(r.right(), r.bottom() - 1)), + QLine(QPoint(r.left() + 1, r.bottom()), QPoint(r.right() - 1, r.bottom())), + QLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top())) + }; + painter->drawLines(lines, 4); + } else { + painter->fillRect(option->rect, menuBackground); + } + + bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable; + bool checked = menuItem->checked; + bool sunken = menuItem->state & State_Sunken; + bool enabled = menuItem->state & State_Enabled; + + bool ignoreCheckMark = false; + int checkcol = qMax(menuItem->maxIconWidth, 20); + +#ifndef QT_NO_COMBOBOX + if (qobject_cast(widget)) + ignoreCheckMark = true; //ignore the checkmarks provided by the QComboMenuDelegate +#endif + + if (!ignoreCheckMark) { + // Check + QRect checkRect(option->rect.left() + 7, option->rect.center().y() - 6, 13, 13); + checkRect = visualRect(menuItem->direction, menuItem->rect, checkRect); + if (checkable) { + if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) { + // Radio button + if (checked || sunken) { + painter->setRenderHint(QPainter::Antialiasing); + painter->setPen(Qt::NoPen); + + QPalette::ColorRole textRole = !enabled ? QPalette::Text: + selected ? QPalette::HighlightedText : QPalette::ButtonText; + painter->setBrush(option->palette.brush( option->palette.currentColorGroup(), textRole)); + painter->drawEllipse(checkRect.adjusted(4, 4, -4, -4)); + } + } else { + // Check box + if (menuItem->icon.isNull()) { + if (checked || sunken) { + QImage image(qt_cleanlooks_menuitem_checkbox_checked); + if (enabled && (menuItem->state & State_Selected)) { + image.setColor(1, 0x55ffffff); + image.setColor(2, 0xAAffffff); + image.setColor(3, 0xBBffffff); + image.setColor(4, 0xFFffffff); + image.setColor(5, 0x33ffffff); + } else { + image.setColor(1, 0x55000000); + image.setColor(2, 0xAA000000); + image.setColor(3, 0xBB000000); + image.setColor(4, 0xFF000000); + image.setColor(5, 0x33000000); + } + painter->drawImage(QPoint(checkRect.center().x() - image.width() / 2, + checkRect.center().y() - image.height() / 2), image); + } + } + } + } + } else { //ignore checkmark + if (menuItem->icon.isNull()) + checkcol = 0; + else + checkcol = menuItem->maxIconWidth; + } + + // Text and icon, ripped from windows style + bool dis = !(menuItem->state & State_Enabled); + bool act = menuItem->state & State_Selected; + const QStyleOption *opt = option; + const QStyleOptionMenuItem *menuitem = menuItem; + + QPainter *p = painter; + QRect vCheckRect = visualRect(opt->direction, menuitem->rect, + QRect(menuitem->rect.x(), menuitem->rect.y(), + checkcol, menuitem->rect.height())); + if (!menuItem->icon.isNull()) { + QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; + if (act && !dis) + mode = QIcon::Active; + QPixmap pixmap; + + int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize, option, widget); + QSize iconSize(smallIconSize, smallIconSize); +#ifndef QT_NO_COMBOBOX + if (const QComboBox *combo = qobject_cast(widget)) + iconSize = combo->iconSize(); +#endif // QT_NO_COMBOBOX + if (checked) + pixmap = menuItem->icon.pixmap(iconSize, mode, QIcon::On); + else + pixmap = menuItem->icon.pixmap(iconSize, mode); + + int pixw = pixmap.width(); + int pixh = pixmap.height(); + + QRect pmr(0, 0, pixw, pixh); + pmr.moveCenter(vCheckRect.center()); + painter->setPen(menuItem->palette.text().color()); + if (checkable && checked) { + QStyleOption opt = *option; + if (act) { + QColor activeColor = mergedColors(option->palette.background().color(), + option->palette.highlight().color()); + opt.palette.setBrush(QPalette::Button, activeColor); + } + opt.state |= State_Sunken; + opt.rect = vCheckRect; + proxy()->drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget); + } + painter->drawPixmap(pmr.topLeft(), pixmap); + } + if (selected) { + painter->setPen(menuItem->palette.highlightedText().color()); + } else { + painter->setPen(menuItem->palette.text().color()); + } + int x, y, w, h; + menuitem->rect.getRect(&x, &y, &w, &h); + int tab = menuitem->tabWidth; + QColor discol; + if (dis) { + discol = menuitem->palette.text().color(); + p->setPen(discol); + } + int xm = windowsItemFrame + checkcol + windowsItemHMargin; + int xpos = menuitem->rect.x() + xm; + + QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); + QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect); + QString s = menuitem->text; + if (!s.isEmpty()) { // draw text + p->save(); + int t = s.indexOf(QLatin1Char('\t')); + int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!styleHint(SH_UnderlineShortcut, menuitem, widget)) + text_flags |= Qt::TextHideMnemonic; + text_flags |= Qt::AlignLeft; + if (t >= 0) { + QRect vShortcutRect = visualRect(opt->direction, menuitem->rect, + QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom()))); + if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { + p->setPen(menuitem->palette.light().color()); + p->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, s.mid(t + 1)); + p->setPen(discol); + } + p->drawText(vShortcutRect, text_flags, s.mid(t + 1)); + s = s.left(t); + } + QFont font = menuitem->font; + // font may not have any "hard" flags set. We override + // the point size so that when it is resolved against the device, this font will win. + // This is mainly to handle cases where someone sets the font on the window + // and then the combo inherits it and passes it onward. At that point the resolve mask + // is very, very weak. This makes it stonger. + font.setPointSizeF(QFontInfo(menuItem->font).pointSizeF()); + + if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) + font.setBold(true); + + p->setFont(font); + if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { + p->setPen(menuitem->palette.light().color()); + p->drawText(vTextRect.adjusted(1, 1, 1, 1), text_flags, s.left(t)); + p->setPen(discol); + } + p->drawText(vTextRect, text_flags, s.left(t)); + p->restore(); + } + + // Arrow + if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow + int dim = (menuItem->rect.height() - 4) / 2; + PrimitiveElement arrow; + arrow = QApplication::isRightToLeft() ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; + int xpos = menuItem->rect.left() + menuItem->rect.width() - 3 - dim; + QRect vSubMenuRect = visualRect(option->direction, menuItem->rect, + QRect(xpos, menuItem->rect.top() + menuItem->rect.height() / 2 - dim / 2, dim, dim)); + QStyleOptionMenuItem newMI = *menuItem; + newMI.rect = vSubMenuRect; + newMI.state = !enabled ? State_None : State_Enabled; + if (selected) + newMI.palette.setColor(QPalette::ButtonText, + newMI.palette.highlightedText().color()); + proxy()->drawPrimitive(arrow, &newMI, painter, widget); + } + } + painter->restore(); + break; + case CE_MenuHMargin: + case CE_MenuVMargin: + break; + case CE_MenuEmptyArea: + break; + case CE_PushButtonLabel: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + QRect ir = button->rect; + uint tf = Qt::AlignVCenter; + if (styleHint(SH_UnderlineShortcut, button, widget)) + tf |= Qt::TextShowMnemonic; + else + tf |= Qt::TextHideMnemonic; + + if (!button->icon.isNull()) { + //Center both icon and text + QPoint point; + + QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal + : QIcon::Disabled; + if (mode == QIcon::Normal && button->state & State_HasFocus) + mode = QIcon::Active; + QIcon::State state = QIcon::Off; + if (button->state & State_On) + state = QIcon::On; + + QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state); + int w = pixmap.width(); + int h = pixmap.height(); + + if (!button->text.isEmpty()) + w += button->fontMetrics.boundingRect(option->rect, tf, button->text).width() + 2; + + point = QPoint(ir.x() + ir.width() / 2 - w / 2, + ir.y() + ir.height() / 2 - h / 2); + + if (button->direction == Qt::RightToLeft) + point.rx() += pixmap.width(); + + painter->drawPixmap(visualPos(button->direction, button->rect, point), pixmap); + + if (button->direction == Qt::RightToLeft) + ir.translate(-point.x() - 2, 0); + else + ir.translate(point.x() + pixmap.width(), 0); + + // left-align text if there is + if (!button->text.isEmpty()) + tf |= Qt::AlignLeft; + + } else { + tf |= Qt::AlignHCenter; + } + + if (button->features & QStyleOptionButton::HasMenu) + ir = ir.adjusted(0, 0, -proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget), 0); + proxy()->drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled), + button->text, QPalette::ButtonText); + } + break; + case CE_MenuBarEmptyArea: + painter->save(); + { + QColor shadow = mergedColors(option->palette.background().color().darker(120), + dark.lighter(140), 60); + + QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y()*2)); + gradient.setColorAt(0, option->palette.button().color()); + gradient.setColorAt(1, option->palette.button().color().darker(110)); + painter->fillRect(rect, gradient); + +#ifndef QT_NO_MAINWINDOW + if (widget && qobject_cast(widget->parentWidget())) { + QPen oldPen = painter->pen(); + painter->setPen(QPen(shadow)); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + } +#endif // QT_NO_MAINWINDOW + } + painter->restore(); + break; +#ifndef QT_NO_TABBAR + case CE_TabBarTabShape: + painter->save(); + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { + + bool rtlHorTabs = (tab->direction == Qt::RightToLeft + && (tab->shape == QTabBar::RoundedNorth + || tab->shape == QTabBar::RoundedSouth)); + bool selected = tab->state & State_Selected; + bool lastTab = ((!rtlHorTabs && tab->position == QStyleOptionTab::End) + || (rtlHorTabs + && tab->position == QStyleOptionTab::Beginning)); + bool onlyTab = tab->position == QStyleOptionTab::OnlyOneTab; + bool leftCornerWidget = (tab->cornerWidgets & QStyleOptionTab::LeftCornerWidget); + + bool atBeginning = ((tab->position == (tab->direction == Qt::LeftToRight ? + QStyleOptionTab::Beginning : QStyleOptionTab::End)) || onlyTab); + + bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab; + bool previousSelected = + ((!rtlHorTabs + && tab->selectedPosition == QStyleOptionTab::PreviousIsSelected) + || (rtlHorTabs + && tab->selectedPosition == QStyleOptionTab::NextIsSelected)); + bool nextSelected = + ((!rtlHorTabs + && tab->selectedPosition == QStyleOptionTab::NextIsSelected) + || (rtlHorTabs + && tab->selectedPosition + == QStyleOptionTab::PreviousIsSelected)); + int tabBarAlignment = proxy()->styleHint(SH_TabBar_Alignment, tab, widget); + bool leftAligned = (!rtlHorTabs && tabBarAlignment == Qt::AlignLeft) + || (rtlHorTabs + && tabBarAlignment == Qt::AlignRight); + + bool rightAligned = (!rtlHorTabs && tabBarAlignment == Qt::AlignRight) + || (rtlHorTabs + && tabBarAlignment == Qt::AlignLeft); + + QColor light = tab->palette.light().color(); + QColor midlight = tab->palette.midlight().color(); + + QColor background = tab->palette.background().color(); + int borderThinkness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget); + if (selected) + borderThinkness /= 2; + QRect r2(option->rect); + int x1 = r2.left(); + int x2 = r2.right(); + int y1 = r2.top(); + int y2 = r2.bottom(); + + QTransform rotMatrix; + bool flip = false; + painter->setPen(shadow); + QColor activeHighlight = option->palette.color(QPalette::Normal, QPalette::Highlight); + switch (tab->shape) { + case QTabBar::RoundedNorth: + break; + case QTabBar::RoundedSouth: + rotMatrix.rotate(180); + rotMatrix.translate(0, -rect.height() + 1); + rotMatrix.scale(-1, 1); + painter->setTransform(rotMatrix, true); + break; + case QTabBar::RoundedWest: + rotMatrix.rotate(180 + 90); + rotMatrix.scale(-1, 1); + flip = true; + painter->setTransform(rotMatrix, true); + break; + case QTabBar::RoundedEast: + rotMatrix.rotate(90); + rotMatrix.translate(0, - rect.width() + 1); + flip = true; + painter->setTransform(rotMatrix, true); + break; + default: + painter->restore(); + QWindowsStyle::drawControl(element, tab, painter, widget); + return; + } + + if (flip) { + QRect tmp = rect; + rect = QRect(tmp.y(), tmp.x(), tmp.height(), tmp.width()); + int temp = x1; + x1 = y1; + y1 = temp; + temp = x2; + x2 = y2; + y2 = temp; + } + + QLinearGradient gradient(rect.topLeft(), rect.bottomLeft()); + if (option->palette.button().gradient()) { + if (selected) + gradient.setStops(option->palette.background().gradient()->stops()); + else + gradient.setStops(option->palette.background().gradient()->stops()); + } + else if (selected) { + gradient.setColorAt(0, option->palette.background().color().lighter(104)); + gradient.setColorAt(1, tabFrameColor); + painter->fillRect(rect.adjusted(0, 2, 0, -1), gradient); + } else { + y1 += 2; + gradient.setColorAt(0, option->palette.background().color()); + gradient.setColorAt(1, dark.lighter(120)); + painter->fillRect(rect.adjusted(0, 2, 0, -2), gradient); + } + + // Delete border + if (selected) { + painter->setPen(QPen(activeHighlight, 0)); + painter->drawLine(x1 + 1, y1 + 1, x2 - 1, y1 + 1); + painter->drawLine(x1 , y1 + 2, x2 , y1 + 2); + } else { + painter->setPen(dark); + painter->drawLine(x1, y2 - 1, x2 + 2, y2 - 1 ); + if (tab->shape == QTabBar::RoundedNorth || tab->shape == QTabBar::RoundedWest) { + painter->setPen(light); + painter->drawLine(x1, y2 , x2, y2 ); + } + } + // Left + if (atBeginning || selected ) { + painter->setPen(light); + painter->drawLine(x1 + 1, y1 + 2 + 1, x1 + 1, y2 - ((onlyOne || atBeginning) && selected && leftAligned ? 0 : borderThinkness) - (atBeginning && leftCornerWidget ? 1 : 0)); + painter->drawPoint(x1 + 1, y1 + 1); + painter->setPen(dark); + painter->drawLine(x1, y1 + 2, x1, y2 - ((onlyOne || atBeginning) && leftAligned ? 0 : borderThinkness) - (atBeginning && leftCornerWidget ? 1 : 0)); + } + // Top + { + int beg = x1 + (previousSelected ? 0 : 2); + int end = x2 - (nextSelected ? 0 : 2); + painter->setPen(light); + + if (!selected)painter->drawLine(beg - 2, y1 + 1, end, y1 + 1); + + if (selected) + painter->setPen(QPen(activeHighlight.darker(150), 0)); + else + painter->setPen(darkOutline); + painter->drawLine(beg, y1 , end, y1); + + if (atBeginning|| selected) { + painter->drawPoint(beg - 1, y1 + 1); + } else if (!atBeginning) { + painter->drawPoint(beg - 1, y1); + painter->drawPoint(beg - 2, y1); + if (!lastTab) { + painter->setPen(dark.lighter(130)); + painter->drawPoint(end + 1, y1); + painter->drawPoint(end + 2 , y1); + painter->drawPoint(end + 2, y1 + 1); + } + } + } + // Right + if (lastTab || selected || onlyOne || !nextSelected) { + painter->setPen(darkOutline); + painter->drawLine(x2, y1 + 2, x2, y2 - ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness)); + if (selected) + painter->setPen(QPen(activeHighlight.darker(150), 0)); + else + painter->setPen(darkOutline); + painter->drawPoint(x2 - 1, y1 + 1); + + if (selected) { + painter->setPen(background.darker(110)); + painter->drawLine(x2 - 1, y1 + 3, x2 - 1, y2 - ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness)); + } + } + } + painter->restore(); + break; + +#endif // QT_NO_TABBAR + default: + QWindowsStyle::drawControl(element,option,painter,widget); + break; + } +} + +/*! + \reimp +*/ +QPalette QCleanlooksStyle::standardPalette () const +{ + QPalette palette = QWindowsStyle::standardPalette(); + palette.setBrush(QPalette::Active, QPalette::Highlight, QColor(98, 140, 178)); + palette.setBrush(QPalette::Inactive, QPalette::Highlight, QColor(145, 141, 126)); + palette.setBrush(QPalette::Disabled, QPalette::Highlight, QColor(145, 141, 126)); + + QColor backGround(239, 235, 231); + + QColor light = backGround.lighter(150); + QColor base = Qt::white; + QColor dark = QColor(170, 156, 143).darker(110); + dark = backGround.darker(150); + QColor darkDisabled = QColor(209, 200, 191).darker(110); + + //### Find the correct disabled text color + palette.setBrush(QPalette::Disabled, QPalette::Text, QColor(190, 190, 190)); + + palette.setBrush(QPalette::Window, backGround); + palette.setBrush(QPalette::Mid, backGround.darker(130)); + palette.setBrush(QPalette::Light, light); + + palette.setBrush(QPalette::Active, QPalette::Base, base); + palette.setBrush(QPalette::Inactive, QPalette::Base, base); + palette.setBrush(QPalette::Disabled, QPalette::Base, backGround); + + palette.setBrush(QPalette::Midlight, palette.mid().color().lighter(110)); + + palette.setBrush(QPalette::All, QPalette::Dark, dark); + palette.setBrush(QPalette::Disabled, QPalette::Dark, darkDisabled); + + QColor button = backGround; + + palette.setBrush(QPalette::Button, button); + + QColor shadow = dark.darker(135); + palette.setBrush(QPalette::Shadow, shadow); + palette.setBrush(QPalette::Disabled, QPalette::Shadow, shadow.lighter(150)); + palette.setBrush(QPalette::HighlightedText, QColor(QRgb(0xffffffff))); + return palette; +} + +/*! + \reimp +*/ +void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const +{ + QColor button = option->palette.button().color(); + QColor dark; + QColor grooveColor; + QColor darkOutline; + dark.setHsv(button.hue(), + qMin(255, (int)(button.saturation()*1.9)), + qMin(255, (int)(button.value()*0.7))); + grooveColor.setHsv(button.hue(), + qMin(255, (int)(button.saturation()*2.6)), + qMin(255, (int)(button.value()*0.9))); + darkOutline.setHsv(button.hue(), + qMin(255, (int)(button.saturation()*3.0)), + qMin(255, (int)(button.value()*0.6))); + + QColor alphaCornerColor; + if (widget) { + // ### backgroundrole/foregroundrole should be part of the style option + alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), darkOutline); + } else { + alphaCornerColor = mergedColors(option->palette.background().color(), darkOutline); + } + QColor gripShadow = grooveColor.darker(110); + QColor buttonShadow = option->palette.button().color().darker(110); + + QColor gradientStartColor = option->palette.button().color().lighter(108); + QColor gradientStopColor = mergedColors(option->palette.button().color().darker(108), dark.lighter(150), 70); + + QColor highlightedGradientStartColor = option->palette.button().color(); + QColor highlightedGradientStopColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 85); + + QColor highlightedDarkInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 35); + QColor highlightedLightInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 58); + + QColor buttonShadowAlpha = option->palette.background().color().darker(105); + + QPalette palette = option->palette; + + switch (control) { +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { + QPixmap cache; + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size()); + if (!QPixmapCache::find(pixmapName, cache)) { + cache = QPixmap(spinBox->rect.size()); + cache.fill(Qt::transparent); + QRect pixmapRect(0, 0, spinBox->rect.width(), spinBox->rect.height()); + QPainter cachePainter(&cache); + + bool isEnabled = (spinBox->state & State_Enabled); + //bool focus = isEnabled && (spinBox->state & State_HasFocus); + bool hover = isEnabled && (spinBox->state & State_MouseOver); + bool sunken = (spinBox->state & State_Sunken); + bool upIsActive = (spinBox->activeSubControls == SC_SpinBoxUp); + bool downIsActive = (spinBox->activeSubControls == SC_SpinBoxDown); + + QRect rect = pixmapRect; + QStyleOptionSpinBox spinBoxCopy = *spinBox; + spinBoxCopy.rect = pixmapRect; + QRect upRect = proxy()->subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxUp, widget); + QRect downRect = proxy()->subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxDown, widget); + + int fw = spinBoxCopy.frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, &spinBoxCopy, widget) : 0; + cachePainter.fillRect(rect.adjusted(1, qMax(fw - 1, 0), -1, -fw), + option->palette.base()); + + QRect r = rect.adjusted(0, 1, 0, -1); + if (spinBox->frame) { + + QColor topShadow = darkOutline; + topShadow.setAlpha(60); + cachePainter.setPen(topShadow); + + // antialias corners + const QPoint points[8] = { + QPoint(r.right(), r.top() + 1), + QPoint(r.right() - 1, r.top() ), + QPoint(r.right(), r.bottom() - 1), + QPoint(r.right() - 1, r.bottom() ), + QPoint(r.left() + 1, r.bottom()), + QPoint(r.left(), r.bottom() - 1), + QPoint(r.left() + 1, r.top()), + QPoint(r.left(), r.top() + 1) + }; + cachePainter.drawPoints(points, 8); + + // draw frame + topShadow.setAlpha(30); + cachePainter.setPen(topShadow); + cachePainter.drawLine(QPoint(r.left() + 2, r.top() - 1), QPoint(r.right() - 2, r.top() - 1)); + + cachePainter.setPen(QPen(option->palette.background().color(), 1)); + cachePainter.drawLine(QPoint(r.left() + 2, r.top() + 1), QPoint(r.right() - 2, r.top() + 1)); + QColor highlight = Qt::white; + highlight.setAlpha(130); + cachePainter.setPen(option->palette.base().color().darker(120)); + cachePainter.drawLine(QPoint(r.left() + 1, r.top() + 1), + QPoint(r.right() - 1, r.top() + 1)); + cachePainter.drawLine(QPoint(r.left() + 1, r.top() + 1), + QPoint(r.left() + 1, r.bottom() - 1)); + cachePainter.setPen(option->palette.base().color()); + cachePainter.drawLine(QPoint(r.right() - 1, r.top() + 1), + QPoint(r.right() - 1, r.bottom() - 1)); + cachePainter.drawLine(QPoint(r.left() + 1, r.bottom() - 1), + QPoint(r.right() - 1, r.bottom() - 1)); + cachePainter.setPen(highlight); + cachePainter.drawLine(QPoint(r.left() + 3, r.bottom() + 1), + QPoint(r.right() - 3, r.bottom() + 1)); + + cachePainter.setPen(QPen(darkOutline, 1)); + + // top and bottom lines + const QLine lines[4] = { + QLine(QPoint(r.left() + 2, r.bottom()), QPoint(r.right()- 2, r.bottom())), + QLine(QPoint(r.left() + 2, r.top()), QPoint(r.right() - 2, r.top())), + QLine(QPoint(r.right(), r.top() + 2), QPoint(r.right(), r.bottom() - 2)), + QLine(QPoint(r.left(), r.top() + 2), QPoint(r.left(), r.bottom() - 2)) + }; + cachePainter.drawLines(lines, 4); + } + + // gradients + qt_cleanlooks_draw_gradient(&cachePainter, upRect, + gradientStartColor.darker(106), + gradientStopColor, TopDown, option->palette.button()); + qt_cleanlooks_draw_gradient(&cachePainter, downRect.adjusted(0, 0, 0, 1), + gradientStartColor.darker(106), + gradientStopColor, TopDown, option->palette.button()); + if (isEnabled) { + if(upIsActive) { + if (sunken) { + cachePainter.fillRect(upRect.adjusted(1, 0, 0, 0), gradientStopColor.darker(110)); + } else if (hover) { + qt_cleanlooks_draw_gradient(&cachePainter, upRect.adjusted(1, 0, 0, 0), + gradientStartColor.lighter(110), + gradientStopColor.lighter(110), TopDown, option->palette.button()); + } + } + if(downIsActive) { + if (sunken) { + cachePainter.fillRect(downRect.adjusted(1, 0, 0, 1), gradientStopColor.darker(110)); + + } else if (hover) { + qt_cleanlooks_draw_gradient(&cachePainter, downRect.adjusted(1, 0, 0, 1), + gradientStartColor.lighter(110), + gradientStopColor.lighter(110), TopDown, option->palette.button()); + } + } + } + + if (spinBox->frame) { + // rounded corners + const QPoint points[4] = { + QPoint(r.left() + 1, r.bottom() - 1), + QPoint(r.left() + 1, r.top() + 1), + QPoint(r.right() - 1, r.bottom() - 1), + QPoint(r.right() - 1, r.top() + 1) + }; + cachePainter.drawPoints(points, 4); + + if (option->state & State_HasFocus) { + QColor darkoutline = option->palette.highlight().color().darker(150); + QColor innerline = mergedColors(option->palette.highlight().color(), Qt::white); + cachePainter.setPen(QPen(innerline, 0)); + if (spinBox->direction == Qt::LeftToRight) { + cachePainter.drawRect(rect.adjusted(1, 2, -3 -downRect.width(), -3)); + cachePainter.setPen(QPen(darkoutline, 0)); + const QLine lines[4] = { + QLine(QPoint(r.left() + 2, r.bottom()), QPoint(r.right()- downRect.width() - 1, r.bottom())), + QLine(QPoint(r.left() + 2, r.top()), QPoint(r.right() - downRect.width() - 1, r.top())), + QLine(QPoint(r.right() - downRect.width() - 1, r.top() + 1), QPoint(r.right()- downRect.width() - 1, r.bottom() - 1)), + QLine(QPoint(r.left(), r.top() + 2), QPoint(r.left(), r.bottom() - 2)) + }; + cachePainter.drawLines(lines, 4); + cachePainter.drawPoint(QPoint(r.left() + 1, r.bottom() - 1)); + cachePainter.drawPoint(QPoint(r.left() + 1, r.top() + 1)); + cachePainter.drawLine(QPoint(r.left(), r.top() + 2), QPoint(r.left(), r.bottom() - 2)); + } else { + cachePainter.drawRect(rect.adjusted(downRect.width() + 2, 2, -2, -3)); + cachePainter.setPen(QPen(darkoutline, 0)); + cachePainter.drawLine(QPoint(r.left() + downRect.width(), r.bottom()), QPoint(r.right()- 2 - 1, r.bottom())); + cachePainter.drawLine(QPoint(r.left() + downRect.width(), r.top()), QPoint(r.right() - 2 - 1, r.top())); + + cachePainter.drawLine(QPoint(r.right(), r.top() + 2), QPoint(r.right(), r.bottom() - 2)); + cachePainter.drawPoint(QPoint(r.right() - 1, r.bottom() - 1)); + cachePainter.drawPoint(QPoint(r.right() - 1, r.top() + 1)); + cachePainter.drawLine(QPoint(r.left() + downRect.width() + 1, r.top()), + QPoint(r.left() + downRect.width() + 1, r.bottom())); + } + } + } + + // outline the up/down buttons + cachePainter.setPen(darkOutline); + QColor light = option->palette.light().color().lighter(); + + if (spinBox->direction == Qt::RightToLeft) { + cachePainter.drawLine(upRect.right(), upRect.top() - 1, upRect.right(), downRect.bottom() + 1); + cachePainter.setPen(light); + cachePainter.drawLine(upRect.right() - 1, upRect.top() + 3, upRect.right() - 1, downRect.bottom() ); + } else { + cachePainter.drawLine(upRect.left(), upRect.top() - 1, upRect.left(), downRect.bottom() + 1); + cachePainter.setPen(light); + cachePainter.drawLine(upRect.left() + 1, upRect.top() , upRect.left() + 1, downRect.bottom() ); + } + if (upIsActive && sunken) { + cachePainter.setPen(gradientStopColor.darker(130)); + cachePainter.drawLine(upRect.left() + 1, upRect.top(), upRect.left() + 1, upRect.bottom()); + cachePainter.drawLine(upRect.left(), upRect.top() - 1, upRect.right(), upRect.top() - 1); + } else { + cachePainter.setPen(light); + cachePainter.drawLine(upRect.topLeft() + QPoint(1, -1), upRect.topRight() + QPoint(-1, -1)); + cachePainter.setPen(darkOutline); + cachePainter.drawLine(upRect.bottomLeft(), upRect.bottomRight()); + } + if (downIsActive && sunken) { + cachePainter.setPen(gradientStopColor.darker(130)); + cachePainter.drawLine(downRect.left() + 1, downRect.top(), downRect.left() + 1, downRect.bottom() + 1); + cachePainter.drawLine(downRect.left(), downRect.top(), downRect.right(), downRect.top()); + cachePainter.setPen(gradientStopColor.darker(110)); + cachePainter.drawLine(downRect.left(), downRect.bottom() + 1, downRect.right(), downRect.bottom() + 1); + } else { + cachePainter.setPen(light); + cachePainter.drawLine(downRect.topLeft() + QPoint(2,0), downRect.topRight()); + } + + if (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) { + int centerX = upRect.center().x(); + int centerY = upRect.center().y(); + cachePainter.setPen(spinBox->palette.foreground().color()); + + // plus/minus + if (spinBox->activeSubControls == SC_SpinBoxUp && sunken) { + cachePainter.drawLine(1 + centerX - 2, 1 + centerY, 1 + centerX + 2, 1 + centerY); + cachePainter.drawLine(1 + centerX, 1 + centerY - 2, 1 + centerX, 1 + centerY + 2); + } else { + cachePainter.drawLine(centerX - 2, centerY, centerX + 2, centerY); + cachePainter.drawLine(centerX, centerY - 2, centerX, centerY + 2); + } + + centerX = downRect.center().x(); + centerY = downRect.center().y(); + if (spinBox->activeSubControls == SC_SpinBoxDown && sunken) { + cachePainter.drawLine(1 + centerX - 2, 1 + centerY, 1 + centerX + 2, 1 + centerY); + } else { + cachePainter.drawLine(centerX - 2, centerY, centerX + 2, centerY); + } + } else if (spinBox->buttonSymbols == QAbstractSpinBox::UpDownArrows){ + // arrows + QImage upArrow(qt_spinbox_button_arrow_up); + upArrow.setColor(1, spinBox->palette.foreground().color().rgba()); + + cachePainter.drawImage(upRect.center().x() - upArrow.width() / 2, + upRect.center().y() - upArrow.height() / 2, + upArrow); + + QImage downArrow(qt_spinbox_button_arrow_down); + downArrow.setColor(1, spinBox->palette.foreground().color().rgba()); + + cachePainter.drawImage(downRect.center().x() - downArrow.width() / 2, + downRect.center().y() - downArrow.height() / 2 + 1, + downArrow); + } + + QColor disabledColor = option->palette.background().color(); + disabledColor.setAlpha(150); + if (!(spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled)) + cachePainter.fillRect(upRect.adjusted(1, 0, 0, 0), disabledColor); + if (!(spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled)) { + cachePainter.fillRect(downRect.adjusted(1, 0, 0, 0), disabledColor); + } + cachePainter.end(); + QPixmapCache::insert(pixmapName, cache); + } + painter->drawPixmap(spinBox->rect.topLeft(), cache); + } + break; +#endif // QT_NO_SPINBOX + case CC_TitleBar: + painter->save(); + if (const QStyleOptionTitleBar *titleBar = qstyleoption_cast(option)) { + const int buttonMargin = 5; + bool active = (titleBar->titleBarState & State_Active); + QRect fullRect = titleBar->rect; + QPalette palette = option->palette; + QColor highlight = option->palette.highlight().color(); + + QColor titleBarFrameBorder(active ? highlight.darker(180): dark.darker(110)); + QColor titleBarHighlight(active ? highlight.lighter(120): palette.background().color().lighter(120)); + QColor textColor(active ? 0xffffff : 0xff000000); + QColor textAlphaColor(active ? 0xffffff : 0xff000000 ); + +#ifdef QT3_SUPPORT + if (widget && widget->inherits("Q3DockWindowTitleBar")) { + QStyleOptionDockWidgetV2 dockwidget; + dockwidget.QStyleOption::operator=(*option); + proxy()->drawControl(CE_DockWidgetTitle, &dockwidget, painter, widget); + } else +#endif // QT3_SUPPORT + { + // Fill title bar gradient + QColor titlebarColor = QColor(active ? highlight: palette.background().color()); + QLinearGradient gradient(option->rect.center().x(), option->rect.top(), + option->rect.center().x(), option->rect.bottom()); + + gradient.setColorAt(0, titlebarColor.lighter(114)); + gradient.setColorAt(0.5, titlebarColor.lighter(102)); + gradient.setColorAt(0.51, titlebarColor.darker(104)); + gradient.setColorAt(1, titlebarColor); + painter->fillRect(option->rect.adjusted(1, 1, -1, 0), gradient); + + // Frame and rounded corners + painter->setPen(titleBarFrameBorder); + + // top outline + painter->drawLine(fullRect.left() + 5, fullRect.top(), fullRect.right() - 5, fullRect.top()); + painter->drawLine(fullRect.left(), fullRect.top() + 4, fullRect.left(), fullRect.bottom()); + const QPoint points[5] = { + QPoint(fullRect.left() + 4, fullRect.top() + 1), + QPoint(fullRect.left() + 3, fullRect.top() + 1), + QPoint(fullRect.left() + 2, fullRect.top() + 2), + QPoint(fullRect.left() + 1, fullRect.top() + 3), + QPoint(fullRect.left() + 1, fullRect.top() + 4) + }; + painter->drawPoints(points, 5); + + painter->drawLine(fullRect.right(), fullRect.top() + 4, fullRect.right(), fullRect.bottom()); + const QPoint points2[5] = { + QPoint(fullRect.right() - 3, fullRect.top() + 1), + QPoint(fullRect.right() - 4, fullRect.top() + 1), + QPoint(fullRect.right() - 2, fullRect.top() + 2), + QPoint(fullRect.right() - 1, fullRect.top() + 3), + QPoint(fullRect.right() - 1, fullRect.top() + 4) + }; + painter->drawPoints(points2, 5); + + // draw bottomline + painter->drawLine(fullRect.right(), fullRect.bottom(), fullRect.left(), fullRect.bottom()); + + // top highlight + painter->setPen(titleBarHighlight); + painter->drawLine(fullRect.left() + 6, fullRect.top() + 1, fullRect.right() - 6, fullRect.top() + 1); + } + // draw title + QRect textRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget); + QFont font = painter->font(); + font.setBold(true); + painter->setFont(font); + painter->setPen(active? (titleBar->palette.text().color().lighter(120)) : + titleBar->palette.text().color() ); + // Note workspace also does elliding but it does not use the correct font + QString title = QFontMetrics(font).elidedText(titleBar->text, Qt::ElideRight, textRect.width() - 14); + painter->drawText(textRect.adjusted(1, 1, 1, 1), title, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter)); + painter->setPen(Qt::white); + if (active) + painter->drawText(textRect, title, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter)); + // min button + if ((titleBar->subControls & SC_TitleBarMinButton) && (titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) && + !(titleBar->titleBarState& Qt::WindowMinimized)) { + QRect minButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget); + if (minButtonRect.isValid()) { + bool hover = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_Sunken); + qt_cleanlooks_draw_mdibutton(painter, titleBar, minButtonRect, hover, sunken); + QRect minButtonIconRect = minButtonRect.adjusted(buttonMargin ,buttonMargin , -buttonMargin, -buttonMargin); + painter->setPen(textColor); + painter->drawLine(minButtonIconRect.center().x() - 2, minButtonIconRect.center().y() + 3, + minButtonIconRect.center().x() + 3, minButtonIconRect.center().y() + 3); + painter->drawLine(minButtonIconRect.center().x() - 2, minButtonIconRect.center().y() + 4, + minButtonIconRect.center().x() + 3, minButtonIconRect.center().y() + 4); + painter->setPen(textAlphaColor); + painter->drawLine(minButtonIconRect.center().x() - 3, minButtonIconRect.center().y() + 3, + minButtonIconRect.center().x() - 3, minButtonIconRect.center().y() + 4); + painter->drawLine(minButtonIconRect.center().x() + 4, minButtonIconRect.center().y() + 3, + minButtonIconRect.center().x() + 4, minButtonIconRect.center().y() + 4); + } + } + // max button + if ((titleBar->subControls & SC_TitleBarMaxButton) && (titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) && + !(titleBar->titleBarState & Qt::WindowMaximized)) { + QRect maxButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget); + if (maxButtonRect.isValid()) { + bool hover = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_Sunken); + qt_cleanlooks_draw_mdibutton(painter, titleBar, maxButtonRect, hover, sunken); + + QRect maxButtonIconRect = maxButtonRect.adjusted(buttonMargin, buttonMargin, -buttonMargin, -buttonMargin); + + painter->setPen(textColor); + painter->drawRect(maxButtonIconRect.adjusted(0, 0, -1, -1)); + painter->drawLine(maxButtonIconRect.left() + 1, maxButtonIconRect.top() + 1, + maxButtonIconRect.right() - 1, maxButtonIconRect.top() + 1); + painter->setPen(textAlphaColor); + const QPoint points[4] = { + maxButtonIconRect.topLeft(), + maxButtonIconRect.topRight(), + maxButtonIconRect.bottomLeft(), + maxButtonIconRect.bottomRight() + }; + painter->drawPoints(points, 4); + } + } + + // close button + if ((titleBar->subControls & SC_TitleBarCloseButton) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) { + QRect closeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget); + if (closeButtonRect.isValid()) { + bool hover = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_Sunken); + qt_cleanlooks_draw_mdibutton(painter, titleBar, closeButtonRect, hover, sunken); + QRect closeIconRect = closeButtonRect.adjusted(buttonMargin, buttonMargin, -buttonMargin, -buttonMargin); + painter->setPen(textAlphaColor); + const QLine lines[4] = { + QLine(closeIconRect.left() + 1, closeIconRect.top(), + closeIconRect.right(), closeIconRect.bottom() - 1), + QLine(closeIconRect.left(), closeIconRect.top() + 1, + closeIconRect.right() - 1, closeIconRect.bottom()), + QLine(closeIconRect.right() - 1, closeIconRect.top(), + closeIconRect.left(), closeIconRect.bottom() - 1), + QLine(closeIconRect.right(), closeIconRect.top() + 1, + closeIconRect.left() + 1, closeIconRect.bottom()) + }; + painter->drawLines(lines, 4); + const QPoint points[4] = { + closeIconRect.topLeft(), + closeIconRect.topRight(), + closeIconRect.bottomLeft(), + closeIconRect.bottomRight() + }; + painter->drawPoints(points, 4); + + painter->setPen(textColor); + painter->drawLine(closeIconRect.left() + 1, closeIconRect.top() + 1, + closeIconRect.right() - 1, closeIconRect.bottom() - 1); + painter->drawLine(closeIconRect.left() + 1, closeIconRect.bottom() - 1, + closeIconRect.right() - 1, closeIconRect.top() + 1); + } + } + + // normalize button + if ((titleBar->subControls & SC_TitleBarNormalButton) && + (((titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) && + (titleBar->titleBarState & Qt::WindowMinimized)) || + ((titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) && + (titleBar->titleBarState & Qt::WindowMaximized)))) { + QRect normalButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget); + if (normalButtonRect.isValid()) { + + bool hover = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_Sunken); + QRect normalButtonIconRect = normalButtonRect.adjusted(buttonMargin, buttonMargin, -buttonMargin, -buttonMargin); + qt_cleanlooks_draw_mdibutton(painter, titleBar, normalButtonRect, hover, sunken); + + QRect frontWindowRect = normalButtonIconRect.adjusted(0, 3, -3, 0); + painter->setPen(textColor); + painter->drawRect(frontWindowRect.adjusted(0, 0, -1, -1)); + painter->drawLine(frontWindowRect.left() + 1, frontWindowRect.top() + 1, + frontWindowRect.right() - 1, frontWindowRect.top() + 1); + painter->setPen(textAlphaColor); + const QPoint points[4] = { + frontWindowRect.topLeft(), + frontWindowRect.topRight(), + frontWindowRect.bottomLeft(), + frontWindowRect.bottomRight() + }; + painter->drawPoints(points, 4); + + QRect backWindowRect = normalButtonIconRect.adjusted(3, 0, 0, -3); + QRegion clipRegion = backWindowRect; + clipRegion -= frontWindowRect; + painter->save(); + painter->setClipRegion(clipRegion); + painter->setPen(textColor); + painter->drawRect(backWindowRect.adjusted(0, 0, -1, -1)); + painter->drawLine(backWindowRect.left() + 1, backWindowRect.top() + 1, + backWindowRect.right() - 1, backWindowRect.top() + 1); + painter->setPen(textAlphaColor); + const QPoint points2[4] = { + backWindowRect.topLeft(), + backWindowRect.topRight(), + backWindowRect.bottomLeft(), + backWindowRect.bottomRight() + }; + painter->drawPoints(points2, 4); + painter->restore(); + } + } + + // context help button + if (titleBar->subControls & SC_TitleBarContextHelpButton + && (titleBar->titleBarFlags & Qt::WindowContextHelpButtonHint)) { + QRect contextHelpButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget); + if (contextHelpButtonRect.isValid()) { + bool hover = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_Sunken); + qt_cleanlooks_draw_mdibutton(painter, titleBar, contextHelpButtonRect, hover, sunken); + + QColor blend; + QImage image(qt_titlebar_context_help); + QColor alpha = textColor; + alpha.setAlpha(128); + image.setColor(1, textColor.rgba()); + image.setColor(2, alpha.rgba()); + painter->setRenderHint(QPainter::SmoothPixmapTransform); + painter->drawImage(contextHelpButtonRect.adjusted(4, 4, -4, -4), image); + } + } + + // shade button + if (titleBar->subControls & SC_TitleBarShadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) { + QRect shadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget); + if (shadeButtonRect.isValid()) { + bool hover = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_Sunken); + qt_cleanlooks_draw_mdibutton(painter, titleBar, shadeButtonRect, hover, sunken); + QImage image(qt_scrollbar_button_arrow_up); + image.setColor(1, textColor.rgba()); + painter->drawImage(shadeButtonRect.adjusted(5, 7, -5, -7), image); + } + } + + // unshade button + if (titleBar->subControls & SC_TitleBarUnshadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) { + QRect unshadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget); + if (unshadeButtonRect.isValid()) { + bool hover = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_Sunken); + qt_cleanlooks_draw_mdibutton(painter, titleBar, unshadeButtonRect, hover, sunken); + QImage image(qt_scrollbar_button_arrow_down); + image.setColor(1, textColor.rgba()); + painter->drawImage(unshadeButtonRect.adjusted(5, 7, -5, -7), image); + } + } + + if ((titleBar->subControls & SC_TitleBarSysMenu) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) { + QRect iconRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget); + if (iconRect.isValid()) { + if (!titleBar->icon.isNull()) { + titleBar->icon.paint(painter, iconRect); + } else { + QStyleOption tool(0); + tool.palette = titleBar->palette; + QPixmap pm = standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16); + tool.rect = iconRect; + painter->save(); + proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm); + painter->restore(); + } + } + } + } + painter->restore(); + break; +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + painter->save(); + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast(option)) { + bool isEnabled = scrollBar->state & State_Enabled; + bool reverse = scrollBar->direction == Qt::RightToLeft; + bool horizontal = scrollBar->orientation == Qt::Horizontal; + bool sunken = scrollBar->state & State_Sunken; + + painter->fillRect(option->rect, option->palette.background()); + + QRect scrollBarSubLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget); + QRect scrollBarAddLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget); + QRect scrollBarSlider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget); + QRect grooveRect = proxy()->subControlRect(control, scrollBar, SC_ScrollBarGroove, widget); + + // paint groove + if (scrollBar->subControls & SC_ScrollBarGroove) { + painter->setBrush(grooveColor); + painter->setPen(Qt::NoPen); + if (horizontal) { + painter->drawRect(grooveRect); + painter->setPen(darkOutline); + painter->drawLine(grooveRect.topLeft(), grooveRect.topRight()); + painter->drawLine(grooveRect.bottomLeft(), grooveRect.bottomRight()); + } else { + painter->drawRect(grooveRect); + painter->setPen(darkOutline); + painter->drawLine(grooveRect.topLeft(), grooveRect.bottomLeft()); + painter->drawLine(grooveRect.topRight(), grooveRect.bottomRight()); + } + } + //paint slider + if (scrollBar->subControls & SC_ScrollBarSlider) { + QRect pixmapRect = scrollBarSlider; + if (horizontal) + pixmapRect.adjust(-1, 0, 0, -1); + else + pixmapRect.adjust(0, -1, -1, 0); + + if (isEnabled) { + QLinearGradient gradient(pixmapRect.center().x(), pixmapRect.top(), + pixmapRect.center().x(), pixmapRect.bottom()); + if (!horizontal) + gradient = QLinearGradient(pixmapRect.left(), pixmapRect.center().y(), + pixmapRect.right(), pixmapRect.center().y()); + + if (option->palette.button().gradient()) { + gradient.setStops(option->palette.button().gradient()->stops()); + } else { + if (sunken || (option->state & State_MouseOver && + (scrollBar->activeSubControls & SC_ScrollBarSlider))) { + gradient.setColorAt(0, gradientStartColor.lighter(110)); + gradient.setColorAt(1, gradientStopColor.lighter(110)); + } else { + gradient.setColorAt(0, gradientStartColor); + gradient.setColorAt(1, gradientStopColor); + } + } + painter->setPen(QPen(darkOutline, 0)); + painter->setBrush(gradient); + painter->drawRect(pixmapRect); + + + //calculate offsets used by highlight and shadow + int yoffset, xoffset; + if (option->state & State_Horizontal) { + xoffset = 0; + yoffset = 1; + } else { + xoffset = 1; + yoffset = 0; + } + //draw slider highlights + painter->setPen(QPen(gradientStopColor, 0)); + painter->drawLine(scrollBarSlider.left() + xoffset, + scrollBarSlider.bottom() - yoffset, + scrollBarSlider.right() - xoffset, + scrollBarSlider.bottom() - yoffset); + painter->drawLine(scrollBarSlider.right() - xoffset, + scrollBarSlider.top() + yoffset, + scrollBarSlider.right() - xoffset, + scrollBarSlider.bottom() - yoffset); + + //draw slider shadow + painter->setPen(QPen(gradientStartColor, 0)); + painter->drawLine(scrollBarSlider.left() + xoffset, + scrollBarSlider.top() + yoffset, + scrollBarSlider.right() - xoffset, + scrollBarSlider.top() + yoffset); + painter->drawLine(scrollBarSlider.left() + xoffset, + scrollBarSlider.top() + yoffset, + scrollBarSlider.left() + xoffset, + scrollBarSlider.bottom() - yoffset); + } else { + QLinearGradient gradient(pixmapRect.center().x(), pixmapRect.top(), + pixmapRect.center().x(), pixmapRect.bottom()); + if (!horizontal) { + gradient = QLinearGradient(pixmapRect.left(), pixmapRect.center().y(), + pixmapRect.right(), pixmapRect.center().y()); + } + if (sunken) { + gradient.setColorAt(0, gradientStartColor.lighter(110)); + gradient.setColorAt(1, gradientStopColor.lighter(110)); + } else { + gradient.setColorAt(0, gradientStartColor); + gradient.setColorAt(1, gradientStopColor); + } + painter->setPen(darkOutline); + painter->setBrush(gradient); + painter->drawRect(pixmapRect); + } + int gripMargin = 4; + //draw grips + if (horizontal) { + for (int i = -3; i< 6 ; i += 3) { + painter->setPen(QPen(gripShadow, 1)); + painter->drawLine( + QPoint(scrollBarSlider.center().x() + i , + scrollBarSlider.top() + gripMargin), + QPoint(scrollBarSlider.center().x() + i, + scrollBarSlider.bottom() - gripMargin)); + painter->setPen(QPen(palette.light(), 1)); + painter->drawLine( + QPoint(scrollBarSlider.center().x() + i + 1, + scrollBarSlider.top() + gripMargin ), + QPoint(scrollBarSlider.center().x() + i + 1, + scrollBarSlider.bottom() - gripMargin)); + } + } else { + for (int i = -3; i < 6 ; i += 3) { + painter->setPen(QPen(gripShadow, 1)); + painter->drawLine( + QPoint(scrollBarSlider.left() + gripMargin , + scrollBarSlider.center().y()+ i), + QPoint(scrollBarSlider.right() - gripMargin, + scrollBarSlider.center().y()+ i)); + painter->setPen(QPen(palette.light(), 1)); + painter->drawLine( + QPoint(scrollBarSlider.left() + gripMargin, + scrollBarSlider.center().y() + 1 + i), + QPoint(scrollBarSlider.right() - gripMargin, + scrollBarSlider.center().y() + 1 + i)); + } + } + } + + // The SubLine (up/left) buttons + if (scrollBar->subControls & SC_ScrollBarSubLine) { + //int scrollBarExtent = proxy()->pixelMetric(PM_ScrollBarExtent, option, widget); + QRect pixmapRect = scrollBarSubLine; + if (isEnabled ) { + QRect fillRect = pixmapRect.adjusted(1, 1, -1, -1); + // Gradients + if ((scrollBar->activeSubControls & SC_ScrollBarSubLine) && sunken) { + qt_cleanlooks_draw_gradient(painter, + QRect(fillRect), + gradientStopColor.darker(120), + gradientStopColor.darker(120), + horizontal ? TopDown : FromLeft, option->palette.button()); + } else { + qt_cleanlooks_draw_gradient(painter, + QRect(fillRect), + gradientStartColor.lighter(105), + gradientStopColor, + horizontal ? TopDown : FromLeft, option->palette.button()); + } + } + // Details + QImage subButton; + if (horizontal) { + subButton = QImage(reverse ? qt_scrollbar_button_right : qt_scrollbar_button_left); + } else { + subButton = QImage(qt_scrollbar_button_up); + } + subButton.setColor(1, alphaCornerColor.rgba()); + subButton.setColor(2, darkOutline.rgba()); + if ((scrollBar->activeSubControls & SC_ScrollBarSubLine) && sunken) { + subButton.setColor(3, gradientStopColor.darker(140).rgba()); + subButton.setColor(4, gradientStopColor.darker(120).rgba()); + } else { + subButton.setColor(3, gradientStartColor.lighter(105).rgba()); + subButton.setColor(4, gradientStopColor.rgba()); + } + subButton.setColor(5, scrollBar->palette.text().color().rgba()); + painter->drawImage(pixmapRect, subButton); + + // Arrows + PrimitiveElement arrow; + if (option->state & State_Horizontal) + arrow = option->direction == Qt::LeftToRight ? PE_IndicatorArrowLeft: PE_IndicatorArrowRight; + else + arrow = PE_IndicatorArrowUp; + QStyleOption arrowOpt = *option; + arrowOpt.rect = scrollBarSubLine.adjusted(3, 3, -2, -2); + proxy()->drawPrimitive(arrow, &arrowOpt, painter, widget); + + + // The AddLine (down/right) button + if (scrollBar->subControls & SC_ScrollBarAddLine) { + QString addLinePixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_addline"), option, QSize(16, 16)); + QRect pixmapRect = scrollBarAddLine; + if (isEnabled) { + QRect fillRect = pixmapRect.adjusted(1, 1, -1, -1); + // Gradients + if ((scrollBar->activeSubControls & SC_ScrollBarAddLine) && sunken) { + qt_cleanlooks_draw_gradient(painter, + fillRect, + gradientStopColor.darker(120), + gradientStopColor.darker(120), + horizontal ? TopDown: FromLeft, option->palette.button()); + } else { + qt_cleanlooks_draw_gradient(painter, + fillRect, + gradientStartColor.lighter(105), + gradientStopColor, + horizontal ? TopDown : FromLeft, option->palette.button()); + } + } + // Details + QImage addButton; + if (horizontal) { + addButton = QImage(reverse ? qt_scrollbar_button_left : qt_scrollbar_button_right); + } else { + addButton = QImage(qt_scrollbar_button_down); + } + addButton.setColor(1, alphaCornerColor.rgba()); + addButton.setColor(2, darkOutline.rgba()); + if ((scrollBar->activeSubControls & SC_ScrollBarAddLine) && sunken) { + addButton.setColor(3, gradientStopColor.darker(140).rgba()); + addButton.setColor(4, gradientStopColor.darker(120).rgba()); + } else { + addButton.setColor(3, gradientStartColor.lighter(105).rgba()); + addButton.setColor(4, gradientStopColor.rgba()); + } + addButton.setColor(5, scrollBar->palette.text().color().rgba()); + painter->drawImage(pixmapRect, addButton); + + PrimitiveElement arrow; + if (option->state & State_Horizontal) + arrow = option->direction == Qt::LeftToRight ? PE_IndicatorArrowRight : PE_IndicatorArrowLeft; + else + arrow = PE_IndicatorArrowDown; + + QStyleOption arrowOpt = *option; + arrowOpt.rect = scrollBarAddLine.adjusted(3, 3, -2, -2); + proxy()->drawPrimitive(arrow, &arrowOpt, painter, widget); + } + } + } + painter->restore(); + break;; +#endif // QT_NO_SCROLLBAR +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + painter->save(); + if (const QStyleOptionComboBox *comboBox = qstyleoption_cast(option)) { + bool sunken = comboBox->state & State_On; // play dead, if combobox has no items + bool isEnabled = (comboBox->state & State_Enabled); + bool focus = isEnabled && (comboBox->state & State_HasFocus); + QPixmap cache; + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("combobox"), option, comboBox->rect.size()); + if (sunken) + pixmapName += QLatin1String("-sunken"); + if (comboBox->editable) + pixmapName += QLatin1String("-editable"); + if (isEnabled) + pixmapName += QLatin1String("-enabled"); + + if (!QPixmapCache::find(pixmapName, cache)) { + cache = QPixmap(comboBox->rect.size()); + cache.fill(Qt::transparent); + QPainter cachePainter(&cache); + QRect pixmapRect(0, 0, comboBox->rect.width(), comboBox->rect.height()); + QStyleOptionComboBox comboBoxCopy = *comboBox; + comboBoxCopy.rect = pixmapRect; + + QRect rect = pixmapRect; + QRect downArrowRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy, + SC_ComboBoxArrow, widget); + QRect editRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy, + SC_ComboBoxEditField, widget); + // Draw a push button + if (comboBox->editable) { + QStyleOptionFrame buttonOption; + buttonOption.QStyleOption::operator=(*comboBox); + buttonOption.rect = rect; + buttonOption.state = comboBox->state & (State_Enabled | State_MouseOver); + + if (sunken) { + buttonOption.state |= State_Sunken; + buttonOption.state &= ~State_MouseOver; + } + + proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget); + + //remove shadow from left side of edit field when pressed: + if (comboBox->direction != Qt::RightToLeft) + cachePainter.fillRect(editRect.left() - 1, editRect.top() + 1, editRect.left(), + editRect.bottom() - 3, option->palette.base()); + + cachePainter.setPen(dark.lighter(110)); + if (!sunken) { + int borderSize = 2; + if (comboBox->direction == Qt::RightToLeft) { + cachePainter.drawLine(QPoint(downArrowRect.right() - 1, downArrowRect.top() + borderSize ), + QPoint(downArrowRect.right() - 1, downArrowRect.bottom() - borderSize)); + cachePainter.setPen(option->palette.light().color()); + cachePainter.drawLine(QPoint(downArrowRect.right(), downArrowRect.top() + borderSize), + QPoint(downArrowRect.right(), downArrowRect.bottom() - borderSize)); + } else { + cachePainter.drawLine(QPoint(downArrowRect.left() , downArrowRect.top() + borderSize), + QPoint(downArrowRect.left() , downArrowRect.bottom() - borderSize)); + cachePainter.setPen(option->palette.light().color()); + cachePainter.drawLine(QPoint(downArrowRect.left() + 1, downArrowRect.top() + borderSize), + QPoint(downArrowRect.left() + 1, downArrowRect.bottom() - borderSize)); + } + } else { + if (comboBox->direction == Qt::RightToLeft) { + cachePainter.drawLine(QPoint(downArrowRect.right(), downArrowRect.top() + 2), + QPoint(downArrowRect.right(), downArrowRect.bottom() - 2)); + + } else { + cachePainter.drawLine(QPoint(downArrowRect.left(), downArrowRect.top() + 2), + QPoint(downArrowRect.left(), downArrowRect.bottom() - 2)); + } + } + } else { + QStyleOptionButton buttonOption; + buttonOption.QStyleOption::operator=(*comboBox); + buttonOption.rect = rect; + buttonOption.state = comboBox->state & (State_Enabled | State_MouseOver); + if (sunken) { + buttonOption.state |= State_Sunken; + buttonOption.state &= ~State_MouseOver; + } + proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget); + + cachePainter.setPen(buttonShadow.darker(102)); + int borderSize = 4; + + if (!sunken) { + if (comboBox->direction == Qt::RightToLeft) { + cachePainter.drawLine(QPoint(downArrowRect.right() + 1, downArrowRect.top() + borderSize), + QPoint(downArrowRect.right() + 1, downArrowRect.bottom() - borderSize)); + cachePainter.setPen(option->palette.light().color()); + cachePainter.drawLine(QPoint(downArrowRect.right(), downArrowRect.top() + borderSize), + QPoint(downArrowRect.right(), downArrowRect.bottom() - borderSize)); + } else { + cachePainter.drawLine(QPoint(downArrowRect.left() - 1, downArrowRect.top() + borderSize), + QPoint(downArrowRect.left() - 1, downArrowRect.bottom() - borderSize)); + cachePainter.setPen(option->palette.light().color()); + cachePainter.drawLine(QPoint(downArrowRect.left() , downArrowRect.top() + borderSize), + QPoint(downArrowRect.left() , downArrowRect.bottom() - borderSize)); + } + } else { + cachePainter.setPen(dark.lighter(110)); + if (comboBox->direction == Qt::RightToLeft) { + cachePainter.drawLine(QPoint(downArrowRect.right() + 1, downArrowRect.top() + borderSize), + QPoint(downArrowRect.right() + 1, downArrowRect.bottom() - borderSize)); + + } else { + cachePainter.drawLine(QPoint(downArrowRect.left() - 1, downArrowRect.top() + borderSize), + QPoint(downArrowRect.left() - 1, downArrowRect.bottom() - borderSize)); + } + } + } + + + if (comboBox->subControls & SC_ComboBoxArrow) { + if (comboBox->editable) { + // Draw the down arrow + QImage downArrow(qt_cleanlooks_arrow_down_xpm); + downArrow.setColor(1, comboBox->palette.foreground().color().rgba()); + cachePainter.drawImage(downArrowRect.center().x() - downArrow.width() / 2, + downArrowRect.center().y() - downArrow.height() / 2 + 1, downArrow); + } else { + // Draw the up/down arrow + QImage upArrow(qt_scrollbar_button_arrow_up); + upArrow.setColor(1, comboBox->palette.foreground().color().rgba()); + QImage downArrow(qt_scrollbar_button_arrow_down); + downArrow.setColor(1, comboBox->palette.foreground().color().rgba()); + cachePainter.drawImage(downArrowRect.center().x() - downArrow.width() / 2, + downArrowRect.center().y() - upArrow.height() - 1 , upArrow); + cachePainter.drawImage(downArrowRect.center().x() - downArrow.width() / 2, + downArrowRect.center().y() + 2, downArrow); + } + } + // Draw the focus rect + if (focus && !comboBox->editable + && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) { + QStyleOptionFocusRect focus; + focus.rect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy, SC_ComboBoxEditField, widget) + .adjusted(0, 2, option->direction == Qt::RightToLeft ? 1 : -1, -2); + proxy()->drawPrimitive(PE_FrameFocusRect, &focus, &cachePainter, widget); + } + cachePainter.end(); + QPixmapCache::insert(pixmapName, cache); + } + painter->drawPixmap(comboBox->rect.topLeft(), cache); + } + painter->restore(); + break; +#endif // QT_NO_COMBOBOX +#ifndef QT_NO_GROUPBOX + case CC_GroupBox: + painter->save(); + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(option)) { + QRect textRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget); + QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxCheckBox, widget); + bool flat = groupBox->features & QStyleOptionFrameV2::Flat; + + if(!flat) { + if (groupBox->subControls & QStyle::SC_GroupBoxFrame) { + QStyleOptionFrameV2 frame; + frame.QStyleOption::operator=(*groupBox); + frame.features = groupBox->features; + frame.lineWidth = groupBox->lineWidth; + frame.midLineWidth = groupBox->midLineWidth; + frame.rect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget); + + painter->save(); + QRegion region(groupBox->rect); + bool ltr = groupBox->direction == Qt::LeftToRight; + region -= checkBoxRect.united(textRect).adjusted(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0); + if (!groupBox->text.isEmpty() || groupBox->subControls & SC_GroupBoxCheckBox) + painter->setClipRegion(region); + frame.palette.setBrush(QPalette::Dark, option->palette.mid().color().lighter(110)); + proxy()->drawPrimitive(PE_FrameGroupBox, &frame, painter); + painter->restore(); + } + } + // Draw title + if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) { + if (!groupBox->text.isEmpty()) { + QColor textColor = groupBox->textColor; + if (textColor.isValid()) + painter->setPen(textColor); + int alignment = int(groupBox->textAlignment); + if (!styleHint(QStyle::SH_UnderlineShortcut, option, widget)) + alignment |= Qt::TextHideMnemonic; + if (flat) { + QFont font = painter->font(); + font.setBold(true); + painter->setFont(font); + if (groupBox->subControls & SC_GroupBoxCheckBox) { + textRect.adjust(checkBoxRect.right() + 4, 0, checkBoxRect.right() + 4, 0); + } + } + painter->drawText(textRect, Qt::TextShowMnemonic | Qt::AlignLeft| alignment, groupBox->text); + } + } + if (groupBox->subControls & SC_GroupBoxCheckBox) { + QStyleOptionButton box; + box.QStyleOption::operator=(*groupBox); + box.rect = checkBoxRect; + proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget); + } + } + painter->restore(); + break; +#endif // QT_NO_GROUPBOX +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget); + QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget); + QRect ticks = proxy()->subControlRect(CC_Slider, option, SC_SliderTickmarks, widget); + + bool horizontal = slider->orientation == Qt::Horizontal; + bool ticksAbove = slider->tickPosition & QSlider::TicksAbove; + bool ticksBelow = slider->tickPosition & QSlider::TicksBelow; + QColor activeHighlight = option->palette.color(QPalette::Normal, QPalette::Highlight); + QPixmap cache; + + QBrush oldBrush = painter->brush(); + QPen oldPen = painter->pen(); + + QColor shadowAlpha(Qt::black); + shadowAlpha.setAlpha(10); + QColor highlightAlpha(Qt::white); + highlightAlpha.setAlpha(80); + + if ((option->subControls & SC_SliderGroove) && groove.isValid()) { + QString groovePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_groove"), option, groove.size()); + QRect pixmapRect(0, 0, groove.width(), groove.height()); + + // draw background groove + if (!QPixmapCache::find(groovePixmapName, cache)) { + cache = QPixmap(pixmapRect.size()); + cache.fill(Qt::transparent); + QPainter groovePainter(&cache); + + groovePainter.setPen(shadowAlpha); + groovePainter.drawLine(1, 0, groove.width(), 0); + groovePainter.drawLine(0, 0, 0, groove.height() - 1); + + groovePainter.setPen(highlightAlpha); + groovePainter.drawLine(1, groove.height() - 1, groove.width() - 1, groove.height() - 1); + groovePainter.drawLine(groove.width() - 1, 1, groove.width() - 1, groove.height() - 1); + QLinearGradient gradient; + if (horizontal) { + gradient.setStart(pixmapRect.center().x(), pixmapRect.top()); + gradient.setFinalStop(pixmapRect.center().x(), pixmapRect.bottom()); + } + else { + gradient.setStart(pixmapRect.left(), pixmapRect.center().y()); + gradient.setFinalStop(pixmapRect.right(), pixmapRect.center().y()); + } + groovePainter.setPen(QPen(darkOutline.darker(110), 0)); + gradient.setColorAt(0, grooveColor.darker(110));//dark.lighter(120)); + gradient.setColorAt(1, grooveColor.lighter(110));//palette.button().color().darker(115)); + groovePainter.setBrush(gradient); + groovePainter.drawRect(pixmapRect.adjusted(1, 1, -2, -2)); + groovePainter.end(); + QPixmapCache::insert(groovePixmapName, cache); + } + painter->drawPixmap(groove.topLeft(), cache); + + // draw blue groove highlight + QRect clipRect; + groovePixmapName += QLatin1String("_blue"); + if (!QPixmapCache::find(groovePixmapName, cache)) { + cache = QPixmap(pixmapRect.size()); + cache.fill(Qt::transparent); + QPainter groovePainter(&cache); + QLinearGradient gradient; + if (horizontal) { + gradient.setStart(pixmapRect.center().x(), pixmapRect.top()); + gradient.setFinalStop(pixmapRect.center().x(), pixmapRect.bottom()); + } + else { + gradient.setStart(pixmapRect.left(), pixmapRect.center().y()); + gradient.setFinalStop(pixmapRect.right(), pixmapRect.center().y()); + } + groovePainter.setPen(QPen(activeHighlight.darker(150), 0)); + gradient.setColorAt(0, activeHighlight.darker(120)); + gradient.setColorAt(1, activeHighlight.lighter(160)); + groovePainter.setBrush(gradient); + groovePainter.drawRect(pixmapRect.adjusted(1, 1, -2, -2)); + groovePainter.end(); + QPixmapCache::insert(groovePixmapName, cache); + } + if (horizontal) { + if (slider->upsideDown) + clipRect = QRect(handle.right(), groove.top(), groove.right() - handle.right(), groove.height()); + else + clipRect = QRect(groove.left(), groove.top(), handle.left(), groove.height()); + } else { + if (slider->upsideDown) + clipRect = QRect(groove.left(), handle.bottom(), groove.width(), groove.height() - handle.bottom()); + else + clipRect = QRect(groove.left(), groove.top(), groove.width(), handle.top() - groove.top()); + } + painter->save(); + painter->setClipRect(clipRect.adjusted(0, 0, 1, 1)); + painter->drawPixmap(groove.topLeft(), cache); + painter->restore(); + } + + // draw handle + if ((option->subControls & SC_SliderHandle) ) { + QString handlePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_handle"), option, handle.size()); + if (!QPixmapCache::find(handlePixmapName, cache)) { + cache = QPixmap(handle.size()); + cache.fill(Qt::transparent); + QRect pixmapRect(0, 0, handle.width(), handle.height()); + QPainter handlePainter(&cache); + + QColor highlightedGradientStartColor = option->palette.button().color(); + QColor highlightedGradientStopColor = option->palette.light().color(); + QColor gradientStartColor = mergedColors(option->palette.button().color().lighter(155), + dark.lighter(155), 50); + QColor gradientStopColor = gradientStartColor.darker(108); + QRect gradRect = pixmapRect.adjusted(2, 2, -2, -2); + + QColor gradientBgStartColor = gradientStartColor; + QColor gradientBgStopColor = gradientStopColor; + + QColor outline = option->state & State_Enabled ? dark : dark.lighter(130); + if (option->state & State_Enabled && option->activeSubControls & SC_SliderHandle) { + gradientBgStartColor = option->palette.highlight().color().lighter(180); + gradientBgStopColor = option->palette.highlight().color().lighter(110); + outline = option->palette.highlight().color().darker(130); + } + + // gradient fill + QRect innerBorder = gradRect; + QRect r = pixmapRect.adjusted(1, 1, -1, -1); + + qt_cleanlooks_draw_gradient(&handlePainter, gradRect, + gradientBgStartColor, + gradientBgStopColor, + horizontal ? TopDown : FromLeft, option->palette.button()); + + handlePainter.setPen(QPen(outline.darker(110), 1)); + handlePainter.drawLine(QPoint(r.left(), r.top() + 3), QPoint(r.left(), r.bottom() - 3)); + handlePainter.drawLine(QPoint(r.right(), r.top() + 3), QPoint(r.right(), r.bottom() - 3)); + handlePainter.drawLine(QPoint(r.left() + 3, r.bottom()), QPoint(r.right() - 3, r.bottom())); + + handlePainter.save(); + handlePainter.setRenderHint(QPainter::Antialiasing); + handlePainter.translate(0.5, 0.5); + const QLine lines[4] = { + QLine(QPoint(r.left(), r.bottom() - 2), QPoint(r.left() + 2, r.bottom())), + QLine(QPoint(r.left(), r.top() + 2), QPoint(r.left() + 2, r.top())), + QLine(QPoint(r.right(), r.bottom() - 2), QPoint(r.right() - 2, r.bottom())), + QLine(QPoint(r.right(), r.top() + 2), QPoint(r.right() - 2, r.top())) + }; + handlePainter.drawLines(lines, 4); + handlePainter.restore();; + handlePainter.setPen(QPen(outline.darker(130), 1)); + handlePainter.drawLine(QPoint(r.left() + 3, r.top()), QPoint(r.right() - 3, r.top())); + QColor cornerAlpha = outline.darker(120); + cornerAlpha.setAlpha(80); + + handlePainter.setPen(cornerAlpha); + if (horizontal) { + handlePainter.drawLine(QPoint(r.left() + 6, r.top()), QPoint(r.left() + 6, r.bottom())); + handlePainter.drawLine(QPoint(r.right() - 6, r.top()), QPoint(r.right() - 6, r.bottom())); + } else { + handlePainter.drawLine(QPoint(r.left(), r.top() + 6), QPoint(r.right(), r.top() + 6)); + handlePainter.drawLine(QPoint(r.left(), r.bottom() - 6), QPoint(r.right(), r.bottom() - 6)); + } + + //handle shadow + handlePainter.setPen(shadowAlpha); + handlePainter.drawLine(QPoint(r.left() + 2, r.bottom() + 1), QPoint(r.right() - 2, r.bottom() + 1)); + handlePainter.drawLine(QPoint(r.right() + 1, r.bottom() - 3), QPoint(r.right() + 1, r.top() + 4)); + handlePainter.drawLine(QPoint(r.right() - 1, r.bottom()), QPoint(r.right() + 1, r.bottom() - 2)); + + qt_cleanlooks_draw_gradient(&handlePainter, horizontal ? + gradRect.adjusted(6, 0, -6, 0) : gradRect.adjusted(0, 6, 0, -6), + gradientStartColor, + gradientStopColor.darker(106), + horizontal ? TopDown : FromLeft, + option->palette.button()); + + //draw grips + for (int i = -3; i< 6 ; i += 3) { + for (int j = -3; j< 6 ; j += 3) { + handlePainter.fillRect(r.center().x() + i, r.center().y() + j, 2, 2, highlightAlpha); + handlePainter.setPen(gripShadow); + handlePainter.drawPoint(r.center().x() + i, r.center().y() + j ); + } + } + handlePainter.end(); + QPixmapCache::insert(handlePixmapName, cache); + } + + painter->drawPixmap(handle.topLeft(), cache); + + if (slider->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*slider); + fropt.rect = slider->rect; + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + } + if (option->subControls & SC_SliderTickmarks) { + painter->setPen(darkOutline); + int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget); + int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget); + int interval = slider->tickInterval; + if (interval <= 0) { + interval = slider->singleStep; + if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval, + available) + - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, + 0, available) < 3) + interval = slider->pageStep; + } + if (interval <= 0) + interval = 1; + + int v = slider->minimum; + int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); + while (v <= slider->maximum + 1) { + if (v == slider->maximum + 1 && interval == 1) + break; + const int v_ = qMin(v, slider->maximum); + int pos = sliderPositionFromValue(slider->minimum, slider->maximum, + v_, (horizontal + ? slider->rect.width() + : slider->rect.height()) - len, + slider->upsideDown) + len / 2; + int extra = 2 - ((v_ == slider->minimum || v_ == slider->maximum) ? 1 : 0); + + if (horizontal) { + if (ticksAbove) { + painter->drawLine(pos, slider->rect.top() + extra, + pos, slider->rect.top() + tickSize); + } + if (ticksBelow) { + painter->drawLine(pos, slider->rect.bottom() - extra, + pos, slider->rect.bottom() - tickSize); + } + } else { + if (ticksAbove) { + painter->drawLine(slider->rect.left() + extra, pos, + slider->rect.left() + tickSize, pos); + } + if (ticksBelow) { + painter->drawLine(slider->rect.right() - extra, pos, + slider->rect.right() - tickSize, pos); + } + } + // in the case where maximum is max int + int nextInterval = v + interval; + if (nextInterval < v) + break; + v = nextInterval; + } + } + painter->setBrush(oldBrush); + painter->setPen(oldPen); + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_DIAL + case CC_Dial: + if (const QStyleOptionSlider *dial = qstyleoption_cast(option)) + QStyleHelper::drawDial(dial, painter); + break; +#endif // QT_NO_DIAL + default: + QWindowsStyle::drawComplexControl(control, option, painter, widget); + break; + } +} + +/*! + \reimp +*/ +int QCleanlooksStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const +{ + int ret = -1; + switch (metric) { + case PM_ToolTipLabelFrameWidth: + ret = 2; + break; + case PM_ButtonDefaultIndicator: + ret = 0; + break; + case PM_ButtonShiftHorizontal: + case PM_ButtonShiftVertical: + ret = 0; + break; + case PM_MessageBoxIconSize: + ret = 48; + break; + case PM_ListViewIconSize: + ret = 24; + break; + case PM_DialogButtonsSeparator: + case PM_SplitterWidth: + ret = 6; + break; + case PM_ScrollBarSliderMin: + ret = 26; + break; + case PM_MenuPanelWidth: //menu framewidth + ret = 2; + break; + case PM_TitleBarHeight: + ret = 24; + break; + case PM_ScrollBarExtent: + ret = 15; + break; + case PM_SliderThickness: + ret = 15; + break; + case PM_SliderLength: + ret = 27; + break; + case PM_DockWidgetTitleMargin: + ret = 1; + break; + case PM_MenuBarVMargin: + ret = 1; + break; + case PM_DefaultFrameWidth: + ret = 2; + break; + case PM_SpinBoxFrameWidth: + ret = 3; + break; + case PM_MenuBarItemSpacing: + ret = 6; + break; + case PM_MenuBarHMargin: + ret = 0; + break; + case PM_ToolBarHandleExtent: + ret = 9; + break; + case PM_ToolBarItemSpacing: + ret = 2; + break; + case PM_ToolBarFrameWidth: + ret = 0; + break; + case PM_ToolBarItemMargin: + ret = 1; + break; + case PM_SmallIconSize: + ret = 16; + break; + case PM_ButtonIconSize: + ret = 24; + break; + case PM_MenuVMargin: + case PM_MenuHMargin: + ret = 0; + break; + case PM_DockWidgetTitleBarButtonMargin: + ret = 4; + break; + case PM_MaximumDragDistance: + return -1; + case PM_TabCloseIndicatorWidth: + case PM_TabCloseIndicatorHeight: + return 20; + default: + break; + } + + return ret != -1 ? ret : QWindowsStyle::pixelMetric(metric, option, widget); +} + +/*! + \reimp +*/ +QSize QCleanlooksStyle::sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const +{ + QSize newSize = QWindowsStyle::sizeFromContents(type, option, size, widget); + switch (type) { + case CT_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + if (!btn->text.isEmpty() && newSize.width() < 80) + newSize.setWidth(80); + if (!btn->icon.isNull() && btn->iconSize.height() > 16) + newSize -= QSize(0, 2); + newSize += QSize(0, 1); + } + if (const QPushButton *button = qobject_cast(widget)) { + if (qobject_cast(button->parentWidget())) { + if (newSize.height() < 32) + newSize.setHeight(32); + } + } + break; +#ifndef QT_NO_GROUPBOX + case CT_GroupBox: + // Since we use a bold font we have to recalculate base width + if (const QGroupBox *gb = qobject_cast(widget)) { + QFont font = gb->font(); + font.setBold(true); + QFontMetrics metrics(font); + int baseWidth = metrics.width(gb->title()) + metrics.width(QLatin1Char(' ')); + if (gb->isCheckable()) { + baseWidth += proxy()->pixelMetric(QStyle::PM_IndicatorWidth, option, widget); + baseWidth += proxy()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, option, widget); + } + newSize.setWidth(qMax(baseWidth, newSize.width())); + } + newSize += QSize(0, 1); + break; +#endif //QT_NO_GROUPBOX + case CT_RadioButton: + case CT_CheckBox: + newSize += QSize(0, 1); + break; + case CT_ToolButton: +#ifndef QT_NO_TOOLBAR + if (widget && qobject_cast(widget->parentWidget())) + newSize += QSize(4, 6); +#endif // QT_NO_TOOLBAR + break; + case CT_SpinBox: + newSize += QSize(0, -2); + break; + case CT_ComboBox: + newSize += QSize(2, 4); + break; + case CT_LineEdit: + newSize += QSize(0, 4); + break; + case CT_MenuBarItem: + newSize += QSize(0, 2); + break; + case CT_MenuItem: + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast(option)) { + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + if (!menuItem->text.isEmpty()) { + newSize.setHeight(menuItem->fontMetrics.height()); + } + } +#ifndef QT_NO_COMBOBOX + else if (!menuItem->icon.isNull()) { + if (const QComboBox *combo = qobject_cast(widget)) { + newSize.setHeight(qMax(combo->iconSize().height() + 2, newSize.height())); + } + } +#endif // QT_NO_COMBOBOX + } + break; + case CT_SizeGrip: + newSize += QSize(4, 4); + break; + case CT_MdiControls: + if (const QStyleOptionComplex *styleOpt = qstyleoption_cast(option)) { + int width = 0; + if (styleOpt->subControls & SC_MdiMinButton) + width += 19 + 1; + if (styleOpt->subControls & SC_MdiNormalButton) + width += 19 + 1; + if (styleOpt->subControls & SC_MdiCloseButton) + width += 19 + 1; + newSize = QSize(width, 19); + } else { + newSize = QSize(60, 19); + } + break; + default: + break; + } + return newSize; +} + +/*! + \reimp +*/ +void QCleanlooksStyle::polish(QApplication *app) +{ + QWindowsStyle::polish(app); +} + +/*! + \reimp +*/ +void QCleanlooksStyle::polish(QWidget *widget) +{ + QWindowsStyle::polish(widget); + if (qobject_cast(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast(widget) +#endif +#ifndef QT_NO_PROGRESSBAR + || qobject_cast(widget) +#endif +#ifndef QT_NO_SCROLLBAR + || qobject_cast(widget) +#endif +#ifndef QT_NO_SPLITTER + || qobject_cast(widget) +#endif + || qobject_cast(widget) +#ifndef QT_NO_SPINBOX + || qobject_cast(widget) +#endif + || (widget->inherits("QWorkspaceChild")) + || (widget->inherits("QDockSeparator")) + || (widget->inherits("QDockWidgetSeparator")) + ) { + widget->setAttribute(Qt::WA_Hover, true); + } +} + +/*! + \reimp +*/ +void QCleanlooksStyle::polish(QPalette &pal) +{ + QWindowsStyle::polish(pal); + //this is a workaround for some themes such as Human, where the contrast + //between text and background is too low. + QColor highlight = pal.highlight().color(); + QColor highlightText = pal.highlightedText().color(); + if (qAbs(qGray(highlight.rgb()) - qGray(highlightText.rgb())) < 150) { + if (qGray(highlightText.rgb()) < 128) + pal.setBrush(QPalette::Highlight, highlight.lighter(145)); + } +} + +/*! + \reimp +*/ +void QCleanlooksStyle::unpolish(QWidget *widget) +{ + QWindowsStyle::unpolish(widget); + if (qobject_cast(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast(widget) +#endif +#ifndef QT_NO_PROGRESSBAR + || qobject_cast(widget) +#endif +#ifndef QT_NO_SCROLLBAR + || qobject_cast(widget) +#endif +#ifndef QT_NO_SPLITTER + || qobject_cast(widget) +#endif + || qobject_cast(widget) +#ifndef QT_NO_SPINBOX + || qobject_cast(widget) +#endif + || (widget->inherits("QWorkspaceChild")) + || (widget->inherits("QDockSeparator")) + || (widget->inherits("QDockWidgetSeparator")) + ) { + widget->setAttribute(Qt::WA_Hover, false); + } +} + +/*! + \reimp +*/ +void QCleanlooksStyle::unpolish(QApplication *app) +{ + QWindowsStyle::unpolish(app); +} + +/*! + \reimp +*/ +QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, + SubControl subControl, const QWidget *widget) const +{ + QRect rect = QWindowsStyle::subControlRect(control, option, subControl, widget); + + switch (control) { +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget); + switch (subControl) { + case SC_SliderHandle: { + if (slider->orientation == Qt::Horizontal) { + rect.setHeight(proxy()->pixelMetric(PM_SliderThickness)); + rect.setWidth(proxy()->pixelMetric(PM_SliderLength)); + int centerY = slider->rect.center().y() - rect.height() / 2; + if (slider->tickPosition & QSlider::TicksAbove) + centerY += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + centerY -= tickSize; + rect.moveTop(centerY); + } else { + rect.setWidth(proxy()->pixelMetric(PM_SliderThickness)); + rect.setHeight(proxy()->pixelMetric(PM_SliderLength)); + int centerX = slider->rect.center().x() - rect.width() / 2; + if (slider->tickPosition & QSlider::TicksAbove) + centerX += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + centerX -= tickSize; + rect.moveLeft(centerX); + } + } + break; + case SC_SliderGroove: { + QPoint grooveCenter = slider->rect.center(); + if (slider->orientation == Qt::Horizontal) { + rect.setHeight(7); + if (slider->tickPosition & QSlider::TicksAbove) + grooveCenter.ry() += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + grooveCenter.ry() -= tickSize; + } else { + rect.setWidth(7); + if (slider->tickPosition & QSlider::TicksAbove) + grooveCenter.rx() += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + grooveCenter.rx() -= tickSize; + } + rect.moveCenter(grooveCenter); + break; + } + default: + break; + } + } + break; +#endif // QT_NO_SLIDER + case CC_ScrollBar: + break; +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(option)) { + QSize bs; + int center = spinbox->rect.height() / 2; + int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0; + int y = fw; + bs.setHeight(qMax(8, spinbox->rect.height()/2 - y)); + bs.setWidth(15); + int x, lx, rx; + x = spinbox->rect.width() - y - bs.width() + 2; + lx = fw; + rx = x - fw; + switch (subControl) { + case SC_SpinBoxUp: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + rect = QRect(x, fw, bs.width(), center - fw); + break; + case SC_SpinBoxDown: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + + rect = QRect(x, center, bs.width(), spinbox->rect.bottom() - center - fw + 1); + break; + case SC_SpinBoxEditField: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) { + rect = QRect(lx, fw, spinbox->rect.width() - 2*fw, spinbox->rect.height() - 2*fw); + } else { + rect = QRect(lx, fw, rx - qMax(fw - 1, 0), spinbox->rect.height() - 2*fw); + } + break; + case SC_SpinBoxFrame: + rect = spinbox->rect; + default: + break; + } + rect = visualRect(spinbox->direction, spinbox->rect, rect); + } + break; +#endif // Qt_NO_SPINBOX +#ifndef QT_NO_GROUPBOX + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(option)) { + int topMargin = 0; + int topHeight = 0; + int verticalAlignment = proxy()->styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget); + bool flat = groupBox->features & QStyleOptionFrameV2::Flat; + if (!groupBox->text.isEmpty()) { + topHeight = groupBox->fontMetrics.height(); + if (verticalAlignment & Qt::AlignVCenter) + topMargin = topHeight / 2; + else if (verticalAlignment & Qt::AlignTop) + topMargin = topHeight; + } + QRect frameRect = groupBox->rect; + frameRect.setTop(topMargin); + if (subControl == SC_GroupBoxFrame) { + return rect; + } + else if (subControl == SC_GroupBoxContents) { + if( flat ) { + int margin = 0; + int leftMarginExtension = 16; + rect = frameRect.adjusted(leftMarginExtension + margin, margin + topHeight, -margin, -margin); + } + break; + } + if(flat) { + if (const QGroupBox *groupBoxWidget = qobject_cast(widget)) { + //Prepare metrics for a bold font + QFont font = widget->font(); + font.setBold(true); + QFontMetrics fontMetrics(font); + + QSize textRect = fontMetrics.boundingRect(groupBoxWidget->title()).size() + QSize(2, 2); + if (subControl == SC_GroupBoxCheckBox) { + int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget); + int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget); + rect.setWidth(indicatorWidth); + rect.setHeight(indicatorHeight); + rect.moveTop((fontMetrics.height() - indicatorHeight) / 2 + 2); + } else if (subControl == SC_GroupBoxLabel) { + rect.setSize(textRect); + } + } + } + } + return rect; +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + switch (subControl) { + case SC_ComboBoxArrow: + rect = visualRect(option->direction, option->rect, rect); + rect.setRect(rect.right() - 18, rect.top() - 2, + 19, rect.height() + 4); + rect = visualRect(option->direction, option->rect, rect); + break; + case SC_ComboBoxEditField: { + int frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth); + rect = visualRect(option->direction, option->rect, rect); + rect.setRect(option->rect.left() + frameWidth, option->rect.top() + frameWidth, + option->rect.width() - 19 - 2 * frameWidth, + option->rect.height() - 2 * frameWidth); + if (const QStyleOptionComboBox *box = qstyleoption_cast(option)) { + if (!box->editable) { + rect.adjust(2, 0, 0, 0); + if (box->state & (State_Sunken | State_On)) + rect.translate(1, 1); + } + } + rect = visualRect(option->direction, option->rect, rect); + break; + } + default: + break; + } + break; +#endif // QT_NO_COMBOBOX +#endif //QT_NO_GROUPBOX + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(option)) { + SubControl sc = subControl; + QRect &ret = rect; + const int indent = 3; + const int controlTopMargin = 3; + const int controlBottomMargin = 3; + const int controlWidthMargin = 2; + const int controlHeight = tb->rect.height() - controlTopMargin - controlBottomMargin ; + const int delta = controlHeight + controlWidthMargin; + int offset = 0; + + bool isMinimized = tb->titleBarState & Qt::WindowMinimized; + bool isMaximized = tb->titleBarState & Qt::WindowMaximized; + + switch (sc) { + case SC_TitleBarLabel: + if (tb->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) { + ret = tb->rect; + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + ret.adjust(delta, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowShadeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) + ret.adjust(0, 0, -delta, 0); + } + break; + case SC_TitleBarContextHelpButton: + if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) + offset += delta; + case SC_TitleBarMinButton: + if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarMinButton) + break; + case SC_TitleBarNormalButton: + if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarNormalButton) + break; + case SC_TitleBarMaxButton: + if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarMaxButton) + break; + case SC_TitleBarShadeButton: + if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarShadeButton) + break; + case SC_TitleBarUnshadeButton: + if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarUnshadeButton) + break; + case SC_TitleBarCloseButton: + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + offset += delta; + else if (sc == SC_TitleBarCloseButton) + break; + ret.setRect(tb->rect.right() - indent - offset, tb->rect.top() + controlTopMargin, + controlHeight, controlHeight); + break; + case SC_TitleBarSysMenu: + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) { + ret.setRect(tb->rect.left() + controlWidthMargin + indent, tb->rect.top() + controlTopMargin, + controlHeight, controlHeight); + } + break; + default: + break; + } + ret = visualRect(tb->direction, tb->rect, ret); + } + break; + default: + break; + } + + return rect; +} + + +/*! + \reimp +*/ +QRect QCleanlooksStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const +{ + return QWindowsStyle::itemPixmapRect(r, flags, pixmap); +} + +/*! + \reimp +*/ +void QCleanlooksStyle::drawItemPixmap(QPainter *painter, const QRect &rect, + int alignment, const QPixmap &pixmap) const +{ + QWindowsStyle::drawItemPixmap(painter, rect, alignment, pixmap); +} + +/*! + \reimp +*/ +QStyle::SubControl QCleanlooksStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *w) const +{ + return QWindowsStyle::hitTestComplexControl(cc, opt, pt, w); +} + +/*! + \reimp +*/ +QPixmap QCleanlooksStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *opt) const +{ + return QWindowsStyle::generatedIconPixmap(iconMode, pixmap, opt); +} + +/*! + \reimp +*/ +int QCleanlooksStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, + QStyleHintReturn *returnData) const +{ + int ret = 0; + switch (hint) { + case SH_ScrollBar_MiddleClickAbsolutePosition: + ret = true; + break; + case SH_EtchDisabledText: + ret = 1; + break; + case SH_Menu_AllowActiveAndDisabled: + ret = false; + break; + case SH_MainWindow_SpaceBelowMenuBar: + ret = 0; + break; + case SH_MenuBar_MouseTracking: + ret = 1; + break; + case SH_TitleBar_AutoRaise: + ret = 1; + break; + case SH_TitleBar_NoBorder: + ret = 1; + break; + case SH_ItemView_ShowDecorationSelected: + ret = true; + break; + case SH_Table_GridLineColor: + if (option) { + ret = option->palette.background().color().darker(120).rgb(); + break; + } + case SH_ComboBox_Popup: +#ifdef QT3_SUPPORT + if (widget && widget->inherits("Q3ComboBox")) + return 0; +#endif + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) + ret = !cmb->editable; + else + ret = 0; + break; + case SH_WindowFrame_Mask: + ret = 1; + if (QStyleHintReturnMask *mask = qstyleoption_cast(returnData)) { + //left rounded corner + mask->region = option->rect; + mask->region -= QRect(option->rect.left(), option->rect.top(), 5, 1); + mask->region -= QRect(option->rect.left(), option->rect.top() + 1, 3, 1); + mask->region -= QRect(option->rect.left(), option->rect.top() + 2, 2, 1); + mask->region -= QRect(option->rect.left(), option->rect.top() + 3, 1, 2); + + //right rounded corner + mask->region -= QRect(option->rect.right() - 4, option->rect.top(), 5, 1); + mask->region -= QRect(option->rect.right() - 2, option->rect.top() + 1, 3, 1); + mask->region -= QRect(option->rect.right() - 1, option->rect.top() + 2, 2, 1); + mask->region -= QRect(option->rect.right() , option->rect.top() + 3, 1, 2); + } + break; + case SH_MessageBox_TextInteractionFlags: + ret = Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse; + break; + case SH_DialogButtonBox_ButtonsHaveIcons: + ret = true; + break; + case SH_MessageBox_CenterButtons: + ret = false; + break; +#ifndef QT_NO_WIZARD + case SH_WizardStyle: + ret = QWizard::ClassicStyle; + break; +#endif + case SH_ItemView_ArrowKeysNavigateIntoChildren: + ret = false; + break; + case SH_Menu_SubMenuPopupDelay: + ret = 225; // default from GtkMenu + break; + default: + ret = QWindowsStyle::styleHint(hint, option, widget, returnData); + break; + } + return ret; +} + +/*! \reimp */ +QRect QCleanlooksStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *w) const +{ + QRect r = QWindowsStyle::subElementRect(sr, opt, w); + switch (sr) { + case SE_PushButtonFocusRect: + r.adjust(0, 1, 0, -1); + break; + case SE_DockWidgetTitleBarText: { + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(opt); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + if (verticalTitleBar) { + r.adjust(0, 0, 0, -4); + } else { + if (opt->direction == Qt::LeftToRight) + r.adjust(4, 0, 0, 0); + else + r.adjust(0, 0, -4, 0); + } + + break; + } + case SE_ProgressBarContents: + r = subElementRect(SE_ProgressBarGroove, opt, w); + break; + default: + break; + } + return r; +} + +/*! + \internal +*/ +QIcon QCleanlooksStyle::standardIconImplementation(StandardPixmap standardIcon, + const QStyleOption *option, + const QWidget *widget) const +{ + return QWindowsStyle::standardIconImplementation(standardIcon, option, widget); +} + +/*! + \reimp + */ +QPixmap QCleanlooksStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget) const +{ + QPixmap pixmap; + +#ifndef QT_NO_IMAGEFORMAT_XPM + switch (standardPixmap) { + case SP_TitleBarNormalButton: + return QPixmap((const char **)dock_widget_restore_xpm); + case SP_TitleBarMinButton: + return QPixmap((const char **)workspace_minimize); + case SP_TitleBarCloseButton: + case SP_DockWidgetCloseButton: + return QPixmap((const char **)dock_widget_close_xpm); + + default: + break; + } +#endif //QT_NO_IMAGEFORMAT_XPM + + return QWindowsStyle::standardPixmap(standardPixmap, opt, widget); +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_CLEANLOOKS || QT_PLUGIN diff --git a/src/widgets/styles/qcleanlooksstyle.h b/src/widgets/styles/qcleanlooksstyle.h new file mode 100644 index 0000000000..9ffa5789c0 --- /dev/null +++ b/src/widgets/styles/qcleanlooksstyle.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLEANLOOKSSTYLE_H +#define QCLEANLOOKSSTYLE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_STYLE_CLEANLOOKS) + +class QCleanlooksStylePrivate; +class Q_GUI_EXPORT QCleanlooksStyle : public QWindowsStyle +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QCleanlooksStyle) + +public: + QCleanlooksStyle(); + ~QCleanlooksStyle(); + + QPalette standardPalette () const; + void drawPrimitive(PrimitiveElement elem, + const QStyleOption *option, + QPainter *painter, const QWidget *widget = 0) const; + void drawControl(ControlElement ce, const QStyleOption *option, QPainter *painter, + const QWidget *widget) const; + int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const; + void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const; + QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const; + QSize sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const; + SubControl hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *w = 0) const; + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, + SubControl sc, const QWidget *widget) const; + QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *opt) const; + int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, + QStyleHintReturn *returnData = 0) const; + QRect itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const; + QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget = 0) const; + void drawItemPixmap(QPainter *painter, const QRect &rect, + int alignment, const QPixmap &pixmap) const; + void drawItemText(QPainter *painter, const QRect &rect, + int flags, const QPalette &pal, bool enabled, + const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const; + void polish(QWidget *widget); + void polish(QApplication *app); + void polish(QPalette &pal); + void unpolish(QWidget *widget); + void unpolish(QApplication *app); + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget = 0) const; + +protected: + QCleanlooksStyle(QCleanlooksStylePrivate &dd); + +}; + +#endif // QT_NO_STYLE_CLEANLOOKS + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QCLEANLOOKSSTYLE_H diff --git a/src/widgets/styles/qcleanlooksstyle_p.h b/src/widgets/styles/qcleanlooksstyle_p.h new file mode 100644 index 0000000000..52cc282578 --- /dev/null +++ b/src/widgets/styles/qcleanlooksstyle_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLEANLOOKSSTYLE_P_H +#define QCLEANLOOKSSTYLE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qwindowsstyle.h" +#include "qwindowsstyle_p.h" + +#ifndef QT_NO_STYLE_CLEANLOOKS + +QT_BEGIN_NAMESPACE + +class QCleanlooksStylePrivate : public QWindowsStylePrivate +{ + Q_DECLARE_PUBLIC(QCleanlooksStyle) +public: + QCleanlooksStylePrivate() + : QWindowsStylePrivate() { + animationFps = 24; + } + + ~QCleanlooksStylePrivate() { + } +}; + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_CLEANLOOKS + +#endif //QCLEANLOOKSSTYLE_P_H diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp new file mode 100644 index 0000000000..8f99d6ad26 --- /dev/null +++ b/src/widgets/styles/qcommonstyle.cpp @@ -0,0 +1,6085 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcommonstyle.h" +#include "qcommonstyle_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef QT_NO_ITEMVIEWS +# include "private/qtextengine_p.h" +#endif + +#ifdef Q_WS_X11 +# include +#elif defined(Q_WS_MAC) +# include +#endif + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QCommonStyle + \brief The QCommonStyle class encapsulates the common Look and Feel of a GUI. + + \ingroup appearance + + This abstract class implements some of the widget's look and feel + that is common to all GUI styles provided and shipped as part of + Qt. + + Since QCommonStyle inherits QStyle, all of its functions are fully documented + in the QStyle documentation. + \omit + , although the + extra functions that QCommonStyle provides, e.g. + drawComplexControl(), drawControl(), drawPrimitive(), + hitTestComplexControl(), subControlRect(), sizeFromContents(), and + subElementRect() are documented here. + \endomit + + \sa QStyle, QMotifStyle, QWindowsStyle +*/ + +/*! + Constructs a QCommonStyle. +*/ +QCommonStyle::QCommonStyle() + : QStyle(*new QCommonStylePrivate) +{ } + +/*! \internal +*/ +QCommonStyle::QCommonStyle(QCommonStylePrivate &dd) + : QStyle(dd) +{ } + +/*! + Destroys the style. +*/ +QCommonStyle::~QCommonStyle() +{ } + + +/*! + \reimp +*/ +void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *widget) const +{ + Q_D(const QCommonStyle); + switch (pe) { + case PE_FrameButtonBevel: + case PE_FrameButtonTool: + qDrawShadeRect(p, opt->rect, opt->palette, + opt->state & (State_Sunken | State_On), 1, 0); + break; + case PE_PanelButtonCommand: + case PE_PanelButtonBevel: + case PE_PanelButtonTool: + case PE_IndicatorButtonDropDown: + qDrawShadePanel(p, opt->rect, opt->palette, + opt->state & (State_Sunken | State_On), 1, + &opt->palette.brush(QPalette::Button)); + break; + case PE_IndicatorViewItemCheck: + proxy()->drawPrimitive(PE_IndicatorCheckBox, opt, p, widget); + break; + case PE_IndicatorCheckBox: + if (opt->state & State_NoChange) { + p->setPen(opt->palette.foreground().color()); + p->fillRect(opt->rect, opt->palette.brush(QPalette::Button)); + p->drawRect(opt->rect); + p->drawLine(opt->rect.topLeft(), opt->rect.bottomRight()); + } else { + qDrawShadePanel(p, opt->rect.x(), opt->rect.y(), opt->rect.width(), opt->rect.height(), + opt->palette, opt->state & (State_Sunken | State_On), 1, + &opt->palette.brush(QPalette::Button)); + } + break; + case PE_IndicatorRadioButton: { + QRect ir = opt->rect; + p->setPen(opt->palette.dark().color()); + p->drawArc(opt->rect, 0, 5760); + if (opt->state & (State_Sunken | State_On)) { + ir.adjust(2, 2, -2, -2); + p->setBrush(opt->palette.foreground()); + p->drawEllipse(ir); + } + break; } + case PE_FrameFocusRect: + if (const QStyleOptionFocusRect *fropt = qstyleoption_cast(opt)) { + QColor bg = fropt->backgroundColor; + QPen oldPen = p->pen(); + if (bg.isValid()) { + int h, s, v; + bg.getHsv(&h, &s, &v); + if (v >= 128) + p->setPen(Qt::black); + else + p->setPen(Qt::white); + } else { + p->setPen(opt->palette.foreground().color()); + } + QRect focusRect = opt->rect.adjusted(1, 1, -1, -1); + p->drawRect(focusRect.adjusted(0, 0, -1, -1)); //draw pen inclusive + p->setPen(oldPen); + } + break; + case PE_IndicatorMenuCheckMark: { + const int markW = opt->rect.width() > 7 ? 7 : opt->rect.width(); + const int markH = markW; + int posX = opt->rect.x() + (opt->rect.width() - markW)/2 + 1; + int posY = opt->rect.y() + (opt->rect.height() - markH)/2; + + QVector a; + a.reserve(markH); + + int i, xx, yy; + xx = posX; + yy = 3 + posY; + for (i = 0; i < markW/2; ++i) { + a << QLineF(xx, yy, xx, yy + 2); + ++xx; + ++yy; + } + yy -= 2; + for (; i < markH; ++i) { + a << QLineF(xx, yy, xx, yy + 2); + ++xx; + --yy; + } + if (!(opt->state & State_Enabled) && !(opt->state & State_On)) { + int pnt; + p->setPen(opt->palette.highlightedText().color()); + QPoint offset(1, 1); + for (pnt = 0; pnt < a.size(); ++pnt) + a[pnt].translate(offset.x(), offset.y()); + p->drawLines(a); + for (pnt = 0; pnt < a.size(); ++pnt) + a[pnt].translate(offset.x(), offset.y()); + } + p->setPen(opt->palette.text().color()); + p->drawLines(a); + break; } + case PE_Frame: + case PE_FrameMenu: + if (const QStyleOptionFrame *frame = qstyleoption_cast(opt)) { + if (pe == PE_FrameMenu || (frame->state & State_Sunken) || (frame->state & State_Raised)) { + qDrawShadePanel(p, frame->rect, frame->palette, frame->state & State_Sunken, + frame->lineWidth); + } else { + qDrawPlainRect(p, frame->rect, frame->palette.foreground().color(), frame->lineWidth); + } + } + break; +#ifndef QT_NO_TOOLBAR + case PE_PanelMenuBar: + if (widget && qobject_cast(widget->parentWidget())) + break; + if (const QStyleOptionFrame *frame = qstyleoption_cast(opt)){ + qDrawShadePanel(p, frame->rect, frame->palette, false, frame->lineWidth, + &frame->palette.brush(QPalette::Button)); + + } + else if (const QStyleOptionToolBar *frame = qstyleoption_cast(opt)){ + qDrawShadePanel(p, frame->rect, frame->palette, false, frame->lineWidth, + &frame->palette.brush(QPalette::Button)); + } + + break; + case PE_PanelMenu: + break; + case PE_PanelToolBar: + break; +#endif // QT_NO_TOOLBAR +#ifndef QT_NO_PROGRESSBAR + case PE_IndicatorProgressChunk: + { + bool vertical = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt)) + vertical = (pb2->orientation == Qt::Vertical); + if (!vertical) { + p->fillRect(opt->rect.x(), opt->rect.y() + 3, opt->rect.width() -2, opt->rect.height() - 6, + opt->palette.brush(QPalette::Highlight)); + } else { + p->fillRect(opt->rect.x() + 2, opt->rect.y(), opt->rect.width() -6, opt->rect.height() - 2, + opt->palette.brush(QPalette::Highlight)); + } + } + break; +#endif // QT_NO_PROGRESSBAR +#ifdef QT3_SUPPORT + case PE_Q3CheckListController: +#ifndef QT_NO_IMAGEFORMAT_XPM + p->drawPixmap(opt->rect.topLeft(), QPixmap(check_list_controller_xpm)); +#endif + break; + case PE_Q3CheckListExclusiveIndicator: + if (const QStyleOptionQ3ListView *lv = qstyleoption_cast(opt)) { + if (lv->items.isEmpty()) + return; + int x = lv->rect.x(), + y = lv->rect.y(); +#define INTARRLEN(x) sizeof(x)/(sizeof(int)*2) + static const int pts1[] = { // dark lines + 1,9, 1,8, 0,7, 0,4, 1,3, 1,2, 2,1, 3,1, 4,0, 7,0, 8,1, 9,1 }; + static const int pts2[] = { // black lines + 2,8, 1,7, 1,4, 2,3, 2,2, 3,2, 4,1, 7,1, 8,2, 9,2 }; + static const int pts3[] = { // background lines + 2,9, 3,9, 4,10, 7,10, 8,9, 9,9, 9,8, 10,7, 10,4, 9,3 }; + static const int pts4[] = { // white lines + 2,10, 3,10, 4,11, 7,11, 8,10, 9,10, 10,9, 10,8, 11,7, + 11,4, 10,3, 10,2 }; + // static const int pts5[] = { // inner fill + // 4,2, 7,2, 9,4, 9,7, 7,9, 4,9, 2,7, 2,4 }; + //QPolygon a; + + if (lv->state & State_Enabled) + p->setPen(lv->palette.text().color()); + else + p->setPen(QPen(lv->viewportPalette.color(QPalette::Disabled, QPalette::Text))); + QPolygon a(INTARRLEN(pts1), pts1); + a.translate(x, y); + //p->setPen(pal.dark()); + p->drawPolyline(a); + a.setPoints(INTARRLEN(pts2), pts2); + a.translate(x, y); + p->drawPolyline(a); + a.setPoints(INTARRLEN(pts3), pts3); + a.translate(x, y); + // p->setPen(black); + p->drawPolyline(a); + a.setPoints(INTARRLEN(pts4), pts4); + a.translate(x, y); + // p->setPen(blue); + p->drawPolyline(a); + // a.setPoints(INTARRLEN(pts5), pts5); + // a.translate(x, y); + // QColor fillColor = isDown() ? g.background() : g.base(); + // p->setPen(fillColor); + // p->setBrush(fillColor); + // p->drawPolygon(a); + if (opt->state & State_On) { + p->setPen(Qt::NoPen); + p->setBrush(opt->palette.text()); + p->drawRect(x + 5, y + 4, 2, 4); + p->drawRect(x + 4, y + 5, 4, 2); + } +#undef INTARRLEN + } + break; + case PE_Q3CheckListIndicator: + if (const QStyleOptionQ3ListView *lv = qstyleoption_cast(opt)) { + if(lv->items.isEmpty()) + break; + QStyleOptionQ3ListViewItem item = lv->items.at(0); + int x = lv->rect.x(), + y = lv->rect.y(), + w = lv->rect.width(), + h = lv->rect.width(), + marg = lv->itemMargin; + + if (lv->state & State_Enabled) + p->setPen(QPen(lv->palette.text().color(), 2)); + else + p->setPen(QPen(lv->viewportPalette.color(QPalette::Disabled, QPalette::Text), 2)); + if (opt->state & State_Selected && !lv->rootIsDecorated + && !(item.features & QStyleOptionQ3ListViewItem::ParentControl)) { + p->fillRect(0, 0, x + marg + w + 4, item.height, + lv->palette.brush(QPalette::Highlight)); + if (item.state & State_Enabled) + p->setPen(QPen(lv->palette.highlightedText().color(), 2)); + } + + if (lv->state & State_NoChange) + p->setBrush(lv->palette.brush(QPalette::Button)); + p->drawRect(x + marg, y + 2, w - 4, h - 4); + ///////////////////// + ++x; + ++y; + if (lv->state & State_On || lv->state & State_NoChange) { + QLineF lines[7]; + int i, + xx = x + 1 + marg, + yy = y + 5; + for (i = 0; i < 3; ++i) { + lines[i] = QLineF(xx, yy, xx, yy + 2); + ++xx; + ++yy; + } + yy -= 2; + for (i = 3; i < 7; ++i) { + lines[i] = QLineF(xx, yy, xx, yy + 2); + ++xx; + --yy; + } + p->drawLines(lines, 7); + } + } + break; +#endif // QT3_SUPPORT + case PE_IndicatorBranch: { + int mid_h = opt->rect.x() + opt->rect.width() / 2; + int mid_v = opt->rect.y() + opt->rect.height() / 2; + int bef_h = mid_h; + int bef_v = mid_v; + int aft_h = mid_h; + int aft_v = mid_v; +#ifndef QT_NO_IMAGEFORMAT_XPM + static const int decoration_size = 9; + static QPixmap open(tree_branch_open_xpm); + static QPixmap closed(tree_branch_closed_xpm); + if (opt->state & State_Children) { + int delta = decoration_size / 2; + bef_h -= delta; + bef_v -= delta; + aft_h += delta; + aft_v += delta; + p->drawPixmap(bef_h, bef_v, opt->state & State_Open ? open : closed); + } +#endif // QT_NO_IMAGEFORMAT_XPM + if (opt->state & State_Item) { + if (opt->direction == Qt::RightToLeft) + p->drawLine(opt->rect.left(), mid_v, bef_h, mid_v); + else + p->drawLine(aft_h, mid_v, opt->rect.right(), mid_v); + } + if (opt->state & State_Sibling) + p->drawLine(mid_h, aft_v, mid_h, opt->rect.bottom()); + if (opt->state & (State_Open | State_Children | State_Item | State_Sibling)) + p->drawLine(mid_h, opt->rect.y(), mid_h, bef_v); + break; } +#ifdef QT3_SUPPORT + case PE_Q3Separator: + qDrawShadeLine(p, opt->rect.left(), opt->rect.top(), opt->rect.right(), opt->rect.bottom(), + opt->palette, opt->state & State_Sunken, 1, 0); + break; +#endif // QT3_SUPPORT + case PE_FrameStatusBarItem: + qDrawShadeRect(p, opt->rect, opt->palette, true, 1, 0, 0); + break; + case PE_IndicatorHeaderArrow: + if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { + QPen oldPen = p->pen(); + if (header->sortIndicator & QStyleOptionHeader::SortUp) { + QPolygon pa(3); + p->setPen(QPen(opt->palette.light(), 0)); + p->drawLine(opt->rect.x() + opt->rect.width(), opt->rect.y(), + opt->rect.x() + opt->rect.width() / 2, opt->rect.y() + opt->rect.height()); + p->setPen(QPen(opt->palette.dark(), 0)); + pa.setPoint(0, opt->rect.x() + opt->rect.width() / 2, opt->rect.y() + opt->rect.height()); + pa.setPoint(1, opt->rect.x(), opt->rect.y()); + pa.setPoint(2, opt->rect.x() + opt->rect.width(), opt->rect.y()); + p->drawPolyline(pa); + } else if (header->sortIndicator & QStyleOptionHeader::SortDown) { + QPolygon pa(3); + p->setPen(QPen(opt->palette.light(), 0)); + pa.setPoint(0, opt->rect.x(), opt->rect.y() + opt->rect.height()); + pa.setPoint(1, opt->rect.x() + opt->rect.width(), opt->rect.y() + opt->rect.height()); + pa.setPoint(2, opt->rect.x() + opt->rect.width() / 2, opt->rect.y()); + p->drawPolyline(pa); + p->setPen(QPen(opt->palette.dark(), 0)); + p->drawLine(opt->rect.x(), opt->rect.y() + opt->rect.height(), + opt->rect.x() + opt->rect.width() / 2, opt->rect.y()); + } + p->setPen(oldPen); + } + break; +#ifndef QT_NO_TABBAR + case PE_FrameTabBarBase: + if (const QStyleOptionTabBarBase *tbb + = qstyleoption_cast(opt)) { + p->save(); + switch (tbb->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + p->setPen(QPen(tbb->palette.light(), 0)); + p->drawLine(tbb->rect.topLeft(), tbb->rect.topRight()); + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + p->setPen(QPen(tbb->palette.light(), 0)); + p->drawLine(tbb->rect.topLeft(), tbb->rect.bottomLeft()); + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + p->setPen(QPen(tbb->palette.shadow(), 0)); + p->drawLine(tbb->rect.left(), tbb->rect.bottom(), + tbb->rect.right(), tbb->rect.bottom()); + p->setPen(QPen(tbb->palette.dark(), 0)); + p->drawLine(tbb->rect.left(), tbb->rect.bottom() - 1, + tbb->rect.right() - 1, tbb->rect.bottom() - 1); + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + p->setPen(QPen(tbb->palette.dark(), 0)); + p->drawLine(tbb->rect.topRight(), tbb->rect.bottomRight()); + break; + } + p->restore(); + } + break; + case PE_IndicatorTabClose: { + if (d->tabBarcloseButtonIcon.isNull()) { + d->tabBarcloseButtonIcon.addPixmap(QPixmap( + QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-closetab-16.png")), + QIcon::Normal, QIcon::Off); + d->tabBarcloseButtonIcon.addPixmap(QPixmap( + QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-closetab-down-16.png")), + QIcon::Normal, QIcon::On); + d->tabBarcloseButtonIcon.addPixmap(QPixmap( + QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-closetab-hover-16.png")), + QIcon::Active, QIcon::Off); + } + + int size = proxy()->pixelMetric(QStyle::PM_SmallIconSize); + QIcon::Mode mode = opt->state & State_Enabled ? + (opt->state & State_Raised ? QIcon::Active : QIcon::Normal) + : QIcon::Disabled; + if (!(opt->state & State_Raised) + && !(opt->state & State_Sunken) + && !(opt->state & QStyle::State_Selected)) + mode = QIcon::Disabled; + + QIcon::State state = opt->state & State_Sunken ? QIcon::On : QIcon::Off; + QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(size, mode, state); + proxy()->drawItemPixmap(p, opt->rect, Qt::AlignCenter, pixmap); + break; + } +#endif // QT_NO_TABBAR + case PE_FrameTabWidget: + case PE_FrameWindow: + qDrawWinPanel(p, opt->rect, opt->palette, false, 0); + break; + case PE_FrameLineEdit: + proxy()->drawPrimitive(PE_Frame, opt, p, widget); + break; +#ifndef QT_NO_GROUPBOX + case PE_FrameGroupBox: + if (const QStyleOptionFrame *frame = qstyleoption_cast(opt)) { + const QStyleOptionFrameV2 *frame2 = qstyleoption_cast(opt); + if (frame2 && (frame2->features & QStyleOptionFrameV2::Flat)) { + QRect fr = frame->rect; + QPoint p1(fr.x(), fr.y() + 1); + QPoint p2(fr.x() + fr.width(), p1.y()); + qDrawShadeLine(p, p1, p2, frame->palette, true, + frame->lineWidth, frame->midLineWidth); + } else { + qDrawShadeRect(p, frame->rect.x(), frame->rect.y(), frame->rect.width(), + frame->rect.height(), frame->palette, true, + frame->lineWidth, frame->midLineWidth); + } + } + break; +#endif // QT_NO_GROUPBOX +#ifndef QT_NO_DOCKWIDGET + case PE_FrameDockWidget: + if (const QStyleOptionFrame *frame = qstyleoption_cast(opt)) { + int lw = frame->lineWidth; + if (lw <= 0) + lw = proxy()->pixelMetric(PM_DockWidgetFrameWidth); + + qDrawShadePanel(p, frame->rect, frame->palette, false, lw); + } + break; +#endif // QT_NO_DOCKWIDGET +#ifndef QT_NO_TOOLBAR + case PE_IndicatorToolBarHandle: + p->save(); + p->translate(opt->rect.x(), opt->rect.y()); + if (opt->state & State_Horizontal) { + int x = opt->rect.width() / 3; + if (opt->direction == Qt::RightToLeft) + x -= 2; + if (opt->rect.height() > 4) { + qDrawShadePanel(p, x, 2, 3, opt->rect.height() - 4, + opt->palette, false, 1, 0); + qDrawShadePanel(p, x+3, 2, 3, opt->rect.height() - 4, + opt->palette, false, 1, 0); + } + } else { + if (opt->rect.width() > 4) { + int y = opt->rect.height() / 3; + qDrawShadePanel(p, 2, y, opt->rect.width() - 4, 3, + opt->palette, false, 1, 0); + qDrawShadePanel(p, 2, y+3, opt->rect.width() - 4, 3, + opt->palette, false, 1, 0); + } + } + p->restore(); + break; + case PE_Q3DockWindowSeparator: + proxy()->drawPrimitive(PE_IndicatorToolBarSeparator, opt, p, widget); + break; + case PE_IndicatorToolBarSeparator: + { + QPoint p1, p2; + if (opt->state & State_Horizontal) { + p1 = QPoint(opt->rect.width()/2, 0); + p2 = QPoint(p1.x(), opt->rect.height()); + } else { + p1 = QPoint(0, opt->rect.height()/2); + p2 = QPoint(opt->rect.width(), p1.y()); + } + qDrawShadeLine(p, p1, p2, opt->palette, 1, 1, 0); + break; + } +#endif // QT_NO_TOOLBAR +#ifndef QT_NO_SPINBOX + case PE_IndicatorSpinPlus: + case PE_IndicatorSpinMinus: { + QRect r = opt->rect; + int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); + QRect br = r.adjusted(fw, fw, -fw, -fw); + + int offset = (opt->state & State_Sunken) ? 1 : 0; + int step = (br.width() + 4) / 5; + p->fillRect(br.x() + offset, br.y() + offset +br.height() / 2 - step / 2, + br.width(), step, + opt->palette.buttonText()); + if (pe == PE_IndicatorSpinPlus) + p->fillRect(br.x() + br.width() / 2 - step / 2 + offset, br.y() + offset, + step, br.height(), + opt->palette.buttonText()); + + break; } + case PE_IndicatorSpinUp: + case PE_IndicatorSpinDown: { + QRect r = opt->rect; + int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); + // QRect br = r.adjusted(fw, fw, -fw, -fw); + int x = r.x(), y = r.y(), w = r.width(), h = r.height(); + int sw = w-4; + if (sw < 3) + break; + else if (!(sw & 1)) + sw--; + sw -= (sw / 7) * 2; // Empty border + int sh = sw/2 + 2; // Must have empty row at foot of arrow + + int sx = x + w / 2 - sw / 2; + int sy = y + h / 2 - sh / 2; + + if (pe == PE_IndicatorSpinUp && fw) + --sy; + + QPolygon a; + if (pe == PE_IndicatorSpinDown) + a.setPoints(3, 0, 1, sw-1, 1, sh-2, sh-1); + else + a.setPoints(3, 0, sh-1, sw-1, sh-1, sh-2, 1); + int bsx = 0; + int bsy = 0; + if (opt->state & State_Sunken) { + bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal); + bsy = proxy()->pixelMetric(PM_ButtonShiftVertical); + } + p->save(); + p->translate(sx + bsx, sy + bsy); + p->setPen(opt->palette.buttonText().color()); + p->setBrush(opt->palette.buttonText()); + p->drawPolygon(a); + p->restore(); + break; } +#endif // QT_NO_SPINBOX + case PE_PanelTipLabel: { + QBrush oldBrush = p->brush(); + QPen oldPen = p->pen(); + p->setPen(QPen(opt->palette.toolTipText(), 0)); + p->setBrush(opt->palette.toolTipBase()); + p->drawRect(opt->rect.adjusted(0, 0, -1, -1)); + p->setPen(oldPen); + p->setBrush(oldBrush); + break; + } +#ifndef QT_NO_TABBAR + case PE_IndicatorTabTear: + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + bool rtl = tab->direction == Qt::RightToLeft; + QRect rect = tab->rect; + QPainterPath path; + + rect.setTop(rect.top() + ((tab->state & State_Selected) ? 1 : 3)); + rect.setBottom(rect.bottom() - ((tab->state & State_Selected) ? 0 : 2)); + + path.moveTo(QPoint(rtl ? rect.right() : rect.left(), rect.top())); + int count = 4; + for(int jags = 1; jags <= count; ++jags, rtl = !rtl) + path.lineTo(QPoint(rtl ? rect.left() : rect.right(), rect.top() + jags * rect.height()/count)); + + p->setPen(QPen(tab->palette.light(), qreal(.8))); + p->setBrush(tab->palette.background()); + p->setRenderHint(QPainter::Antialiasing); + p->drawPath(path); + } + break; +#endif // QT_NO_TABBAR +#ifndef QT_NO_LINEEDIT + case PE_PanelLineEdit: + if (const QStyleOptionFrame *panel = qstyleoption_cast(opt)) { + p->fillRect(panel->rect.adjusted(panel->lineWidth, panel->lineWidth, -panel->lineWidth, -panel->lineWidth), + panel->palette.brush(QPalette::Base)); + + if (panel->lineWidth > 0) + proxy()->drawPrimitive(PE_FrameLineEdit, panel, p, widget); + } + break; +#endif // QT_NO_LINEEDIT +#ifndef QT_NO_COLUMNVIEW + case PE_IndicatorColumnViewArrow: { + if (const QStyleOptionViewItem *viewOpt = qstyleoption_cast(opt)) { + bool reverse = (viewOpt->direction == Qt::RightToLeft); + p->save(); + QPainterPath path; + int x = viewOpt->rect.x() + 1; + int offset = (viewOpt->rect.height() / 3); + int height = (viewOpt->rect.height()) - offset * 2; + if (height % 2 == 1) + --height; + int x2 = x + height - 1; + if (reverse) { + x = viewOpt->rect.x() + viewOpt->rect.width() - 1; + x2 = x - height + 1; + } + path.moveTo(x, viewOpt->rect.y() + offset); + path.lineTo(x, viewOpt->rect.y() + offset + height); + path.lineTo(x2, viewOpt->rect.y() + offset+height/2); + path.closeSubpath(); + if (viewOpt->state & QStyle::State_Selected ) { + if (viewOpt->showDecorationSelected) { + QColor color = viewOpt->palette.color(QPalette::Active, QPalette::HighlightedText); + p->setPen(color); + p->setBrush(color); + } else { + QColor color = viewOpt->palette.color(QPalette::Active, QPalette::WindowText); + p->setPen(color); + p->setBrush(color); + } + + } else { + QColor color = viewOpt->palette.color(QPalette::Active, QPalette::Mid); + p->setPen(color); + p->setBrush(color); + } + p->drawPath(path); + + // draw the vertical and top triangle line + if (!(viewOpt->state & QStyle::State_Selected)) { + QPainterPath lines; + lines.moveTo(x, viewOpt->rect.y() + offset); + lines.lineTo(x, viewOpt->rect.y() + offset + height); + lines.moveTo(x, viewOpt->rect.y() + offset); + lines.lineTo(x2, viewOpt->rect.y() + offset+height/2); + QColor color = viewOpt->palette.color(QPalette::Active, QPalette::Dark); + p->setPen(color); + p->drawPath(lines); + } + p->restore(); + } + break; } +#endif //QT_NO_COLUMNVIEW + case PE_IndicatorItemViewItemDrop: { + QRect rect = opt->rect; + if (opt->rect.height() == 0) + p->drawLine(rect.topLeft(), rect.topRight()); + else + p->drawRect(rect); + break; } +#ifndef QT_NO_ITEMVIEWS + case PE_PanelItemViewRow: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(opt)) { + QPalette::ColorGroup cg = (widget ? widget->isEnabled() : (vopt->state & QStyle::State_Enabled)) + ? QPalette::Normal : QPalette::Disabled; + if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active)) + cg = QPalette::Inactive; + + if ((vopt->state & QStyle::State_Selected) && proxy()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, opt, widget)) + p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::Highlight)); + else if (vopt->features & QStyleOptionViewItemV2::Alternate) + p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::AlternateBase)); + } + break; + case PE_PanelItemViewItem: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(opt)) { + QPalette::ColorGroup cg = (widget ? widget->isEnabled() : (vopt->state & QStyle::State_Enabled)) + ? QPalette::Normal : QPalette::Disabled; + if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active)) + cg = QPalette::Inactive; + + if (vopt->showDecorationSelected && (vopt->state & QStyle::State_Selected)) { + p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::Highlight)); + } else { + if (vopt->backgroundBrush.style() != Qt::NoBrush) { + QPointF oldBO = p->brushOrigin(); + p->setBrushOrigin(vopt->rect.topLeft()); + p->fillRect(vopt->rect, vopt->backgroundBrush); + p->setBrushOrigin(oldBO); + } + + if (vopt->state & QStyle::State_Selected) { + QRect textRect = subElementRect(QStyle::SE_ItemViewItemText, opt, widget); + p->fillRect(textRect, vopt->palette.brush(cg, QPalette::Highlight)); + } + } + } + break; +#endif //QT_NO_ITEMVIEWS + case PE_PanelScrollAreaCorner: { + const QBrush brush(opt->palette.brush(QPalette::Window)); + p->fillRect(opt->rect, brush); + } break; + default: + break; + } +} + +#ifndef QT_NO_TOOLBUTTON +static void drawArrow(const QStyle *style, const QStyleOptionToolButton *toolbutton, + const QRect &rect, QPainter *painter, const QWidget *widget = 0) +{ + QStyle::PrimitiveElement pe; + switch (toolbutton->arrowType) { + case Qt::LeftArrow: + pe = QStyle::PE_IndicatorArrowLeft; + break; + case Qt::RightArrow: + pe = QStyle::PE_IndicatorArrowRight; + break; + case Qt::UpArrow: + pe = QStyle::PE_IndicatorArrowUp; + break; + case Qt::DownArrow: + pe = QStyle::PE_IndicatorArrowDown; + break; + default: + return; + } + QStyleOption arrowOpt; + arrowOpt.rect = rect; + arrowOpt.palette = toolbutton->palette; + arrowOpt.state = toolbutton->state; + style->drawPrimitive(pe, &arrowOpt, painter, widget); +} +#endif // QT_NO_TOOLBUTTON + +#ifndef QT_NO_ITEMVIEWS + +QSize QCommonStylePrivate::viewItemSize(const QStyleOptionViewItemV4 *option, int role) const +{ + Q_Q(const QCommonStyle); + + const QWidget *widget = option->widget; + switch (role) { + case Qt::CheckStateRole: + if (option->features & QStyleOptionViewItemV2::HasCheckIndicator) + return QSize(q->pixelMetric(QStyle::PM_IndicatorWidth, option, widget), + q->pixelMetric(QStyle::PM_IndicatorHeight, option, widget)); + break; + case Qt::DisplayRole: + if (option->features & QStyleOptionViewItemV2::HasDisplay) { + QTextOption textOption; + textOption.setWrapMode(QTextOption::WordWrap); + QTextLayout textLayout; + textLayout.setTextOption(textOption); + textLayout.setFont(option->font); + textLayout.setText(option->text); + const bool wrapText = option->features & QStyleOptionViewItemV2::WrapText; + const int textMargin = q->pixelMetric(QStyle::PM_FocusFrameHMargin, option, widget) + 1; + QRect bounds = option->rect; + switch (option->decorationPosition) { + case QStyleOptionViewItem::Left: + case QStyleOptionViewItem::Right: + bounds.setWidth(wrapText && bounds.isValid() ? bounds.width() - 2 * textMargin : QFIXED_MAX); + break; + case QStyleOptionViewItem::Top: + case QStyleOptionViewItem::Bottom: + bounds.setWidth(wrapText ? option->decorationSize.width() : QFIXED_MAX); + break; + default: + break; + } + + qreal height = 0, widthUsed = 0; + textLayout.beginLayout(); + while (true) { + QTextLine line = textLayout.createLine(); + if (!line.isValid()) + break; + line.setLineWidth(bounds.width()); + line.setPosition(QPointF(0, height)); + height += line.height(); + widthUsed = qMax(widthUsed, line.naturalTextWidth()); + } + textLayout.endLayout(); + const QSize size(qCeil(widthUsed), qCeil(height)); + return QSize(size.width() + 2 * textMargin, size.height()); + } + break; + case Qt::DecorationRole: + if (option->features & QStyleOptionViewItemV2::HasDecoration) { + return option->decorationSize; + } + break; + default: + break; + } + + return QSize(0, 0); +} + +static QSizeF viewItemTextLayout(QTextLayout &textLayout, int lineWidth) +{ + qreal height = 0; + qreal widthUsed = 0; + textLayout.beginLayout(); + while (true) { + QTextLine line = textLayout.createLine(); + if (!line.isValid()) + break; + line.setLineWidth(lineWidth); + line.setPosition(QPointF(0, height)); + height += line.height(); + widthUsed = qMax(widthUsed, line.naturalTextWidth()); + } + textLayout.endLayout(); + return QSizeF(widthUsed, height); +} + +void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewItemV4 *option, const QRect &rect) const +{ + Q_Q(const QCommonStyle); + const QWidget *widget = option->widget; + const int textMargin = q->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1; + + QRect textRect = rect.adjusted(textMargin, 0, -textMargin, 0); // remove width padding + const bool wrapText = option->features & QStyleOptionViewItemV2::WrapText; + QTextOption textOption; + textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap); + textOption.setTextDirection(option->direction); + textOption.setAlignment(QStyle::visualAlignment(option->direction, option->displayAlignment)); + QTextLayout textLayout; + textLayout.setTextOption(textOption); + textLayout.setFont(option->font); + textLayout.setText(option->text); + + QSizeF textLayoutSize = viewItemTextLayout(textLayout, textRect.width()); + + QString elidedText; + qreal height = 0; + qreal width = 0; + int elidedIndex = -1; + const int lineCount = textLayout.lineCount(); + for (int j = 0; j < lineCount; ++j) { + const QTextLine line = textLayout.lineAt(j); + if (j + 1 <= lineCount - 1) { + const QTextLine nextLine = textLayout.lineAt(j + 1); + if ((nextLine.y() + nextLine.height()) > textRect.height()) { + int start = line.textStart(); + int length = line.textLength() + nextLine.textLength(); + const QStackTextEngine engine(textLayout.text().mid(start, length), option->font); + elidedText = engine.elidedText(option->textElideMode, textRect.width()); + height += line.height(); + width = textRect.width(); + elidedIndex = j; + break; + } + } + if (line.naturalTextWidth() > textRect.width()) { + int start = line.textStart(); + int length = line.textLength(); + const QStackTextEngine engine(textLayout.text().mid(start, length), option->font); + elidedText = engine.elidedText(option->textElideMode, textRect.width()); + height += line.height(); + width = textRect.width(); + elidedIndex = j; + break; + } + width = qMax(width, line.width()); + height += line.height(); + } + + const QRect layoutRect = QStyle::alignedRect(option->direction, option->displayAlignment, + QSize(int(width), int(height)), textRect); + const QPointF position = layoutRect.topLeft(); + for (int i = 0; i < lineCount; ++i) { + const QTextLine line = textLayout.lineAt(i); + if (i == elidedIndex) { + qreal x = position.x() + line.x(); + qreal y = position.y() + line.y() + line.ascent(); + p->save(); + p->setFont(option->font); + p->drawText(QPointF(x, y), elidedText); + p->restore(); + break; + } + line.draw(p, position); + } +} + +/*! \internal + compute the position for the different component of an item (pixmap, text, checkbox) + + Set sizehint to false to layout the elements inside opt->rect. Set sizehint to true to ignore + opt->rect and return rectangles in infinite space + + Code duplicated in QItemDelegate::doLayout +*/ +void QCommonStylePrivate::viewItemLayout(const QStyleOptionViewItemV4 *opt, QRect *checkRect, + QRect *pixmapRect, QRect *textRect, bool sizehint) const +{ + Q_Q(const QCommonStyle); + Q_ASSERT(checkRect && pixmapRect && textRect); + *pixmapRect = QRect(QPoint(0, 0), viewItemSize(opt, Qt::DecorationRole)); + *textRect = QRect(QPoint(0, 0), viewItemSize(opt, Qt::DisplayRole)); + *checkRect = QRect(QPoint(0, 0), viewItemSize(opt, Qt::CheckStateRole)); + + const QWidget *widget = opt->widget; + const bool hasCheck = checkRect->isValid(); + const bool hasPixmap = pixmapRect->isValid(); + const bool hasText = textRect->isValid(); + const int textMargin = hasText ? q->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, widget) + 1 : 0; + const int pixmapMargin = hasPixmap ? q->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, widget) + 1 : 0; + const int checkMargin = hasCheck ? q->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, widget) + 1 : 0; + int x = opt->rect.left(); + int y = opt->rect.top(); + int w, h; + + if (textRect->height() == 0 && (!hasPixmap || !sizehint)) { + //if there is no text, we still want to have a decent height for the item sizeHint and the editor size + textRect->setHeight(opt->fontMetrics.height()); + } + + QSize pm(0, 0); + if (hasPixmap) { + pm = pixmapRect->size(); + pm.rwidth() += 2 * pixmapMargin; + } + if (sizehint) { + h = qMax(checkRect->height(), qMax(textRect->height(), pm.height())); + if (opt->decorationPosition == QStyleOptionViewItem::Left + || opt->decorationPosition == QStyleOptionViewItem::Right) { + w = textRect->width() + pm.width(); + } else { + w = qMax(textRect->width(), pm.width()); + } + } else { + w = opt->rect.width(); + h = opt->rect.height(); + } + + int cw = 0; + QRect check; + if (hasCheck) { + cw = checkRect->width() + 2 * checkMargin; + if (sizehint) w += cw; + if (opt->direction == Qt::RightToLeft) { + check.setRect(x + w - cw, y, cw, h); + } else { + check.setRect(x, y, cw, h); + } + } + + QRect display; + QRect decoration; + switch (opt->decorationPosition) { + case QStyleOptionViewItem::Top: { + if (hasPixmap) + pm.setHeight(pm.height() + pixmapMargin); // add space + h = sizehint ? textRect->height() : h - pm.height(); + + if (opt->direction == Qt::RightToLeft) { + decoration.setRect(x, y, w - cw, pm.height()); + display.setRect(x, y + pm.height(), w - cw, h); + } else { + decoration.setRect(x + cw, y, w - cw, pm.height()); + display.setRect(x + cw, y + pm.height(), w - cw, h); + } + break; } + case QStyleOptionViewItem::Bottom: { + if (hasText) + textRect->setHeight(textRect->height() + textMargin); // add space + h = sizehint ? textRect->height() + pm.height() : h; + + if (opt->direction == Qt::RightToLeft) { + display.setRect(x, y, w - cw, textRect->height()); + decoration.setRect(x, y + textRect->height(), w - cw, h - textRect->height()); + } else { + display.setRect(x + cw, y, w - cw, textRect->height()); + decoration.setRect(x + cw, y + textRect->height(), w - cw, h - textRect->height()); + } + break; } + case QStyleOptionViewItem::Left: { + if (opt->direction == Qt::LeftToRight) { + decoration.setRect(x + cw, y, pm.width(), h); + display.setRect(decoration.right() + 1, y, w - pm.width() - cw, h); + } else { + display.setRect(x, y, w - pm.width() - cw, h); + decoration.setRect(display.right() + 1, y, pm.width(), h); + } + break; } + case QStyleOptionViewItem::Right: { + if (opt->direction == Qt::LeftToRight) { + display.setRect(x + cw, y, w - pm.width() - cw, h); + decoration.setRect(display.right() + 1, y, pm.width(), h); + } else { + decoration.setRect(x, y, pm.width(), h); + display.setRect(decoration.right() + 1, y, w - pm.width() - cw, h); + } + break; } + default: + qWarning("doLayout: decoration position is invalid"); + decoration = *pixmapRect; + break; + } + + if (!sizehint) { // we only need to do the internal layout if we are going to paint + *checkRect = QStyle::alignedRect(opt->direction, Qt::AlignCenter, + checkRect->size(), check); + *pixmapRect = QStyle::alignedRect(opt->direction, opt->decorationAlignment, + pixmapRect->size(), decoration); + // the text takes up all available space, unless the decoration is not shown as selected + if (opt->showDecorationSelected) + *textRect = display; + else + *textRect = QStyle::alignedRect(opt->direction, opt->displayAlignment, + textRect->size().boundedTo(display.size()), display); + } else { + *checkRect = check; + *pixmapRect = decoration; + *textRect = display; + } +} +#endif // QT_NO_ITEMVIEWS + + +#ifndef QT_NO_TABBAR +/*! \internal + Compute the textRect and the pixmapRect from the opt rect + + Uses the same computation than in QTabBar::tabSizeHint + */ +void QCommonStylePrivate::tabLayout(const QStyleOptionTabV3 *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const +{ + Q_ASSERT(textRect); + Q_ASSERT(iconRect); + QRect tr = opt->rect; + bool verticalTabs = opt->shape == QTabBar::RoundedEast + || opt->shape == QTabBar::RoundedWest + || opt->shape == QTabBar::TriangularEast + || opt->shape == QTabBar::TriangularWest; + if (verticalTabs) + tr.setRect(0, 0, tr.height(), tr.width()); //0, 0 as we will have a translate transform + + int verticalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftVertical, opt, widget); + int horizontalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, opt, widget); + int hpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2; + int vpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2; + if (opt->shape == QTabBar::RoundedSouth || opt->shape == QTabBar::TriangularSouth) + verticalShift = -verticalShift; + tr.adjust(hpadding, verticalShift - vpadding, horizontalShift - hpadding, vpadding); + bool selected = opt->state & QStyle::State_Selected; + if (selected) { + tr.setTop(tr.top() - verticalShift); + tr.setRight(tr.right() - horizontalShift); + } + + // left widget + if (!opt->leftButtonSize.isEmpty()) { + tr.setLeft(tr.left() + 4 + + (verticalTabs ? opt->leftButtonSize.height() : opt->leftButtonSize.width())); + } + // right widget + if (!opt->rightButtonSize.isEmpty()) { + tr.setRight(tr.right() - 4 - + (verticalTabs ? opt->rightButtonSize.height() : opt->rightButtonSize.width())); + } + + // icon + if (!opt->icon.isNull()) { + QSize iconSize = opt->iconSize; + if (!iconSize.isValid()) { + int iconExtent = proxyStyle->pixelMetric(QStyle::PM_SmallIconSize); + iconSize = QSize(iconExtent, iconExtent); + } + QSize tabIconSize = opt->icon.actualSize(iconSize, + (opt->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled, + (opt->state & QStyle::State_Selected) ? QIcon::On : QIcon::Off ); + + *iconRect = QRect(tr.left(), tr.center().y() - tabIconSize.height() / 2, + tabIconSize.width(), tabIconSize .height()); + if (!verticalTabs) + *iconRect = proxyStyle->visualRect(opt->direction, opt->rect, *iconRect); + tr.setLeft(tr.left() + tabIconSize.width() + 4); + } + + if (!verticalTabs) + tr = proxyStyle->visualRect(opt->direction, opt->rect, tr); + + *textRect = tr; +} +#endif //QT_NO_TABBAR + + +/*! + \reimp +*/ +void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, + QPainter *p, const QWidget *widget) const +{ + Q_D(const QCommonStyle); + switch (element) { + + case CE_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + proxy()->drawControl(CE_PushButtonBevel, btn, p, widget); + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); + proxy()->drawControl(CE_PushButtonLabel, &subopt, p, widget); + if (btn->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*btn); + fropt.rect = subElementRect(SE_PushButtonFocusRect, btn, widget); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + break; + case CE_PushButtonBevel: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + QRect br = btn->rect; + int dbi = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget); + if (btn->features & QStyleOptionButton::DefaultButton) + proxy()->drawPrimitive(PE_FrameDefaultButton, opt, p, widget); + if (btn->features & QStyleOptionButton::AutoDefaultButton) + br.setCoords(br.left() + dbi, br.top() + dbi, br.right() - dbi, br.bottom() - dbi); + if (!(btn->features & (QStyleOptionButton::Flat | QStyleOptionButton::CommandLinkButton)) + || btn->state & (State_Sunken | State_On) + || (btn->features & QStyleOptionButton::CommandLinkButton && btn->state & State_MouseOver)) { + QStyleOptionButton tmpBtn = *btn; + tmpBtn.rect = br; + proxy()->drawPrimitive(PE_PanelButtonCommand, &tmpBtn, p, widget); + } + if (btn->features & QStyleOptionButton::HasMenu) { + int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget); + QRect ir = btn->rect; + QStyleOptionButton newBtn = *btn; + newBtn.rect = QRect(ir.right() - mbi + 2, ir.height()/2 - mbi/2 + 3, mbi - 6, mbi - 6); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); + } + } + break; + case CE_PushButtonLabel: + if (const QStyleOptionButton *button = qstyleoption_cast(opt)) { + QRect textRect = button->rect; + uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic; + if (!proxy()->styleHint(SH_UnderlineShortcut, button, widget)) + tf |= Qt::TextHideMnemonic; + + if (!button->icon.isNull()) { + //Center both icon and text + QRect iconRect; + QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled; + if (mode == QIcon::Normal && button->state & State_HasFocus) + mode = QIcon::Active; + QIcon::State state = QIcon::Off; + if (button->state & State_On) + state = QIcon::On; + + QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state); + int labelWidth = pixmap.width(); + int labelHeight = pixmap.height(); + int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint() + int textWidth = button->fontMetrics.boundingRect(opt->rect, tf, button->text).width(); + if (!button->text.isEmpty()) + labelWidth += (textWidth + iconSpacing); + + iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2, + textRect.y() + (textRect.height() - labelHeight) / 2, + pixmap.width(), pixmap.height()); + + iconRect = visualRect(button->direction, textRect, iconRect); + + tf |= Qt::AlignLeft; //left align, we adjust the text-rect instead + + if (button->direction == Qt::RightToLeft) + textRect.setRight(iconRect.left() - iconSpacing); + else + textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing); + + if (button->state & (State_On | State_Sunken)) + iconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget), + proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget)); + p->drawPixmap(iconRect, pixmap); + } else { + tf |= Qt::AlignHCenter; + } + if (button->state & (State_On | State_Sunken)) + textRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget), + proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget)); + + if (button->features & QStyleOptionButton::HasMenu) { + int indicatorSize = proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget); + if (button->direction == Qt::LeftToRight) + textRect = textRect.adjusted(0, 0, -indicatorSize, 0); + else + textRect = textRect.adjusted(indicatorSize, 0, 0, 0); + } + proxy()->drawItemText(p, textRect, tf, button->palette, (button->state & State_Enabled), + button->text, QPalette::ButtonText); + } + break; + case CE_RadioButton: + case CE_CheckBox: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + bool isRadio = (element == CE_RadioButton); + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator + : SE_CheckBoxIndicator, btn, widget); + proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox, + &subopt, p, widget); + subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents + : SE_CheckBoxContents, btn, widget); + proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, widget); + if (btn->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*btn); + fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect + : SE_CheckBoxFocusRect, btn, widget); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + break; + case CE_RadioButtonLabel: + case CE_CheckBoxLabel: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + uint alignment = visualAlignment(btn->direction, Qt::AlignLeft | Qt::AlignVCenter); + + if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget)) + alignment |= Qt::TextHideMnemonic; + QPixmap pix; + QRect textRect = btn->rect; + if (!btn->icon.isNull()) { + pix = btn->icon.pixmap(btn->iconSize, btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled); + proxy()->drawItemPixmap(p, btn->rect, alignment, pix); + if (btn->direction == Qt::RightToLeft) + textRect.setRight(textRect.right() - btn->iconSize.width() - 4); + else + textRect.setLeft(textRect.left() + btn->iconSize.width() + 4); + } + if (!btn->text.isEmpty()){ + proxy()->drawItemText(p, textRect, alignment | Qt::TextShowMnemonic, + btn->palette, btn->state & State_Enabled, btn->text, QPalette::WindowText); + } + } + break; +#ifndef QT_NO_MENU + case CE_MenuScroller: { + p->fillRect(opt->rect, opt->palette.background()); + QStyleOption arrowOpt = *opt; + arrowOpt.state |= State_Enabled; + proxy()->drawPrimitive(((opt->state & State_DownArrow) ? PE_IndicatorArrowDown : PE_IndicatorArrowUp), + &arrowOpt, p, widget); + break; } + case CE_MenuTearoff: + if (opt->state & State_Selected) + p->fillRect(opt->rect, opt->palette.brush(QPalette::Highlight)); + else + p->fillRect(opt->rect, opt->palette.brush(QPalette::Button)); + p->setPen(QPen(opt->palette.dark().color(), 1, Qt::DashLine)); + p->drawLine(opt->rect.x() + 2, opt->rect.y() + opt->rect.height() / 2 - 1, + opt->rect.x() + opt->rect.width() - 4, + opt->rect.y() + opt->rect.height() / 2 - 1); + p->setPen(QPen(opt->palette.light().color(), 1, Qt::DashLine)); + p->drawLine(opt->rect.x() + 2, opt->rect.y() + opt->rect.height() / 2, + opt->rect.x() + opt->rect.width() - 4, opt->rect.y() + opt->rect.height() / 2); + break; +#endif // QT_NO_MENU +#ifndef QT_NO_MENUBAR + case CE_MenuBarItem: + if (const QStyleOptionMenuItem *mbi = qstyleoption_cast(opt)) { + uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip + | Qt::TextSingleLine; + if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget)) + alignment |= Qt::TextHideMnemonic; + QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), (mbi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled); + if (!pix.isNull()) + proxy()->drawItemPixmap(p,mbi->rect, alignment, pix); + else + proxy()->drawItemText(p, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, + mbi->text, QPalette::ButtonText); + } + break; + case CE_MenuBarEmptyArea: + if (widget && !widget->testAttribute(Qt::WA_NoSystemBackground)) + p->eraseRect(opt->rect); + break; +#endif // QT_NO_MENUBAR +#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBar: + if (const QStyleOptionProgressBar *pb + = qstyleoption_cast(opt)) { + QStyleOptionProgressBarV2 subopt = *pb; + subopt.rect = subElementRect(SE_ProgressBarGroove, pb, widget); + proxy()->drawControl(CE_ProgressBarGroove, &subopt, p, widget); + subopt.rect = subElementRect(SE_ProgressBarContents, pb, widget); + proxy()->drawControl(CE_ProgressBarContents, &subopt, p, widget); + if (pb->textVisible) { + subopt.rect = subElementRect(SE_ProgressBarLabel, pb, widget); + proxy()->drawControl(CE_ProgressBarLabel, &subopt, p, widget); + } + } + break; + case CE_ProgressBarGroove: + if (opt->rect.isValid()) + qDrawShadePanel(p, opt->rect, opt->palette, true, 1, + &opt->palette.brush(QPalette::Window)); + break; + case CE_ProgressBarLabel: + if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { + bool vertical = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt)) { + vertical = (pb2->orientation == Qt::Vertical); + } + if (!vertical) { + QPalette::ColorRole textRole = QPalette::NoRole; + if ((pb->textAlignment & Qt::AlignCenter) && pb->textVisible + && ((qint64(pb->progress) - qint64(pb->minimum)) * 2 >= (qint64(pb->maximum) - qint64(pb->minimum)))) { + textRole = QPalette::HighlightedText; + //Draw text shadow, This will increase readability when the background of same color + QRect shadowRect(pb->rect); + shadowRect.translate(1,1); + QColor shadowColor = (pb->palette.color(textRole).value() <= 128) + ? QColor(255,255,255,160) : QColor(0,0,0,160); + QPalette shadowPalette = pb->palette; + shadowPalette.setColor(textRole, shadowColor); + proxy()->drawItemText(p, shadowRect, Qt::AlignCenter | Qt::TextSingleLine, shadowPalette, + pb->state & State_Enabled, pb->text, textRole); + } + proxy()->drawItemText(p, pb->rect, Qt::AlignCenter | Qt::TextSingleLine, pb->palette, + pb->state & State_Enabled, pb->text, textRole); + } + } + break; + case CE_ProgressBarContents: + if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { + + QRect rect = pb->rect; + bool vertical = false; + bool inverted = false; + qint64 minimum = qint64(pb->minimum); + qint64 maximum = qint64(pb->maximum); + qint64 progress = qint64(pb->progress); + + // Get extra style options if version 2 + const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt); + if (pb2) { + vertical = (pb2->orientation == Qt::Vertical); + inverted = pb2->invertedAppearance; + } + QMatrix m; + + if (vertical) { + rect = QRect(rect.y(), rect.x(), rect.height(), rect.width()); // flip width and height + m.rotate(90); + m.translate(0, -(rect.height() + rect.y()*2)); + } + + QPalette pal2 = pb->palette; + // Correct the highlight color if it is the same as the background + if (pal2.highlight() == pal2.background()) + pal2.setColor(QPalette::Highlight, pb->palette.color(QPalette::Active, + QPalette::Highlight)); + bool reverse = ((!vertical && (pb->direction == Qt::RightToLeft)) || vertical); + if (inverted) + reverse = !reverse; + int w = rect.width(); + if (pb->minimum == 0 && pb->maximum == 0) { + // draw busy indicator + int x = (progress - minimum) % (w * 2); + if (x > w) + x = 2 * w - x; + x = reverse ? rect.right() - x : x + rect.x(); + p->setPen(QPen(pal2.highlight().color(), 4)); + p->drawLine(x, rect.y(), x, rect.height()); + } else { + const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, pb, widget); + if (!unit_width) + return; + + int u; + if (unit_width > 1) + u = ((rect.width() + unit_width) / unit_width); + else + u = w / unit_width; + qint64 p_v = progress - minimum; + qint64 t_s = (maximum - minimum) ? (maximum - minimum) : qint64(1); + + if (u > 0 && p_v >= INT_MAX / u && t_s >= u) { + // scale down to something usable. + p_v /= u; + t_s /= u; + } + + // nu < tnu, if last chunk is only a partial chunk + int tnu, nu; + tnu = nu = p_v * u / t_s; + + if (nu * unit_width > w) + --nu; + + // Draw nu units out of a possible u of unit_width + // width, each a rectangle bordered by background + // color, all in a sunken panel with a percentage text + // display at the end. + int x = 0; + int x0 = reverse ? rect.right() - ((unit_width > 1) ? unit_width : 0) + : rect.x(); + + QStyleOptionProgressBarV2 pbBits = *pb; + pbBits.rect = rect; + pbBits.palette = pal2; + int myY = pbBits.rect.y(); + int myHeight = pbBits.rect.height(); + pbBits.state = State_None; + for (int i = 0; i < nu; ++i) { + pbBits.rect.setRect(x0 + x, myY, unit_width, myHeight); + pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect(); + proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget); + x += reverse ? -unit_width : unit_width; + } + + // Draw the last partial chunk to fill up the + // progress bar entirely + if (nu < tnu) { + int pixels_left = w - (nu * unit_width); + int offset = reverse ? x0 + x + unit_width-pixels_left : x0 + x; + pbBits.rect.setRect(offset, myY, pixels_left, myHeight); + pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect(); + proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget); + } + } + } + break; +#endif // QT_NO_PROGRESSBAR + case CE_HeaderLabel: + if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { + QRect rect = header->rect; + if (!header->icon.isNull()) { + QPixmap pixmap + = header->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), (header->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled); + int pixw = pixmap.width(); + + QRect aligned = alignedRect(header->direction, QFlag(header->iconAlignment), pixmap.size(), rect); + QRect inter = aligned.intersected(rect); + p->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width(), inter.height()); + + if (header->direction == Qt::LeftToRight) + rect.setLeft(rect.left() + pixw + 2); + else + rect.setRight(rect.right() - pixw - 2); + } + if (header->state & QStyle::State_On) { + QFont fnt = p->font(); + fnt.setBold(true); + p->setFont(fnt); + } + proxy()->drawItemText(p, rect, header->textAlignment, header->palette, + (header->state & State_Enabled), header->text, QPalette::ButtonText); + } + break; +#ifndef QT_NO_TOOLBUTTON + case CE_ToolButtonLabel: + if (const QStyleOptionToolButton *toolbutton + = qstyleoption_cast(opt)) { + QRect rect = toolbutton->rect; + int shiftX = 0; + int shiftY = 0; + if (toolbutton->state & (State_Sunken | State_On)) { + shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget); + shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, toolbutton, widget); + } + // Arrow type always overrules and is always shown + bool hasArrow = toolbutton->features & QStyleOptionToolButton::Arrow; + if (((!hasArrow && toolbutton->icon.isNull()) && !toolbutton->text.isEmpty()) + || toolbutton->toolButtonStyle == Qt::ToolButtonTextOnly) { + int alignment = Qt::AlignCenter | Qt::TextShowMnemonic; + if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget)) + alignment |= Qt::TextHideMnemonic; + rect.translate(shiftX, shiftY); + p->setFont(toolbutton->font); + proxy()->drawItemText(p, rect, alignment, toolbutton->palette, + opt->state & State_Enabled, toolbutton->text, + QPalette::ButtonText); + } else { + QPixmap pm; + QSize pmSize = toolbutton->iconSize; + if (!toolbutton->icon.isNull()) { + QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off; + QIcon::Mode mode; + if (!(toolbutton->state & State_Enabled)) + mode = QIcon::Disabled; + else if ((opt->state & State_MouseOver) && (opt->state & State_AutoRaise)) + mode = QIcon::Active; + else + mode = QIcon::Normal; + pm = toolbutton->icon.pixmap(toolbutton->rect.size().boundedTo(toolbutton->iconSize), + mode, state); + pmSize = pm.size(); + } + + if (toolbutton->toolButtonStyle != Qt::ToolButtonIconOnly) { + p->setFont(toolbutton->font); + QRect pr = rect, + tr = rect; + int alignment = Qt::TextShowMnemonic; + if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget)) + alignment |= Qt::TextHideMnemonic; + + if (toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { + pr.setHeight(pmSize.height() + 6); + tr.adjust(0, pr.height() - 1, 0, -2); + pr.translate(shiftX, shiftY); + if (!hasArrow) { + proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pm); + } else { + drawArrow(this, toolbutton, pr, p, widget); + } + alignment |= Qt::AlignCenter; + } else { + pr.setWidth(pmSize.width() + 8); + tr.adjust(pr.width(), 0, 0, 0); + pr.translate(shiftX, shiftY); + if (!hasArrow) { + proxy()->drawItemPixmap(p, QStyle::visualRect(opt->direction, rect, pr), Qt::AlignCenter, pm); + } else { + drawArrow(this, toolbutton, pr, p, widget); + } + alignment |= Qt::AlignLeft | Qt::AlignVCenter; + } + tr.translate(shiftX, shiftY); + proxy()->drawItemText(p, QStyle::visualRect(opt->direction, rect, tr), alignment, toolbutton->palette, + toolbutton->state & State_Enabled, toolbutton->text, + QPalette::ButtonText); + } else { + rect.translate(shiftX, shiftY); + if (hasArrow) { + drawArrow(this, toolbutton, rect, p, widget); + } else { + proxy()->drawItemPixmap(p, rect, Qt::AlignCenter, pm); + } + } + } + } + break; +#endif // QT_NO_TOOLBUTTON +#ifndef QT_NO_TOOLBOX + case CE_ToolBoxTab: + if (const QStyleOptionToolBox *tb = qstyleoption_cast(opt)) { + proxy()->drawControl(CE_ToolBoxTabShape, tb, p, widget); + proxy()->drawControl(CE_ToolBoxTabLabel, tb, p, widget); + } + break; + case CE_ToolBoxTabShape: + if (const QStyleOptionToolBox *tb = qstyleoption_cast(opt)) { + int d = 20 + tb->rect.height() - 3; + QPolygon a(7); + if (tb->direction != Qt::RightToLeft) { + a.setPoint(0, -1, tb->rect.height() + 1); + a.setPoint(1, -1, 1); + a.setPoint(2, tb->rect.width() - d, 1); + a.setPoint(3, tb->rect.width() - 20, tb->rect.height() - 2); + a.setPoint(4, tb->rect.width() - 1, tb->rect.height() - 2); + a.setPoint(5, tb->rect.width() - 1, tb->rect.height() + 1); + a.setPoint(6, -1, tb->rect.height() + 1); + } else { + a.setPoint(0, tb->rect.width(), tb->rect.height() + 1); + a.setPoint(1, tb->rect.width(), 1); + a.setPoint(2, d - 1, 1); + a.setPoint(3, 20 - 1, tb->rect.height() - 2); + a.setPoint(4, 0, tb->rect.height() - 2); + a.setPoint(5, 0, tb->rect.height() + 1); + a.setPoint(6, tb->rect.width(), tb->rect.height() + 1); + } + + p->setPen(tb->palette.mid().color().darker(150)); + p->drawPolygon(a); + p->setPen(tb->palette.light().color()); + if (tb->direction != Qt::RightToLeft) { + p->drawLine(0, 2, tb->rect.width() - d, 2); + p->drawLine(tb->rect.width() - d - 1, 2, tb->rect.width() - 21, tb->rect.height() - 1); + p->drawLine(tb->rect.width() - 20, tb->rect.height() - 1, + tb->rect.width(), tb->rect.height() - 1); + } else { + p->drawLine(tb->rect.width() - 1, 2, d - 1, 2); + p->drawLine(d, 2, 20, tb->rect.height() - 1); + p->drawLine(19, tb->rect.height() - 1, + -1, tb->rect.height() - 1); + } + p->setBrush(Qt::NoBrush); + } + break; +#endif // QT_NO_TOOLBOX +#ifndef QT_NO_TABBAR + case CE_TabBarTab: + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + proxy()->drawControl(CE_TabBarTabShape, tab, p, widget); + proxy()->drawControl(CE_TabBarTabLabel, tab, p, widget); + } + break; + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + p->save(); + + QRect rect(tab->rect); + bool selected = tab->state & State_Selected; + bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab; + int tabOverlap = onlyOne ? 0 : proxy()->pixelMetric(PM_TabBarTabOverlap, opt, widget); + + if (!selected) { + switch (tab->shape) { + case QTabBar::TriangularNorth: + rect.adjust(0, 0, 0, -tabOverlap); + if(!selected) + rect.adjust(1, 1, -1, 0); + break; + case QTabBar::TriangularSouth: + rect.adjust(0, tabOverlap, 0, 0); + if(!selected) + rect.adjust(1, 0, -1, -1); + break; + case QTabBar::TriangularEast: + rect.adjust(tabOverlap, 0, 0, 0); + if(!selected) + rect.adjust(0, 1, -1, -1); + break; + case QTabBar::TriangularWest: + rect.adjust(0, 0, -tabOverlap, 0); + if(!selected) + rect.adjust(1, 1, 0, -1); + break; + default: + break; + } + } + + p->setPen(QPen(tab->palette.foreground(), 0)); + if (selected) { + p->setBrush(tab->palette.base()); + } else { + if (widget && widget->parentWidget()) + p->setBrush(widget->parentWidget()->palette().background()); + else + p->setBrush(tab->palette.background()); + } + + int y; + int x; + QPolygon a(10); + switch (tab->shape) { + case QTabBar::TriangularNorth: + case QTabBar::TriangularSouth: { + a.setPoint(0, 0, -1); + a.setPoint(1, 0, 0); + y = rect.height() - 2; + x = y / 3; + a.setPoint(2, x++, y - 1); + ++x; + a.setPoint(3, x++, y++); + a.setPoint(4, x, y); + + int i; + int right = rect.width() - 1; + for (i = 0; i < 5; ++i) + a.setPoint(9 - i, right - a.point(i).x(), a.point(i).y()); + if (tab->shape == QTabBar::TriangularNorth) + for (i = 0; i < 10; ++i) + a.setPoint(i, a.point(i).x(), rect.height() - 1 - a.point(i).y()); + + a.translate(rect.left(), rect.top()); + p->setRenderHint(QPainter::Antialiasing); + p->translate(0, 0.5); + + QPainterPath path; + path.addPolygon(a); + p->drawPath(path); + break; } + case QTabBar::TriangularEast: + case QTabBar::TriangularWest: { + a.setPoint(0, -1, 0); + a.setPoint(1, 0, 0); + x = rect.width() - 2; + y = x / 3; + a.setPoint(2, x - 1, y++); + ++y; + a.setPoint(3, x++, y++); + a.setPoint(4, x, y); + int i; + int bottom = rect.height() - 1; + for (i = 0; i < 5; ++i) + a.setPoint(9 - i, a.point(i).x(), bottom - a.point(i).y()); + if (tab->shape == QTabBar::TriangularWest) + for (i = 0; i < 10; ++i) + a.setPoint(i, rect.width() - 1 - a.point(i).x(), a.point(i).y()); + a.translate(rect.left(), rect.top()); + p->setRenderHint(QPainter::Antialiasing); + p->translate(0.5, 0); + QPainterPath path; + path.addPolygon(a); + p->drawPath(path); + break; } + default: + break; + } + p->restore(); + } + break; + case CE_ToolBoxTabLabel: + if (const QStyleOptionToolBox *tb = qstyleoption_cast(opt)) { + bool enabled = tb->state & State_Enabled; + bool selected = tb->state & State_Selected; + QPixmap pm = tb->icon.pixmap(proxy()->pixelMetric(QStyle::PM_SmallIconSize, tb, widget), + enabled ? QIcon::Normal : QIcon::Disabled); + + QRect cr = subElementRect(QStyle::SE_ToolBoxTabContents, tb, widget); + QRect tr, ir; + int ih = 0; + if (pm.isNull()) { + tr = cr; + tr.adjust(4, 0, -8, 0); + } else { + int iw = pm.width() + 4; + ih = pm.height(); + ir = QRect(cr.left() + 4, cr.top(), iw + 2, ih); + tr = QRect(ir.right(), cr.top(), cr.width() - ir.right() - 4, cr.height()); + } + + if (selected && proxy()->styleHint(QStyle::SH_ToolBox_SelectedPageTitleBold, tb, widget)) { + QFont f(p->font()); + f.setBold(true); + p->setFont(f); + } + + QString txt = tb->fontMetrics.elidedText(tb->text, Qt::ElideRight, tr.width()); + + if (ih) + p->drawPixmap(ir.left(), (tb->rect.height() - ih) / 2, pm); + + int alignment = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic; + if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, tb, widget)) + alignment |= Qt::TextHideMnemonic; + proxy()->drawItemText(p, tr, alignment, tb->palette, enabled, txt, QPalette::ButtonText); + + if (!txt.isEmpty() && opt->state & State_HasFocus) { + QStyleOptionFocusRect opt; + opt.rect = tr; + opt.palette = tb->palette; + opt.state = QStyle::State_None; + proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, widget); + } + } + break; + case CE_TabBarTabLabel: + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + QStyleOptionTabV3 tabV2(*tab); + QRect tr = tabV2.rect; + bool verticalTabs = tabV2.shape == QTabBar::RoundedEast + || tabV2.shape == QTabBar::RoundedWest + || tabV2.shape == QTabBar::TriangularEast + || tabV2.shape == QTabBar::TriangularWest; + + int alignment = Qt::AlignCenter | Qt::TextShowMnemonic; + if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget)) + alignment |= Qt::TextHideMnemonic; + + if (verticalTabs) { + p->save(); + int newX, newY, newRot; + if (tabV2.shape == QTabBar::RoundedEast || tabV2.shape == QTabBar::TriangularEast) { + newX = tr.width() + tr.x(); + newY = tr.y(); + newRot = 90; + } else { + newX = tr.x(); + newY = tr.y() + tr.height(); + newRot = -90; + } + QTransform m = QTransform::fromTranslate(newX, newY); + m.rotate(newRot); + p->setTransform(m, true); + } + QRect iconRect; + d->tabLayout(&tabV2, widget, &tr, &iconRect); + tr = proxy()->subElementRect(SE_TabBarTabText, opt, widget); //we compute tr twice because the style may override subElementRect + + if (!tabV2.icon.isNull()) { + QPixmap tabIcon = tabV2.icon.pixmap(tabV2.iconSize, + (tabV2.state & State_Enabled) ? QIcon::Normal + : QIcon::Disabled, + (tabV2.state & State_Selected) ? QIcon::On + : QIcon::Off); + p->drawPixmap(iconRect.x(), iconRect.y(), tabIcon); + } + + proxy()->drawItemText(p, tr, alignment, tab->palette, tab->state & State_Enabled, tab->text, QPalette::WindowText); + if (verticalTabs) + p->restore(); + + if (tabV2.state & State_HasFocus) { + const int OFFSET = 1 + pixelMetric(PM_DefaultFrameWidth); + + int x1, x2; + x1 = tabV2.rect.left(); + x2 = tabV2.rect.right() - 1; + + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*tab); + fropt.rect.setRect(x1 + 1 + OFFSET, tabV2.rect.y() + OFFSET, + x2 - x1 - 2*OFFSET, tabV2.rect.height() - 2*OFFSET); + drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + break; +#endif // QT_NO_TABBAR +#ifndef QT_NO_SIZEGRIP + case CE_SizeGrip: { + p->save(); + int x, y, w, h; + opt->rect.getRect(&x, &y, &w, &h); + + int sw = qMin(h, w); + if (h > w) + p->translate(0, h - w); + else + p->translate(w - h, 0); + + int sx = x; + int sy = y; + int s = sw / 3; + + Qt::Corner corner; + if (const QStyleOptionSizeGrip *sgOpt = qstyleoption_cast(opt)) + corner = sgOpt->corner; + else if (opt->direction == Qt::RightToLeft) + corner = Qt::BottomLeftCorner; + else + corner = Qt::BottomRightCorner; + + if (corner == Qt::BottomLeftCorner) { + sx = x + sw; + for (int i = 0; i < 4; ++i) { + p->setPen(QPen(opt->palette.light().color(), 1)); + p->drawLine(x, sy - 1 , sx + 1, sw); + p->setPen(QPen(opt->palette.dark().color(), 1)); + p->drawLine(x, sy, sx, sw); + p->setPen(QPen(opt->palette.dark().color(), 1)); + p->drawLine(x, sy + 1, sx - 1, sw); + sx -= s; + sy += s; + } + } else if (corner == Qt::BottomRightCorner) { + for (int i = 0; i < 4; ++i) { + p->setPen(QPen(opt->palette.light().color(), 1)); + p->drawLine(sx - 1, sw, sw, sy - 1); + p->setPen(QPen(opt->palette.dark().color(), 1)); + p->drawLine(sx, sw, sw, sy); + p->setPen(QPen(opt->palette.dark().color(), 1)); + p->drawLine(sx + 1, sw, sw, sy + 1); + sx += s; + sy += s; + } + } else if (corner == Qt::TopRightCorner) { + sy = y + sw; + for (int i = 0; i < 4; ++i) { + p->setPen(QPen(opt->palette.light().color(), 1)); + p->drawLine(sx - 1, y, sw, sy + 1); + p->setPen(QPen(opt->palette.dark().color(), 1)); + p->drawLine(sx, y, sw, sy); + p->setPen(QPen(opt->palette.dark().color(), 1)); + p->drawLine(sx + 1, y, sw, sy - 1); + sx += s; + sy -= s; + } + } else if (corner == Qt::TopLeftCorner) { + for (int i = 0; i < 4; ++i) { + p->setPen(QPen(opt->palette.light().color(), 1)); + p->drawLine(x, sy - 1, sx - 1, y); + p->setPen(QPen(opt->palette.dark().color(), 1)); + p->drawLine(x, sy, sx, y); + p->setPen(QPen(opt->palette.dark().color(), 1)); + p->drawLine(x, sy + 1, sx + 1, y); + sx += s; + sy += s; + } + } + p->restore(); + break; } +#endif // QT_NO_SIZEGRIP +#ifndef QT_NO_RUBBERBAND + case CE_RubberBand: { + if (const QStyleOptionRubberBand *rbOpt = qstyleoption_cast(opt)) { + QPixmap tiledPixmap(16, 16); + QPainter pixmapPainter(&tiledPixmap); + pixmapPainter.setPen(Qt::NoPen); + pixmapPainter.setBrush(Qt::Dense4Pattern); + pixmapPainter.setBackground(QBrush(opt->palette.base())); + pixmapPainter.setBackgroundMode(Qt::OpaqueMode); + pixmapPainter.drawRect(0, 0, tiledPixmap.width(), tiledPixmap.height()); + pixmapPainter.end(); + // ### workaround for borked XRENDER + tiledPixmap = QPixmap::fromImage(tiledPixmap.toImage()); + + p->save(); + QRect r = opt->rect; + QStyleHintReturnMask mask; + if (proxy()->styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask)) + p->setClipRegion(mask.region); + p->drawTiledPixmap(r.x(), r.y(), r.width(), r.height(), tiledPixmap); + p->setPen(opt->palette.color(QPalette::Active, QPalette::WindowText)); + p->setBrush(Qt::NoBrush); + p->drawRect(r.adjusted(0, 0, -1, -1)); + if (rbOpt->shape == QRubberBand::Rectangle) + p->drawRect(r.adjusted(3, 3, -4, -4)); + p->restore(); + } + break; } +#endif // QT_NO_RUBBERBAND +#ifndef QT_NO_DOCKWIDGET + case CE_DockWidgetTitle: + if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast(opt)) { + QRect r = dwOpt->rect.adjusted(0, 0, -1, -1); + if (dwOpt->movable) { + p->setPen(dwOpt->palette.color(QPalette::Dark)); + p->drawRect(r); + } + + if (!dwOpt->title.isEmpty()) { + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(opt); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + + if (verticalTitleBar) { + QSize s = r.size(); + s.transpose(); + r.setSize(s); + + p->save(); + p->translate(r.left(), r.top() + r.width()); + p->rotate(-90); + p->translate(-r.left(), -r.top()); + } + + const int indent = p->fontMetrics().descent(); + proxy()->drawItemText(p, r.adjusted(indent + 1, 1, -indent - 1, -1), + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette, + dwOpt->state & State_Enabled, dwOpt->title, + QPalette::WindowText); + + if (verticalTitleBar) + p->restore(); + } + } + break; +#endif // QT_NO_DOCKWIDGET + case CE_Header: + if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { + QRegion clipRegion = p->clipRegion(); + p->setClipRect(opt->rect); + proxy()->drawControl(CE_HeaderSection, header, p, widget); + QStyleOptionHeader subopt = *header; + subopt.rect = subElementRect(SE_HeaderLabel, header, widget); + if (subopt.rect.isValid()) + proxy()->drawControl(CE_HeaderLabel, &subopt, p, widget); + if (header->sortIndicator != QStyleOptionHeader::None) { + subopt.rect = subElementRect(SE_HeaderArrow, opt, widget); + proxy()->drawPrimitive(PE_IndicatorHeaderArrow, &subopt, p, widget); + } + p->setClipRegion(clipRegion); + } + break; + case CE_FocusFrame: + p->fillRect(opt->rect, opt->palette.foreground()); + break; + case CE_HeaderSection: + qDrawShadePanel(p, opt->rect, opt->palette, + opt->state & State_Sunken, 1, + &opt->palette.brush(QPalette::Button)); + break; + case CE_HeaderEmptyArea: + p->fillRect(opt->rect, opt->palette.background()); + break; +#ifndef QT_NO_COMBOBOX + case CE_ComboBoxLabel: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { + QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget); + p->save(); + p->setClipRect(editRect); + if (!cb->currentIcon.isNull()) { + QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal + : QIcon::Disabled; + QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode); + QRect iconRect(editRect); + iconRect.setWidth(cb->iconSize.width() + 4); + iconRect = alignedRect(cb->direction, + Qt::AlignLeft | Qt::AlignVCenter, + iconRect.size(), editRect); + if (cb->editable) + p->fillRect(iconRect, opt->palette.brush(QPalette::Base)); + proxy()->drawItemPixmap(p, iconRect, Qt::AlignCenter, pixmap); + + if (cb->direction == Qt::RightToLeft) + editRect.translate(-4 - cb->iconSize.width(), 0); + else + editRect.translate(cb->iconSize.width() + 4, 0); + } + if (!cb->currentText.isEmpty() && !cb->editable) { + proxy()->drawItemText(p, editRect.adjusted(1, 0, -1, 0), + visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter), + cb->palette, cb->state & State_Enabled, cb->currentText); + } + p->restore(); + } + break; +#endif // QT_NO_COMBOBOX +#ifndef QT_NO_TOOLBAR + case CE_ToolBar: + if (const QStyleOptionToolBar *toolBar = qstyleoption_cast(opt)) { + // Compatibility with styles that use PE_PanelToolBar + QStyleOptionFrame frame; + frame.QStyleOption::operator=(*toolBar); + frame.lineWidth = toolBar->lineWidth; + frame.midLineWidth = toolBar->midLineWidth; + proxy()->drawPrimitive(PE_PanelToolBar, opt, p, widget); + + if (widget && qobject_cast(widget->parentWidget())) + break; + qDrawShadePanel(p, toolBar->rect, toolBar->palette, false, toolBar->lineWidth, + &toolBar->palette.brush(QPalette::Button)); + } + break; +#endif // QT_NO_TOOLBAR + case CE_ColumnViewGrip: { + // draw background gradients + QLinearGradient g(0, 0, opt->rect.width(), 0); + g.setColorAt(0, opt->palette.color(QPalette::Active, QPalette::Mid)); + g.setColorAt(0.5, Qt::white); + p->fillRect(QRect(0, 0, opt->rect.width(), opt->rect.height()), g); + + // draw the two lines + QPen pen(p->pen()); + pen.setWidth(opt->rect.width()/20); + pen.setColor(opt->palette.color(QPalette::Active, QPalette::Dark)); + p->setPen(pen); + + int line1starting = opt->rect.width()*8 / 20; + int line2starting = opt->rect.width()*13 / 20; + int top = opt->rect.height()*20/75; + int bottom = opt->rect.height() - 1 - top; + p->drawLine(line1starting, top, line1starting, bottom); + p->drawLine(line2starting, top, line2starting, bottom); + } + break; + +#ifndef QT_NO_ITEMVIEWS + case CE_ItemViewItem: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(opt)) { + p->save(); + p->setClipRect(opt->rect); + + QRect checkRect = subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget); + QRect iconRect = subElementRect(SE_ItemViewItemDecoration, vopt, widget); + QRect textRect = subElementRect(SE_ItemViewItemText, vopt, widget); + + // draw the background + proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, widget); + + // draw the check mark + if (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator) { + QStyleOptionViewItemV4 option(*vopt); + option.rect = checkRect; + option.state = option.state & ~QStyle::State_HasFocus; + + switch (vopt->checkState) { + case Qt::Unchecked: + option.state |= QStyle::State_Off; + break; + case Qt::PartiallyChecked: + option.state |= QStyle::State_NoChange; + break; + case Qt::Checked: + option.state |= QStyle::State_On; + break; + } + proxy()->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, p, widget); + } + + // draw the icon + QIcon::Mode mode = QIcon::Normal; + if (!(vopt->state & QStyle::State_Enabled)) + mode = QIcon::Disabled; + else if (vopt->state & QStyle::State_Selected) + mode = QIcon::Selected; + QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off; + vopt->icon.paint(p, iconRect, vopt->decorationAlignment, mode, state); + + // draw the text + if (!vopt->text.isEmpty()) { + QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled + ? QPalette::Normal : QPalette::Disabled; + if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active)) + cg = QPalette::Inactive; + + if (vopt->state & QStyle::State_Selected) { + p->setPen(vopt->palette.color(cg, QPalette::HighlightedText)); + } else { + p->setPen(vopt->palette.color(cg, QPalette::Text)); + } + if (vopt->state & QStyle::State_Editing) { + p->setPen(vopt->palette.color(cg, QPalette::Text)); + p->drawRect(textRect.adjusted(0, 0, -1, -1)); + } + + d->viewItemDrawText(p, vopt, textRect); + } + + // draw the focus rect + if (vopt->state & QStyle::State_HasFocus) { + QStyleOptionFocusRect o; + o.QStyleOption::operator=(*vopt); + o.rect = proxy()->subElementRect(SE_ItemViewItemFocusRect, vopt, widget); + o.state |= QStyle::State_KeyboardFocusChange; + o.state |= QStyle::State_Item; + QPalette::ColorGroup cg = (vopt->state & QStyle::State_Enabled) + ? QPalette::Normal : QPalette::Disabled; + o.backgroundColor = vopt->palette.color(cg, (vopt->state & QStyle::State_Selected) + ? QPalette::Highlight : QPalette::Window); + proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, p, widget); + } + + p->restore(); + } + break; + +#endif // QT_NO_ITEMVIEWS +#ifndef QT_NO_FRAME + case CE_ShapedFrame: + if (const QStyleOptionFrameV3 *f = qstyleoption_cast(opt)) { + int frameShape = f->frameShape; + int frameShadow = QFrame::Plain; + if (f->state & QStyle::State_Sunken) { + frameShadow = QFrame::Sunken; + } else if (f->state & QStyle::State_Raised) { + frameShadow = QFrame::Raised; + } + + int lw = f->lineWidth; + int mlw = f->midLineWidth; + QPalette::ColorRole foregroundRole = QPalette::WindowText; + if (widget) + foregroundRole = widget->foregroundRole(); + + switch (frameShape) { + case QFrame::Box: + if (frameShadow == QFrame::Plain) { + qDrawPlainRect(p, f->rect, f->palette.color(foregroundRole), lw); + } else { + qDrawShadeRect(p, f->rect, f->palette, frameShadow == QFrame::Sunken, lw, mlw); + } + break; + case QFrame::StyledPanel: + //keep the compatibility with Qt 4.4 if there is a proxy style. + //be sure to call drawPrimitive(QStyle::PE_Frame) on the proxy style + if (widget) { + widget->style()->drawPrimitive(QStyle::PE_Frame, opt, p, widget); + } else { + proxy()->drawPrimitive(QStyle::PE_Frame, opt, p, widget); + } + break; + case QFrame::Panel: + if (frameShadow == QFrame::Plain) { + qDrawPlainRect(p, f->rect, f->palette.color(foregroundRole), lw); + } else { + qDrawShadePanel(p, f->rect, f->palette, frameShadow == QFrame::Sunken, lw); + } + break; + case QFrame::WinPanel: + if (frameShadow == QFrame::Plain) { + qDrawPlainRect(p, f->rect, f->palette.color(foregroundRole), lw); + } else { + qDrawWinPanel(p, f->rect, f->palette, frameShadow == QFrame::Sunken); + } + break; + case QFrame::HLine: + case QFrame::VLine: { + QPoint p1, p2; + if (frameShape == QFrame::HLine) { + p1 = QPoint(opt->rect.x(), opt->rect.height() / 2); + p2 = QPoint(opt->rect.x() + opt->rect.width(), p1.y()); + } else { + p1 = QPoint(opt->rect.x()+opt->rect.width() / 2, 0); + p2 = QPoint(p1.x(), opt->rect.height()); + } + if (frameShadow == QFrame::Plain) { + QPen oldPen = p->pen(); + p->setPen(QPen(opt->palette.brush(foregroundRole), lw)); + p->drawLine(p1, p2); + p->setPen(oldPen); + } else { + qDrawShadeLine(p, p1, p2, f->palette, frameShadow == QFrame::Sunken, lw, mlw); + } + break; + } + } + } + break; +#endif + default: + break; + } +} + +/*! + \reimp +*/ +QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, + const QWidget *widget) const +{ + Q_D(const QCommonStyle); + QRect r; + switch (sr) { + case SE_PushButtonContents: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + int dx1, dx2; + dx1 = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget); + if (btn->features & QStyleOptionButton::AutoDefaultButton) + dx1 += proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget); + dx2 = dx1 * 2; + r.setRect(opt->rect.x() + dx1, opt->rect.y() + dx1, opt->rect.width() - dx2, + opt->rect.height() - dx2); + r = visualRect(opt->direction, opt->rect, r); + } + break; + case SE_PushButtonFocusRect: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + int dbw1 = 0, dbw2 = 0; + if (btn->features & QStyleOptionButton::AutoDefaultButton){ + dbw1 = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget); + dbw2 = dbw1 * 2; + } + + int dfw1 = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget) + 1, + dfw2 = dfw1 * 2; + + r.setRect(btn->rect.x() + dfw1 + dbw1, btn->rect.y() + dfw1 + dbw1, + btn->rect.width() - dfw2 - dbw2, btn->rect.height()- dfw2 - dbw2); + r = visualRect(opt->direction, opt->rect, r); + } + break; + case SE_CheckBoxIndicator: + { + int h = proxy()->pixelMetric(PM_IndicatorHeight, opt, widget); + r.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - h) / 2), + proxy()->pixelMetric(PM_IndicatorWidth, opt, widget), h); + r = visualRect(opt->direction, opt->rect, r); + } + break; + + case SE_CheckBoxContents: + { + // Deal with the logical first, then convert it back to screen coords. + QRect ir = visualRect(opt->direction, opt->rect, + subElementRect(SE_CheckBoxIndicator, opt, widget)); + int spacing = proxy()->pixelMetric(PM_CheckBoxLabelSpacing, opt, widget); + r.setRect(ir.right() + spacing, opt->rect.y(), opt->rect.width() - ir.width() - spacing, + opt->rect.height()); + r = visualRect(opt->direction, opt->rect, r); + } + break; + + case SE_CheckBoxFocusRect: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + if (btn->icon.isNull() && btn->text.isEmpty()) { + r = subElementRect(SE_CheckBoxIndicator, opt, widget); + r.adjust(1, 1, -1, -1); + break; + } + // As above, deal with the logical first, then convert it back to screen coords. + QRect cr = visualRect(btn->direction, btn->rect, + subElementRect(SE_CheckBoxContents, btn, widget)); + + QRect iconRect, textRect; + if (!btn->text.isEmpty()) { + textRect = itemTextRect(opt->fontMetrics, cr, Qt::AlignAbsolute | Qt::AlignLeft + | Qt::AlignVCenter | Qt::TextShowMnemonic, + btn->state & State_Enabled, btn->text); + } + if (!btn->icon.isNull()) { + iconRect = itemPixmapRect(cr, Qt::AlignAbsolute | Qt::AlignLeft | Qt::AlignVCenter + | Qt::TextShowMnemonic, + btn->icon.pixmap(btn->iconSize, QIcon::Normal)); + if (!textRect.isEmpty()) + textRect.translate(iconRect.right() + 4, 0); + } + r = iconRect | textRect; + r.adjust(-3, -2, 3, 2); + r = r.intersected(btn->rect); + r = visualRect(btn->direction, btn->rect, r); + } + break; + + case SE_RadioButtonIndicator: + { + int h = proxy()->pixelMetric(PM_ExclusiveIndicatorHeight, opt, widget); + r.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - h) / 2), + proxy()->pixelMetric(PM_ExclusiveIndicatorWidth, opt, widget), h); + r = visualRect(opt->direction, opt->rect, r); + } + break; + + case SE_RadioButtonContents: + { + QRect ir = visualRect(opt->direction, opt->rect, + subElementRect(SE_RadioButtonIndicator, opt, widget)); + int spacing = proxy()->pixelMetric(PM_RadioButtonLabelSpacing, opt, widget); + r.setRect(ir.left() + ir.width() + spacing, opt->rect.y(), opt->rect.width() - ir.width() - spacing, + opt->rect.height()); + r = visualRect(opt->direction, opt->rect, r); + break; + } + + case SE_RadioButtonFocusRect: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + if (btn->icon.isNull() && btn->text.isEmpty()) { + r = subElementRect(SE_RadioButtonIndicator, opt, widget); + r.adjust(1, 1, -1, -1); + break; + } + QRect cr = visualRect(btn->direction, btn->rect, + subElementRect(SE_RadioButtonContents, opt, widget)); + + QRect iconRect, textRect; + if (!btn->text.isEmpty()){ + textRect = itemTextRect(opt->fontMetrics, cr, Qt::AlignAbsolute | Qt::AlignLeft | Qt::AlignVCenter + | Qt::TextShowMnemonic, btn->state & State_Enabled, btn->text); + } + if (!btn->icon.isNull()) { + iconRect = itemPixmapRect(cr, Qt::AlignAbsolute | Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, + btn->icon.pixmap(btn->iconSize, QIcon::Normal)); + if (!textRect.isEmpty()) + textRect.translate(iconRect.right() + 4, 0); + } + r = iconRect | textRect; + r.adjust(-3, -2, 3, 2); + r = r.intersected(btn->rect); + r = visualRect(btn->direction, btn->rect, r); + } + break; +#ifndef QT_NO_SLIDER + case SE_SliderFocusRect: + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget); + int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget); + if (slider->orientation == Qt::Horizontal) + r.setRect(0, tickOffset - 1, slider->rect.width(), thickness + 2); + else + r.setRect(tickOffset - 1, 0, thickness + 2, slider->rect.height()); + r = r.intersected(slider->rect); + r = visualRect(opt->direction, opt->rect, r); + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_PROGRESSBAR + case SE_ProgressBarGroove: + case SE_ProgressBarContents: + case SE_ProgressBarLabel: + if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { + int textw = 0; + bool vertical = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt)) { + vertical = (pb2->orientation == Qt::Vertical); + } + if (!vertical) { + if (pb->textVisible) + textw = qMax(pb->fontMetrics.width(pb->text), pb->fontMetrics.width(QLatin1String("100%"))) + 6; + } + + if ((pb->textAlignment & Qt::AlignCenter) == 0) { + if (sr != SE_ProgressBarLabel) + r.setCoords(pb->rect.left(), pb->rect.top(), + pb->rect.right() - textw, pb->rect.bottom()); + else + r.setCoords(pb->rect.right() - textw, pb->rect.top(), + pb->rect.right(), pb->rect.bottom()); + } else { + r = pb->rect; + } + r = visualRect(pb->direction, pb->rect, r); + } + break; +#endif // QT_NO_PROGRESSBAR +#ifdef QT3_SUPPORT + case SE_Q3DockWindowHandleRect: + if (const QStyleOptionQ3DockWindow *dw = qstyleoption_cast(opt)) { + if (!dw->docked || !dw->closeEnabled) + r.setRect(0, 0, dw->rect.width(), dw->rect.height()); + else { + if (dw->state & State_Horizontal) + r.setRect(0, 15, dw->rect.width(), dw->rect.height() - 15); + else + r.setRect(0, 1, dw->rect.width() - 15, dw->rect.height() - 1); + } + r = visualRect(opt->direction, opt->rect, r); + } + break; +#endif // QT3_SUPPORT +#ifndef QT_NO_COMBOBOX + case SE_ComboBoxFocusRect: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { + int margin = cb->frame ? 3 : 0; + r.setRect(opt->rect.left() + margin, opt->rect.top() + margin, + opt->rect.width() - 2*margin - 16, opt->rect.height() - 2*margin); + r = visualRect(opt->direction, opt->rect, r); + } + break; +#endif // QT_NO_COMBOBOX +#ifndef QT_NO_TOOLBOX + case SE_ToolBoxTabContents: + r = opt->rect; + r.adjust(0, 0, -30, 0); + break; +#endif // QT_NO_TOOLBOX + case SE_HeaderLabel: { + int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget); + r.setRect(opt->rect.x() + margin, opt->rect.y() + margin, + opt->rect.width() - margin * 2, opt->rect.height() - margin * 2); + + if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { + // Subtract width needed for arrow, if there is one + if (header->sortIndicator != QStyleOptionHeader::None) { + if (opt->state & State_Horizontal) + r.setWidth(r.width() - (opt->rect.height() / 2) - (margin * 2)); + else + r.setHeight(r.height() - (opt->rect.width() / 2) - (margin * 2)); + } + } + r = visualRect(opt->direction, opt->rect, r); + break; } + case SE_HeaderArrow: { + int h = opt->rect.height(); + int w = opt->rect.width(); + int x = opt->rect.x(); + int y = opt->rect.y(); + int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget); + + if (opt->state & State_Horizontal) { + int horiz_size = h / 2; + r.setRect(x + w - margin * 2 - horiz_size, y + 5, + horiz_size, h - margin * 2 - 5); + } else { + int vert_size = w / 2; + r.setRect(x + 5, y + h - margin * 2 - vert_size, + w - margin * 2 - 5, vert_size); + } + r = visualRect(opt->direction, opt->rect, r); + break; } + + case SE_RadioButtonClickRect: + r = subElementRect(SE_RadioButtonFocusRect, opt, widget); + r |= subElementRect(SE_RadioButtonIndicator, opt, widget); + break; + case SE_CheckBoxClickRect: + r = subElementRect(SE_CheckBoxFocusRect, opt, widget); + r |= subElementRect(SE_CheckBoxIndicator, opt, widget); + break; +#ifndef QT_NO_TABWIDGET + case SE_TabWidgetTabBar: + if (const QStyleOptionTabWidgetFrame *twf + = qstyleoption_cast(opt)) { + r.setSize(twf->tabBarSize); + const uint alingMask = Qt::AlignLeft | Qt::AlignRight | Qt::AlignHCenter; + switch (twf->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + // Constrain the size now, otherwise, center could get off the page + // This of course repeated for all the other directions + r.setWidth(qMin(r.width(), twf->rect.width() + - twf->leftCornerWidgetSize.width() + - twf->rightCornerWidgetSize.width())); + switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) { + default: + case Qt::AlignLeft: + r.moveTopLeft(QPoint(twf->leftCornerWidgetSize.width(), 0)); + break; + case Qt::AlignHCenter: + r.moveTopLeft(QPoint(twf->rect.center().x() - qRound(r.width() / 2.0f) + + (twf->leftCornerWidgetSize.width() / 2) + - (twf->rightCornerWidgetSize.width() / 2), 0)); + break; + case Qt::AlignRight: + r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width() + - twf->rightCornerWidgetSize.width(), 0)); + break; + } + r = visualRect(twf->direction, twf->rect, r); + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + r.setWidth(qMin(r.width(), twf->rect.width() + - twf->leftCornerWidgetSize.width() + - twf->rightCornerWidgetSize.width())); + switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) { + default: + case Qt::AlignLeft: + r.moveTopLeft(QPoint(twf->leftCornerWidgetSize.width(), + twf->rect.height() - twf->tabBarSize.height())); + break; + case Qt::AlignHCenter: + r.moveTopLeft(QPoint(twf->rect.center().x() - qRound(r.width() / 2.0f) + + (twf->leftCornerWidgetSize.width() / 2) + - (twf->rightCornerWidgetSize.width() / 2), + twf->rect.height() - twf->tabBarSize.height())); + break; + case Qt::AlignRight: + r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width() + - twf->rightCornerWidgetSize.width(), + twf->rect.height() - twf->tabBarSize.height())); + break; + } + r = visualRect(twf->direction, twf->rect, r); + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + r.setHeight(qMin(r.height(), twf->rect.height() + - twf->leftCornerWidgetSize.height() + - twf->rightCornerWidgetSize.height())); + switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) { + default: + case Qt::AlignLeft: + r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width(), + twf->leftCornerWidgetSize.height())); + break; + case Qt::AlignHCenter: + r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width(), + twf->rect.center().y() - r.height() / 2)); + break; + case Qt::AlignRight: + r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width(), + twf->rect.height() - twf->tabBarSize.height() + - twf->rightCornerWidgetSize.height())); + break; + } + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + r.setHeight(qMin(r.height(), twf->rect.height() + - twf->leftCornerWidgetSize.height() + - twf->rightCornerWidgetSize.height())); + switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) { + default: + case Qt::AlignLeft: + r.moveTopLeft(QPoint(0, twf->leftCornerWidgetSize.height())); + break; + case Qt::AlignHCenter: + r.moveTopLeft(QPoint(0, twf->rect.center().y() - r.height() / 2)); + break; + case Qt::AlignRight: + r.moveTopLeft(QPoint(0, twf->rect.height() - twf->tabBarSize.height() + - twf->rightCornerWidgetSize.height())); + break; + } + break; + } + } + break; + case SE_TabWidgetTabPane: + case SE_TabWidgetTabContents: + if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast(opt)) { + QStyleOptionTab tabopt; + tabopt.shape = twf->shape; + int overlap = proxy()->pixelMetric(PM_TabBarBaseOverlap, &tabopt, widget); + if (twf->lineWidth == 0) + overlap = 0; + switch (twf->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + r = QRect(QPoint(0,qMax(twf->tabBarSize.height() - overlap, 0)), + QSize(twf->rect.width(), qMin(twf->rect.height() - twf->tabBarSize.height() + overlap, twf->rect.height()))); + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + r = QRect(QPoint(0,0), QSize(twf->rect.width(), qMin(twf->rect.height() - twf->tabBarSize.height() + overlap, twf->rect.height()))); + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + r = QRect(QPoint(0, 0), QSize(qMin(twf->rect.width() - twf->tabBarSize.width() + overlap, twf->rect.width()), twf->rect.height())); + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + r = QRect(QPoint(qMax(twf->tabBarSize.width() - overlap, 0), 0), + QSize(qMin(twf->rect.width() - twf->tabBarSize.width() + overlap, twf->rect.width()), twf->rect.height())); + break; + } + if (sr == SE_TabWidgetTabContents && twf->lineWidth > 0) + r.adjust(2, 2, -2, -2); + } + break; + case SE_TabWidgetLeftCorner: + if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast(opt)) { + QRect paneRect = subElementRect(SE_TabWidgetTabPane, twf, widget); + switch (twf->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + r = QRect(QPoint(paneRect.x(), paneRect.y() - twf->leftCornerWidgetSize.height()), + twf->leftCornerWidgetSize); + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + r = QRect(QPoint(paneRect.x(), paneRect.height()), twf->leftCornerWidgetSize); + break; + default: + break; + } + r = visualRect(twf->direction, twf->rect, r); + } + break; + case SE_TabWidgetRightCorner: + if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast(opt)) { + QRect paneRect = subElementRect(SE_TabWidgetTabPane, twf, widget); + switch (twf->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + r = QRect(QPoint(paneRect.width() - twf->rightCornerWidgetSize.width(), + paneRect.y() - twf->rightCornerWidgetSize.height()), + twf->rightCornerWidgetSize); + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + r = QRect(QPoint(paneRect.width() - twf->rightCornerWidgetSize.width(), + paneRect.height()), twf->rightCornerWidgetSize); + break; + default: + break; + } + r = visualRect(twf->direction, twf->rect, r); + } + break; + case SE_TabBarTabText: + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + QStyleOptionTabV3 tabV3(*tab); + QRect dummyIconRect; + d->tabLayout(&tabV3, widget, &r, &dummyIconRect); + } + break; + case SE_TabBarTabLeftButton: + case SE_TabBarTabRightButton: + if (const QStyleOptionTabV3 *tab = qstyleoption_cast(opt)) { + bool selected = tab->state & State_Selected; + int verticalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget); + int horizontalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget); + int hpadding = proxy()->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2; + hpadding = qMax(hpadding, 4); //workaround KStyle returning 0 because they workaround an old bug in Qt + + bool verticalTabs = tab->shape == QTabBar::RoundedEast + || tab->shape == QTabBar::RoundedWest + || tab->shape == QTabBar::TriangularEast + || tab->shape == QTabBar::TriangularWest; + + QRect tr = tab->rect; + if (tab->shape == QTabBar::RoundedSouth || tab->shape == QTabBar::TriangularSouth) + verticalShift = -verticalShift; + if (verticalTabs) { + qSwap(horizontalShift, verticalShift); + horizontalShift *= -1; + verticalShift *= -1; + } + if (tab->shape == QTabBar::RoundedWest || tab->shape == QTabBar::TriangularWest) + horizontalShift = -horizontalShift; + + tr.adjust(0, 0, horizontalShift, verticalShift); + if (selected) + { + tr.setBottom(tr.bottom() - verticalShift); + tr.setRight(tr.right() - horizontalShift); + } + + QSize size = (sr == SE_TabBarTabLeftButton) ? tab->leftButtonSize : tab->rightButtonSize; + int w = size.width(); + int h = size.height(); + int midHeight = static_cast(qCeil(float(tr.height() - h) / 2)); + int midWidth = ((tr.width() - w) / 2); + + bool atTheTop = true; + switch (tab->shape) { + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + atTheTop = (sr == SE_TabBarTabLeftButton); + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + atTheTop = (sr == SE_TabBarTabRightButton); + break; + default: + if (sr == SE_TabBarTabLeftButton) + r = QRect(tab->rect.x() + hpadding, midHeight, w, h); + else + r = QRect(tab->rect.right() - w - hpadding, midHeight, w, h); + r = visualRect(tab->direction, tab->rect, r); + } + if (verticalTabs) { + if (atTheTop) + r = QRect(midWidth, tr.y() + tab->rect.height() - hpadding - h, w, h); + else + r = QRect(midWidth, tr.y() + hpadding, w, h); + } + } + + break; +#endif // QT_NO_TABWIDGET +#ifndef QT_NO_TABBAR + case SE_TabBarTearIndicator: + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + switch (tab->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + r.setRect(tab->rect.left(), tab->rect.top(), 4, opt->rect.height()); + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + r.setRect(tab->rect.left(), tab->rect.top(), opt->rect.width(), 4); + break; + default: + break; + } + r = visualRect(opt->direction, opt->rect, r); + } + break; +#endif + case SE_TreeViewDisclosureItem: + r = opt->rect; + break; + case SE_LineEditContents: + if (const QStyleOptionFrame *f = qstyleoption_cast(opt)) { + r = f->rect.adjusted(f->lineWidth, f->lineWidth, -f->lineWidth, -f->lineWidth); + r = visualRect(opt->direction, opt->rect, r); + } + break; + case SE_FrameContents: + if (const QStyleOptionFrameV2 *f = qstyleoption_cast(opt)) { + int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, f, widget); + r = opt->rect.adjusted(fw, fw, -fw, -fw); + r = visualRect(opt->direction, opt->rect, r); + } + break; + case SE_ShapedFrameContents: + if (const QStyleOptionFrameV3 *f = qstyleoption_cast(opt)) { + int frameShape = f->frameShape; + int frameShadow = QFrame::Plain; + if (f->state & QStyle::State_Sunken) { + frameShadow = QFrame::Sunken; + } else if (f->state & QStyle::State_Raised) { + frameShadow = QFrame::Raised; + } + + int frameWidth = 0; + + switch (frameShape) { + case QFrame::NoFrame: + frameWidth = 0; + break; + + case QFrame::Box: + case QFrame::HLine: + case QFrame::VLine: + switch (frameShadow) { + case QFrame::Plain: + frameWidth = f->lineWidth; + break; + case QFrame::Raised: + case QFrame::Sunken: + frameWidth = (short)(f->lineWidth*2 + f->midLineWidth); + break; + } + break; + + case QFrame::StyledPanel: + //keep the compatibility with Qt 4.4 if there is a proxy style. + //be sure to call drawPrimitive(QStyle::SE_FrameContents) on the proxy style + if (widget) + return widget->style()->subElementRect(QStyle::SE_FrameContents, opt, widget); + else + return subElementRect(QStyle::SE_FrameContents, opt, widget); + break; + + case QFrame::WinPanel: + frameWidth = 2; + break; + + case QFrame::Panel: + switch (frameShadow) { + case QFrame::Plain: + case QFrame::Raised: + case QFrame::Sunken: + frameWidth = f->lineWidth; + break; + } + break; + } + r = f->rect.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth); + } + break; +#ifndef QT_NO_DOCKWIDGET + case SE_DockWidgetCloseButton: + case SE_DockWidgetFloatButton: + case SE_DockWidgetTitleBarText: + case SE_DockWidgetIcon: { + int iconSize = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); + int buttonMargin = proxy()->pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget); + int margin = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, opt, widget); + QRect rect = opt->rect; + + const QStyleOptionDockWidget *dwOpt + = qstyleoption_cast(opt); + bool canClose = dwOpt == 0 ? true : dwOpt->closable; + bool canFloat = dwOpt == 0 ? false : dwOpt->floatable; + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(opt); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + + // If this is a vertical titlebar, we transpose and work as if it was + // horizontal, then transpose again. + + if (verticalTitleBar) { + QSize size = rect.size(); + size.transpose(); + rect.setSize(size); + } + + do { + + int right = rect.right(); + int left = rect.left(); + + QRect closeRect; + if (canClose) { + QSize sz = standardIcon(QStyle::SP_TitleBarCloseButton, + opt, widget).actualSize(QSize(iconSize, iconSize)); + sz += QSize(buttonMargin, buttonMargin); + if (verticalTitleBar) + sz.transpose(); + closeRect = QRect(right - sz.width(), + rect.center().y() - sz.height()/2, + sz.width(), sz.height()); + right = closeRect.left() - 1; + } + if (sr == SE_DockWidgetCloseButton) { + r = closeRect; + break; + } + + QRect floatRect; + if (canFloat) { + QSize sz = standardIcon(QStyle::SP_TitleBarNormalButton, + opt, widget).actualSize(QSize(iconSize, iconSize)); + sz += QSize(buttonMargin, buttonMargin); + if (verticalTitleBar) + sz.transpose(); + floatRect = QRect(right - sz.width(), + rect.center().y() - sz.height()/2, + sz.width(), sz.height()); + right = floatRect.left() - 1; + } + if (sr == SE_DockWidgetFloatButton) { + r = floatRect; + break; + } + + QRect iconRect; + if (const QDockWidget *dw = qobject_cast(widget)) { + QIcon icon; + if (dw->isFloating()) + icon = dw->windowIcon(); + if (!icon.isNull() + && icon.cacheKey() != QApplication::windowIcon().cacheKey()) { + QSize sz = icon.actualSize(QSize(r.height(), r.height())); + if (verticalTitleBar) + sz.transpose(); + iconRect = QRect(left, rect.center().y() - sz.height()/2, + sz.width(), sz.height()); + left = iconRect.right() + margin; + } + } + if (sr == SE_DockWidgetIcon) { + r = iconRect; + break; + } + + QRect textRect = QRect(left, rect.top(), + right - left, rect.height()); + if (sr == SE_DockWidgetTitleBarText) { + r = textRect; + break; + } + + } while (false); + + if (verticalTitleBar) { + r = QRect(rect.left() + r.top() - rect.top(), + rect.top() + rect.right() - r.right(), + r.height(), r.width()); + } else { + r = visualRect(opt->direction, rect, r); + } + break; + } +#endif +#ifndef QT_NO_ITEMVIEWS + case SE_ItemViewItemCheckIndicator: + if (!qstyleoption_cast(opt)) { + r = subElementRect(SE_CheckBoxIndicator, opt, widget); + break; + } + case SE_ItemViewItemDecoration: + case SE_ItemViewItemText: + case SE_ItemViewItemFocusRect: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(opt)) { + if (!d->isViewItemCached(*vopt)) { + d->viewItemLayout(vopt, &d->checkRect, &d->decorationRect, &d->displayRect, false); + if (d->cachedOption) { + delete d->cachedOption; + d->cachedOption = 0; + } + d->cachedOption = new QStyleOptionViewItemV4(*vopt); + } + if (sr == SE_ViewItemCheckIndicator) + r = d->checkRect; + else if (sr == SE_ItemViewItemDecoration) + r = d->decorationRect; + else if (sr == SE_ItemViewItemText || sr == SE_ItemViewItemFocusRect) + r = d->displayRect; + } + break; +#endif //QT_NO_ITEMVIEWS +#ifndef QT_NO_TOOLBAR + case SE_ToolBarHandle: + if (const QStyleOptionToolBar *tbopt = qstyleoption_cast(opt)) { + if (tbopt->features & QStyleOptionToolBar::Movable) { + ///we need to access the widget here because the style option doesn't + //have all the information we need (ie. the layout's margin) + const QToolBar *tb = qobject_cast(widget); + const int margin = tb && tb->layout() ? tb->layout()->margin() : 2; + const int handleExtent = pixelMetric(QStyle::PM_ToolBarHandleExtent, opt, tb); + if (tbopt->state & QStyle::State_Horizontal) { + r = QRect(margin, margin, handleExtent, tbopt->rect.height() - 2*margin); + r = QStyle::visualRect(tbopt->direction, tbopt->rect, r); + } else { + r = QRect(margin, margin, tbopt->rect.width() - 2*margin, handleExtent); + } + } + } + break; +#endif //QT_NO_TOOLBAR + default: + break; + } + return r; +} + +#ifndef QT_NO_DIAL + +static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a) +{ + int width = dial->rect.width(); + int height = dial->rect.height(); + int r = qMin(width, height) / 2; + int currentSliderPosition = dial->upsideDown ? dial->sliderPosition : (dial->maximum - dial->sliderPosition); + + if (dial->maximum == dial->minimum) + a = Q_PI / 2; + else if (dial->dialWrapping) + a = Q_PI * 3 / 2 - (currentSliderPosition - dial->minimum) * 2 * Q_PI + / (dial->maximum - dial->minimum); + else + a = (Q_PI * 8 - (currentSliderPosition - dial->minimum) * 10 * Q_PI + / (dial->maximum - dial->minimum)) / 6; + + int xc = width / 2; + int yc = height / 2; + + int len = r - QStyleHelper::calcBigLineSize(r) - 5; + if (len < 5) + len = 5; + int back = len / 2; + + QPolygonF arrow(3); + arrow[0] = QPointF(0.5 + xc + len * qCos(a), + 0.5 + yc - len * qSin(a)); + arrow[1] = QPointF(0.5 + xc + back * qCos(a + Q_PI * 5 / 6), + 0.5 + yc - back * qSin(a + Q_PI * 5 / 6)); + arrow[2] = QPointF(0.5 + xc + back * qCos(a - Q_PI * 5 / 6), + 0.5 + yc - back * qSin(a - Q_PI * 5 / 6)); + return arrow; +} + +#endif // QT_NO_DIAL + +/*! + \reimp +*/ +void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + QPainter *p, const QWidget *widget) const +{ + switch (cc) { +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + if (slider->subControls == SC_SliderTickmarks) { + int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget); + int ticks = slider->tickPosition; + int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget); + int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); + int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget); + int interval = slider->tickInterval; + if (interval <= 0) { + interval = slider->singleStep; + if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval, + available) + - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, + 0, available) < 3) + interval = slider->pageStep; + } + if (!interval) + interval = 1; + int fudge = len / 2; + int pos; + // Since there is no subrect for tickmarks do a translation here. + p->save(); + p->translate(slider->rect.x(), slider->rect.y()); + p->setPen(slider->palette.foreground().color()); + int v = slider->minimum; + while (v <= slider->maximum + 1) { + if (v == slider->maximum + 1 && interval == 1) + break; + const int v_ = qMin(v, slider->maximum); + pos = QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, + v_, available) + fudge; + if (slider->orientation == Qt::Horizontal) { + if (ticks & QSlider::TicksAbove) + p->drawLine(pos, 0, pos, tickOffset - 2); + if (ticks & QSlider::TicksBelow) + p->drawLine(pos, tickOffset + thickness + 1, pos, + slider->rect.height()-1); + } else { + if (ticks & QSlider::TicksAbove) + p->drawLine(0, pos, tickOffset - 2, pos); + if (ticks & QSlider::TicksBelow) + p->drawLine(tickOffset + thickness + 1, pos, + slider->rect.width()-1, pos); + } + // in the case where maximum is max int + int nextInterval = v + interval; + if (nextInterval < v) + break; + v = nextInterval; + } + p->restore(); + } + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(opt)) { + // Make a copy here and reset it for each primitive. + QStyleOptionSlider newScrollbar = *scrollbar; + State saveFlags = scrollbar->state; + + if (scrollbar->subControls & SC_ScrollBarSubLine) { + newScrollbar.state = saveFlags; + newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSubLine, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarSubLine)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + proxy()->drawControl(CE_ScrollBarSubLine, &newScrollbar, p, widget); + } + } + if (scrollbar->subControls & SC_ScrollBarAddLine) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarAddLine, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarAddLine)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + proxy()->drawControl(CE_ScrollBarAddLine, &newScrollbar, p, widget); + } + } + if (scrollbar->subControls & SC_ScrollBarSubPage) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSubPage, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarSubPage)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + proxy()->drawControl(CE_ScrollBarSubPage, &newScrollbar, p, widget); + } + } + if (scrollbar->subControls & SC_ScrollBarAddPage) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarAddPage, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarAddPage)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + proxy()->drawControl(CE_ScrollBarAddPage, &newScrollbar, p, widget); + } + } + if (scrollbar->subControls & SC_ScrollBarFirst) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarFirst, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarFirst)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + proxy()->drawControl(CE_ScrollBarFirst, &newScrollbar, p, widget); + } + } + if (scrollbar->subControls & SC_ScrollBarLast) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarLast, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarLast)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + proxy()->drawControl(CE_ScrollBarLast, &newScrollbar, p, widget); + } + } + if (scrollbar->subControls & SC_ScrollBarSlider) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSlider, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarSlider)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + proxy()->drawControl(CE_ScrollBarSlider, &newScrollbar, p, widget); + + if (scrollbar->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(newScrollbar); + fropt.rect.setRect(newScrollbar.rect.x() + 2, newScrollbar.rect.y() + 2, + newScrollbar.rect.width() - 5, + newScrollbar.rect.height() - 5); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + } + } + break; +#endif // QT_NO_SCROLLBAR +#ifdef QT3_SUPPORT + case CC_Q3ListView: + if (const QStyleOptionQ3ListView *lv = qstyleoption_cast(opt)) { + if (lv->subControls & SC_Q3ListView) + p->fillRect(lv->rect, lv->viewportPalette.brush(lv->viewportBGRole)); + } + break; +#endif // QT3_SUPPORT +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *sb = qstyleoption_cast(opt)) { + QStyleOptionSpinBox copy = *sb; + PrimitiveElement pe; + + if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) { + QRect r = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget); + qDrawWinPanel(p, r, sb->palette, true); + } + + if (sb->subControls & SC_SpinBoxUp) { + copy.subControls = SC_SpinBoxUp; + QPalette pal2 = sb->palette; + if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled)) { + pal2.setCurrentColorGroup(QPalette::Disabled); + copy.state &= ~State_Enabled; + } + + copy.palette = pal2; + + if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken)) { + copy.state |= State_On; + copy.state |= State_Sunken; + } else { + copy.state |= State_Raised; + copy.state &= ~State_Sunken; + } + pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus + : PE_IndicatorSpinUp); + + copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget); + proxy()->drawPrimitive(PE_PanelButtonBevel, ©, p, widget); + copy.rect.adjust(3, 0, -4, 0); + proxy()->drawPrimitive(pe, ©, p, widget); + } + + if (sb->subControls & SC_SpinBoxDown) { + copy.subControls = SC_SpinBoxDown; + copy.state = sb->state; + QPalette pal2 = sb->palette; + if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled)) { + pal2.setCurrentColorGroup(QPalette::Disabled); + copy.state &= ~State_Enabled; + } + copy.palette = pal2; + + if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken)) { + copy.state |= State_On; + copy.state |= State_Sunken; + } else { + copy.state |= State_Raised; + copy.state &= ~State_Sunken; + } + pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus + : PE_IndicatorSpinDown); + + copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget); + proxy()->drawPrimitive(PE_PanelButtonBevel, ©, p, widget); + copy.rect.adjust(3, 0, -4, 0); + proxy()->drawPrimitive(pe, ©, p, widget); + } + } + break; +#endif // QT_NO_SPINBOX +#ifndef QT_NO_TOOLBUTTON + case CC_ToolButton: + if (const QStyleOptionToolButton *toolbutton + = qstyleoption_cast(opt)) { + QRect button, menuarea; + button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget); + menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget); + + State bflags = toolbutton->state & ~State_Sunken; + + if (bflags & State_AutoRaise) { + if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) { + bflags &= ~State_Raised; + } + } + State mflags = bflags; + if (toolbutton->state & State_Sunken) { + if (toolbutton->activeSubControls & SC_ToolButton) + bflags |= State_Sunken; + mflags |= State_Sunken; + } + + QStyleOption tool(0); + tool.palette = toolbutton->palette; + if (toolbutton->subControls & SC_ToolButton) { + if (bflags & (State_Sunken | State_On | State_Raised)) { + tool.rect = button; + tool.state = bflags; + proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + } + } + + if (toolbutton->state & State_HasFocus) { + QStyleOptionFocusRect fr; + fr.QStyleOption::operator=(*toolbutton); + fr.rect.adjust(3, 3, -3, -3); + if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup) + fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, + toolbutton, widget), 0); + proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget); + } + QStyleOptionToolButton label = *toolbutton; + label.state = bflags; + int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); + label.rect = button.adjusted(fw, fw, -fw, -fw); + proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); + + if (toolbutton->subControls & SC_ToolButtonMenu) { + tool.rect = menuarea; + tool.state = mflags; + if (mflags & (State_Sunken | State_On | State_Raised)) + proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget); + } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { + int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget); + QRect ir = toolbutton->rect; + QStyleOptionToolButton newBtn = *toolbutton; + newBtn.rect = QRect(ir.right() + 5 - mbi, ir.y() + ir.height() - mbi + 4, mbi - 6, mbi - 6); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); + } + } + break; +#endif // QT_NO_TOOLBUTTON + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(opt)) { + QRect ir; + if (opt->subControls & SC_TitleBarLabel) { + QColor left = tb->palette.highlight().color(); + QColor right = tb->palette.base().color(); + + QBrush fillBrush(left); + if (left != right) { + QPoint p1(tb->rect.x(), tb->rect.top() + tb->rect.height()/2); + QPoint p2(tb->rect.right(), tb->rect.top() + tb->rect.height()/2); + QLinearGradient lg(p1, p2); + lg.setColorAt(0, left); + lg.setColorAt(1, right); + fillBrush = lg; + } + + p->fillRect(opt->rect, fillBrush); + + ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget); + + p->setPen(tb->palette.highlightedText().color()); + p->drawText(ir.x() + 2, ir.y(), ir.width() - 2, ir.height(), + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text); + } + + bool down = false; + QPixmap pm; + + QStyleOption tool(0); + tool.palette = tb->palette; + if (tb->subControls & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) { + ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarCloseButton, widget); + down = tb->activeSubControls & SC_TitleBarCloseButton && (opt->state & State_Sunken); + if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool +#ifndef QT_NO_DOCKWIDGET + || qobject_cast(widget) +#endif + ) + pm = standardIcon(SP_DockWidgetCloseButton, &tool, widget).pixmap(10, 10); + else + pm = standardIcon(SP_TitleBarCloseButton, &tool, widget).pixmap(10, 10); + tool.rect = ir; + tool.state = down ? State_Sunken : State_Raised; + proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + + p->save(); + if (down) + p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget)); + proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + + if (tb->subControls & SC_TitleBarMaxButton + && tb->titleBarFlags & Qt::WindowMaximizeButtonHint + && !(tb->titleBarState & Qt::WindowMaximized)) { + ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarMaxButton, widget); + + down = tb->activeSubControls & SC_TitleBarMaxButton && (opt->state & State_Sunken); + pm = standardIcon(SP_TitleBarMaxButton, &tool, widget).pixmap(10, 10); + tool.rect = ir; + tool.state = down ? State_Sunken : State_Raised; + proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + + p->save(); + if (down) + p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget)); + proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + + if (tb->subControls & SC_TitleBarMinButton + && tb->titleBarFlags & Qt::WindowMinimizeButtonHint + && !(tb->titleBarState & Qt::WindowMinimized)) { + ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarMinButton, widget); + down = tb->activeSubControls & SC_TitleBarMinButton && (opt->state & State_Sunken); + pm = standardIcon(SP_TitleBarMinButton, &tool, widget).pixmap(10, 10); + tool.rect = ir; + tool.state = down ? State_Sunken : State_Raised; + proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + + p->save(); + if (down) + p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget)); + proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + + bool drawNormalButton = (tb->subControls & SC_TitleBarNormalButton) + && (((tb->titleBarFlags & Qt::WindowMinimizeButtonHint) + && (tb->titleBarState & Qt::WindowMinimized)) + || ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint) + && (tb->titleBarState & Qt::WindowMaximized))); + + if (drawNormalButton) { + ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarNormalButton, widget); + down = tb->activeSubControls & SC_TitleBarNormalButton && (opt->state & State_Sunken); + pm = standardIcon(SP_TitleBarNormalButton, &tool, widget).pixmap(10, 10); + tool.rect = ir; + tool.state = down ? State_Sunken : State_Raised; + proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + + p->save(); + if (down) + p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget)); + proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + + if (tb->subControls & SC_TitleBarShadeButton + && tb->titleBarFlags & Qt::WindowShadeButtonHint + && !(tb->titleBarState & Qt::WindowMinimized)) { + ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarShadeButton, widget); + down = (tb->activeSubControls & SC_TitleBarShadeButton && (opt->state & State_Sunken)); + pm = standardIcon(SP_TitleBarShadeButton, &tool, widget).pixmap(10, 10); + tool.rect = ir; + tool.state = down ? State_Sunken : State_Raised; + proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + p->save(); + if (down) + p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget)); + proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + + if (tb->subControls & SC_TitleBarUnshadeButton + && tb->titleBarFlags & Qt::WindowShadeButtonHint + && tb->titleBarState & Qt::WindowMinimized) { + ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarUnshadeButton, widget); + + down = tb->activeSubControls & SC_TitleBarUnshadeButton && (opt->state & State_Sunken); + pm = standardIcon(SP_TitleBarUnshadeButton, &tool, widget).pixmap(10, 10); + tool.rect = ir; + tool.state = down ? State_Sunken : State_Raised; + proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + p->save(); + if (down) + p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget)); + proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + if (tb->subControls & SC_TitleBarContextHelpButton + && tb->titleBarFlags & Qt::WindowContextHelpButtonHint) { + ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarContextHelpButton, widget); + + down = tb->activeSubControls & SC_TitleBarContextHelpButton && (opt->state & State_Sunken); + pm = standardIcon(SP_TitleBarContextHelpButton, &tool, widget).pixmap(10, 10); + tool.rect = ir; + tool.state = down ? State_Sunken : State_Raised; + proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + p->save(); + if (down) + p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget)); + proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + if (tb->subControls & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) { + ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarSysMenu, widget); + if (!tb->icon.isNull()) { + tb->icon.paint(p, ir); + } else { + int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget); + pm = standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(iconSize, iconSize); + tool.rect = ir; + p->save(); + proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + } + } + break; +#ifndef QT_NO_DIAL + case CC_Dial: + if (const QStyleOptionSlider *dial = qstyleoption_cast(opt)) { + // OK, this is more a port of things over + p->save(); + + // avoid dithering + if (p->paintEngine()->hasFeature(QPaintEngine::Antialiasing)) + p->setRenderHint(QPainter::Antialiasing); + + int width = dial->rect.width(); + int height = dial->rect.height(); + qreal r = qMin(width, height) / 2; + qreal d_ = r / 6; + qreal dx = dial->rect.x() + d_ + (width - 2 * r) / 2 + 1; + qreal dy = dial->rect.y() + d_ + (height - 2 * r) / 2 + 1; + QRect br = QRect(int(dx), int(dy), int(r * 2 - 2 * d_ - 2), int(r * 2 - 2 * d_ - 2)); + + QPalette pal = opt->palette; + // draw notches + if (dial->subControls & QStyle::SC_DialTickmarks) { + p->setPen(pal.foreground().color()); + p->drawLines(QStyleHelper::calcLines(dial)); + } + + if (dial->state & State_Enabled) { + p->setBrush(pal.brush(QPalette::ColorRole(proxy()->styleHint(SH_Dial_BackgroundRole, + dial, widget)))); + p->setPen(Qt::NoPen); + p->drawEllipse(br); + p->setBrush(Qt::NoBrush); + } + p->setPen(QPen(pal.dark().color())); + p->drawArc(br, 60 * 16, 180 * 16); + p->setPen(QPen(pal.light().color())); + p->drawArc(br, 240 * 16, 180 * 16); + + qreal a; + QPolygonF arrow(calcArrow(dial, a)); + + p->setPen(Qt::NoPen); + p->setBrush(pal.button()); + p->drawPolygon(arrow); + + a = QStyleHelper::angle(QPointF(width / 2, height / 2), arrow[0]); + p->setBrush(Qt::NoBrush); + + if (a <= 0 || a > 200) { + p->setPen(pal.light().color()); + p->drawLine(arrow[2], arrow[0]); + p->drawLine(arrow[1], arrow[2]); + p->setPen(pal.dark().color()); + p->drawLine(arrow[0], arrow[1]); + } else if (a > 0 && a < 45) { + p->setPen(pal.light().color()); + p->drawLine(arrow[2], arrow[0]); + p->setPen(pal.dark().color()); + p->drawLine(arrow[1], arrow[2]); + p->drawLine(arrow[0], arrow[1]); + } else if (a >= 45 && a < 135) { + p->setPen(pal.dark().color()); + p->drawLine(arrow[2], arrow[0]); + p->drawLine(arrow[1], arrow[2]); + p->setPen(pal.light().color()); + p->drawLine(arrow[0], arrow[1]); + } else if (a >= 135 && a < 200) { + p->setPen(pal.dark().color()); + p->drawLine(arrow[2], arrow[0]); + p->setPen(pal.light().color()); + p->drawLine(arrow[0], arrow[1]); + p->drawLine(arrow[1], arrow[2]); + } + + // draw focus rect around the dial + QStyleOptionFocusRect fropt; + fropt.rect = dial->rect; + fropt.state = dial->state; + fropt.palette = dial->palette; + if (fropt.state & QStyle::State_HasFocus) { + br.adjust(0, 0, 2, 2); + if (dial->subControls & SC_DialTickmarks) { + int r = qMin(width, height) / 2; + br.translate(-r / 6, - r / 6); + br.setWidth(br.width() + r / 3); + br.setHeight(br.height() + r / 3); + } + fropt.rect = br.adjusted(-2, -2, 2, 2); + proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, p, widget); + } + p->restore(); + } + break; +#endif // QT_NO_DIAL +#ifndef QT_NO_GROUPBOX + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(opt)) { + // Draw frame + QRect textRect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, widget); + QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, widget); + if (groupBox->subControls & QStyle::SC_GroupBoxFrame) { + QStyleOptionFrameV2 frame; + frame.QStyleOption::operator=(*groupBox); + frame.features = groupBox->features; + frame.lineWidth = groupBox->lineWidth; + frame.midLineWidth = groupBox->midLineWidth; + frame.rect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, widget); + p->save(); + QRegion region(groupBox->rect); + if (!groupBox->text.isEmpty()) { + bool ltr = groupBox->direction == Qt::LeftToRight; + QRect finalRect; + if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) { + finalRect = checkBoxRect.united(textRect); + finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0); + } else { + finalRect = textRect; + } + region -= finalRect; + } + p->setClipRegion(region); + proxy()->drawPrimitive(PE_FrameGroupBox, &frame, p, widget); + p->restore(); + } + + // Draw title + if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) { + QColor textColor = groupBox->textColor; + if (textColor.isValid()) + p->setPen(textColor); + int alignment = int(groupBox->textAlignment); + if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, opt, widget)) + alignment |= Qt::TextHideMnemonic; + + proxy()->drawItemText(p, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment, + groupBox->palette, groupBox->state & State_Enabled, groupBox->text, + textColor.isValid() ? QPalette::NoRole : QPalette::WindowText); + + if (groupBox->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*groupBox); + fropt.rect = textRect; + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + + // Draw checkbox + if (groupBox->subControls & SC_GroupBoxCheckBox) { + QStyleOptionButton box; + box.QStyleOption::operator=(*groupBox); + box.rect = checkBoxRect; + proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, p, widget); + } + } + break; +#endif // QT_NO_GROUPBOX +#ifndef QT_NO_WORKSPACE + case CC_MdiControls: + { + QStyleOptionButton btnOpt; + btnOpt.QStyleOption::operator=(*opt); + btnOpt.state &= ~State_MouseOver; + int bsx = 0; + int bsy = 0; + if (opt->subControls & QStyle::SC_MdiCloseButton) { + if (opt->activeSubControls & QStyle::SC_MdiCloseButton && (opt->state & State_Sunken)) { + btnOpt.state |= State_Sunken; + btnOpt.state &= ~State_Raised; + bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal); + bsy = proxy()->pixelMetric(PM_ButtonShiftVertical); + } else { + btnOpt.state |= State_Raised; + btnOpt.state &= ~State_Sunken; + bsx = 0; + bsy = 0; + } + btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiCloseButton, widget); + proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget); + QPixmap pm = standardIcon(SP_TitleBarCloseButton).pixmap(16, 16); + proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm); + } + if (opt->subControls & QStyle::SC_MdiNormalButton) { + if (opt->activeSubControls & QStyle::SC_MdiNormalButton && (opt->state & State_Sunken)) { + btnOpt.state |= State_Sunken; + btnOpt.state &= ~State_Raised; + bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal); + bsy = proxy()->pixelMetric(PM_ButtonShiftVertical); + } else { + btnOpt.state |= State_Raised; + btnOpt.state &= ~State_Sunken; + bsx = 0; + bsy = 0; + } + btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiNormalButton, widget); + proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget); + QPixmap pm = standardIcon(SP_TitleBarNormalButton).pixmap(16, 16); + proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm); + } + if (opt->subControls & QStyle::SC_MdiMinButton) { + if (opt->activeSubControls & QStyle::SC_MdiMinButton && (opt->state & State_Sunken)) { + btnOpt.state |= State_Sunken; + btnOpt.state &= ~State_Raised; + bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal); + bsy = proxy()->pixelMetric(PM_ButtonShiftVertical); + } else { + btnOpt.state |= State_Raised; + btnOpt.state &= ~State_Sunken; + bsx = 0; + bsy = 0; + } + btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiMinButton, widget); + proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget); + QPixmap pm = standardIcon(SP_TitleBarMinButton).pixmap(16, 16); + proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm); + } + } + break; +#endif // QT_NO_WORKSPACE + + default: + qWarning("QCommonStyle::drawComplexControl: Control %d not handled", cc); + } +} + +/*! + \reimp +*/ +QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *widget) const +{ + SubControl sc = SC_None; + switch (cc) { +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + QRect r = proxy()->subControlRect(cc, slider, SC_SliderHandle, widget); + if (r.isValid() && r.contains(pt)) { + sc = SC_SliderHandle; + } else { + r = proxy()->subControlRect(cc, slider, SC_SliderGroove ,widget); + if (r.isValid() && r.contains(pt)) + sc = SC_SliderGroove; + } + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(opt)) { + QRect r; + uint ctrl = SC_ScrollBarAddLine; + while (ctrl <= SC_ScrollBarGroove) { + r = proxy()->subControlRect(cc, scrollbar, QStyle::SubControl(ctrl), widget); + if (r.isValid() && r.contains(pt)) { + sc = QStyle::SubControl(ctrl); + break; + } + ctrl <<= 1; + } + } + break; +#endif // QT_NO_SCROLLBAR +#ifndef QT_NO_TOOLBUTTON + case CC_ToolButton: + if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast(opt)) { + QRect r; + uint ctrl = SC_ToolButton; + while (ctrl <= SC_ToolButtonMenu) { + r = proxy()->subControlRect(cc, toolbutton, QStyle::SubControl(ctrl), widget); + if (r.isValid() && r.contains(pt)) { + sc = QStyle::SubControl(ctrl); + break; + } + ctrl <<= 1; + } + } + break; +#endif // QT_NO_TOOLBUTTON +#ifdef QT3_SUPPORT + case CC_Q3ListView: + if (const QStyleOptionQ3ListView *lv = qstyleoption_cast(opt)) { + if (pt.x() >= 0 && pt.x() < lv->treeStepSize) + sc = SC_Q3ListViewExpand; + } + break; +#endif // QT3_SUPPORT +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(opt)) { + QRect r; + uint ctrl = SC_SpinBoxUp; + while (ctrl <= SC_SpinBoxEditField) { + r = proxy()->subControlRect(cc, spinbox, QStyle::SubControl(ctrl), widget); + if (r.isValid() && r.contains(pt)) { + sc = QStyle::SubControl(ctrl); + break; + } + ctrl <<= 1; + } + } + break; +#endif // QT_NO_SPINBOX + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(opt)) { + QRect r; + uint ctrl = SC_TitleBarSysMenu; + + while (ctrl <= SC_TitleBarLabel) { + r = proxy()->subControlRect(cc, tb, QStyle::SubControl(ctrl), widget); + if (r.isValid() && r.contains(pt)) { + sc = QStyle::SubControl(ctrl); + break; + } + ctrl <<= 1; + } + } + break; +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { + QRect r; + uint ctrl = SC_ComboBoxArrow; // Start here and go down. + while (ctrl > 0) { + r = proxy()->subControlRect(cc, cb, QStyle::SubControl(ctrl), widget); + if (r.isValid() && r.contains(pt)) { + sc = QStyle::SubControl(ctrl); + break; + } + ctrl >>= 1; + } + } + break; +#endif // QT_NO_COMBOBOX +#ifndef QT_NO_GROUPBOX + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(opt)) { + QRect r; + uint ctrl = SC_GroupBoxCheckBox; + while (ctrl <= SC_GroupBoxFrame) { + r = proxy()->subControlRect(cc, groupBox, QStyle::SubControl(ctrl), widget); + if (r.isValid() && r.contains(pt)) { + sc = QStyle::SubControl(ctrl); + break; + } + ctrl <<= 1; + } + } + break; +#endif // QT_NO_GROUPBOX + case CC_MdiControls: + { + QRect r; + uint ctrl = SC_MdiMinButton; + while (ctrl <= SC_MdiCloseButton) { + r = proxy()->subControlRect(CC_MdiControls, opt, QStyle::SubControl(ctrl), widget); + if (r.isValid() && r.contains(pt) && (opt->subControls & ctrl)) { + sc = QStyle::SubControl(ctrl); + return sc; + } + ctrl <<= 1; + } + } + break; + default: + qWarning("QCommonStyle::hitTestComplexControl: Case %d not handled", cc); + } + return sc; +} + +/*! + \reimp +*/ +QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, + SubControl sc, const QWidget *widget) const +{ + QRect ret; + switch (cc) { +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget); + int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget); + + switch (sc) { + case SC_SliderHandle: { + int sliderPos = 0; + int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); + bool horizontal = slider->orientation == Qt::Horizontal; + sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum, + slider->sliderPosition, + (horizontal ? slider->rect.width() + : slider->rect.height()) - len, + slider->upsideDown); + if (horizontal) + ret.setRect(slider->rect.x() + sliderPos, slider->rect.y() + tickOffset, len, thickness); + else + ret.setRect(slider->rect.x() + tickOffset, slider->rect.y() + sliderPos, thickness, len); + break; } + case SC_SliderGroove: + if (slider->orientation == Qt::Horizontal) + ret.setRect(slider->rect.x(), slider->rect.y() + tickOffset, + slider->rect.width(), thickness); + else + ret.setRect(slider->rect.x() + tickOffset, slider->rect.y(), + thickness, slider->rect.height()); + break; + default: + break; + } + ret = visualRect(slider->direction, slider->rect, ret); + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(opt)) { + const QRect scrollBarRect = scrollbar->rect; + int sbextent = proxy()->pixelMetric(PM_ScrollBarExtent, scrollbar, widget); + int maxlen = ((scrollbar->orientation == Qt::Horizontal) ? + scrollBarRect.width() : scrollBarRect.height()) - (sbextent * 2); + int sliderlen; + + // calculate slider length + if (scrollbar->maximum != scrollbar->minimum) { + uint range = scrollbar->maximum - scrollbar->minimum; + sliderlen = (qint64(scrollbar->pageStep) * maxlen) / (range + scrollbar->pageStep); + + int slidermin = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollbar, widget); + if (sliderlen < slidermin || range > INT_MAX / 2) + sliderlen = slidermin; + if (sliderlen > maxlen) + sliderlen = maxlen; + } else { + sliderlen = maxlen; + } + + int sliderstart = sbextent + sliderPositionFromValue(scrollbar->minimum, + scrollbar->maximum, + scrollbar->sliderPosition, + maxlen - sliderlen, + scrollbar->upsideDown); + + switch (sc) { + case SC_ScrollBarSubLine: // top/left button + if (scrollbar->orientation == Qt::Horizontal) { + int buttonWidth = qMin(scrollBarRect.width() / 2, sbextent); + ret.setRect(0, 0, buttonWidth, scrollBarRect.height()); + } else { + int buttonHeight = qMin(scrollBarRect.height() / 2, sbextent); + ret.setRect(0, 0, scrollBarRect.width(), buttonHeight); + } + break; + case SC_ScrollBarAddLine: // bottom/right button + if (scrollbar->orientation == Qt::Horizontal) { + int buttonWidth = qMin(scrollBarRect.width()/2, sbextent); + ret.setRect(scrollBarRect.width() - buttonWidth, 0, buttonWidth, scrollBarRect.height()); + } else { + int buttonHeight = qMin(scrollBarRect.height()/2, sbextent); + ret.setRect(0, scrollBarRect.height() - buttonHeight, scrollBarRect.width(), buttonHeight); + } + break; + case SC_ScrollBarSubPage: // between top/left button and slider + if (scrollbar->orientation == Qt::Horizontal) + ret.setRect(sbextent, 0, sliderstart - sbextent, scrollBarRect.height()); + else + ret.setRect(0, sbextent, scrollBarRect.width(), sliderstart - sbextent); + break; + case SC_ScrollBarAddPage: // between bottom/right button and slider + if (scrollbar->orientation == Qt::Horizontal) + ret.setRect(sliderstart + sliderlen, 0, + maxlen - sliderstart - sliderlen + sbextent, scrollBarRect.height()); + else + ret.setRect(0, sliderstart + sliderlen, scrollBarRect.width(), + maxlen - sliderstart - sliderlen + sbextent); + break; + case SC_ScrollBarGroove: + if (scrollbar->orientation == Qt::Horizontal) + ret.setRect(sbextent, 0, scrollBarRect.width() - sbextent * 2, + scrollBarRect.height()); + else + ret.setRect(0, sbextent, scrollBarRect.width(), + scrollBarRect.height() - sbextent * 2); + break; + case SC_ScrollBarSlider: + if (scrollbar->orientation == Qt::Horizontal) + ret.setRect(sliderstart, 0, sliderlen, scrollBarRect.height()); + else + ret.setRect(0, sliderstart, scrollBarRect.width(), sliderlen); + break; + default: + break; + } + ret = visualRect(scrollbar->direction, scrollBarRect, ret); + } + break; +#endif // QT_NO_SCROLLBAR +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(opt)) { + QSize bs; + int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0; + bs.setHeight(qMax(8, spinbox->rect.height()/2 - fw)); + // 1.6 -approximate golden mean + bs.setWidth(qMax(16, qMin(bs.height() * 8 / 5, spinbox->rect.width() / 4))); + bs = bs.expandedTo(QApplication::globalStrut()); + int y = fw + spinbox->rect.y(); + int x, lx, rx; + x = spinbox->rect.x() + spinbox->rect.width() - fw - bs.width(); + lx = fw; + rx = x - fw; + switch (sc) { + case SC_SpinBoxUp: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + ret = QRect(x, y, bs.width(), bs.height()); + break; + case SC_SpinBoxDown: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + + ret = QRect(x, y + bs.height(), bs.width(), bs.height()); + break; + case SC_SpinBoxEditField: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) { + ret = QRect(lx, fw, spinbox->rect.width() - 2*fw, spinbox->rect.height() - 2*fw); + } else { + ret = QRect(lx, fw, rx, spinbox->rect.height() - 2*fw); + } + break; + case SC_SpinBoxFrame: + ret = spinbox->rect; + default: + break; + } + ret = visualRect(spinbox->direction, spinbox->rect, ret); + } + break; +#endif // Qt_NO_SPINBOX +#ifndef QT_NO_TOOLBUTTON + case CC_ToolButton: + if (const QStyleOptionToolButton *tb = qstyleoption_cast(opt)) { + int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, tb, widget); + ret = tb->rect; + switch (sc) { + case SC_ToolButton: + if ((tb->features + & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay)) + == QStyleOptionToolButton::MenuButtonPopup) + ret.adjust(0, 0, -mbi, 0); + break; + case SC_ToolButtonMenu: + if ((tb->features + & (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay)) + == QStyleOptionToolButton::MenuButtonPopup) + ret.adjust(ret.width() - mbi, 0, 0, 0); + break; + default: + break; + } + ret = visualRect(tb->direction, tb->rect, ret); + } + break; +#endif // QT_NO_TOOLBUTTON +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { + int x = cb->rect.x(), + y = cb->rect.y(), + wi = cb->rect.width(), + he = cb->rect.height(); + int xpos = x; + int margin = cb->frame ? 3 : 0; + int bmarg = cb->frame ? 2 : 0; + xpos += wi - bmarg - 16; + + + switch (sc) { + case SC_ComboBoxFrame: + ret = cb->rect; + break; + case SC_ComboBoxArrow: + ret.setRect(xpos, y + bmarg, 16, he - 2*bmarg); + break; + case SC_ComboBoxEditField: + ret.setRect(x + margin, y + margin, wi - 2 * margin - 16, he - 2 * margin); + break; + case SC_ComboBoxListBoxPopup: + ret = cb->rect; + break; + default: + break; + } + ret = visualRect(cb->direction, cb->rect, ret); + } + break; +#endif // QT_NO_COMBOBOX + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(opt)) { + const int controlMargin = 2; + const int controlHeight = tb->rect.height() - controlMargin *2; + const int delta = controlHeight + controlMargin; + int offset = 0; + + bool isMinimized = tb->titleBarState & Qt::WindowMinimized; + bool isMaximized = tb->titleBarState & Qt::WindowMaximized; + + switch (sc) { + case SC_TitleBarLabel: + if (tb->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) { + ret = tb->rect; + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + ret.adjust(delta, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowShadeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) + ret.adjust(0, 0, -delta, 0); + } + break; + case SC_TitleBarContextHelpButton: + if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) + offset += delta; + case SC_TitleBarMinButton: + if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarMinButton) + break; + case SC_TitleBarNormalButton: + if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarNormalButton) + break; + case SC_TitleBarMaxButton: + if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarMaxButton) + break; + case SC_TitleBarShadeButton: + if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarShadeButton) + break; + case SC_TitleBarUnshadeButton: + if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarUnshadeButton) + break; + case SC_TitleBarCloseButton: + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + offset += delta; + else if (sc == SC_TitleBarCloseButton) + break; + ret.setRect(tb->rect.right() - offset, tb->rect.top() + controlMargin, + controlHeight, controlHeight); + break; + case SC_TitleBarSysMenu: + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) { + ret.setRect(tb->rect.left() + controlMargin, tb->rect.top() + controlMargin, + controlHeight, controlHeight); + } + break; + default: + break; + } + ret = visualRect(tb->direction, tb->rect, ret); + } + break; +#ifndef QT_NO_GROUPBOX + case CC_GroupBox: { + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(opt)) { + switch (sc) { + case SC_GroupBoxFrame: + // FALL THROUGH + case SC_GroupBoxContents: { + int topMargin = 0; + int topHeight = 0; + int verticalAlignment = proxy()->styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget); + if (groupBox->text.size() || (groupBox->subControls & QStyle::SC_GroupBoxCheckBox)) { + topHeight = groupBox->fontMetrics.height(); + if (verticalAlignment & Qt::AlignVCenter) + topMargin = topHeight / 2; + else if (verticalAlignment & Qt::AlignTop) + topMargin = topHeight; + } + + QRect frameRect = groupBox->rect; + frameRect.setTop(topMargin); + + if (sc == SC_GroupBoxFrame) { + ret = frameRect; + break; + } + + int frameWidth = 0; + if (!(widget && widget->inherits("Q3GroupBox")) + && ((groupBox->features & QStyleOptionFrameV2::Flat) == 0)) { + frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth, groupBox, widget); + } + ret = frameRect.adjusted(frameWidth, frameWidth + topHeight - topMargin, + -frameWidth, -frameWidth); + break; + } + case SC_GroupBoxCheckBox: + // FALL THROUGH + case SC_GroupBoxLabel: { + QFontMetrics fontMetrics = groupBox->fontMetrics; + int h = fontMetrics.height(); + int tw = fontMetrics.size(Qt::TextShowMnemonic, groupBox->text + QLatin1Char(' ')).width(); + int marg = (groupBox->features & QStyleOptionFrameV2::Flat) ? 0 : 8; + ret = groupBox->rect.adjusted(marg, 0, -marg, 0); + ret.setHeight(h); + + int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget); + int indicatorSpace = proxy()->pixelMetric(PM_CheckBoxLabelSpacing, opt, widget) - 1; + bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox; + int checkBoxSize = hasCheckBox ? (indicatorWidth + indicatorSpace) : 0; + + // Adjusted rect for label + indicatorWidth + indicatorSpace + QRect totalRect = alignedRect(groupBox->direction, groupBox->textAlignment, + QSize(tw + checkBoxSize, h), ret); + + // Adjust totalRect if checkbox is set + if (hasCheckBox) { + bool ltr = groupBox->direction == Qt::LeftToRight; + int left = 0; + // Adjust for check box + if (sc == SC_GroupBoxCheckBox) { + int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, opt, widget); + left = ltr ? totalRect.left() : (totalRect.right() - indicatorWidth); + int top = totalRect.top() + (fontMetrics.height() - indicatorHeight) / 2; + totalRect.setRect(left, top, indicatorWidth, indicatorHeight); + // Adjust for label + } else { + left = ltr ? (totalRect.left() + checkBoxSize - 2) : totalRect.left(); + totalRect.setRect(left, totalRect.top(), + totalRect.width() - checkBoxSize, totalRect.height()); + } + } + ret = totalRect; + break; + } + default: + break; + } + } + break; + } +#endif // QT_NO_GROUPBOX +#ifndef QT_NO_WORKSPACE + case CC_MdiControls: + { + int numSubControls = 0; + if (opt->subControls & SC_MdiCloseButton) + ++numSubControls; + if (opt->subControls & SC_MdiMinButton) + ++numSubControls; + if (opt->subControls & SC_MdiNormalButton) + ++numSubControls; + if (numSubControls == 0) + break; + + int buttonWidth = opt->rect.width()/ numSubControls - 1; + int offset = 0; + switch (sc) { + case SC_MdiCloseButton: + // Only one sub control, no offset needed. + if (numSubControls == 1) + break; + offset += buttonWidth + 2; + //FALL THROUGH + case SC_MdiNormalButton: + // No offset needed if + // 1) There's only one sub control + // 2) We have a close button and a normal button (offset already added in SC_MdiClose) + if (numSubControls == 1 || (numSubControls == 2 && !(opt->subControls & SC_MdiMinButton))) + break; + if (opt->subControls & SC_MdiNormalButton) + offset += buttonWidth; + break; + default: + break; + } + + // Subtract one pixel if we only have one sub control. At this point + // buttonWidth is the actual width + 1 pixel margin, but we don't want the + // margin when there are no other controllers. + if (numSubControls == 1) + --buttonWidth; + ret = QRect(offset, 0, buttonWidth, opt->rect.height()); + break; + } +#endif // QT_NO_WORKSPACE + default: + qWarning("QCommonStyle::subControlRect: Case %d not handled", cc); + } + return ret; +} + +/*! \reimp */ +int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWidget *widget) const +{ + int ret; + + switch (m) { + case PM_FocusFrameVMargin: + case PM_FocusFrameHMargin: + ret = 2; + break; + case PM_MenuBarVMargin: + case PM_MenuBarHMargin: + ret = 0; + break; + case PM_DialogButtonsSeparator: + ret = int(QStyleHelper::dpiScaled(5.)); + break; + case PM_DialogButtonsButtonWidth: + ret = int(QStyleHelper::dpiScaled(70.)); + break; + case PM_DialogButtonsButtonHeight: + ret = int(QStyleHelper::dpiScaled(30.)); + break; + case PM_CheckListControllerSize: + case PM_CheckListButtonSize: + ret = int(QStyleHelper::dpiScaled(16.)); + break; + case PM_TitleBarHeight: { + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(opt)) { + if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool) { + ret = qMax(widget ? widget->fontMetrics().height() : opt->fontMetrics.height(), 16); +#ifndef QT_NO_DOCKWIDGET + } else if (qobject_cast(widget)) { + ret = qMax(widget->fontMetrics().height(), int(QStyleHelper::dpiScaled(13))); +#endif + } else { + ret = qMax(widget ? widget->fontMetrics().height() : opt->fontMetrics.height(), 18); + } + } else { + ret = int(QStyleHelper::dpiScaled(18.)); + } + + break; } + case PM_ScrollBarSliderMin: + ret = int(QStyleHelper::dpiScaled(9.)); + break; + + case PM_ButtonMargin: + ret = int(QStyleHelper::dpiScaled(6.)); + break; + + case PM_DockWidgetTitleBarButtonMargin: + ret = int(QStyleHelper::dpiScaled(2.)); + break; + + case PM_ButtonDefaultIndicator: + ret = 0; + break; + + case PM_MenuButtonIndicator: + ret = int(QStyleHelper::dpiScaled(12.)); + break; + + case PM_ButtonShiftHorizontal: + case PM_ButtonShiftVertical: + + case PM_DefaultFrameWidth: + ret = 2; + break; + + case PM_ComboBoxFrameWidth: + case PM_SpinBoxFrameWidth: + case PM_MenuPanelWidth: + case PM_TabBarBaseOverlap: + case PM_TabBarBaseHeight: + ret = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); + break; + + case PM_MdiSubWindowFrameWidth: + ret = int(QStyleHelper::dpiScaled(4.)); + break; + + case PM_MdiSubWindowMinimizedWidth: + ret = int(QStyleHelper::dpiScaled(196.)); + break; + +#ifndef QT_NO_SCROLLBAR + case PM_ScrollBarExtent: + if (const QStyleOptionSlider *sb = qstyleoption_cast(opt)) { + int s = sb->orientation == Qt::Horizontal ? + QApplication::globalStrut().height() + : QApplication::globalStrut().width(); + ret = qMax(16, s); + } else { + ret = int(QStyleHelper::dpiScaled(16.)); + } + break; +#endif + case PM_MaximumDragDistance: + ret = -1; + break; + +#ifndef QT_NO_SLIDER + case PM_SliderThickness: + ret = int(QStyleHelper::dpiScaled(16.)); + break; + + case PM_SliderTickmarkOffset: + if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { + int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height() + : sl->rect.width(); + int thickness = proxy()->pixelMetric(PM_SliderControlThickness, sl, widget); + int ticks = sl->tickPosition; + + if (ticks == QSlider::TicksBothSides) + ret = (space - thickness) / 2; + else if (ticks == QSlider::TicksAbove) + ret = space - thickness; + else + ret = 0; + } else { + ret = 0; + } + break; + + case PM_SliderSpaceAvailable: + if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { + if (sl->orientation == Qt::Horizontal) + ret = sl->rect.width() - proxy()->pixelMetric(PM_SliderLength, sl, widget); + else + ret = sl->rect.height() - proxy()->pixelMetric(PM_SliderLength, sl, widget); + } else { + ret = 0; + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_DOCKWIDGET + case PM_DockWidgetSeparatorExtent: + ret = int(QStyleHelper::dpiScaled(6.)); + break; + + case PM_DockWidgetHandleExtent: + ret = int(QStyleHelper::dpiScaled(8.)); + break; + case PM_DockWidgetTitleMargin: + ret = 0; + break; + case PM_DockWidgetFrameWidth: + ret = 1; + break; +#endif // QT_NO_DOCKWIDGET + + case PM_SpinBoxSliderHeight: + case PM_MenuBarPanelWidth: + ret = 2; + break; + + case PM_MenuBarItemSpacing: + ret = 0; + break; + +#ifndef QT_NO_TOOLBAR + case PM_ToolBarFrameWidth: + ret = 1; + break; + + case PM_ToolBarItemMargin: + ret = 0; + break; + + case PM_ToolBarItemSpacing: + ret = int(QStyleHelper::dpiScaled(4.)); + break; + + case PM_ToolBarHandleExtent: + ret = int(QStyleHelper::dpiScaled(8.)); + break; + + case PM_ToolBarSeparatorExtent: + ret = int(QStyleHelper::dpiScaled(6.)); + break; + + case PM_ToolBarExtensionExtent: + ret = int(QStyleHelper::dpiScaled(12.)); + break; +#endif // QT_NO_TOOLBAR + +#ifndef QT_NO_TABBAR + case PM_TabBarTabOverlap: + ret = 3; + break; + + case PM_TabBarTabHSpace: + ret = int(QStyleHelper::dpiScaled(24.)); + break; + + case PM_TabBarTabShiftHorizontal: + ret = 0; + break; + + case PM_TabBarTabShiftVertical: + ret = 2; + break; + + case PM_TabBarTabVSpace: { + const QStyleOptionTab *tb = qstyleoption_cast(opt); + if (tb && (tb->shape == QTabBar::RoundedNorth || tb->shape == QTabBar::RoundedSouth + || tb->shape == QTabBar::RoundedWest || tb->shape == QTabBar::RoundedEast)) + ret = 8; + else + if(tb && (tb->shape == QTabBar::TriangularWest || tb->shape == QTabBar::TriangularEast)) + ret = 3; + else + ret = 2; + break; } +#endif + + case PM_ProgressBarChunkWidth: + ret = 9; + break; + + case PM_IndicatorWidth: + ret = int(QStyleHelper::dpiScaled(13.)); + break; + + case PM_IndicatorHeight: + ret = int(QStyleHelper::dpiScaled(13.)); + break; + + case PM_ExclusiveIndicatorWidth: + ret = int(QStyleHelper::dpiScaled(12.)); + break; + + case PM_ExclusiveIndicatorHeight: + ret = int(QStyleHelper::dpiScaled(12.)); + break; + + case PM_MenuTearoffHeight: + ret = int(QStyleHelper::dpiScaled(10.)); + break; + + case PM_MenuScrollerHeight: + ret = int(QStyleHelper::dpiScaled(10.)); + break; + + case PM_MenuDesktopFrameWidth: + case PM_MenuHMargin: + case PM_MenuVMargin: + ret = 0; + break; + + case PM_HeaderMargin: + ret = int(QStyleHelper::dpiScaled(4.)); + break; + case PM_HeaderMarkSize: + ret = int(QStyleHelper::dpiScaled(32.)); + break; + case PM_HeaderGripMargin: + ret = int(QStyleHelper::dpiScaled(4.)); + break; + case PM_TabBarScrollButtonWidth: + ret = int(QStyleHelper::dpiScaled(16.)); + break; + case PM_LayoutLeftMargin: + case PM_LayoutTopMargin: + case PM_LayoutRightMargin: + case PM_LayoutBottomMargin: + { + bool isWindow = false; + if (opt) { + isWindow = (opt->state & State_Window); + } else if (widget) { + isWindow = widget->isWindow(); + } + ret = proxy()->pixelMetric(isWindow ? PM_DefaultTopLevelMargin : PM_DefaultChildMargin); + } + break; + case PM_LayoutHorizontalSpacing: + case PM_LayoutVerticalSpacing: + ret = proxy()->pixelMetric(PM_DefaultLayoutSpacing); + break; + + case PM_DefaultTopLevelMargin: + ret = int(QStyleHelper::dpiScaled(11.)); + break; + case PM_DefaultChildMargin: + ret = int(QStyleHelper::dpiScaled(9.)); + break; + case PM_DefaultLayoutSpacing: + ret = int(QStyleHelper::dpiScaled(6.)); + break; + + case PM_ToolBarIconSize: + ret = qt_guiPlatformPlugin()->platformHint(QGuiPlatformPlugin::PH_ToolBarIconSize); + if (!ret) + ret = int(QStyleHelper::dpiScaled(24.)); + break; + + case PM_TabBarIconSize: + case PM_ListViewIconSize: + ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); + break; + + case PM_ButtonIconSize: + case PM_SmallIconSize: + ret = int(QStyleHelper::dpiScaled(16.)); + break; + case PM_IconViewIconSize: + ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget); + break; + + case PM_LargeIconSize: + ret = int(QStyleHelper::dpiScaled(32.)); + break; + + case PM_ToolTipLabelFrameWidth: + ret = 1; + break; + case PM_CheckBoxLabelSpacing: + case PM_RadioButtonLabelSpacing: + ret = int(QStyleHelper::dpiScaled(6.)); + break; + case PM_SizeGripSize: + ret = int(QStyleHelper::dpiScaled(13.)); + break; + case PM_MessageBoxIconSize: +#ifdef Q_WS_MAC + if (QApplication::desktopSettingsAware()) { + ret = 64; // No DPI scaling, it's handled elsewhere. + } else +#endif + { + ret = int(QStyleHelper::dpiScaled(32.)); + } + break; + case PM_TextCursorWidth: + ret = 1; + break; + case PM_TabBar_ScrollButtonOverlap: + ret = 1; + break; + case PM_TabCloseIndicatorWidth: + case PM_TabCloseIndicatorHeight: + ret = int(QStyleHelper::dpiScaled(16.)); + break; + case PM_ScrollView_ScrollBarSpacing: + ret = 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); + break; + case PM_SubMenuOverlap: + ret = -proxy()->pixelMetric(QStyle::PM_MenuPanelWidth, opt, widget); + break; + default: + ret = 0; + break; + } + + return ret; +} + +/*! + \reimp +*/ +QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, + const QSize &csz, const QWidget *widget) const +{ + Q_D(const QCommonStyle); + QSize sz(csz); + switch (ct) { + case CT_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + int w = csz.width(), + h = csz.height(), + bm = proxy()->pixelMetric(PM_ButtonMargin, btn, widget), + fw = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget) * 2; + w += bm + fw; + h += bm + fw; + if (btn->features & QStyleOptionButton::AutoDefaultButton){ + int dbw = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget) * 2; + w += dbw; + h += dbw; + } + sz = QSize(w, h); + } + break; + case CT_RadioButton: + case CT_CheckBox: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + bool isRadio = (ct == CT_RadioButton); + + int w = proxy()->pixelMetric(isRadio ? PM_ExclusiveIndicatorWidth + : PM_IndicatorWidth, btn, widget); + int h = proxy()->pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight + : PM_IndicatorHeight, btn, widget); + + int margins = 0; + // we add 4 pixels for label margins + if (!btn->icon.isNull() || !btn->text.isEmpty()) + margins = 4 + proxy()->pixelMetric(isRadio ? PM_RadioButtonLabelSpacing + : PM_CheckBoxLabelSpacing, opt, widget); + sz += QSize(w + margins, 4); + sz.setHeight(qMax(sz.height(), h)); + } + break; +#ifndef QT_NO_MENU + case CT_MenuItem: + if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { + bool checkable = mi->menuHasCheckableItems; + int maxpmw = mi->maxIconWidth; + int w = sz.width(), h = sz.height(); + if (mi->menuItemType == QStyleOptionMenuItem::Separator) { + w = 10; + h = 2; + } else { + h = mi->fontMetrics.height() + 8; + if (!mi->icon.isNull()) { + int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); + h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4); + } + } + if (mi->text.contains(QLatin1Char('\t'))) + w += 12; + if (maxpmw > 0) + w += maxpmw + 6; + if (checkable && maxpmw < 20) + w += 20 - maxpmw; + if (checkable || maxpmw > 0) + w += 2; + w += 12; + sz = QSize(w, h); + } + break; +#endif // QT_NO_MENU +#ifndef QT_NO_TOOLBUTTON + case CT_ToolButton: + sz = QSize(sz.width() + 6, sz.height() + 5); + break; +#endif // QT_NO_TOOLBUTTON +#ifndef QT_NO_COMBOBOX + case CT_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(opt)) { + int fw = cmb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) * 2 : 0; + const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1); + // QItemDelegate::sizeHint expands the textMargins two times, thus the 2*textMargins... + int other = qMax(23, 2*textMargins + proxy()->pixelMetric(QStyle::PM_ScrollBarExtent, opt, widget)); + sz = QSize(sz.width() + fw + other, sz.height() + fw); + } + break; +#endif // QT_NO_COMBOBOX + case CT_HeaderSection: + if (const QStyleOptionHeader *hdr = qstyleoption_cast(opt)) { + bool nullIcon = hdr->icon.isNull(); + int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, hdr, widget); + int iconSize = nullIcon ? 0 : proxy()->pixelMetric(QStyle::PM_SmallIconSize, hdr, widget); + QSize txt = hdr->fontMetrics.size(0, hdr->text); + sz.setHeight(margin + qMax(iconSize, txt.height()) + margin); + sz.setWidth((nullIcon ? 0 : margin) + iconSize + + (hdr->text.isNull() ? 0 : margin) + txt.width() + margin); + } + break; + case CT_TabWidget: + sz += QSize(4, 4); + break; + case CT_LineEdit: + if (const QStyleOptionFrame *f = qstyleoption_cast(opt)) + sz += QSize(2*f->lineWidth, 2*f->lineWidth); + break; +#ifndef QT_NO_GROUPBOX + case CT_GroupBox: + if (const QGroupBox *grb = static_cast(widget)) + sz += QSize(!grb->isFlat() ? 16 : 0, 0); + break; +#endif // QT_NO_GROUPBOX + case CT_MdiControls: + if (const QStyleOptionComplex *styleOpt = qstyleoption_cast(opt)) { + int width = 1; + if (styleOpt->subControls & SC_MdiMinButton) + width += 16 + 1; + if (styleOpt->subControls & SC_MdiNormalButton) + width += 16 + 1; + if (styleOpt->subControls & SC_MdiCloseButton) + width += 16 + 1; + sz = QSize(width, 16); + } else { + sz = QSize(52, 16); + } + break; +#ifndef QT_NO_ITEMVIEWS + case CT_ItemViewItem: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(opt)) { + QRect decorationRect, displayRect, checkRect; + d->viewItemLayout(vopt, &checkRect, &decorationRect, &displayRect, true); + sz = (decorationRect|displayRect|checkRect).size(); + } + break; +#endif // QT_NO_ITEMVIEWS + case CT_ScrollBar: + case CT_MenuBar: + case CT_Menu: + case CT_MenuBarItem: + case CT_Q3Header: + case CT_Slider: + case CT_ProgressBar: + case CT_TabBarTab: + // just return the contentsSize for now + // fall through intended + default: + break; + } + return sz; +} + + +/*! \reimp */ +int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *widget, + QStyleHintReturn *hret) const +{ + int ret = 0; + + switch (sh) { + case SH_Menu_KeyboardSearch: + ret = false; + break; + case SH_Slider_AbsoluteSetButtons: + ret = Qt::MidButton; + break; + case SH_Slider_PageSetButtons: + ret = Qt::LeftButton; + break; + case SH_ScrollBar_ContextMenu: + ret = true; + break; + case SH_DialogButtons_DefaultButton: // This value not used anywhere. + ret = QDialogButtonBox::AcceptRole; + break; +#ifndef QT_NO_GROUPBOX + case SH_GroupBox_TextLabelVerticalAlignment: + ret = Qt::AlignVCenter; + break; + + case SH_GroupBox_TextLabelColor: + ret = opt ? int(opt->palette.color(QPalette::Text).rgba()) : 0; + break; +#endif // QT_NO_GROUPBOX + + case SH_Q3ListViewExpand_SelectMouseType: + case SH_TabBar_SelectMouseType: + ret = QEvent::MouseButtonPress; + break; + +#ifdef QT3_SUPPORT + case SH_GUIStyle: + ret = Qt::WindowsStyle; + break; +#endif + + case SH_TabBar_Alignment: + case SH_Header_ArrowAlignment: + ret = Qt::AlignLeft; + break; + + case SH_TitleBar_AutoRaise: + ret = false; + break; + + case SH_Menu_SubMenuPopupDelay: + ret = 256; + break; + + case SH_ProgressDialog_TextLabelAlignment: + ret = Qt::AlignCenter; + break; + + case SH_BlinkCursorWhenTextSelected: + ret = 1; + break; + + case SH_Table_GridLineColor: + if (opt) + ret = opt->palette.color(QPalette::Mid).rgb(); + else + ret = -1; + break; + case SH_LineEdit_PasswordCharacter: { + const QFontMetrics &fm = opt ? opt->fontMetrics + : (widget ? widget->fontMetrics() : QFontMetrics(QFont())); + ret = 0; + if (fm.inFont(QChar(0x25CF))) { + ret = 0x25CF; + } else if (fm.inFont(QChar(0x2022))) { + ret = 0x2022; + } else { + ret = '*'; + } + break; + } + + + case SH_ToolBox_SelectedPageTitleBold: + ret = 1; + break; + + case SH_UnderlineShortcut: + ret = 1; + break; + + case SH_SpinBox_ClickAutoRepeatRate: + ret = 150; + break; + + case SH_SpinBox_ClickAutoRepeatThreshold: + ret = 500; + break; + + case SH_SpinBox_KeyPressAutoRepeatRate: + ret = 75; + break; + + case SH_Menu_SelectionWrap: + ret = true; + break; + + case SH_Menu_FillScreenWithScroll: + ret = true; + break; + + case SH_ToolTipLabel_Opacity: + ret = 255; + break; + + case SH_Button_FocusPolicy: + ret = Qt::StrongFocus; + break; + + case SH_MenuBar_DismissOnSecondClick: + ret = 1; + break; + + case SH_MessageBox_UseBorderForButtonSpacing: + ret = 0; + break; + + case SH_ToolButton_PopupDelay: + ret = 600; + break; + + case SH_FocusFrame_Mask: + ret = 1; + if (widget) { + if(QStyleHintReturnMask *mask = qstyleoption_cast(hret)) { + mask->region = widget->rect(); + int vmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin), + hmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin); + mask->region -= QRect(widget->rect().adjusted(hmargin, vmargin, -hmargin, -vmargin)); + } + } + break; +#ifndef QT_NO_RUBBERBAND + case SH_RubberBand_Mask: + if (const QStyleOptionRubberBand *rbOpt = qstyleoption_cast(opt)) { + ret = 0; + if (rbOpt->shape == QRubberBand::Rectangle) { + ret = true; + if(QStyleHintReturnMask *mask = qstyleoption_cast(hret)) { + mask->region = opt->rect; + int margin = proxy()->pixelMetric(PM_DefaultFrameWidth) * 2; + mask->region -= opt->rect.adjusted(margin, margin, -margin, -margin); + } + } + } + break; +#endif // QT_NO_RUBBERBAND + case SH_SpinControls_DisableOnBounds: + ret = 1; + break; + + case SH_Dial_BackgroundRole: + ret = QPalette::Window; + break; + + case SH_ComboBox_LayoutDirection: + ret = opt ? opt->direction : Qt::LeftToRight; + break; + + case SH_ItemView_EllipsisLocation: + ret = Qt::AlignTrailing; + break; + + case SH_ItemView_ShowDecorationSelected: + ret = false; + break; + + case SH_ItemView_ActivateItemOnSingleClick: + ret = qt_guiPlatformPlugin()->platformHint(QGuiPlatformPlugin::PH_ItemView_ActivateItemOnSingleClick); + break; + + case SH_TitleBar_ModifyNotification: + ret = true; + break; + case SH_ScrollBar_RollBetweenButtons: + ret = false; + break; + case SH_TabBar_ElideMode: + ret = Qt::ElideNone; + break; + case SH_DialogButtonLayout: + ret = QDialogButtonBox::WinLayout; +#ifdef Q_WS_X11 + if (X11->desktopEnvironment == DE_KDE) + ret = QDialogButtonBox::KdeLayout; + else if (X11->desktopEnvironment == DE_GNOME) + ret = QDialogButtonBox::GnomeLayout; +#endif + break; + case SH_ComboBox_PopupFrameStyle: + ret = QFrame::StyledPanel | QFrame::Plain; + break; + case SH_MessageBox_TextInteractionFlags: + ret = Qt::LinksAccessibleByMouse; + break; + case SH_DialogButtonBox_ButtonsHaveIcons: +#ifdef Q_WS_X11 + return true; +#endif + ret = 0; + break; + case SH_SpellCheckUnderlineStyle: + ret = QTextCharFormat::WaveUnderline; + break; + case SH_MessageBox_CenterButtons: + ret = true; + break; + case SH_ItemView_MovementWithoutUpdatingSelection: + ret = true; + break; + case SH_FocusFrame_AboveWidget: + ret = false; + break; +#ifndef QT_NO_TABWIDGET + case SH_TabWidget_DefaultTabPosition: + ret = QTabWidget::North; + break; +#endif + case SH_ToolBar_Movable: + ret = true; + break; + case SH_TextControl_FocusIndicatorTextCharFormat: + ret = true; + if (QStyleHintReturnVariant *vret = qstyleoption_cast(hret)) { + QPen outline(opt->palette.color(QPalette::Text), 1, Qt::DotLine); + QTextCharFormat fmt; + fmt.setProperty(QTextFormat::OutlinePen, outline); + vret->variant = fmt; + } + break; +#ifndef QT_NO_WIZARD + case SH_WizardStyle: + ret = QWizard::ClassicStyle; + break; +#endif + case SH_FormLayoutWrapPolicy: + ret = QFormLayout::DontWrapRows; + break; + case SH_FormLayoutFieldGrowthPolicy: + ret = QFormLayout::AllNonFixedFieldsGrow; + break; + case SH_FormLayoutFormAlignment: + ret = Qt::AlignLeft | Qt::AlignTop; + break; + case SH_FormLayoutLabelAlignment: + ret = Qt::AlignLeft; + break; + case SH_ItemView_ArrowKeysNavigateIntoChildren: + ret = false; + break; + case SH_ItemView_DrawDelegateFrame: + ret = 0; + break; +#ifndef QT_NO_TABBAR + case SH_TabBar_CloseButtonPosition: + ret = QTabBar::RightSide; + break; +#endif + case SH_DockWidget_ButtonsHaveFrame: + ret = true; + break; + case SH_ToolButtonStyle: + ret = qt_guiPlatformPlugin()->platformHint(QGuiPlatformPlugin::PH_ToolButtonStyle); + break; + case SH_RequestSoftwareInputPanel: + ret = RSIP_OnMouseClickAndAlreadyFocused; + break; + default: + ret = 0; + break; + } + + return ret; +} + +/*! \reimp */ +QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, + const QWidget *widget) const +{ + const bool rtl = (option && option->direction == Qt::RightToLeft) || (!option && QApplication::isRightToLeft()); +#ifdef QT_NO_IMAGEFORMAT_PNG + Q_UNUSED(widget); + Q_UNUSED(sp); +#else + QPixmap pixmap; + + if (QApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) { + switch (sp) { + case SP_DialogYesButton: + case SP_DialogOkButton: + pixmap = QIcon::fromTheme(QLatin1String("dialog-ok")).pixmap(16); + break; + case SP_DialogApplyButton: + pixmap = QIcon::fromTheme(QLatin1String("dialog-ok-apply")).pixmap(16); + break; + case SP_DialogDiscardButton: + pixmap = QIcon::fromTheme(QLatin1String("edit-delete")).pixmap(16); + break; + case SP_DialogCloseButton: + pixmap = QIcon::fromTheme(QLatin1String("dialog-close")).pixmap(16); + break; + case SP_DirHomeIcon: + pixmap = QIcon::fromTheme(QLatin1String("user-home")).pixmap(16); + break; + case SP_MessageBoxInformation: + pixmap = QIcon::fromTheme(QLatin1String("messagebox_info")).pixmap(16); + break; + case SP_MessageBoxWarning: + pixmap = QIcon::fromTheme(QLatin1String("messagebox_warning")).pixmap(16); + break; + case SP_MessageBoxCritical: + pixmap = QIcon::fromTheme(QLatin1String("messagebox_critical")).pixmap(16); + break; + case SP_MessageBoxQuestion: + pixmap = QIcon::fromTheme(QLatin1String("help")).pixmap(16); + break; + case SP_DialogOpenButton: + case SP_DirOpenIcon: + pixmap = QIcon::fromTheme(QLatin1String("folder-open")).pixmap(16); + break; + case SP_FileIcon: + pixmap = QIcon::fromTheme(QLatin1String("text-x-generic"), + QIcon::fromTheme(QLatin1String("empty"))).pixmap(16); + break; + case SP_DirClosedIcon: + case SP_DirIcon: + pixmap = QIcon::fromTheme(QLatin1String("folder")).pixmap(16); + break; + case SP_DriveFDIcon: + pixmap = QIcon::fromTheme(QLatin1String("media-floppy"), + QIcon::fromTheme(QLatin1String("3floppy_unmount"))).pixmap(16); + break; + case SP_ComputerIcon: + pixmap = QIcon::fromTheme(QLatin1String("computer"), + QIcon::fromTheme(QLatin1String("system"))).pixmap(16); + break; + case SP_DesktopIcon: + pixmap = QIcon::fromTheme(QLatin1String("user-desktop"), + QIcon::fromTheme(QLatin1String("desktop"))).pixmap(16); + break; + case SP_TrashIcon: + pixmap = QIcon::fromTheme(QLatin1String("user-trash"), + QIcon::fromTheme(QLatin1String("trashcan_empty"))).pixmap(16); + break; + case SP_DriveCDIcon: + case SP_DriveDVDIcon: + pixmap = QIcon::fromTheme(QLatin1String("media-optical"), + QIcon::fromTheme(QLatin1String("cdrom_unmount"))).pixmap(16); + break; + case SP_DriveHDIcon: + pixmap = QIcon::fromTheme(QLatin1String("drive-harddisk"), + QIcon::fromTheme(QLatin1String("hdd_unmount"))).pixmap(16); + break; + case SP_FileDialogToParent: + pixmap = QIcon::fromTheme(QLatin1String("go-up"), + QIcon::fromTheme(QLatin1String("up"))).pixmap(16); + break; + case SP_FileDialogNewFolder: + pixmap = QIcon::fromTheme(QLatin1String("folder_new")).pixmap(16); + break; + case SP_ArrowUp: + pixmap = QIcon::fromTheme(QLatin1String("go-up"), + QIcon::fromTheme(QLatin1String("up"))).pixmap(16); + break; + case SP_ArrowDown: + pixmap = QIcon::fromTheme(QLatin1String("go-down"), + QIcon::fromTheme(QLatin1String("down"))).pixmap(16); + break; + case SP_ArrowRight: + pixmap = QIcon::fromTheme(QLatin1String("go-next"), + QIcon::fromTheme(QLatin1String("forward"))).pixmap(16); + break; + case SP_ArrowLeft: + pixmap = QIcon::fromTheme(QLatin1String("go-previous"), + QIcon::fromTheme(QLatin1String("back"))).pixmap(16); + break; + case SP_FileDialogDetailedView: + pixmap = QIcon::fromTheme(QLatin1String("view_detailed")).pixmap(16); + break; + case SP_FileDialogListView: + pixmap = QIcon::fromTheme(QLatin1String("view_icon")).pixmap(16); + break; + case SP_BrowserReload: + pixmap = QIcon::fromTheme(QLatin1String("reload")).pixmap(16); + break; + case SP_BrowserStop: + pixmap = QIcon::fromTheme(QLatin1String("process-stop")).pixmap(16); + break; + case SP_MediaPlay: + pixmap = QIcon::fromTheme(QLatin1String("media-playback-start")).pixmap(16); + break; + case SP_MediaPause: + pixmap = QIcon::fromTheme(QLatin1String("media-playback-pause")).pixmap(16); + break; + case SP_MediaStop: + pixmap = QIcon::fromTheme(QLatin1String("media-playback-stop")).pixmap(16); + break; + case SP_MediaSeekForward: + pixmap = QIcon::fromTheme(QLatin1String("media-seek-forward")).pixmap(16); + break; + case SP_MediaSeekBackward: + pixmap = QIcon::fromTheme(QLatin1String("media-seek-backward")).pixmap(16); + break; + case SP_MediaSkipForward: + pixmap = QIcon::fromTheme(QLatin1String("media-skip-backward")).pixmap(16); + break; + case SP_MediaSkipBackward: + pixmap = QIcon::fromTheme(QLatin1String("media-skip-backward")).pixmap(16); + break; + case SP_DialogResetButton: + pixmap = QIcon::fromTheme(QLatin1String("edit-clear")).pixmap(24); + break; + case SP_DialogHelpButton: + pixmap = QIcon::fromTheme(QLatin1String("help-contents")).pixmap(24); + break; + case SP_DialogNoButton: + case SP_DialogCancelButton: + pixmap = QIcon::fromTheme(QLatin1String("dialog-cancel"), + QIcon::fromTheme(QLatin1String("process-stop"))).pixmap(24); + break; + case SP_DialogSaveButton: + pixmap = QIcon::fromTheme(QLatin1String("document-save")).pixmap(24); + break; + case SP_FileLinkIcon: + pixmap = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")).pixmap(16); + if (!pixmap.isNull()) { + QPixmap fileIcon = QIcon::fromTheme(QLatin1String("text-x-generic")).pixmap(16); + if (fileIcon.isNull()) + fileIcon = QIcon::fromTheme(QLatin1String("empty")).pixmap(16); + if (!fileIcon.isNull()) { + QPainter painter(&fileIcon); + painter.drawPixmap(0, 0, 16, 16, pixmap); + return fileIcon; + } + } + break; + case SP_DirLinkIcon: + pixmap = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")).pixmap(16); + if (!pixmap.isNull()) { + QPixmap dirIcon = QIcon::fromTheme(QLatin1String("folder")).pixmap(16); + if (!dirIcon.isNull()) { + QPainter painter(&dirIcon); + painter.drawPixmap(0, 0, 16, 16, pixmap); + return dirIcon; + } + } + break; + default: + break; + } + } + + if (!pixmap.isNull()) + return pixmap; +#endif //QT_NO_IMAGEFORMAT_PNG + switch (sp) { +#ifndef QT_NO_IMAGEFORMAT_XPM + case SP_ToolBarHorizontalExtensionButton: + if (rtl) { + QImage im(tb_extension_arrow_h_xpm); + im = im.convertToFormat(QImage::Format_ARGB32).mirrored(true, false); + return QPixmap::fromImage(im); + } + return QPixmap(tb_extension_arrow_h_xpm); + case SP_ToolBarVerticalExtensionButton: + return QPixmap(tb_extension_arrow_v_xpm); + case SP_FileDialogStart: + return QPixmap(filedialog_start_xpm); + case SP_FileDialogEnd: + return QPixmap(filedialog_end_xpm); +#endif +#ifndef QT_NO_IMAGEFORMAT_PNG + case SP_CommandLink: + case SP_ArrowForward: + if (rtl) + return proxy()->standardPixmap(SP_ArrowLeft, option, widget); + return proxy()->standardPixmap(SP_ArrowRight, option, widget); + case SP_ArrowBack: + if (rtl) + return proxy()->standardPixmap(SP_ArrowRight, option, widget); + return proxy()->standardPixmap(SP_ArrowLeft, option, widget); + case SP_ArrowLeft: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/left-16.png")); + case SP_ArrowRight: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/right-16.png")); + case SP_ArrowUp: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/up-16.png")); + case SP_ArrowDown: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/down-16.png")); + case SP_FileDialogToParent: + return proxy()->standardPixmap(SP_ArrowUp, option, widget); + case SP_FileDialogNewFolder: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-16.png")); + case SP_FileDialogDetailedView: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-16.png")); + case SP_FileDialogInfoView: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-16.png")); + case SP_FileDialogContentsView: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-16.png")); + case SP_FileDialogListView: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-16.png")); + case SP_FileDialogBack: + return proxy()->standardPixmap(SP_ArrowBack, option, widget); + case SP_DriveHDIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/harddrive-16.png")); + case SP_TrashIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/trash-16.png")); + case SP_DriveFDIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/floppy-16.png")); + case SP_DriveNetIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/networkdrive-16.png")); + case SP_DesktopIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/desktop-16.png")); + case SP_ComputerIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/computer-16.png")); + case SP_DriveCDIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-16.png")); + case SP_DriveDVDIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-16.png")); + case SP_DirHomeIcon: + case SP_DirOpenIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/diropen-16.png")); + case SP_DirIcon: + case SP_DirClosedIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/dirclosed-16.png")); + case SP_DirLinkIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/dirlink-16.png")); + case SP_FileIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/file-16.png")); + case SP_FileLinkIcon: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-16.png")); + case SP_DialogOkButton: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-16.png")); + case SP_DialogCancelButton: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-16.png")); + case SP_DialogHelpButton: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-16.png")); + case SP_DialogOpenButton: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png")); + case SP_DialogSaveButton: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-16.png")); + case SP_DialogCloseButton: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-16.png")); + case SP_DialogApplyButton: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-16.png")); + case SP_DialogResetButton: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-16.png")); + case SP_DialogDiscardButton: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-16.png")); + case SP_DialogYesButton: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-16.png")); + case SP_DialogNoButton: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-16.png")); + case SP_BrowserReload: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-24.png")); + case SP_BrowserStop: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/stop-24.png")); + case SP_MediaPlay: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-32.png")); + case SP_MediaPause: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-32.png")); + case SP_MediaStop: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-32.png")); + case SP_MediaSeekForward: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-32.png")); + case SP_MediaSeekBackward: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-32.png")); + case SP_MediaSkipForward: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-32.png")); + case SP_MediaSkipBackward: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-32.png")); + case SP_MediaVolume: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-16.png")); + case SP_MediaVolumeMuted: + return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-muted-16.png")); +#endif // QT_NO_IMAGEFORMAT_PNG + default: + break; + } + return QPixmap(); +} + +/*! + \internal +*/ +QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget) const +{ + QIcon icon; + const bool rtl = (option && option->direction == Qt::RightToLeft) || (!option && QApplication::isRightToLeft()); + if (QApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) { + switch (standardIcon) { + case SP_DirHomeIcon: + icon = QIcon::fromTheme(QLatin1String("user-home")); + break; + case SP_MessageBoxInformation: + icon = QIcon::fromTheme(QLatin1String("dialog-information")); + break; + case SP_MessageBoxWarning: + icon = QIcon::fromTheme(QLatin1String("dialog-warning")); + break; + case SP_MessageBoxCritical: + icon = QIcon::fromTheme(QLatin1String("dialog-error")); + break; + case SP_MessageBoxQuestion: + icon = QIcon::fromTheme(QLatin1String("dialog-question")); + break; + case SP_DialogOpenButton: + case SP_DirOpenIcon: + icon = QIcon::fromTheme(QLatin1String("folder-open")); + break; + case SP_DialogSaveButton: + icon = QIcon::fromTheme(QLatin1String("document-save")); + break; + case SP_DialogApplyButton: + icon = QIcon::fromTheme(QLatin1String("dialog-ok-apply")); + break; + case SP_DialogYesButton: + case SP_DialogOkButton: + icon = QIcon::fromTheme(QLatin1String("dialog-ok")); + break; + case SP_DialogDiscardButton: + icon = QIcon::fromTheme(QLatin1String("edit-delete")); + break; + case SP_DialogResetButton: + icon = QIcon::fromTheme(QLatin1String("edit-clear")); + break; + case SP_DialogHelpButton: + icon = QIcon::fromTheme(QLatin1String("help-contents")); + break; + case SP_FileIcon: + icon = QIcon::fromTheme(QLatin1String("text-x-generic")); + break; + case SP_DirClosedIcon: + case SP_DirIcon: + icon = QIcon::fromTheme(QLatin1String("folder")); + break; + case SP_DriveFDIcon: + icon = QIcon::fromTheme(QLatin1String("floppy_unmount")); + break; + case SP_ComputerIcon: + icon = QIcon::fromTheme(QLatin1String("computer"), + QIcon::fromTheme(QLatin1String("system"))); + break; + case SP_DesktopIcon: + icon = QIcon::fromTheme(QLatin1String("user-desktop")); + break; + case SP_TrashIcon: + icon = QIcon::fromTheme(QLatin1String("user-trash")); + break; + case SP_DriveCDIcon: + case SP_DriveDVDIcon: + icon = QIcon::fromTheme(QLatin1String("media-optical")); + break; + case SP_DriveHDIcon: + icon = QIcon::fromTheme(QLatin1String("drive-harddisk")); + break; + case SP_FileDialogToParent: + icon = QIcon::fromTheme(QLatin1String("go-up")); + break; + case SP_FileDialogNewFolder: + icon = QIcon::fromTheme(QLatin1String("folder-new")); + break; + case SP_ArrowUp: + icon = QIcon::fromTheme(QLatin1String("go-up")); + break; + case SP_ArrowDown: + icon = QIcon::fromTheme(QLatin1String("go-down")); + break; + case SP_ArrowRight: + icon = QIcon::fromTheme(QLatin1String("go-next")); + break; + case SP_ArrowLeft: + icon = QIcon::fromTheme(QLatin1String("go-previous")); + break; + case SP_DialogCancelButton: + icon = QIcon::fromTheme(QLatin1String("dialog-cancel"), + QIcon::fromTheme(QLatin1String("process-stop"))); + break; + case SP_DialogCloseButton: + icon = QIcon::fromTheme(QLatin1String("window-close")); + break; + case SP_FileDialogDetailedView: + icon = QIcon::fromTheme(QLatin1String("view-list-details")); + break; + case SP_FileDialogListView: + icon = QIcon::fromTheme(QLatin1String("view-list-icons")); + break; + case SP_BrowserReload: + icon = QIcon::fromTheme(QLatin1String("view-refresh")); + break; + case SP_BrowserStop: + icon = QIcon::fromTheme(QLatin1String("process-stop")); + break; + case SP_MediaPlay: + icon = QIcon::fromTheme(QLatin1String("media-playback-start")); + break; + case SP_MediaPause: + icon = QIcon::fromTheme(QLatin1String("media-playback-pause")); + break; + case SP_MediaStop: + icon = QIcon::fromTheme(QLatin1String("media-playback-stop")); + break; + case SP_MediaSeekForward: + icon = QIcon::fromTheme(QLatin1String("media-seek-forward")); + break; + case SP_MediaSeekBackward: + icon = QIcon::fromTheme(QLatin1String("media-seek-backward")); + break; + case SP_MediaSkipForward: + icon = QIcon::fromTheme(QLatin1String("media-skip-forward")); + break; + case SP_MediaSkipBackward: + icon = QIcon::fromTheme(QLatin1String("media-skip-backward")); + break; + case SP_MediaVolume: + icon = QIcon::fromTheme(QLatin1String("audio-volume-medium")); + break; + case SP_MediaVolumeMuted: + icon = QIcon::fromTheme(QLatin1String("audio-volume-muted")); + break; + case SP_ArrowForward: + if (rtl) + return standardIconImplementation(SP_ArrowLeft, option, widget); + return standardIconImplementation(SP_ArrowRight, option, widget); + case SP_ArrowBack: + if (rtl) + return standardIconImplementation(SP_ArrowRight, option, widget); + return standardIconImplementation(SP_ArrowLeft, option, widget); + case SP_FileLinkIcon: + { + QIcon linkIcon = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")); + if (!linkIcon.isNull()) { + QIcon baseIcon = standardIconImplementation(SP_FileIcon, option, widget); + const QList sizes = baseIcon.availableSizes(QIcon::Normal, QIcon::Off); + for (int i = 0 ; i < sizes.size() ; ++i) { + int size = sizes[i].width(); + QPixmap basePixmap = baseIcon.pixmap(size); + QPixmap linkPixmap = linkIcon.pixmap(size/2); + QPainter painter(&basePixmap); + painter.drawPixmap(size/2, size/2, linkPixmap); + icon.addPixmap(basePixmap); + } + } + } + break; + case SP_DirLinkIcon: + { + QIcon linkIcon = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")); + if (!linkIcon.isNull()) { + QIcon baseIcon = standardIconImplementation(SP_DirIcon, option, widget); + const QList sizes = baseIcon.availableSizes(QIcon::Normal, QIcon::Off); + for (int i = 0 ; i < sizes.size() ; ++i) { + int size = sizes[i].width(); + QPixmap basePixmap = baseIcon.pixmap(size); + QPixmap linkPixmap = linkIcon.pixmap(size/2); + QPainter painter(&basePixmap); + painter.drawPixmap(size/2, size/2, linkPixmap); + icon.addPixmap(basePixmap); + } + } + } + break; + default: + break; + } + } // if (QApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) + if (!icon.isNull()) + return icon; +#if defined(Q_WS_MAC) + if (QApplication::desktopSettingsAware()) { + OSType iconType = 0; + switch (standardIcon) { + case QStyle::SP_MessageBoxQuestion: + iconType = kQuestionMarkIcon; + break; + case QStyle::SP_MessageBoxInformation: + iconType = kAlertNoteIcon; + break; + case QStyle::SP_MessageBoxWarning: + iconType = kAlertCautionIcon; + break; + case QStyle::SP_MessageBoxCritical: + iconType = kAlertStopIcon; + break; + case SP_DesktopIcon: + iconType = kDesktopIcon; + break; + case SP_TrashIcon: + iconType = kTrashIcon; + break; + case SP_ComputerIcon: + iconType = kComputerIcon; + break; + case SP_DriveFDIcon: + iconType = kGenericFloppyIcon; + break; + case SP_DriveHDIcon: + iconType = kGenericHardDiskIcon; + break; + case SP_DriveCDIcon: + case SP_DriveDVDIcon: + iconType = kGenericCDROMIcon; + break; + case SP_DriveNetIcon: + iconType = kGenericNetworkIcon; + break; + case SP_DirOpenIcon: + iconType = kOpenFolderIcon; + break; + case SP_DirClosedIcon: + case SP_DirLinkIcon: + iconType = kGenericFolderIcon; + break; + case SP_FileLinkIcon: + case SP_FileIcon: + iconType = kGenericDocumentIcon; + break; + case SP_DirIcon: { + // A rather special case + QIcon closeIcon = QStyle::standardIcon(SP_DirClosedIcon, option, widget); + QIcon openIcon = QStyle::standardIcon(SP_DirOpenIcon, option, widget); + closeIcon.addPixmap(openIcon.pixmap(16, 16), QIcon::Normal, QIcon::On); + closeIcon.addPixmap(openIcon.pixmap(32, 32), QIcon::Normal, QIcon::On); + closeIcon.addPixmap(openIcon.pixmap(64, 64), QIcon::Normal, QIcon::On); + closeIcon.addPixmap(openIcon.pixmap(128, 128), QIcon::Normal, QIcon::On); + return closeIcon; + } + case SP_TitleBarNormalButton: + case SP_TitleBarCloseButton: { + QIcon titleBarIcon; + if (standardIcon == SP_TitleBarCloseButton) { + titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/closedock-16.png")); + titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/closedock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On); + } else { + titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/dockdock-16.png")); + titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/dockdock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On); + } + return titleBarIcon; + } + default: + break; + } + if (iconType != 0) { + QIcon retIcon; + IconRef icon; + IconRef overlayIcon = 0; + if (iconType != kGenericApplicationIcon) { + GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon); + } else { + FSRef fsRef; + ProcessSerialNumber psn = { 0, kCurrentProcess }; + GetProcessBundleLocation(&psn, &fsRef); + GetIconRefFromFileInfo(&fsRef, 0, 0, 0, 0, kIconServicesNormalUsageFlag, &icon, 0); + if (standardIcon == SP_MessageBoxCritical) { + overlayIcon = icon; + GetIconRef(kOnSystemDisk, kSystemIconsCreator, kAlertCautionIcon, &icon); + } + } + if (icon) { + qt_mac_constructQIconFromIconRef(icon, overlayIcon, &retIcon, standardIcon); + ReleaseIconRef(icon); + } + if (overlayIcon) + ReleaseIconRef(overlayIcon); + return retIcon; + } + } // if (QApplication::desktopSettingsAware()) +#endif // Q_WS_MAC + + switch (standardIcon) { +#ifndef QT_NO_IMAGEFORMAT_PNG + case SP_FileDialogNewFolder: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-128.png"), QSize(128, 128)); + break; + case SP_FileDialogBack: + return standardIconImplementation(SP_ArrowBack, option, widget); + case SP_FileDialogToParent: + return standardIconImplementation(SP_ArrowUp, option, widget); + case SP_FileDialogDetailedView: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-128.png"), QSize(128, 128)); + break; + case SP_FileDialogInfoView: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-128.png"), QSize(128, 128)); + break; + case SP_FileDialogContentsView: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-128.png"), QSize(128, 128)); + break; + case SP_FileDialogListView: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-128.png"), QSize(128, 128)); + break; + case SP_DialogOkButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-128.png"), QSize(128, 128)); + break; + case SP_DialogCancelButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-128.png"), QSize(128, 128)); + break; + case SP_DialogHelpButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-128.png"), QSize(128, 128)); + break; + case SP_DialogOpenButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-128.png"), QSize(128, 128)); + break; + case SP_DialogSaveButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-128.png"), QSize(128, 128)); + break; + case SP_DialogCloseButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-128.png"), QSize(128, 128)); + break; + case SP_DialogApplyButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-128.png"), QSize(128, 128)); + break; + case SP_DialogResetButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-128.png"), QSize(128, 128)); + break; + case SP_DialogDiscardButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-128.png"), QSize(128, 128)); + break; + case SP_DialogYesButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-128.png"), QSize(128, 128)); + break; + case SP_DialogNoButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-128.png"), QSize(128, 128)); + break; + case SP_ArrowForward: + if (rtl) + return standardIconImplementation(SP_ArrowLeft, option, widget); + return standardIconImplementation(SP_ArrowRight, option, widget); + case SP_ArrowBack: + if (rtl) + return standardIconImplementation(SP_ArrowRight, option, widget); + return standardIconImplementation(SP_ArrowLeft, option, widget); + case SP_ArrowLeft: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-128.png"), QSize(128, 128)); + break; + case SP_ArrowRight: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-128.png"), QSize(128, 128)); + break; + case SP_ArrowUp: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-128.png"), QSize(128, 128)); + break; + case SP_ArrowDown: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-128.png"), QSize(128, 128)); + break; + case SP_DirHomeIcon: + case SP_DirIcon: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dirclosed-16.png"), + QSize(), QIcon::Normal, QIcon::Off); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/diropen-16.png"), + QSize(), QIcon::Normal, QIcon::On); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dirclosed-32.png"), + QSize(32, 32), QIcon::Normal, QIcon::Off); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/diropen-32.png"), + QSize(32, 32), QIcon::Normal, QIcon::On); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dirclosed-128.png"), + QSize(128, 128), QIcon::Normal, QIcon::Off); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/diropen-128.png"), + QSize(128, 128), QIcon::Normal, QIcon::On); + break; + case SP_DriveCDIcon: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-128.png"), QSize(128, 128)); + break; + case SP_DriveDVDIcon: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-128.png"), QSize(128, 128)); + break; + case SP_FileIcon: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-128.png"), QSize(128, 128)); + break; + case SP_FileLinkIcon: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-128.png"), QSize(128, 128)); + break; + case SP_TrashIcon: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-32.png"), QSize(32, 32)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-128.png"), QSize(128, 128)); + break; + case SP_BrowserReload: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-24.png"), QSize(24, 24)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-32.png"), QSize(32, 32)); + break; + case SP_BrowserStop: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/stop-24.png"), QSize(24, 24)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/stop-32.png"), QSize(32, 32)); + break; + case SP_MediaPlay: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-32.png"), QSize(32, 32)); + break; + case SP_MediaPause: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-32.png"), QSize(32, 32)); + break; + case SP_MediaStop: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-32.png"), QSize(32, 32)); + break; + case SP_MediaSeekForward: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-32.png"), QSize(32, 32)); + break; + case SP_MediaSeekBackward: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-32.png"), QSize(32, 32)); + break; + case SP_MediaSkipForward: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-32.png"), QSize(32, 32)); + break; + case SP_MediaSkipBackward: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-16.png"), QSize(16, 16)); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-32.png"), QSize(32, 32)); + break; + case SP_MediaVolume: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-16.png"), QSize(16, 16)); + break; + case SP_MediaVolumeMuted: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-muted-16.png"), QSize(16, 16)); + break; +#endif // QT_NO_IMAGEFORMAT_PNG + default: + icon.addPixmap(proxy()->standardPixmap(standardIcon, option, widget)); + break; + } + return icon; +} + +static inline uint qt_intensity(uint r, uint g, uint b) +{ + // 30% red, 59% green, 11% blue + return (77 * r + 150 * g + 28 * b) / 255; +} + +/*! \reimp */ +QPixmap QCommonStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *opt) const +{ + switch (iconMode) { + case QIcon::Disabled: { + QImage im = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); + + // Create a colortable based on the background (black -> bg -> white) + QColor bg = opt->palette.color(QPalette::Disabled, QPalette::Window); + int red = bg.red(); + int green = bg.green(); + int blue = bg.blue(); + uchar reds[256], greens[256], blues[256]; + for (int i=0; i<128; ++i) { + reds[i] = uchar((red * (i<<1)) >> 8); + greens[i] = uchar((green * (i<<1)) >> 8); + blues[i] = uchar((blue * (i<<1)) >> 8); + } + for (int i=0; i<128; ++i) { + reds[i+128] = uchar(qMin(red + (i << 1), 255)); + greens[i+128] = uchar(qMin(green + (i << 1), 255)); + blues[i+128] = uchar(qMin(blue + (i << 1), 255)); + } + + int intensity = qt_intensity(red, green, blue); + const int factor = 191; + + // High intensity colors needs dark shifting in the color table, while + // low intensity colors needs light shifting. This is to increase the + // percieved contrast. + if ((red - factor > green && red - factor > blue) + || (green - factor > red && green - factor > blue) + || (blue - factor > red && blue - factor > green)) + intensity = qMin(255, intensity + 91); + else if (intensity <= 128) + intensity -= 51; + + for (int y=0; ypalette.color(QPalette::Normal, QPalette::Highlight); + color.setAlphaF(qreal(0.3)); + QPainter painter(&img); + painter.setCompositionMode(QPainter::CompositionMode_SourceAtop); + painter.fillRect(0, 0, img.width(), img.height(), color); + painter.end(); + return QPixmap::fromImage(img); } + case QIcon::Active: + return pixmap; + default: + break; + } + return pixmap; +} + +/*! + \reimp +*/ +void QCommonStyle::polish(QPalette &pal) +{ + QStyle::polish(pal); +} + +/*! + \reimp + */ +void QCommonStyle::polish(QWidget *widget) +{ + QStyle::polish(widget); +} + +/*! + \reimp + */ +void QCommonStyle::unpolish(QWidget *widget) +{ + QStyle::unpolish(widget); +} + +/*! + \reimp +*/ +void QCommonStyle::polish(QApplication *app) +{ + QStyle::polish(app); +} + +/*! + \reimp + */ +void QCommonStyle::unpolish(QApplication *application) +{ + Q_D(const QCommonStyle); + d->tabBarcloseButtonIcon = QIcon(); + QStyle::unpolish(application); +} + + +QT_END_NAMESPACE diff --git a/src/widgets/styles/qcommonstyle.h b/src/widgets/styles/qcommonstyle.h new file mode 100644 index 0000000000..2b42367aac --- /dev/null +++ b/src/widgets/styles/qcommonstyle.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOMMONSTYLE_H +#define QCOMMONSTYLE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE +QT_MODULE(Gui) + +class QCommonStylePrivate; + +class Q_GUI_EXPORT QCommonStyle: public QStyle +{ + Q_OBJECT + +public: + QCommonStyle(); + ~QCommonStyle(); + + void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const; + void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const; + QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const; + void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, + const QWidget *w = 0) const; + SubControl hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *w = 0) const; + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, + const QWidget *w = 0) const; + QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, + const QSize &contentsSize, const QWidget *widget = 0) const; + + int pixelMetric(PixelMetric m, const QStyleOption *opt = 0, const QWidget *widget = 0) const; + + int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0, + QStyleHintReturn *shret = 0) const; + + QPixmap standardPixmap(StandardPixmap sp, const QStyleOption *opt = 0, + const QWidget *widget = 0) const; + + QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *opt) const; + + void polish(QPalette &); + void polish(QApplication *app); + void polish(QWidget *widget); + void unpolish(QWidget *widget); + void unpolish(QApplication *application); + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt = 0, + const QWidget *widget = 0) const; + +protected: + QCommonStyle(QCommonStylePrivate &dd); + +private: + Q_DECLARE_PRIVATE(QCommonStyle) + Q_DISABLE_COPY(QCommonStyle) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QCOMMONSTYLE_H diff --git a/src/widgets/styles/qcommonstyle_p.h b/src/widgets/styles/qcommonstyle_p.h new file mode 100644 index 0000000000..a02bd44259 --- /dev/null +++ b/src/widgets/styles/qcommonstyle_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOMMONSTYLE_P_H +#define QCOMMONSTYLE_P_H + +#include "qcommonstyle.h" +#include "qstyle_p.h" + +#include "qstyleoption.h" + +QT_BEGIN_NAMESPACE + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +class QStringList; + +// Private class +class QCommonStylePrivate : public QStylePrivate +{ + Q_DECLARE_PUBLIC(QCommonStyle) +public: + inline QCommonStylePrivate() +#ifndef QT_NO_ITEMVIEWS + : cachedOption(0) +#endif + { } + +#ifndef QT_NO_ITEMVIEWS + ~QCommonStylePrivate() + { + delete cachedOption; + } + void viewItemDrawText(QPainter *p, const QStyleOptionViewItemV4 *option, const QRect &rect) const; + void viewItemLayout(const QStyleOptionViewItemV4 *opt, QRect *checkRect, + QRect *pixmapRect, QRect *textRect, bool sizehint) const; + QSize viewItemSize(const QStyleOptionViewItemV4 *option, int role) const; + + mutable QRect decorationRect, displayRect, checkRect; + mutable QStyleOptionViewItemV4 *cachedOption; + bool isViewItemCached(const QStyleOptionViewItemV4 &option) const { + return cachedOption && (option.rect == cachedOption->rect + && option.direction == cachedOption->direction + && option.state == cachedOption->state + && option.displayAlignment == cachedOption->displayAlignment + && option.decorationAlignment == cachedOption->decorationAlignment + && option.decorationPosition == cachedOption->decorationPosition + && option.decorationSize == cachedOption->decorationSize + && option.font == cachedOption->font + && option.features == cachedOption->features + && option.widget == cachedOption->widget + && option.index == cachedOption->index + && option.icon.isNull() == cachedOption->icon.isNull() + && option.text == cachedOption->text + && option.viewItemPosition == cachedOption->viewItemPosition); + } +#endif + mutable QIcon tabBarcloseButtonIcon; +#ifndef QT_NO_TABBAR + void tabLayout(const QStyleOptionTabV3 *opt, const QWidget *widget, QRect *textRect, QRect *pixmapRect) const; +#endif +}; + +QT_END_NAMESPACE + +#endif //QCOMMONSTYLE_P_H diff --git a/src/widgets/styles/qcommonstylepixmaps_p.h b/src/widgets/styles/qcommonstylepixmaps_p.h new file mode 100644 index 0000000000..fb87c0e7a7 --- /dev/null +++ b/src/widgets/styles/qcommonstylepixmaps_p.h @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT_NO_IMAGEFORMAT_XPM + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +static const char * const check_list_controller_xpm[] = { +"16 16 4 1", +" c None", +". c #000000000000", +"X c #FFFFFFFF0000", +"o c #C71BC30BC71B", +" ", +" ", +" .......... ", +" .XXXXXXXX. ", +" .XXXXXXXX.oo ", +" .XXXXXXXX.oo ", +" .XXXXXXXX.oo ", +" .XXXXXXXX.oo ", +" .XXXXXXXX.oo ", +" .XXXXXXXX.oo ", +" .XXXXXXXX.oo ", +" ..........oo ", +" oooooooooo ", +" oooooooooo ", +" ", +" "}; + +static const char * const tree_branch_open_xpm[] = { +"9 9 2 1", +" c None", +"# c #000000", +"#########", +"# #", +"# ##### #", +"# ### #", +"# ### #", +"# # #", +"# # #", +"# #", +"#########"}; + +static const char * const tree_branch_closed_xpm[] = { +"9 9 2 1", +" c None", +"# c #000000", +"#########", +"# #", +"# # #", +"# ### #", +"# ##### #", +"# ### #", +"# # #", +"# #", +"#########"}; + +static const char * const tb_extension_arrow_v_xpm[] = { + "5 8 3 1", + " c None", + ". c #000000", + "+ c none", + ".+++.", + "..+..", + "+...+", + "++.++", + ".+++.", + "..+..", + "+...+", + "++.++" +}; + +static const char * const tb_extension_arrow_h_xpm[] = { + "8 5 3 1", + " c None", + ". c #000000", + "+ c none", + "..++..++", + "+..++..+", + "++..++..", + "+..++..+", + "..++..++", +}; + +static const char * const filedialog_start_xpm[]={ + "16 15 8 1", + "a c #cec6bd", + "# c #000000", + "e c #ffff00", + "b c #999999", + "f c #cccccc", + "d c #dcdcdc", + "c c #ffffff", + ". c None", + ".....######aaaaa", + "...bb#cccc##aaaa", + "..bcc#cccc#d#aaa", + ".bcef#cccc#dd#aa", + ".bcfe#cccc#####a", + ".bcef#ccccccccc#", + "bbbbbbbbbbbbccc#", + "bccccccccccbbcc#", + "bcefefefefee#bc#", + ".bcefefefefef#c#", + ".bcfefefefefe#c#", + "..bcfefefefeeb##", + "..bbbbbbbbbbbbb#", + "...#############", + "................"}; + +static const char * const filedialog_end_xpm[]={ + "16 15 9 1", + "d c #a0a0a0", + "c c #c3c3c3", + "# c #cec6bd", + ". c #000000", + "f c #ffff00", + "e c #999999", + "g c #cccccc", + "b c #ffffff", + "a c None", + "......####aaaaaa", + ".bbbb..###aaaaaa", + ".bbbb.c.##aaaaaa", + ".bbbb....ddeeeea", + ".bbbbbbb.bbbbbe.", + ".bbbbbbb.bcfgfe.", + "eeeeeeeeeeeeefe.", + "ebbbbbbbbbbeege.", + "ebfgfgfgfgff.ee.", + "aebfgfgfgfgfg.e.", + "aebgfgfgfgfgf.e.", + "aaebgfgfgfgffe..", + "aaeeeeeeeeeeeee.", + "aaa.............", + "aaaaaaaaaaaaaaaa"}; + +#endif // QT_NO_IMAGEFORMAT_XPM diff --git a/src/widgets/styles/qdrawutil.cpp b/src/widgets/styles/qdrawutil.cpp new file mode 100644 index 0000000000..c674da8394 --- /dev/null +++ b/src/widgets/styles/qdrawutil.cpp @@ -0,0 +1,1053 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdrawutil.h" +#include "qbitmap.h" +#include "qpixmapcache.h" +#include "qpainter.h" +#include "qpalette.h" +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \headerfile + \title Drawing Utility Functions + + \sa QPainter +*/ + +/*! + \fn void qDrawShadeLine(QPainter *painter, int x1, int y1, int x2, int y2, + const QPalette &palette, bool sunken, + int lineWidth, int midLineWidth) + \relates + + Draws a horizontal (\a y1 == \a y2) or vertical (\a x1 == \a x2) + shaded line using the given \a painter. Note that nothing is + drawn if \a y1 != \a y2 and \a x1 != \a x2 (i.e. the line is + neither horizontal nor vertical). + + The provided \a palette specifies the shading colors (\l + {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l + {QPalette::mid()}{middle} colors). The given \a lineWidth + specifies the line width for each of the lines; it is not the + total line width. The given \a midLineWidth specifies the width of + a middle line drawn in the QPalette::mid() color. + + The line appears sunken if \a sunken is true, otherwise raised. + + \warning This function does not look at QWidget::style() or + QApplication::style(). Use the drawing functions in QStyle to + make widgets that follow the current GUI style. + + + Alternatively you can use a QFrame widget and apply the + QFrame::setFrameStyle() function to display a shaded line: + + \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 0 + + \sa qDrawShadeRect(), qDrawShadePanel(), QStyle +*/ + +void qDrawShadeLine(QPainter *p, int x1, int y1, int x2, int y2, + const QPalette &pal, bool sunken, + int lineWidth, int midLineWidth) +{ + if (!(p && lineWidth >= 0 && midLineWidth >= 0)) { + qWarning("qDrawShadeLine: Invalid parameters"); + return; + } + int tlw = lineWidth*2 + midLineWidth; // total line width + QPen oldPen = p->pen(); // save pen + if (sunken) + p->setPen(pal.color(QPalette::Dark)); + else + p->setPen(pal.light().color()); + QPolygon a; + int i; + if (y1 == y2) { // horizontal line + int y = y1 - tlw/2; + if (x1 > x2) { // swap x1 and x2 + int t = x1; + x1 = x2; + x2 = t; + } + x2--; + for (i=0; idrawPolyline(a); + } + if (midLineWidth > 0) { + p->setPen(pal.mid().color()); + for (i=0; idrawLine(x1+lineWidth, y+lineWidth+i, + x2-lineWidth, y+lineWidth+i); + } + if (sunken) + p->setPen(pal.light().color()); + else + p->setPen(pal.dark().color()); + for (i=0; idrawPolyline(a); + } + } + else if (x1 == x2) { // vertical line + int x = x1 - tlw/2; + if (y1 > y2) { // swap y1 and y2 + int t = y1; + y1 = y2; + y2 = t; + } + y2--; + for (i=0; idrawPolyline(a); + } + if (midLineWidth > 0) { + p->setPen(pal.mid().color()); + for (i=0; idrawLine(x+lineWidth+i, y1+lineWidth, x+lineWidth+i, y2); + } + if (sunken) + p->setPen(pal.light().color()); + else + p->setPen(pal.dark().color()); + for (i=0; idrawPolyline(a); + } + } + p->setPen(oldPen); +} + +/*! + \fn void qDrawShadeRect(QPainter *painter, int x, int y, int width, int height, + const QPalette &palette, bool sunken, + int lineWidth, int midLineWidth, + const QBrush *fill) + \relates + + Draws the shaded rectangle beginning at (\a x, \a y) with the + given \a width and \a height using the provided \a painter. + + The provide \a palette specifies the shading colors (\l + {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l + {QPalette::mid()}{middle} colors. The given \a lineWidth + specifies the line width for each of the lines; it is not the + total line width. The \a midLineWidth specifies the width of a + middle line drawn in the QPalette::mid() color. The rectangle's + interior is filled with the \a fill brush unless \a fill is 0. + + The rectangle appears sunken if \a sunken is true, otherwise + raised. + + \warning This function does not look at QWidget::style() or + QApplication::style(). Use the drawing functions in QStyle to make + widgets that follow the current GUI style. + + Alternatively you can use a QFrame widget and apply the + QFrame::setFrameStyle() function to display a shaded rectangle: + + \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 1 + + \sa qDrawShadeLine(), qDrawShadePanel(), qDrawPlainRect(), QStyle +*/ + +void qDrawShadeRect(QPainter *p, int x, int y, int w, int h, + const QPalette &pal, bool sunken, + int lineWidth, int midLineWidth, + const QBrush *fill) +{ + if (w == 0 || h == 0) + return; + if (! (w > 0 && h > 0 && lineWidth >= 0 && midLineWidth >= 0)) { + qWarning("qDrawShadeRect: Invalid parameters"); + return; + } + QPen oldPen = p->pen(); + if (sunken) + p->setPen(pal.dark().color()); + else + p->setPen(pal.light().color()); + int x1=x, y1=y, x2=x+w-1, y2=y+h-1; + + if (lineWidth == 1 && midLineWidth == 0) {// standard shade rectangle + p->drawRect(x1, y1, w-2, h-2); + if (sunken) + p->setPen(pal.light().color()); + else + p->setPen(pal.dark().color()); + QLineF lines[4] = { QLineF(x1+1, y1+1, x2-2, y1+1), + QLineF(x1+1, y1+2, x1+1, y2-2), + QLineF(x1, y2, x2, y2), + QLineF(x2,y1, x2,y2-1) }; + p->drawLines(lines, 4); // draw bottom/right lines + } else { // more complicated + int m = lineWidth+midLineWidth; + int i, j=0, k=m; + for (i=0; idrawLines(lines, 4); + k++; + } + p->setPen(pal.mid().color()); + j = lineWidth*2; + for (i=0; idrawRect(x1+lineWidth+i, y1+lineWidth+i, w-j-1, h-j-1); + j += 2; + } + if (sunken) + p->setPen(pal.light().color()); + else + p->setPen(pal.dark().color()); + k = m; + for (i=0; idrawLines(lines, 4); + k++; + } + } + if (fill) { + QBrush oldBrush = p->brush(); + int tlw = lineWidth + midLineWidth; + p->setPen(Qt::NoPen); + p->setBrush(*fill); + p->drawRect(x+tlw, y+tlw, w-2*tlw, h-2*tlw); + p->setBrush(oldBrush); + } + p->setPen(oldPen); // restore pen +} + + +/*! + \fn void qDrawShadePanel(QPainter *painter, int x, int y, int width, int height, + const QPalette &palette, bool sunken, + int lineWidth, const QBrush *fill) + \relates + + Draws the shaded panel beginning at (\a x, \a y) with the given \a + width and \a height using the provided \a painter and the given \a + lineWidth. + + The given \a palette specifies the shading colors (\l + {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l + {QPalette::mid()}{middle} colors). The panel's interior is filled + with the \a fill brush unless \a fill is 0. + + The panel appears sunken if \a sunken is true, otherwise raised. + + \warning This function does not look at QWidget::style() or + QApplication::style(). Use the drawing functions in QStyle to make + widgets that follow the current GUI style. + + Alternatively you can use a QFrame widget and apply the + QFrame::setFrameStyle() function to display a shaded panel: + + \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 2 + + \sa qDrawWinPanel(), qDrawShadeLine(), qDrawShadeRect(), QStyle +*/ + +void qDrawShadePanel(QPainter *p, int x, int y, int w, int h, + const QPalette &pal, bool sunken, + int lineWidth, const QBrush *fill) +{ + if (w == 0 || h == 0) + return; + if (!(w > 0 && h > 0 && lineWidth >= 0)) { + qWarning("qDrawShadePanel: Invalid parameters"); + } + QColor shade = pal.dark().color(); + QColor light = pal.light().color(); + if (fill) { + if (fill->color() == shade) + shade = pal.shadow().color(); + if (fill->color() == light) + light = pal.midlight().color(); + } + QPen oldPen = p->pen(); // save pen + QVector lines; + lines.reserve(2*lineWidth); + + if (sunken) + p->setPen(shade); + else + p->setPen(light); + int x1, y1, x2, y2; + int i; + x1 = x; + y1 = y2 = y; + x2 = x+w-2; + for (i=0; idrawLines(lines); + lines.clear(); + if (sunken) + p->setPen(light); + else + p->setPen(shade); + x1 = x; + y1 = y2 = y+h-1; + x2 = x+w-1; + for (i=0; idrawLines(lines); + if (fill) // fill with fill color + p->fillRect(x+lineWidth, y+lineWidth, w-lineWidth*2, h-lineWidth*2, *fill); + p->setPen(oldPen); // restore pen +} + + +/*! + \internal + This function draws a rectangle with two pixel line width. + It is called from qDrawWinButton() and qDrawWinPanel(). + + c1..c4 and fill are used: + + 1 1 1 1 1 2 + 1 3 3 3 4 2 + 1 3 F F 4 2 + 1 3 F F 4 2 + 1 4 4 4 4 2 + 2 2 2 2 2 2 +*/ + +static void qDrawWinShades(QPainter *p, + int x, int y, int w, int h, + const QColor &c1, const QColor &c2, + const QColor &c3, const QColor &c4, + const QBrush *fill) +{ + if (w < 2 || h < 2) // can't do anything with that + return; + QPen oldPen = p->pen(); + QPoint a[3] = { QPoint(x, y+h-2), QPoint(x, y), QPoint(x+w-2, y) }; + p->setPen(c1); + p->drawPolyline(a, 3); + QPoint b[3] = { QPoint(x, y+h-1), QPoint(x+w-1, y+h-1), QPoint(x+w-1, y) }; + p->setPen(c2); + p->drawPolyline(b, 3); + if (w > 4 && h > 4) { + QPoint c[3] = { QPoint(x+1, y+h-3), QPoint(x+1, y+1), QPoint(x+w-3, y+1) }; + p->setPen(c3); + p->drawPolyline(c, 3); + QPoint d[3] = { QPoint(x+1, y+h-2), QPoint(x+w-2, y+h-2), QPoint(x+w-2, y+1) }; + p->setPen(c4); + p->drawPolyline(d, 3); + if (fill) + p->fillRect(QRect(x+2, y+2, w-4, h-4), *fill); + } + p->setPen(oldPen); +} + + +/*! + \fn void qDrawWinButton(QPainter *painter, int x, int y, int width, int height, + const QPalette &palette, bool sunken, + const QBrush *fill) + \relates + + Draws the Windows-style button specified by the given point (\a x, + \a y}, \a width and \a height using the provided \a painter with a + line width of 2 pixels. The button's interior is filled with the + \a{fill} brush unless \a fill is 0. + + The given \a palette specifies the shading colors (\l + {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l + {QPalette::mid()}{middle} colors). + + The button appears sunken if \a sunken is true, otherwise raised. + + \warning This function does not look at QWidget::style() or + QApplication::style()-> Use the drawing functions in QStyle to make + widgets that follow the current GUI style. + + \sa qDrawWinPanel(), QStyle +*/ + +void qDrawWinButton(QPainter *p, int x, int y, int w, int h, + const QPalette &pal, bool sunken, + const QBrush *fill) +{ + if (sunken) + qDrawWinShades(p, x, y, w, h, + pal.shadow().color(), pal.light().color(), pal.dark().color(), + pal.button().color(), fill); + else + qDrawWinShades(p, x, y, w, h, + pal.light().color(), pal.shadow().color(), pal.button().color(), + pal.dark().color(), fill); +} + +/*! + \fn void qDrawWinPanel(QPainter *painter, int x, int y, int width, int height, + const QPalette &palette, bool sunken, + const QBrush *fill) + \relates + + Draws the Windows-style panel specified by the given point(\a x, + \a y), \a width and \a height using the provided \a painter with a + line width of 2 pixels. The button's interior is filled with the + \a fill brush unless \a fill is 0. + + The given \a palette specifies the shading colors. The panel + appears sunken if \a sunken is true, otherwise raised. + + \warning This function does not look at QWidget::style() or + QApplication::style(). Use the drawing functions in QStyle to make + widgets that follow the current GUI style. + + Alternatively you can use a QFrame widget and apply the + QFrame::setFrameStyle() function to display a shaded panel: + + \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 3 + + \sa qDrawShadePanel(), qDrawWinButton(), QStyle +*/ + +void qDrawWinPanel(QPainter *p, int x, int y, int w, int h, + const QPalette &pal, bool sunken, + const QBrush *fill) +{ + if (sunken) + qDrawWinShades(p, x, y, w, h, + pal.dark().color(), pal.light().color(), pal.shadow().color(), + pal.midlight().color(), fill); + else + qDrawWinShades(p, x, y, w, h, + pal.light().color(), pal.shadow().color(), pal.midlight().color(), + pal.dark().color(), fill); +} + +/*! + \fn void qDrawPlainRect(QPainter *painter, int x, int y, int width, int height, const QColor &lineColor, + int lineWidth, const QBrush *fill) + \relates + + Draws the plain rectangle beginning at (\a x, \a y) with the given + \a width and \a height, using the specified \a painter, \a lineColor + and \a lineWidth. The rectangle's interior is filled with the \a + fill brush unless \a fill is 0. + + \warning This function does not look at QWidget::style() or + QApplication::style(). Use the drawing functions in QStyle to make + widgets that follow the current GUI style. + + Alternatively you can use a QFrame widget and apply the + QFrame::setFrameStyle() function to display a plain rectangle: + + \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 4 + + \sa qDrawShadeRect(), QStyle +*/ + +void qDrawPlainRect(QPainter *p, int x, int y, int w, int h, const QColor &c, + int lineWidth, const QBrush *fill) +{ + if (w == 0 || h == 0) + return; + if (!(w > 0 && h > 0 && lineWidth >= 0)) { + qWarning("qDrawPlainRect: Invalid parameters"); + } + QPen oldPen = p->pen(); + QBrush oldBrush = p->brush(); + p->setPen(c); + p->setBrush(Qt::NoBrush); + for (int i=0; idrawRect(x+i, y+i, w-i*2 - 1, h-i*2 - 1); + if (fill) { // fill with fill color + p->setPen(Qt::NoPen); + p->setBrush(*fill); + p->drawRect(x+lineWidth, y+lineWidth, w-lineWidth*2, h-lineWidth*2); + } + p->setPen(oldPen); + p->setBrush(oldBrush); +} + +/***************************************************************************** + Overloaded functions. + *****************************************************************************/ + +/*! + \fn void qDrawShadeLine(QPainter *painter, const QPoint &p1, const QPoint &p2, + const QPalette &palette, bool sunken, int lineWidth, int midLineWidth) + \relates + \overload + + Draws a horizontal or vertical shaded line between \a p1 and \a p2 + using the given \a painter. Note that nothing is drawn if the line + between the points would be neither horizontal nor vertical. + + The provided \a palette specifies the shading colors (\l + {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l + {QPalette::mid()}{middle} colors). The given \a lineWidth + specifies the line width for each of the lines; it is not the + total line width. The given \a midLineWidth specifies the width of + a middle line drawn in the QPalette::mid() color. + + The line appears sunken if \a sunken is true, otherwise raised. + + \warning This function does not look at QWidget::style() or + QApplication::style(). Use the drawing functions in QStyle to + make widgets that follow the current GUI style. + + + Alternatively you can use a QFrame widget and apply the + QFrame::setFrameStyle() function to display a shaded line: + + \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 5 + + \sa qDrawShadeRect(), qDrawShadePanel(), QStyle +*/ + +void qDrawShadeLine(QPainter *p, const QPoint &p1, const QPoint &p2, + const QPalette &pal, bool sunken, + int lineWidth, int midLineWidth) +{ + qDrawShadeLine(p, p1.x(), p1.y(), p2.x(), p2.y(), pal, sunken, + lineWidth, midLineWidth); +} + +/*! + \fn void qDrawShadeRect(QPainter *painter, const QRect &rect, const QPalette &palette, + bool sunken, int lineWidth, int midLineWidth, const QBrush *fill) + \relates + \overload + + Draws the shaded rectangle specified by \a rect using the given \a painter. + + The provide \a palette specifies the shading colors (\l + {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l + {QPalette::mid()}{middle} colors. The given \a lineWidth + specifies the line width for each of the lines; it is not the + total line width. The \a midLineWidth specifies the width of a + middle line drawn in the QPalette::mid() color. The rectangle's + interior is filled with the \a fill brush unless \a fill is 0. + + The rectangle appears sunken if \a sunken is true, otherwise + raised. + + \warning This function does not look at QWidget::style() or + QApplication::style(). Use the drawing functions in QStyle to make + widgets that follow the current GUI style. + + Alternatively you can use a QFrame widget and apply the + QFrame::setFrameStyle() function to display a shaded rectangle: + + \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 6 + + \sa qDrawShadeLine(), qDrawShadePanel(), qDrawPlainRect(), QStyle +*/ + +void qDrawShadeRect(QPainter *p, const QRect &r, + const QPalette &pal, bool sunken, + int lineWidth, int midLineWidth, + const QBrush *fill) +{ + qDrawShadeRect(p, r.x(), r.y(), r.width(), r.height(), pal, sunken, + lineWidth, midLineWidth, fill); +} + +/*! + \fn void qDrawShadePanel(QPainter *painter, const QRect &rect, const QPalette &palette, + bool sunken, int lineWidth, const QBrush *fill) + \relates + \overload + + Draws the shaded panel at the rectangle specified by \a rect using the + given \a painter and the given \a lineWidth. + + The given \a palette specifies the shading colors (\l + {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l + {QPalette::mid()}{middle} colors). The panel's interior is filled + with the \a fill brush unless \a fill is 0. + + The panel appears sunken if \a sunken is true, otherwise raised. + + \warning This function does not look at QWidget::style() or + QApplication::style(). Use the drawing functions in QStyle to make + widgets that follow the current GUI style. + + Alternatively you can use a QFrame widget and apply the + QFrame::setFrameStyle() function to display a shaded panel: + + \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 7 + + \sa qDrawWinPanel(), qDrawShadeLine(), qDrawShadeRect(), QStyle +*/ + +void qDrawShadePanel(QPainter *p, const QRect &r, + const QPalette &pal, bool sunken, + int lineWidth, const QBrush *fill) +{ + qDrawShadePanel(p, r.x(), r.y(), r.width(), r.height(), pal, sunken, + lineWidth, fill); +} + +/*! + \fn void qDrawWinButton(QPainter *painter, const QRect &rect, const QPalette &palette, + bool sunken, const QBrush *fill) + \relates + \overload + + Draws the Windows-style button at the rectangle specified by \a rect using + the given \a painter with a line width of 2 pixels. The button's interior + is filled with the \a{fill} brush unless \a fill is 0. + + The given \a palette specifies the shading colors (\l + {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l + {QPalette::mid()}{middle} colors). + + The button appears sunken if \a sunken is true, otherwise raised. + + \warning This function does not look at QWidget::style() or + QApplication::style()-> Use the drawing functions in QStyle to make + widgets that follow the current GUI style. + + \sa qDrawWinPanel(), QStyle +*/ + +void qDrawWinButton(QPainter *p, const QRect &r, + const QPalette &pal, bool sunken, const QBrush *fill) +{ + qDrawWinButton(p, r.x(), r.y(), r.width(), r.height(), pal, sunken, fill); +} + +/*! + \fn void qDrawWinPanel(QPainter *painter, const QRect &rect, const QPalette &palette, + bool sunken, const QBrush *fill) + \overload + + Draws the Windows-style panel at the rectangle specified by \a rect using + the given \a painter with a line width of 2 pixels. The button's interior + is filled with the \a fill brush unless \a fill is 0. + + The given \a palette specifies the shading colors. The panel + appears sunken if \a sunken is true, otherwise raised. + + \warning This function does not look at QWidget::style() or + QApplication::style(). Use the drawing functions in QStyle to make + widgets that follow the current GUI style. + + Alternatively you can use a QFrame widget and apply the + QFrame::setFrameStyle() function to display a shaded panel: + + \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 8 + + \sa qDrawShadePanel(), qDrawWinButton(), QStyle +*/ + +void qDrawWinPanel(QPainter *p, const QRect &r, + const QPalette &pal, bool sunken, const QBrush *fill) +{ + qDrawWinPanel(p, r.x(), r.y(), r.width(), r.height(), pal, sunken, fill); +} + +/*! + \fn void qDrawPlainRect(QPainter *painter, const QRect &rect, const QColor &lineColor, int lineWidth, const QBrush *fill) + \relates + \overload + + Draws the plain rectangle specified by \a rect using the given \a painter, + \a lineColor and \a lineWidth. The rectangle's interior is filled with the + \a fill brush unless \a fill is 0. + + \warning This function does not look at QWidget::style() or + QApplication::style(). Use the drawing functions in QStyle to make + widgets that follow the current GUI style. + + Alternatively you can use a QFrame widget and apply the + QFrame::setFrameStyle() function to display a plain rectangle: + + \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 9 + + \sa qDrawShadeRect(), QStyle +*/ + +void qDrawPlainRect(QPainter *p, const QRect &r, const QColor &c, + int lineWidth, const QBrush *fill) +{ + qDrawPlainRect(p, r.x(), r.y(), r.width(), r.height(), c, + lineWidth, fill); +} + + +/*! + \class QTileRules + \since 4.6 + + Holds the rules used to draw a pixmap or image split into nine segments, + similar to \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}. + + \sa Qt::TileRule, QMargins +*/ + +/*! \fn QTileRules::QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule) + Constructs a QTileRules with the given \a horizontalRule and + \a verticalRule. + */ + +/*! \fn QTileRules::QTileRules(Qt::TileRule rule) + Constructs a QTileRules with the given \a rule used for both + the horizontal rule and the vertical rule. + */ + +/*! + \fn void qDrawBorderPixmap(QPainter *painter, const QRect &target, const QMargins &margins, const QPixmap &pixmap) + \relates + \since 4.6 + \overload + + \brief The qDrawBorderPixmap function is for drawing a pixmap into + the margins of a rectangle. + + Draws the given \a pixmap into the given \a target rectangle, using the + given \a painter. The pixmap will be split into nine segments and drawn + according to the \a margins structure. +*/ + +typedef QVarLengthArray QPixmapFragmentsArray; + +/*! + \since 4.6 + + Draws the indicated \a sourceRect rectangle from the given \a pixmap into + the given \a targetRect rectangle, using the given \a painter. The pixmap + will be split into nine segments according to the given \a targetMargins + and \a sourceMargins structures. Finally, the pixmap will be drawn + according to the given \a rules. + + This function is used to draw a scaled pixmap, similar to + \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images} + + \sa Qt::TileRule, QTileRules, QMargins +*/ + +void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, + const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins, + const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints) +{ + QPainter::PixmapFragment d; + d.opacity = 1.0; + d.rotation = 0.0; + + QPixmapFragmentsArray opaqueData; + QPixmapFragmentsArray translucentData; + + // source center + const int sourceCenterTop = sourceRect.top() + sourceMargins.top(); + const int sourceCenterLeft = sourceRect.left() + sourceMargins.left(); + const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom() + 1; + const int sourceCenterRight = sourceRect.right() - sourceMargins.right() + 1; + const int sourceCenterWidth = sourceCenterRight - sourceCenterLeft; + const int sourceCenterHeight = sourceCenterBottom - sourceCenterTop; + // target center + const int targetCenterTop = targetRect.top() + targetMargins.top(); + const int targetCenterLeft = targetRect.left() + targetMargins.left(); + const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom() + 1; + const int targetCenterRight = targetRect.right() - targetMargins.right() + 1; + const int targetCenterWidth = targetCenterRight - targetCenterLeft; + const int targetCenterHeight = targetCenterBottom - targetCenterTop; + + QVarLengthArray xTarget; // x-coordinates of target rectangles + QVarLengthArray yTarget; // y-coordinates of target rectangles + + int columns = 3; + int rows = 3; + if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0) + columns = qMax(3, 2 + qCeil(targetCenterWidth / qreal(sourceCenterWidth))); + if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0) + rows = qMax(3, 2 + qCeil(targetCenterHeight / qreal(sourceCenterHeight))); + + xTarget.resize(columns + 1); + yTarget.resize(rows + 1); + + bool oldAA = painter->testRenderHint(QPainter::Antialiasing); + if (painter->paintEngine()->type() != QPaintEngine::OpenGL + && painter->paintEngine()->type() != QPaintEngine::OpenGL2 + && oldAA && painter->combinedTransform().type() != QTransform::TxNone) { + painter->setRenderHint(QPainter::Antialiasing, false); + } + + xTarget[0] = targetRect.left(); + xTarget[1] = targetCenterLeft; + xTarget[columns - 1] = targetCenterRight; + xTarget[columns] = targetRect.left() + targetRect.width(); + + yTarget[0] = targetRect.top(); + yTarget[1] = targetCenterTop; + yTarget[rows - 1] = targetCenterBottom; + yTarget[rows] = targetRect.top() + targetRect.height(); + + qreal dx = targetCenterWidth; + qreal dy = targetCenterHeight; + + switch (rules.horizontal) { + case Qt::StretchTile: + dx = targetCenterWidth; + break; + case Qt::RepeatTile: + dx = sourceCenterWidth; + break; + case Qt::RoundTile: + dx = targetCenterWidth / qreal(columns - 2); + break; + } + + for (int i = 2; i < columns - 1; ++i) + xTarget[i] = xTarget[i - 1] + dx; + + switch (rules.vertical) { + case Qt::StretchTile: + dy = targetCenterHeight; + break; + case Qt::RepeatTile: + dy = sourceCenterHeight; + break; + case Qt::RoundTile: + dy = targetCenterHeight / qreal(rows - 2); + break; + } + + for (int i = 2; i < rows - 1; ++i) + yTarget[i] = yTarget[i - 1] + dy; + + // corners + if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left + d.x = (0.5 * (xTarget[1] + xTarget[0])); + d.y = (0.5 * (yTarget[1] + yTarget[0])); + d.sourceLeft = sourceRect.left(); + d.sourceTop = sourceRect.top(); + d.width = sourceMargins.left(); + d.height = sourceMargins.top(); + d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; + d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; + if (hints & QDrawBorderPixmap::OpaqueTopLeft) + opaqueData.append(d); + else + translucentData.append(d); + } + if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right + d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); + d.y = (0.5 * (yTarget[1] + yTarget[0])); + d.sourceLeft = sourceCenterRight; + d.sourceTop = sourceRect.top(); + d.width = sourceMargins.right(); + d.height = sourceMargins.top(); + d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; + d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; + if (hints & QDrawBorderPixmap::OpaqueTopRight) + opaqueData.append(d); + else + translucentData.append(d); + } + if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left + d.x = (0.5 * (xTarget[1] + xTarget[0])); + d.y =(0.5 * (yTarget[rows] + yTarget[rows - 1])); + d.sourceLeft = sourceRect.left(); + d.sourceTop = sourceCenterBottom; + d.width = sourceMargins.left(); + d.height = sourceMargins.bottom(); + d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; + d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; + if (hints & QDrawBorderPixmap::OpaqueBottomLeft) + opaqueData.append(d); + else + translucentData.append(d); + } + if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right + d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); + d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1])); + d.sourceLeft = sourceCenterRight; + d.sourceTop = sourceCenterBottom; + d.width = sourceMargins.right(); + d.height = sourceMargins.bottom(); + d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; + d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; + if (hints & QDrawBorderPixmap::OpaqueBottomRight) + opaqueData.append(d); + else + translucentData.append(d); + } + + // horizontal edges + if (targetCenterWidth > 0 && sourceCenterWidth > 0) { + if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top + QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData; + d.sourceLeft = sourceCenterLeft; + d.sourceTop = sourceRect.top(); + d.width = sourceCenterWidth; + d.height = sourceMargins.top(); + d.y = (0.5 * (yTarget[1] + yTarget[0])); + d.scaleX = dx / d.width; + d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; + for (int i = 1; i < columns - 1; ++i) { + d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); + data.append(d); + } + if (rules.horizontal == Qt::RepeatTile) + data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX); + } + if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom + QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData; + d.sourceLeft = sourceCenterLeft; + d.sourceTop = sourceCenterBottom; + d.width = sourceCenterWidth; + d.height = sourceMargins.bottom(); + d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1])); + d.scaleX = dx / d.width; + d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; + for (int i = 1; i < columns - 1; ++i) { + d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); + data.append(d); + } + if (rules.horizontal == Qt::RepeatTile) + data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX); + } + } + + // vertical edges + if (targetCenterHeight > 0 && sourceCenterHeight > 0) { + if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left + QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData; + d.sourceLeft = sourceRect.left(); + d.sourceTop = sourceCenterTop; + d.width = sourceMargins.left(); + d.height = sourceCenterHeight; + d.x = (0.5 * (xTarget[1] + xTarget[0])); + d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; + d.scaleY = dy / d.height; + for (int i = 1; i < rows - 1; ++i) { + d.y = (0.5 * (yTarget[i + 1] + yTarget[i])); + data.append(d); + } + if (rules.vertical == Qt::RepeatTile) + data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY); + } + if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right + QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData; + d.sourceLeft = sourceCenterRight; + d.sourceTop = sourceCenterTop; + d.width = sourceMargins.right(); + d.height = sourceCenterHeight; + d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); + d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; + d.scaleY = dy / d.height; + for (int i = 1; i < rows - 1; ++i) { + d.y = (0.5 * (yTarget[i + 1] + yTarget[i])); + data.append(d); + } + if (rules.vertical == Qt::RepeatTile) + data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY); + } + } + + // center + if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) { + QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData; + d.sourceLeft = sourceCenterLeft; + d.sourceTop = sourceCenterTop; + d.width = sourceCenterWidth; + d.height = sourceCenterHeight; + d.scaleX = dx / d.width; + d.scaleY = dy / d.height; + + qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX; + qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY; + + for (int j = 1; j < rows - 1; ++j) { + d.y = (0.5 * (yTarget[j + 1] + yTarget[j])); + for (int i = 1; i < columns - 1; ++i) { + d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); + data.append(d); + } + if (rules.horizontal == Qt::RepeatTile) + data[data.size() - 1].width = repeatWidth; + } + if (rules.vertical == Qt::RepeatTile) { + for (int i = 1; i < columns - 1; ++i) + data[data.size() - i].height = repeatHeight; + } + } + + if (opaqueData.size()) + painter->drawPixmapFragments(opaqueData.data(), opaqueData.size(), pixmap, QPainter::OpaqueHint); + if (translucentData.size()) + painter->drawPixmapFragments(translucentData.data(), translucentData.size(), pixmap); + + if (oldAA) + painter->setRenderHint(QPainter::Antialiasing, true); +} + +QT_END_NAMESPACE diff --git a/src/widgets/styles/qdrawutil.h b/src/widgets/styles/qdrawutil.h new file mode 100644 index 0000000000..f46f720f2c --- /dev/null +++ b/src/widgets/styles/qdrawutil.h @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDRAWUTIL_H +#define QDRAWUTIL_H + +#include +#include // char*->QString conversion +#include +#include +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPainter; +class QPalette; +class QPoint; +class QColor; +class QBrush; +class QRect; + +// +// Standard shade drawing +// + +Q_GUI_EXPORT void qDrawShadeLine(QPainter *p, int x1, int y1, int x2, int y2, + const QPalette &pal, bool sunken = true, + int lineWidth = 1, int midLineWidth = 0); + +Q_GUI_EXPORT void qDrawShadeLine(QPainter *p, const QPoint &p1, const QPoint &p2, + const QPalette &pal, bool sunken = true, + int lineWidth = 1, int midLineWidth = 0); + +Q_GUI_EXPORT void qDrawShadeRect(QPainter *p, int x, int y, int w, int h, + const QPalette &pal, bool sunken = false, + int lineWidth = 1, int midLineWidth = 0, + const QBrush *fill = 0); + +Q_GUI_EXPORT void qDrawShadeRect(QPainter *p, const QRect &r, + const QPalette &pal, bool sunken = false, + int lineWidth = 1, int midLineWidth = 0, + const QBrush *fill = 0); + +Q_GUI_EXPORT void qDrawShadePanel(QPainter *p, int x, int y, int w, int h, + const QPalette &pal, bool sunken = false, + int lineWidth = 1, const QBrush *fill = 0); + +Q_GUI_EXPORT void qDrawShadePanel(QPainter *p, const QRect &r, + const QPalette &pal, bool sunken = false, + int lineWidth = 1, const QBrush *fill = 0); + +Q_GUI_EXPORT void qDrawWinButton(QPainter *p, int x, int y, int w, int h, + const QPalette &pal, bool sunken = false, + const QBrush *fill = 0); + +Q_GUI_EXPORT void qDrawWinButton(QPainter *p, const QRect &r, + const QPalette &pal, bool sunken = false, + const QBrush *fill = 0); + +Q_GUI_EXPORT void qDrawWinPanel(QPainter *p, int x, int y, int w, int h, + const QPalette &pal, bool sunken = false, + const QBrush *fill = 0); + +Q_GUI_EXPORT void qDrawWinPanel(QPainter *p, const QRect &r, + const QPalette &pal, bool sunken = false, + const QBrush *fill = 0); + +Q_GUI_EXPORT void qDrawPlainRect(QPainter *p, int x, int y, int w, int h, const QColor &, + int lineWidth = 1, const QBrush *fill = 0); + +Q_GUI_EXPORT void qDrawPlainRect(QPainter *p, const QRect &r, const QColor &, + int lineWidth = 1, const QBrush *fill = 0); + + + +struct QTileRules +{ + inline QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule) + : horizontal(horizontalRule), vertical(verticalRule) {} + inline QTileRules(Qt::TileRule rule = Qt::StretchTile) + : horizontal(rule), vertical(rule) {} + Qt::TileRule horizontal; + Qt::TileRule vertical; +}; + +#ifndef Q_QDOC +// For internal use only. +namespace QDrawBorderPixmap +{ + enum DrawingHint + { + OpaqueTopLeft = 0x0001, + OpaqueTop = 0x0002, + OpaqueTopRight = 0x0004, + OpaqueLeft = 0x0008, + OpaqueCenter = 0x0010, + OpaqueRight = 0x0020, + OpaqueBottomLeft = 0x0040, + OpaqueBottom = 0x0080, + OpaqueBottomRight = 0x0100, + OpaqueCorners = OpaqueTopLeft | OpaqueTopRight | OpaqueBottomLeft | OpaqueBottomRight, + OpaqueEdges = OpaqueTop | OpaqueLeft | OpaqueRight | OpaqueBottom, + OpaqueFrame = OpaqueCorners | OpaqueEdges, + OpaqueAll = OpaqueCenter | OpaqueFrame + }; + + Q_DECLARE_FLAGS(DrawingHints, DrawingHint) +} +#endif + +Q_GUI_EXPORT void qDrawBorderPixmap(QPainter *painter, + const QRect &targetRect, + const QMargins &targetMargins, + const QPixmap &pixmap, + const QRect &sourceRect, + const QMargins &sourceMargins, + const QTileRules &rules = QTileRules() +#ifndef Q_QDOC + , QDrawBorderPixmap::DrawingHints hints = 0 +#endif + ); + +inline void qDrawBorderPixmap(QPainter *painter, + const QRect &target, + const QMargins &margins, + const QPixmap &pixmap) +{ + qDrawBorderPixmap(painter, target, margins, pixmap, pixmap.rect(), margins); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDRAWUTIL_H diff --git a/src/widgets/styles/qgtkpainter.cpp b/src/widgets/styles/qgtkpainter.cpp new file mode 100644 index 0000000000..68ade04984 --- /dev/null +++ b/src/widgets/styles/qgtkpainter.cpp @@ -0,0 +1,721 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgtkpainter_p.h" + +#include +#if !defined(QT_NO_STYLE_GTK) + +// This class is primarily a wrapper around the gtk painter functions +// and takes care of converting all such calls into cached Qt pixmaps. + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +#undef GTK_OBJECT_FLAGS +#define GTK_OBJECT_FLAGS(obj)(((GtkObject*)(obj))->flags) + +#if Q_BYTE_ORDER == Q_BIG_ENDIAN +# define QT_RED 3 +# define QT_GREEN 2 +# define QT_BLUE 1 +# define QT_ALPHA 0 +#else +# define QT_RED 0 +# define QT_GREEN 1 +# define QT_BLUE 2 +# define QT_ALPHA 3 +#endif +# define GTK_RED 2 +# define GTK_GREEN 1 +# define GTK_BLUE 0 +# define GTK_ALPHA 3 + +// To recover alpha we apply the gtk painting function two times to +// white, and black window backgrounds. This can be used to +// recover the premultiplied alpha channel +QPixmap QGtkPainter::renderTheme(uchar *bdata, uchar *wdata, const QRect &rect) +{ + const int bytecount = rect.width() * rect.height() * 4; + for (int index = 0; index < bytecount ; index += 4) { + uchar val = bdata[index + GTK_BLUE]; + if (m_alpha) { + int alphaval = qMax(bdata[index + GTK_BLUE] - wdata[index + GTK_BLUE], + bdata[index + GTK_GREEN] - wdata[index + GTK_GREEN]); + alphaval = qMax(alphaval, bdata[index + GTK_RED] - wdata[index + GTK_RED]) + 255; + bdata[index + QT_ALPHA] = alphaval; + } + bdata[index + QT_RED] = bdata[index + GTK_RED]; + bdata[index + QT_GREEN] = bdata[index + GTK_GREEN]; + bdata[index + QT_BLUE] = val; + } + QImage converted((const uchar*)bdata, rect.width(), rect.height(), m_alpha ? + QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); + + if (m_hflipped || m_vflipped) { + return QPixmap::fromImage(converted.mirrored(m_hflipped, m_vflipped)); + } else { + // on raster graphicssystem we need to do a copy here, because + // we intend to deallocate the qimage bits shortly after... + return QPixmap::fromImage(converted.copy()); + } +} + +// This macro is responsible for painting any GtkStyle painting function onto a QPixmap +#define DRAW_TO_CACHE(draw_func) \ + if (rect.width() > QWIDGETSIZE_MAX || rect.height() > QWIDGETSIZE_MAX) \ + return; \ + QRect pixmapRect(0, 0, rect.width(), rect.height()); \ + { \ + GdkPixmap *pixmap = QGtkStylePrivate::gdk_pixmap_new((GdkDrawable*)(m_window->window), \ + rect.width(), rect.height(), -1); \ + if (!pixmap) \ + return; \ + style = QGtkStylePrivate::gtk_style_attach (style, m_window->window); \ + QGtkStylePrivate::gdk_draw_rectangle(pixmap, m_alpha ? style->black_gc : *style->bg_gc, true, \ + 0, 0, rect.width(), rect.height()); \ + draw_func; \ + GdkPixbuf *imgb = QGtkStylePrivate::gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, rect.width(), rect.height());\ + if (!imgb) \ + return; \ + imgb = QGtkStylePrivate::gdk_pixbuf_get_from_drawable(imgb, pixmap, NULL, 0, 0, 0, 0, \ + rect.width(), rect.height()); \ + uchar* bdata = (uchar*)QGtkStylePrivate::gdk_pixbuf_get_pixels(imgb); \ + if (m_alpha) { \ + QGtkStylePrivate::gdk_draw_rectangle(pixmap, style->white_gc, true, 0, 0, rect.width(), rect.height()); \ + draw_func; \ + GdkPixbuf *imgw = QGtkStylePrivate::gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, rect. \ + width(), rect.height()); \ + if (!imgw) \ + return; \ + imgw = QGtkStylePrivate::gdk_pixbuf_get_from_drawable(imgw, pixmap, NULL, 0, 0, 0, 0, \ + rect.width(), rect.height()); \ + uchar* wdata = (uchar*)QGtkStylePrivate::gdk_pixbuf_get_pixels(imgw); \ + cache = renderTheme(bdata, wdata, rect); \ + QGtkStylePrivate::gdk_pixbuf_unref(imgw); \ + } else { \ + cache = renderTheme(bdata, 0, rect); \ + } \ + QGtkStylePrivate::gdk_drawable_unref(pixmap); \ + QGtkStylePrivate::gdk_pixbuf_unref(imgb); \ + } + +QGtkPainter::QGtkPainter(QPainter *_painter) + : m_window(QGtkStylePrivate::gtkWidget("GtkWindow")) + , m_painter(_painter) + , m_alpha(true) + , m_hflipped(false) + , m_vflipped(false) + , m_usePixmapCache(true) +{} + + +static QString uniqueName(const QString &key, GtkStateType state, GtkShadowType shadow, + const QSize &size, GtkWidget *widget = 0) +{ + // Note the widget arg should ideally use the widget path, though would compromise performance + QString tmp = key + % HexString(state) + % HexString(shadow) + % HexString(size.width()) + % HexString(size.height()) + % HexString(quint64(widget)); + return tmp; +} + + +GtkStateType QGtkPainter::gtkState(const QStyleOption *option) + +{ + GtkStateType state = GTK_STATE_NORMAL; + if (!(option->state & QStyle::State_Enabled)) + state = GTK_STATE_INSENSITIVE; + else if (option->state & QStyle::State_MouseOver) + state = GTK_STATE_PRELIGHT; + + return state; +} + + +GtkStyle* QGtkPainter::getStyle(GtkWidget *gtkWidget) + +{ + Q_ASSERT(gtkWidget); + GtkStyle* style = gtkWidget->style; + Q_ASSERT(style); + return style; +} + +QPixmap QGtkPainter::getIcon(const char* iconName, GtkIconSize size) +{ + GtkStyle *style = QGtkStylePrivate::gtkStyle(); + GtkIconSet* iconSet = QGtkStylePrivate::gtk_icon_factory_lookup_default (iconName); + GdkPixbuf* icon = QGtkStylePrivate::gtk_icon_set_render_icon(iconSet, + style, + GTK_TEXT_DIR_LTR, + GTK_STATE_NORMAL, + size, + NULL, + "button"); + uchar* data = (uchar*)QGtkStylePrivate::gdk_pixbuf_get_pixels(icon); + int width = QGtkStylePrivate::gdk_pixbuf_get_width(icon); + int height = QGtkStylePrivate::gdk_pixbuf_get_height(icon); + QImage converted(width, height, QImage::Format_ARGB32); + uchar* tdata = (uchar*)converted.bits(); + + for ( int index = 0 ; index < height * width*4 ; index +=4 ) { + //int index = y * rowstride + x; + tdata[index + QT_RED] = data[index + GTK_RED]; + tdata[index + QT_GREEN] = data[index + GTK_GREEN]; + tdata[index + QT_BLUE] = data[index + GTK_BLUE]; + tdata[index + QT_ALPHA] = data[index + GTK_ALPHA]; + } + + QGtkStylePrivate::gdk_pixbuf_unref(icon); + + // should we free iconset? + return QPixmap::fromImage(converted); + +} + +// Note currently painted without alpha for performance reasons +void QGtkPainter::paintBoxGap(GtkWidget *gtkWidget, const gchar* part, + const QRect &paintRect, GtkStateType state, + GtkShadowType shadow, GtkPositionType gap_side, + gint x, gint width, + GtkStyle *style) +{ + if (!paintRect.isValid()) + return; + + QPixmap cache; + QRect rect = paintRect; + + // To avoid exhausting cache on large tabframes we cheat a bit by + // tiling the center part. + + const int maxHeight = 256; + const int border = 16; + if (rect.height() > maxHeight && (gap_side == GTK_POS_TOP || gap_side == GTK_POS_BOTTOM)) + rect.setHeight(2 * border + 1); + + QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget) + % HexString(gap_side) + % HexString(width) + % HexString(x); + + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_box_gap (style, + pixmap, + state, + shadow, + NULL, + gtkWidget, + (gchar*)part, + 0, 0, + rect.width(), + rect.height(), + gap_side, + x, + width)); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + if (rect.size() != paintRect.size()) { + // We assume we can stretch the middle tab part + // Note: the side effect of this is that pinstripe patterns will get fuzzy + const QSize size = cache.size(); + // top part + m_painter->drawPixmap(QRect(paintRect.left(), paintRect.top(), + paintRect.width(), border), cache, + QRect(0, 0, size.width(), border)); + + // tiled center part + QPixmap tilePart(cache.width(), 1); + QPainter scanLinePainter(&tilePart); + scanLinePainter.drawPixmap(QRect(0, 0, tilePart.width(), tilePart.height()), cache, QRect(0, border, size.width(), 1)); + scanLinePainter.end(); + m_painter->drawTiledPixmap(QRect(paintRect.left(), paintRect.top() + border, + paintRect.width(), paintRect.height() - 2*border), tilePart); + + // bottom part + m_painter->drawPixmap(QRect(paintRect.left(), paintRect.top() + paintRect.height() - border, + paintRect.width(), border), cache, + QRect(0, size.height() - border, size.width(), border)); + } else + m_painter->drawPixmap(paintRect.topLeft(), cache); +} + +void QGtkPainter::paintBox(GtkWidget *gtkWidget, const gchar* part, + const QRect &paintRect, GtkStateType state, + GtkShadowType shadow, GtkStyle *style, + const QString &pmKey) +{ + if (!paintRect.isValid()) + return; + + QPixmap cache; + QRect rect = paintRect; + + // To avoid exhausting cache on large tabframes we cheat a bit by + // tiling the center part. + + const int maxHeight = 256; + const int maxArea = 256*512; + const int border = 32; + if (rect.height() > maxHeight && (rect.width()*rect.height() > maxArea)) + rect.setHeight(2 * border + 1); + + QString pixmapName = uniqueName(QLS(part), state, shadow, + rect.size(), gtkWidget) % pmKey; + + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_box (style, + pixmap, + state, + shadow, + NULL, + gtkWidget, + part, + 0, 0, + rect.width(), + rect.height())); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + if (rect.size() != paintRect.size()) { + // We assume we can stretch the middle tab part + // Note: the side effect of this is that pinstripe patterns will get fuzzy + const QSize size = cache.size(); + // top part + m_painter->drawPixmap(QRect(paintRect.left(), paintRect.top(), + paintRect.width(), border), cache, + QRect(0, 0, size.width(), border)); + + // tiled center part + QPixmap tilePart(cache.width(), 1); + QPainter scanLinePainter(&tilePart); + scanLinePainter.drawPixmap(QRect(0, 0, tilePart.width(), tilePart.height()), cache, QRect(0, border, size.width(), 1)); + scanLinePainter.end(); + m_painter->drawTiledPixmap(QRect(paintRect.left(), paintRect.top() + border, + paintRect.width(), paintRect.height() - 2*border), tilePart); + + // bottom part + m_painter->drawPixmap(QRect(paintRect.left(), paintRect.top() + paintRect.height() - border, + paintRect.width(), border), cache, + QRect(0, size.height() - border, size.width(), border)); + } else + m_painter->drawPixmap(paintRect.topLeft(), cache); +} + +void QGtkPainter::paintHline(GtkWidget *gtkWidget, const gchar* part, + const QRect &rect, GtkStateType state, + GtkStyle *style, int x1, int x2, int y, + const QString &pmKey) +{ + if (!rect.isValid()) + return; + + QPixmap cache; + QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget) + % HexString(x1) + % HexString(x2) + % HexString(y) + % pmKey; + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_hline (style, + pixmap, + state, + NULL, + gtkWidget, + part, + x1, x2, y)); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + + m_painter->drawPixmap(rect.topLeft(), cache); +} + +void QGtkPainter::paintVline(GtkWidget *gtkWidget, const gchar* part, + const QRect &rect, GtkStateType state, + GtkStyle *style, int y1, int y2, int x, + const QString &pmKey) +{ + if (!rect.isValid()) + return; + + QPixmap cache; + QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget) + % HexString(y1) + % HexString(y2) + % HexString(x) + % pmKey; + + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_vline (style, + pixmap, + state, + NULL, + gtkWidget, + part, + y1, y2, + x)); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + m_painter->drawPixmap(rect.topLeft(), cache); +} + + +void QGtkPainter::paintExpander(GtkWidget *gtkWidget, + const gchar* part, const QRect &rect, + GtkStateType state, GtkExpanderStyle expander_state, + GtkStyle *style, const QString &pmKey) +{ + if (!rect.isValid()) + return; + + QPixmap cache; + QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget) + % HexString(expander_state) + % pmKey; + + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_expander (style, pixmap, + state, NULL, + gtkWidget, part, + rect.width()/2, + rect.height()/2, + expander_state)); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + + m_painter->drawPixmap(rect.topLeft(), cache); +} + +void QGtkPainter::paintFocus(GtkWidget *gtkWidget, const gchar* part, + const QRect &rect, GtkStateType state, + GtkStyle *style, const QString &pmKey) +{ + if (!rect.isValid()) + return; + + QPixmap cache; + QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget) % pmKey; + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_focus (style, pixmap, state, NULL, + gtkWidget, + part, + 0, 0, + rect.width(), + rect.height())); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + + m_painter->drawPixmap(rect.topLeft(), cache); +} + + +void QGtkPainter::paintResizeGrip(GtkWidget *gtkWidget, const gchar* part, + const QRect &rect, GtkStateType state, + GtkShadowType shadow, GdkWindowEdge edge, + GtkStyle *style, const QString &pmKey) +{ + if (!rect.isValid()) + return; + + QPixmap cache; + QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget) % pmKey; + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_resize_grip (style, pixmap, state, + NULL, gtkWidget, + part, edge, 0, 0, + rect.width(), + rect.height())); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + + m_painter->drawPixmap(rect.topLeft(), cache); +} + + +void QGtkPainter::paintArrow(GtkWidget *gtkWidget, const gchar* part, + const QRect &arrowrect, GtkArrowType arrow_type, + GtkStateType state, GtkShadowType shadow, + gboolean fill, GtkStyle *style, const QString &pmKey) +{ + QRect rect = m_cliprect.isValid() ? m_cliprect : arrowrect; + if (!rect.isValid()) + return; + + QPixmap cache; + QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) + % HexString(arrow_type) + % pmKey; + + GdkRectangle gtkCliprect = {0, 0, rect.width(), rect.height()}; + int xOffset = m_cliprect.isValid() ? arrowrect.x() - m_cliprect.x() : 0; + int yOffset = m_cliprect.isValid() ? arrowrect.y() - m_cliprect.y() : 0; + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_arrow (style, pixmap, state, shadow, + >kCliprect, + gtkWidget, + part, + arrow_type, fill, + xOffset, yOffset, + arrowrect.width(), + arrowrect.height())) + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + + m_painter->drawPixmap(rect.topLeft(), cache); +} + + +void QGtkPainter::paintHandle(GtkWidget *gtkWidget, const gchar* part, const QRect &rect, + GtkStateType state, GtkShadowType shadow, + GtkOrientation orientation, GtkStyle *style) +{ + if (!rect.isValid()) + return; + + QPixmap cache; + QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) + % HexString(orientation); + + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_handle (style, + pixmap, + state, + shadow, + NULL, + gtkWidget, + part, 0, 0, + rect.width(), + rect.height(), + orientation)); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + m_painter->drawPixmap(rect.topLeft(), cache); +} + + +void QGtkPainter::paintSlider(GtkWidget *gtkWidget, const gchar* part, const QRect &rect, + GtkStateType state, GtkShadowType shadow, + GtkStyle *style, GtkOrientation orientation, + const QString &pmKey) +{ + if (!rect.isValid()) + return; + + QPixmap cache; + QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget) % pmKey; + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_slider (style, + pixmap, + state, + shadow, + NULL, + gtkWidget, + part, + 0, 0, + rect.width(), + rect.height(), + orientation)); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + m_painter->drawPixmap(rect.topLeft(), cache); +} + + +void QGtkPainter::paintShadow(GtkWidget *gtkWidget, const gchar* part, + const QRect &rect, GtkStateType state, + GtkShadowType shadow, GtkStyle *style, + const QString &pmKey) + +{ + if (!rect.isValid()) + return; + + QRect r = rect; + QPixmap cache; + QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) % pmKey; + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_shadow(style, pixmap, state, shadow, NULL, + gtkWidget, part, 0, 0, rect.width(), rect.height())); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + m_painter->drawPixmap(rect.topLeft(), cache); +} + +void QGtkPainter::paintFlatBox(GtkWidget *gtkWidget, const gchar* part, + const QRect &rect, GtkStateType state, + GtkShadowType shadow, GtkStyle *style, + const QString &pmKey) +{ + if (!rect.isValid()) + return; + QRect r = rect; + QPixmap cache; + QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) % pmKey; + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_flat_box (style, + pixmap, + state, + shadow, + NULL, + gtkWidget, + part, 0, 0, + rect.width(), + rect.height())); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + m_painter->drawPixmap(rect.topLeft(), cache); +} + +void QGtkPainter::paintExtention(GtkWidget *gtkWidget, + const gchar *part, const QRect &rect, + GtkStateType state, GtkShadowType shadow, + GtkPositionType gap_pos, GtkStyle *style) +{ + if (!rect.isValid()) + return; + + QRect r = rect; + QPixmap cache; + QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget) + % HexString(gap_pos); + + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_extension (style, pixmap, state, shadow, + NULL, gtkWidget, + (gchar*)part, 0, 0, + rect.width(), + rect.height(), + gap_pos)); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + + m_painter->drawPixmap(rect.topLeft(), cache); +} + +void QGtkPainter::paintOption(GtkWidget *gtkWidget, const QRect &radiorect, + GtkStateType state, GtkShadowType shadow, + GtkStyle *style, const QString &detail) + +{ + QRect rect = m_cliprect.isValid() ? m_cliprect : radiorect; + if (!rect.isValid()) + return; + + QRect r = rect; + QPixmap cache; + QString pixmapName = uniqueName(detail, state, shadow, rect.size()); + GdkRectangle gtkCliprect = {0, 0, rect.width(), rect.height()}; + int xOffset = m_cliprect.isValid() ? radiorect.x() - m_cliprect.x() : 0; + int yOffset = m_cliprect.isValid() ? radiorect.y() - m_cliprect.y() : 0; + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_option(style, pixmap, + state, shadow, + >kCliprect, + gtkWidget, + detail.toLatin1(), + xOffset, yOffset, + radiorect.width(), + radiorect.height())); + + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + + m_painter->drawPixmap(rect.topLeft(), cache); +} + +void QGtkPainter::paintCheckbox(GtkWidget *gtkWidget, const QRect &checkrect, + GtkStateType state, GtkShadowType shadow, + GtkStyle *style, const QString &detail) + +{ + QRect rect = m_cliprect.isValid() ? m_cliprect : checkrect; + if (!rect.isValid()) + return; + + QRect r = rect; + QPixmap cache; + QString pixmapName = uniqueName(detail, state, shadow, rect.size()); + GdkRectangle gtkCliprect = {0, 0, rect.width(), rect.height()}; + int xOffset = m_cliprect.isValid() ? checkrect.x() - m_cliprect.x() : 0; + int yOffset = m_cliprect.isValid() ? checkrect.y() - m_cliprect.y() : 0; + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_check (style, + pixmap, + state, + shadow, + >kCliprect, + gtkWidget, + detail.toLatin1(), + xOffset, yOffset, + checkrect.width(), + checkrect.height())); + if (m_usePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + + m_painter->drawPixmap(rect.topLeft(), cache); +} + +QT_END_NAMESPACE + +#endif //!defined(QT_NO_STYLE_GTK) diff --git a/src/widgets/styles/qgtkpainter_p.h b/src/widgets/styles/qgtkpainter_p.h new file mode 100644 index 0000000000..1c253798a8 --- /dev/null +++ b/src/widgets/styles/qgtkpainter_p.h @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGTKPAINTER_H +#define QGTKPAINTER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#if !defined(QT_NO_STYLE_GTK) + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGtkPainter +{ + +public: + QGtkPainter(QPainter *painter); + GtkStyle *getStyle(GtkWidget *gtkWidget); + GtkStateType gtkState(const QStyleOption *option); + + void setAlphaSupport(bool value) { m_alpha = value; } + void setClipRect(const QRect &rect) { m_cliprect = rect; } + void setFlipHorizontal(bool value) { m_hflipped = value; } + void setFlipVertical(bool value) { m_vflipped = value; } + void setUsePixmapCache(bool value) { m_usePixmapCache = value; } + + void paintBoxGap(GtkWidget *gtkWidget, const gchar* part, const QRect &rect, + GtkStateType state, GtkShadowType shadow, GtkPositionType gap_side, gint x, + gint width, GtkStyle *style); + void paintBox(GtkWidget *gtkWidget, const gchar* part, + const QRect &rect, GtkStateType state, GtkShadowType shadow, GtkStyle *style, + const QString &pmKey = QString()); + void paintHline(GtkWidget *gtkWidget, const gchar* part, const QRect &rect, GtkStateType state, GtkStyle *style, + int x1, int x2, int y, const QString &pmKey = QString()); + void paintVline(GtkWidget *gtkWidget, const gchar* part, const QRect &rect, GtkStateType state, GtkStyle *style, + int y1, int y2, int x, const QString &pmKey = QString()); + void paintExpander(GtkWidget *gtkWidget, const gchar* part, const QRect &rect, GtkStateType state, + GtkExpanderStyle expander_state, GtkStyle *style, const QString &pmKey = QString()); + void paintFocus(GtkWidget *gtkWidget, const gchar* part, const QRect &rect, GtkStateType state, GtkStyle *style, + const QString &pmKey = QString()); + void paintResizeGrip(GtkWidget *gtkWidget, const gchar* part, const QRect &rect, GtkStateType state, GtkShadowType shadow, + GdkWindowEdge edge, GtkStyle *style, const QString &pmKey = QString()); + void paintArrow(GtkWidget *gtkWidget, const gchar* part, const QRect &arrowrect, GtkArrowType arrow_type, GtkStateType state, GtkShadowType shadow, + gboolean fill, GtkStyle *style, const QString &pmKey = QString()); + void paintHandle(GtkWidget *gtkWidget, const gchar* part, const QRect &rect, + GtkStateType state, GtkShadowType shadow, GtkOrientation orientation, GtkStyle *style); + void paintSlider(GtkWidget *gtkWidget, const gchar* part, const QRect &rect, GtkStateType state, GtkShadowType shadow, + GtkStyle *style, GtkOrientation orientation, const QString &pmKey = QString()); + void paintShadow(GtkWidget *gtkWidget, const gchar* part, const QRect &rect, GtkStateType state, GtkShadowType shadow, + GtkStyle *style, const QString &pmKey = QString()); + void paintFlatBox(GtkWidget *gtkWidget, const gchar* part, const QRect &rect, GtkStateType state, GtkShadowType shadow, GtkStyle *style, const QString & = QString()); + void paintExtention(GtkWidget *gtkWidget, const gchar *part, const QRect &rect, GtkStateType state, GtkShadowType shadow, + GtkPositionType gap_pos, GtkStyle *style); + void paintOption(GtkWidget *gtkWidget, const QRect &rect, GtkStateType state, GtkShadowType shadow, GtkStyle *style, const QString &detail); + void paintCheckbox(GtkWidget *gtkWidget, const QRect &rect, GtkStateType state, GtkShadowType shadow, GtkStyle *style, const QString &detail); + + static QPixmap getIcon(const char* iconName, GtkIconSize size = GTK_ICON_SIZE_BUTTON); +private: + QPixmap renderTheme(uchar *bdata, uchar *wdata, const QRect&); + + GtkWidget *m_window; + QPainter *m_painter; + bool m_alpha; + bool m_hflipped; + bool m_vflipped; + bool m_usePixmapCache; + QRect m_cliprect; + +}; + +QT_END_NAMESPACE + +#endif //!defined(QT_NO_STYLE_QGTK) + +#endif // QGTKPAINTER_H diff --git a/src/widgets/styles/qgtkstyle.cpp b/src/widgets/styles/qgtkstyle.cpp new file mode 100644 index 0000000000..277e3025b5 --- /dev/null +++ b/src/widgets/styles/qgtkstyle.cpp @@ -0,0 +1,3563 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgtkstyle.h" + +#if !defined(QT_NO_STYLE_GTK) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef signals // Collides with GTK stymbols +#include +#include +#include +#include + + +QT_BEGIN_NAMESPACE + +static const char * const dock_widget_close_xpm[] = + { + "11 13 5 1", + " c None", + ". c #D5CFCB", + "+ c #6C6A67", + "@ c #6C6A67", + "$ c #B5B0AC", + " ", + " @@@@@@@@@ ", + "@+ +@", + "@ +@ @+ @", + "@ @@@ @@@ @", + "@ @@@@@ @", + "@ @@@ @", + "@ @@@@@ @", + "@ @@@ @@@ @", + "@ +@ @+ @", + "@+ +@", + " @@@@@@@@@ ", + " " + }; + +static const char * const dock_widget_restore_xpm[] = + { + "11 13 5 1", + " c None", + ". c #D5CFCB", + "+ c #6C6A67", + "@ c #6C6A67", + "# c #6C6A67", + " ", + " @@@@@@@@@ ", + "@+ +@", + "@ #@@@# @", + "@ @ @ @", + "@ #@@@# @ @", + "@ @ @ @ @", + "@ @ @@@ @", + "@ @ @ @", + "@ #@@@@ @", + "@+ +@", + " @@@@@@@@@ ", + " " + }; + +static const int groupBoxBottomMargin = 2; // space below the groupbox +static const int groupBoxTitleMargin = 6; // space between contents and title +static const int groupBoxTopMargin = 2; + +/*! + Returns the configuration string for \a value. + Returns \a fallback if \a value is not found. + */ +QString QGtkStyle::getGConfString(const QString &value, const QString &fallback) +{ + return QGtkStylePrivate::getGConfString(value, fallback); +} + +/*! + Returns the configuration boolean for \a key. + Returns \a fallback if \a key is not found. + */ +bool QGtkStyle::getGConfBool(const QString &key, bool fallback) +{ + return QGtkStylePrivate::getGConfBool(key, fallback); +} + +static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50) +{ + const int maxFactor = 100; + QColor tmp = colorA; + tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor); + tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor); + tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor); + return tmp; +} + +static GdkColor fromQColor(const QColor &color) +{ + GdkColor retval; + retval.red = color.red() * 255; + retval.green = color.green() * 255; + retval.blue = color.blue() * 255; + return retval; +} + +/*! + \class QGtkStyle + \brief The QGtkStyle class provides a widget style rendered by GTK+ + \since 4.5 + + The QGtkStyle style provides a look and feel that integrates well + into GTK-based desktop environments such as the XFCe and GNOME. + + It does this by making use of the GTK+ theme engine, ensuring + that Qt applications look and feel native on these platforms. + + Note: The style requires GTK+ version 2.10 or later. + The Qt3-based "Qt" GTK+ theme engine will not work with QGtkStyle. + + \sa {Cleanlooks Style Widget Gallery}, QWindowsXPStyle, QMacStyle, QWindowsStyle, + QCDEStyle, QMotifStyle, QPlastiqueStyle, QCleanlooksStyle +*/ + +/*! + Constructs a QGtkStyle object. +*/ +QGtkStyle::QGtkStyle() + : QCleanlooksStyle(*new QGtkStylePrivate) +{ + Q_D(QGtkStyle); + d->init(); +} + +/*! + \internal + + Constructs a QGtkStyle object. +*/ +QGtkStyle::QGtkStyle(QGtkStylePrivate &dd) + : QCleanlooksStyle(dd) +{ + Q_D(QGtkStyle); + d->init(); +} + + +/*! + Destroys the QGtkStyle object. +*/ +QGtkStyle::~QGtkStyle() +{ +} + +/*! + \reimp +*/ +QPalette QGtkStyle::standardPalette() const +{ + Q_D(const QGtkStyle); + + QPalette palette = QCleanlooksStyle::standardPalette(); + if (d->isThemeAvailable()) { + GtkStyle *style = d->gtkStyle(); + GtkWidget *gtkButton = d->gtkWidget("GtkButton"); + GtkWidget *gtkEntry = d->getTextColorWidget(); + GdkColor gdkBg, gdkBase, gdkText, gdkForeground, gdkSbg, gdkSfg, gdkaSbg, gdkaSfg; + QColor bg, base, text, fg, highlight, highlightText, inactiveHighlight, inactiveHighlightedTExt; + gdkBg = style->bg[GTK_STATE_NORMAL]; + gdkForeground = gtkButton->style->fg[GTK_STATE_NORMAL]; + + // Our base and selected color is primarily used for text + // so we assume a gtkEntry will have the most correct value + gdkBase = gtkEntry->style->base[GTK_STATE_NORMAL]; + gdkText = gtkEntry->style->text[GTK_STATE_NORMAL]; + gdkSbg = gtkEntry->style->base[GTK_STATE_SELECTED]; + gdkSfg = gtkEntry->style->text[GTK_STATE_SELECTED]; + + // The ACTIVE base color is really used for inactive windows + gdkaSbg = gtkEntry->style->base[GTK_STATE_ACTIVE]; + gdkaSfg = gtkEntry->style->text[GTK_STATE_ACTIVE]; + + bg = QColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); + text = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + fg = QColor(gdkForeground.red>>8, gdkForeground.green>>8, gdkForeground.blue>>8); + base = QColor(gdkBase.red>>8, gdkBase.green>>8, gdkBase.blue>>8); + highlight = QColor(gdkSbg.red>>8, gdkSbg.green>>8, gdkSbg.blue>>8); + highlightText = QColor(gdkSfg.red>>8, gdkSfg.green>>8, gdkSfg.blue>>8); + inactiveHighlight = QColor(gdkaSbg.red>>8, gdkaSbg.green>>8, gdkaSbg.blue>>8); + inactiveHighlightedTExt = QColor(gdkaSfg.red>>8, gdkaSfg.green>>8, gdkaSfg.blue>>8); + + palette.setColor(QPalette::HighlightedText, highlightText); + + + palette.setColor(QPalette::Light, bg.lighter(125)); + palette.setColor(QPalette::Shadow, bg.darker(130)); + palette.setColor(QPalette::Dark, bg.darker(120)); + palette.setColor(QPalette::Text, text); + palette.setColor(QPalette::WindowText, fg); + palette.setColor(QPalette::ButtonText, fg); + palette.setColor(QPalette::Base, base); + + QColor alternateRowColor = palette.base().color().lighter(93); // ref gtkstyle.c draw_flat_box + GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView"); + GdkColor *gtkAltBase = NULL; + d->gtk_widget_style_get(gtkTreeView, "odd-row-color", >kAltBase, NULL); + if (gtkAltBase) { + alternateRowColor = QColor(gtkAltBase->red>>8, gtkAltBase->green>>8, gtkAltBase->blue>>8); + d->gdk_color_free(gtkAltBase); + } + palette.setColor(QPalette::AlternateBase, alternateRowColor); + + palette.setColor(QPalette::Window, bg); + palette.setColor(QPalette::Button, bg); + palette.setColor(QPalette::Background, bg); + QColor disabled((fg.red() + bg.red()) / 2, + (fg.green() + bg.green())/ 2, + (fg.blue() + bg.blue()) / 2); + palette.setColor(QPalette::Disabled, QPalette::Text, disabled); + palette.setColor(QPalette::Disabled, QPalette::WindowText, disabled); + palette.setColor(QPalette::Disabled, QPalette::Foreground, disabled); + palette.setColor(QPalette::Disabled, QPalette::ButtonText, disabled); + palette.setColor(QPalette::Highlight, highlight); + // calculate disabled colors by removing saturation + highlight.setHsv(highlight.hue(), 0, highlight.value(), highlight.alpha()); + highlightText.setHsv(highlightText.hue(), 0, highlightText.value(), highlightText.alpha()); + palette.setColor(QPalette::Disabled, QPalette::Highlight, highlight); + palette.setColor(QPalette::Disabled, QPalette::HighlightedText, highlightText); + + palette.setColor(QPalette::Inactive, QPalette::HighlightedText, inactiveHighlightedTExt); + palette.setColor(QPalette::Inactive, QPalette::Highlight, inactiveHighlight); + + style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(), "gtk-tooltips", "GtkWindow", + d->gtk_window_get_type()); + if (style) { + gdkText = style->fg[GTK_STATE_NORMAL]; + text = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + palette.setColor(QPalette::ToolTipText, text); + } + } + return palette; +} + +/*! + \reimp +*/ +void QGtkStyle::polish(QPalette &palette) +{ + Q_D(QGtkStyle); + + // QCleanlooksStyle will alter the palette, hence we do + // not want to polish the palette unless we are using it as + // the fallback + if (!d->isThemeAvailable()) + QCleanlooksStyle::polish(palette); + else + palette = palette.resolve(standardPalette()); +} + +/*! + \reimp +*/ +void QGtkStyle::polish(QApplication *app) +{ + Q_D(QGtkStyle); + + QCleanlooksStyle::polish(app); + // Custom fonts and palettes with QtConfig are intentionally + // not supported as these should be entirely determined by + // current Gtk settings + if (app->desktopSettingsAware() && d->isThemeAvailable()) { + QApplicationPrivate::setSystemPalette(standardPalette()); + QApplicationPrivate::setSystemFont(d->getThemeFont()); + d->applyCustomPaletteHash(); + if (!d->isKDE4Session()) { + qt_filedialog_open_filename_hook = &QGtkStylePrivate::openFilename; + qt_filedialog_save_filename_hook = &QGtkStylePrivate::saveFilename; + qt_filedialog_open_filenames_hook = &QGtkStylePrivate::openFilenames; + qt_filedialog_existing_directory_hook = &QGtkStylePrivate::openDirectory; + qApp->installEventFilter(&d->filter); + } + } +} + +/*! + \reimp +*/ +void QGtkStyle::unpolish(QApplication *app) +{ + Q_D(QGtkStyle); + + QCleanlooksStyle::unpolish(app); + QPixmapCache::clear(); + + if (app->desktopSettingsAware() && d->isThemeAvailable() + && !d->isKDE4Session()) { + qt_filedialog_open_filename_hook = 0; + qt_filedialog_save_filename_hook = 0; + qt_filedialog_open_filenames_hook = 0; + qt_filedialog_existing_directory_hook = 0; + qApp->removeEventFilter(&d->filter); + } +} + +/*! + \reimp +*/ + +void QGtkStyle::polish(QWidget *widget) +{ + Q_D(QGtkStyle); + + QCleanlooksStyle::polish(widget); + if (!d->isThemeAvailable()) + return; + if (qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget)) + widget->setAttribute(Qt::WA_Hover); + else if (QTreeView *tree = qobject_cast (widget)) + tree->viewport()->setAttribute(Qt::WA_Hover); +} + +/*! + \reimp +*/ +void QGtkStyle::unpolish(QWidget *widget) +{ + QCleanlooksStyle::unpolish(widget); +} + +/*! + \reimp +*/ +int QGtkStyle::pixelMetric(PixelMetric metric, + const QStyleOption *option, + const QWidget *widget) const +{ + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) + return QCleanlooksStyle::pixelMetric(metric, option, widget); + + switch (metric) { + case PM_DefaultFrameWidth: + if (qobject_cast(widget)) { + if (GtkStyle *style = + d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(), + "*.GtkScrolledWindow", + "*.GtkScrolledWindow", + d->gtk_window_get_type())) + return qMax(style->xthickness, style->ythickness); + } + return 2; + + case PM_MenuButtonIndicator: + return 20; + + case PM_TabBarBaseOverlap: + return 1; + + case PM_ToolBarSeparatorExtent: + return 11; + + case PM_ToolBarFrameWidth: + return 1; + + case PM_ToolBarItemSpacing: + return 0; + + case PM_ButtonShiftHorizontal: { + GtkWidget *gtkButton = d->gtkWidget("GtkButton"); + guint horizontal_shift; + d->gtk_widget_style_get(gtkButton, "child-displacement-x", &horizontal_shift, NULL); + return horizontal_shift; + } + + case PM_ButtonShiftVertical: { + GtkWidget *gtkButton = d->gtkWidget("GtkButton"); + guint vertical_shift; + d->gtk_widget_style_get(gtkButton, "child-displacement-y", &vertical_shift, NULL); + return vertical_shift; + } + + case PM_MenuBarPanelWidth: + return 0; + + case PM_MenuPanelWidth: { + GtkWidget *gtkMenu = d->gtkWidget("GtkMenu"); + guint horizontal_padding = 0; + // horizontal-padding is used by Maemo to get thicker borders + if (!d->gtk_check_version(2, 10, 0)) + d->gtk_widget_style_get(gtkMenu, "horizontal-padding", &horizontal_padding, NULL); + int padding = qMax(gtkMenu->style->xthickness, horizontal_padding); + return padding; + } + + case PM_ButtonIconSize: { + int retVal = 24; + GtkSettings *settings = d->gtk_settings_get_default(); + gchararray icon_sizes; + g_object_get(settings, "gtk-icon-sizes", &icon_sizes, NULL); + QStringList values = QString(QLS(icon_sizes)).split(QLatin1Char(':')); + g_free(icon_sizes); + QChar splitChar(QLatin1Char(',')); + foreach (const QString &value, values) { + if (value.startsWith(QLS("gtk-button="))) { + QString iconSize = value.right(value.size() - 11); + + if (iconSize.contains(splitChar)) + retVal = iconSize.split(splitChar)[0].toInt(); + break; + } + } + return retVal; + } + + case PM_MenuVMargin: + + case PM_MenuHMargin: + return 0; + + case PM_DockWidgetTitleMargin: + return 0; + + case PM_DockWidgetTitleBarButtonMargin: + return 5; + + case PM_TabBarTabVSpace: + return 12; + + case PM_TabBarTabHSpace: + return 14; + + case PM_TabBarTabShiftVertical: + return 2; + + case PM_ToolBarHandleExtent: + return 9; + + case PM_SplitterWidth: + return 6; + + case PM_SliderThickness: + case PM_SliderControlThickness: { + GtkWidget *gtkScale = d->gtkWidget("GtkHScale"); + gint val; + d->gtk_widget_style_get(gtkScale, "slider-width", &val, NULL); + if (metric == PM_SliderControlThickness) + return val + 2*gtkScale->style->ythickness; + return val; + } + + case PM_ScrollBarExtent: { + gint sliderLength; + gint trough_border; + GtkWidget *hScrollbar = d->gtkWidget("GtkHScrollbar"); + d->gtk_widget_style_get(hScrollbar, + "trough-border", &trough_border, + "slider-width", &sliderLength, + NULL); + return sliderLength + trough_border*2; + } + + case PM_ScrollBarSliderMin: + return 34; + + case PM_SliderLength: + gint val; + d->gtk_widget_style_get(d->gtkWidget("GtkHScale"), "slider-length", &val, NULL); + return val; + + case PM_ExclusiveIndicatorWidth: + case PM_ExclusiveIndicatorHeight: + case PM_IndicatorWidth: + case PM_IndicatorHeight: { + GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton"); + gint size, spacing; + d->gtk_widget_style_get(gtkCheckButton, "indicator-spacing", &spacing, "indicator-size", &size, NULL); + return size + 2 * spacing; + } + + case PM_MenuBarVMargin: { + GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar"); + return qMax(0, gtkMenubar->style->ythickness); + } + case PM_ScrollView_ScrollBarSpacing: + { + gint spacing = 3; + GtkWidget *gtkScrollWindow = d->gtkWidget("GtkScrolledWindow"); + Q_ASSERT(gtkScrollWindow); + d->gtk_widget_style_get(gtkScrollWindow, "scrollbar-spacing", &spacing, NULL); + return spacing; + } + case PM_SubMenuOverlap: { + gint offset = 0; + GtkWidget *gtkMenu = d->gtkWidget("GtkMenu"); + d->gtk_widget_style_get(gtkMenu, "horizontal-offset", &offset, NULL); + return offset; + } + default: + return QCleanlooksStyle::pixelMetric(metric, option, widget); + } +} + +/*! + \reimp +*/ +int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, + + QStyleHintReturn *returnData = 0) const +{ + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) + return QCleanlooksStyle::styleHint(hint, option, widget, returnData); + + switch (hint) { + + case SH_DialogButtonLayout: { + int ret = QDialogButtonBox::GnomeLayout; + gboolean alternateOrder = 0; + GtkSettings *settings = d->gtk_settings_get_default(); + g_object_get(settings, "gtk-alternative-button-order", &alternateOrder, NULL); + + if (alternateOrder) + ret = QDialogButtonBox::WinLayout; + + return ret; + } + + break; + + case SH_ToolButtonStyle: + { + if (d->isKDE4Session()) + return QCleanlooksStyle::styleHint(hint, option, widget, returnData); + GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar"); + GtkToolbarStyle toolbar_style = GTK_TOOLBAR_ICONS; + g_object_get(gtkToolbar, "toolbar-style", &toolbar_style, NULL); + switch (toolbar_style) { + case GTK_TOOLBAR_TEXT: + return Qt::ToolButtonTextOnly; + case GTK_TOOLBAR_BOTH: + return Qt::ToolButtonTextUnderIcon; + case GTK_TOOLBAR_BOTH_HORIZ: + return Qt::ToolButtonTextBesideIcon; + case GTK_TOOLBAR_ICONS: + default: + return Qt::ToolButtonIconOnly; + } + } + break; + case SH_SpinControls_DisableOnBounds: + return int(true); + + case SH_DitherDisabledText: + return int(false); + + case SH_ComboBox_Popup: { + GtkWidget *gtkComboBox = d->gtkWidget("GtkComboBox"); + gboolean appears_as_list; + d->gtk_widget_style_get((GtkWidget*)gtkComboBox, "appears-as-list", &appears_as_list, NULL); + return appears_as_list ? 0 : 1; + } + + case SH_MenuBar_AltKeyNavigation: + return int(false); + + case SH_EtchDisabledText: + return int(false); + + case SH_Menu_SubMenuPopupDelay: { + gint delay = 225; + GtkSettings *settings = d->gtk_settings_get_default(); + g_object_get(settings, "gtk-menu-popup-delay", &delay, NULL); + return delay; + } + + case SH_ScrollView_FrameOnlyAroundContents: { + gboolean scrollbars_within_bevel = false; + if (widget && widget->isWindow()) + scrollbars_within_bevel = true; + else if (!d->gtk_check_version(2, 12, 0)) { + GtkWidget *gtkScrollWindow = d->gtkWidget("GtkScrolledWindow"); + d->gtk_widget_style_get(gtkScrollWindow, "scrollbars-within-bevel", &scrollbars_within_bevel, NULL); + } + return !scrollbars_within_bevel; + } + + case SH_DialogButtonBox_ButtonsHaveIcons: { + static bool buttonsHaveIcons = d->getGConfBool(QLS("/desktop/gnome/interface/buttons_have_icons")); + return buttonsHaveIcons; + } + + case SH_UnderlineShortcut: { + gboolean underlineShortcut = true; + if (!d->gtk_check_version(2, 12, 0)) { + GtkSettings *settings = d->gtk_settings_get_default(); + g_object_get(settings, "gtk-enable-mnemonics", &underlineShortcut, NULL); + } + return underlineShortcut; + } + + default: + return QCleanlooksStyle::styleHint(hint, option, widget, returnData); + } +} + +/*! + \reimp +*/ +void QGtkStyle::drawPrimitive(PrimitiveElement element, + const QStyleOption *option, + QPainter *painter, + const QWidget *widget) const +{ + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) { + QCleanlooksStyle::drawPrimitive(element, option, painter, widget); + return; + } + + GtkStyle* style = d->gtkStyle(); + QGtkPainter gtkPainter(painter); + + switch (element) { + case PE_Frame: { + if (widget && widget->inherits("QComboBoxPrivateContainer")){ + QStyleOption copy = *option; + copy.state |= State_Raised; + proxy()->drawPrimitive(PE_PanelMenu, ©, painter, widget); + break; + } + // Drawing the entire itemview frame is very expensive, especially on the native X11 engine + // Instead we cheat a bit and draw a border image without the center part, hence only scaling + // thin rectangular images + const int pmSize = 64; + const int border = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget); + const QString pmKey = QLatin1Literal("windowframe") % HexString(option->state); + + QPixmap pixmap; + QRect pmRect(QPoint(0,0), QSize(pmSize, pmSize)); + + // Only draw through style once + if (!QPixmapCache::find(pmKey, pixmap)) { + pixmap = QPixmap(pmSize, pmSize); + pixmap.fill(Qt::transparent); + QPainter pmPainter(&pixmap); + QGtkPainter gtkFramePainter(&pmPainter); + gtkFramePainter.setUsePixmapCache(false); // Don't cache twice + + GtkShadowType shadow_type = GTK_SHADOW_NONE; + if (option->state & State_Sunken) + shadow_type = GTK_SHADOW_IN; + else if (option->state & State_Raised) + shadow_type = GTK_SHADOW_OUT; + + GtkStyle *style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(), + "*.GtkScrolledWindow", "*.GtkScrolledWindow", d->gtk_window_get_type()); + if (style) + gtkFramePainter.paintShadow(d->gtkWidget("GtkFrame"), "viewport", pmRect, + option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, + shadow_type, style); + QPixmapCache::insert(pmKey, pixmap); + } + + QRect rect = option->rect; + const int rw = rect.width() - border; + const int rh = rect.height() - border; + const int pw = pmRect.width() - border; + const int ph = pmRect.height() - border; + + // Sidelines + painter->drawPixmap(rect.adjusted(border, 0, -border, -rh), pixmap, pmRect.adjusted(border, 0, -border,-ph)); + painter->drawPixmap(rect.adjusted(border, rh, -border, 0), pixmap, pmRect.adjusted(border, ph,-border,0)); + painter->drawPixmap(rect.adjusted(0, border, -rw, -border), pixmap, pmRect.adjusted(0, border, -pw, -border)); + painter->drawPixmap(rect.adjusted(rw, border, 0, -border), pixmap, pmRect.adjusted(pw, border, 0, -border)); + + // Corners + painter->drawPixmap(rect.adjusted(0, 0, -rw, -rh), pixmap, pmRect.adjusted(0, 0, -pw,-ph)); + painter->drawPixmap(rect.adjusted(rw, 0, 0, -rh), pixmap, pmRect.adjusted(pw, 0, 0,-ph)); + painter->drawPixmap(rect.adjusted(0, rh, -rw, 0), pixmap, pmRect.adjusted(0, ph, -pw,0)); + painter->drawPixmap(rect.adjusted(rw, rh, 0, 0), pixmap, pmRect.adjusted(pw, ph, 0,0)); + } + break; + + case PE_PanelTipLabel: { + GtkWidget *gtkWindow = d->gtkWidget("GtkWindow"); // The Murrine Engine currently assumes a widget is passed + style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(), "gtk-tooltips", "GtkWindow", + d->gtk_window_get_type()); + gtkPainter.paintFlatBox(gtkWindow, "tooltip", option->rect, GTK_STATE_NORMAL, GTK_SHADOW_NONE, style); + } + break; + + case PE_PanelStatusBar: { + if (widget && widget->testAttribute(Qt::WA_SetPalette) && + option->palette.resolve() & (1 << QPalette::Window)) { + // Respect custom palette + painter->fillRect(option->rect, option->palette.window()); + break; + } + GtkShadowType shadow_type; + GtkWidget *gtkStatusbarFrame = d->gtkWidget("GtkStatusbar.GtkFrame"); + d->gtk_widget_style_get(gtkStatusbarFrame->parent, "shadow-type", &shadow_type, NULL); + gtkPainter.paintShadow(gtkStatusbarFrame, "frame", option->rect, GTK_STATE_NORMAL, + shadow_type, gtkStatusbarFrame->style); + } + break; + + case PE_IndicatorHeaderArrow: + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + GtkWidget *gtkTreeHeader = d->gtkWidget("GtkTreeView.GtkButton"); + GtkStateType state = gtkPainter.gtkState(option); + style = gtkTreeHeader->style; + GtkArrowType type = GTK_ARROW_UP; + QRect r = header->rect; + QImage arrow; + // This sorting indicator inversion is intentional, and follows the GNOME HIG. + // See http://library.gnome.org/devel/hig-book/stable/controls-lists.html.en#controls-lists-sortable + if (header->sortIndicator & QStyleOptionHeader::SortUp) + type = GTK_ARROW_UP; + else if (header->sortIndicator & QStyleOptionHeader::SortDown) + type = GTK_ARROW_DOWN; + + gtkPainter.paintArrow(gtkTreeHeader, "button", option->rect.adjusted(1, 1, -1, -1), type, state, + GTK_SHADOW_NONE, FALSE, style); + } + break; + + case PE_FrameFocusRect: + if (!widget || qobject_cast(widget)) + QCleanlooksStyle::drawPrimitive(element, option, painter, widget); + else { + // ### this mess should move to subcontrolrect + QRect frameRect = option->rect.adjusted(1, 1, -1, -2); + + if (qobject_cast(widget)) { + GtkWidget *gtkNotebook = d->gtkWidget("GtkNotebook"); + style = gtkPainter.getStyle(gtkNotebook); + gtkPainter.paintFocus(gtkNotebook, "tab", frameRect.adjusted(-1, 1, 1, 1), GTK_STATE_ACTIVE, style); + } else { + gtkPainter.paintFocus(NULL, "tab", frameRect, GTK_STATE_ACTIVE, style); + } + } + break; + + case PE_IndicatorBranch: + if (option->state & State_Children) { + QRect rect = option->rect; + rect = QRect(0, 0, 12, 12); + rect.moveCenter(option->rect.center()); + rect.translate(2, 0); + GtkExpanderStyle openState = GTK_EXPANDER_EXPANDED; + GtkExpanderStyle closedState = GTK_EXPANDER_COLLAPSED; + GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView"); + + GtkStateType state = GTK_STATE_NORMAL; + if (!(option->state & State_Enabled)) + state = GTK_STATE_INSENSITIVE; + else if (option->state & State_MouseOver) + state = GTK_STATE_PRELIGHT; + + gtkPainter.paintExpander(gtkTreeView, "treeview", rect, state, + option->state & State_Open ? openState : closedState , gtkTreeView->style); + } + break; + + case PE_PanelItemViewRow: + // This primitive is only used to draw selection behind selected expander arrows. + // We try not to decorate the tree branch background unless you inherit from StyledItemDelegate + // The reason for this is that a lot of code that relies on custom item delegates will look odd having + // a gradient on the branch but a flat shaded color on the item itself. + QCommonStyle::drawPrimitive(element, option, painter, widget); + if (!option->state & State_Selected) { + break; + } else { + if (const QAbstractItemView *view = qobject_cast(widget)) { + if (!qobject_cast(view->itemDelegate())) + break; + } + } // fall through + + case PE_PanelItemViewItem: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(option)) { + uint resolve_mask = vopt->palette.resolve(); + if (vopt->backgroundBrush.style() != Qt::NoBrush + || (resolve_mask & (1 << QPalette::Base))) + { + QPointF oldBO = painter->brushOrigin(); + painter->setBrushOrigin(vopt->rect.topLeft()); + painter->fillRect(vopt->rect, vopt->backgroundBrush); + painter->setBrushOrigin(oldBO); + if (!(option->state & State_Selected)) + break; + } + if (GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView")) { + const char *detail = "cell_even_ruled"; + if (vopt && vopt->features & QStyleOptionViewItemV2::Alternate) + detail = "cell_odd_ruled"; + bool isActive = option->state & State_Active; + QString key; + if (isActive ) { + // Required for active/non-active window appearance + key = QLS("a"); + GTK_WIDGET_SET_FLAGS(gtkTreeView, GTK_HAS_FOCUS); + } + bool isEnabled = (widget ? widget->isEnabled() : (vopt->state & QStyle::State_Enabled)); + gtkPainter.paintFlatBox(gtkTreeView, detail, option->rect, + option->state & State_Selected ? GTK_STATE_SELECTED : + isEnabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, + GTK_SHADOW_OUT, gtkTreeView->style, key); + if (isActive ) + GTK_WIDGET_UNSET_FLAGS(gtkTreeView, GTK_HAS_FOCUS); + } + } + break; + case PE_IndicatorToolBarSeparator: + { + const int margin = 6; + GtkWidget *gtkSeparator = d->gtkWidget("GtkToolbar.GtkSeparatorToolItem"); + if (option->state & State_Horizontal) { + const int offset = option->rect.width()/2; + QRect rect = option->rect.adjusted(offset, margin, 0, -margin); + painter->setPen(QPen(option->palette.background().color().darker(110))); + gtkPainter.paintVline( gtkSeparator, "vseparator", + rect, GTK_STATE_NORMAL, gtkSeparator->style, + 0, rect.height(), 0); + } else { //Draw vertical separator + const int offset = option->rect.height()/2; + QRect rect = option->rect.adjusted(margin, offset, -margin, 0); + painter->setPen(QPen(option->palette.background().color().darker(110))); + gtkPainter.paintHline( gtkSeparator, "hseparator", + rect, GTK_STATE_NORMAL, gtkSeparator->style, + 0, rect.width(), 0); + } + } + break; + + case PE_IndicatorToolBarHandle: { + GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar"); + GtkShadowType shadow_type; + d->gtk_widget_style_get(gtkToolbar, "shadow-type", &shadow_type, NULL); + //Note when the toolbar is horizontal, the handle is vertical + painter->setClipRect(option->rect); + gtkPainter.paintHandle(gtkToolbar, "toolbar", option->rect.adjusted(-1, -1 ,0 ,1), + GTK_STATE_NORMAL, shadow_type, !(option->state & State_Horizontal) ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, gtkToolbar->style); + } + break; + + case PE_IndicatorArrowUp: + case PE_IndicatorArrowDown: + case PE_IndicatorArrowLeft: + case PE_IndicatorArrowRight: { + + + GtkArrowType type = GTK_ARROW_UP; + + switch (element) { + + case PE_IndicatorArrowDown: + type = GTK_ARROW_DOWN; + break; + + case PE_IndicatorArrowLeft: + type = GTK_ARROW_LEFT; + break; + + case PE_IndicatorArrowRight: + type = GTK_ARROW_RIGHT; + break; + + default: + break; + } + int size = qMin(option->rect.height(), option->rect.width()); + int border = (size > 9) ? (size/4) : 0; //Allow small arrows to have exact dimensions + int bsx = 0, bsy = 0; + if (option->state & State_Sunken) { + bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal); + bsy = proxy()->pixelMetric(PM_ButtonShiftVertical); + } + QRect arrowRect = option->rect.adjusted(border + bsx, border + bsy, -border + bsx, -border + bsy); + GtkShadowType shadow = option->state & State_Sunken ? GTK_SHADOW_IN : GTK_SHADOW_OUT; + GtkStateType state = gtkPainter.gtkState(option); + + QColor arrowColor = option->palette.buttonText().color(); + GtkWidget *gtkArrow = d->gtkWidget("GtkArrow"); + GdkColor color = fromQColor(arrowColor); + d->gtk_widget_modify_fg (gtkArrow, state, &color); + gtkPainter.paintArrow(gtkArrow, "button", arrowRect, + type, state, shadow, FALSE, gtkArrow->style, + QString::number(arrowColor.rgba(), 16)); + // Passing NULL will revert the color change + d->gtk_widget_modify_fg (gtkArrow, state, NULL); + } + break; + + case PE_FrameGroupBox: + // Do nothing here, the GNOME groupboxes are flat + break; + + case PE_PanelMenu: { + GtkWidget *gtkMenu = d->gtkWidget("GtkMenu"); + gtkPainter.setAlphaSupport(false); // Note, alpha disabled for performance reasons + gtkPainter.paintBox(gtkMenu, "menu", option->rect, GTK_STATE_NORMAL, GTK_SHADOW_OUT, gtkMenu->style, QString()); + } + break; + + case PE_FrameMenu: + //This is actually done by PE_Widget due to a clipping issue + //Otherwise Menu items will not be able to span the entire menu width + + // This is only used by floating tool bars + if (qobject_cast(widget)) { + GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar"); + gtkPainter.paintBox( gtkMenubar, "toolbar", option->rect, + GTK_STATE_NORMAL, GTK_SHADOW_OUT, style); + gtkPainter.paintBox( gtkMenubar, "menu", option->rect, + GTK_STATE_NORMAL, GTK_SHADOW_OUT, style); + } + break; + + case PE_FrameLineEdit: { + GtkWidget *gtkEntry = d->gtkWidget("GtkEntry"); + + + gboolean interior_focus; + gint focus_line_width; + QRect rect = option->rect; + d->gtk_widget_style_get(gtkEntry, + "interior-focus", &interior_focus, + "focus-line-width", &focus_line_width, NULL); + + // See https://bugzilla.mozilla.org/show_bug.cgi?id=405421 for info about this hack + g_object_set_data(G_OBJECT(gtkEntry), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); + + if (!interior_focus && option->state & State_HasFocus) + rect.adjust(focus_line_width, focus_line_width, -focus_line_width, -focus_line_width); + + if (option->state & State_HasFocus) + GTK_WIDGET_SET_FLAGS(gtkEntry, GTK_HAS_FOCUS); + gtkPainter.paintShadow(gtkEntry, "entry", rect, option->state & State_Enabled ? + GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, + GTK_SHADOW_IN, gtkEntry->style, + option->state & State_HasFocus ? QLS("focus") : QString()); + if (!interior_focus && option->state & State_HasFocus) + gtkPainter.paintShadow(gtkEntry, "entry", option->rect, option->state & State_Enabled ? + GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE, + GTK_SHADOW_IN, gtkEntry->style, QLS("GtkEntryShadowIn")); + + if (option->state & State_HasFocus) + GTK_WIDGET_UNSET_FLAGS(gtkEntry, GTK_HAS_FOCUS); + } + break; + + case PE_PanelLineEdit: + if (const QStyleOptionFrame *panel = qstyleoption_cast(option)) { + GtkWidget *gtkEntry = d->gtkWidget("GtkEntry"); + if (panel->lineWidth > 0) + proxy()->drawPrimitive(PE_FrameLineEdit, option, painter, widget); + uint resolve_mask = option->palette.resolve(); + QRect textRect = option->rect.adjusted(gtkEntry->style->xthickness, gtkEntry->style->ythickness, + -gtkEntry->style->xthickness, -gtkEntry->style->ythickness); + + if (widget && widget->testAttribute(Qt::WA_SetPalette) && + resolve_mask & (1 << QPalette::Base)) // Palette overridden by user + painter->fillRect(textRect, option->palette.base()); + else + gtkPainter.paintFlatBox( gtkEntry, "entry_bg", textRect, + option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, GTK_SHADOW_NONE, gtkEntry->style); + } + break; + + case PE_FrameTabWidget: + if (const QStyleOptionTabWidgetFrame *frame = qstyleoption_cast(option)) { + GtkWidget *gtkNotebook = d->gtkWidget("GtkNotebook"); + style = gtkPainter.getStyle(gtkNotebook); + gtkPainter.setAlphaSupport(false); + GtkShadowType shadow = GTK_SHADOW_OUT; + GtkStateType state = GTK_STATE_NORMAL; // Only state supported by gtknotebook + bool reverse = (option->direction == Qt::RightToLeft); + QGtkStylePrivate::gtk_widget_set_direction(gtkNotebook, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + if (const QStyleOptionTabWidgetFrameV2 *tabframe = qstyleoption_cast(option)) { + GtkPositionType frameType = GTK_POS_TOP; + QTabBar::Shape shape = frame->shape; + int gapStart = 0; + int gapSize = 0; + if (shape == QTabBar::RoundedNorth || shape == QTabBar::RoundedSouth) { + frameType = (shape == QTabBar::RoundedNorth) ? GTK_POS_TOP : GTK_POS_BOTTOM; + gapStart = tabframe->selectedTabRect.left(); + gapSize = tabframe->selectedTabRect.width(); + } else { + frameType = (shape == QTabBar::RoundedWest) ? GTK_POS_LEFT : GTK_POS_RIGHT; + gapStart = tabframe->selectedTabRect.y(); + gapSize = tabframe->selectedTabRect.height(); + } + gtkPainter.paintBoxGap(gtkNotebook, "notebook", option->rect, state, shadow, frameType, + gapStart, gapSize, style); + break; // done + } + + // Note this is only the fallback option + gtkPainter.paintBox(gtkNotebook, "notebook", option->rect, state, shadow, style); + } + break; + + case PE_PanelButtonCommand: + case PE_PanelButtonTool: { + bool isDefault = false; + bool isTool = (element == PE_PanelButtonTool); + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) + isDefault = btn->features & QStyleOptionButton::DefaultButton; + + // don't draw a frame for tool buttons that have the autoRaise flag and are not enabled or on + if (isTool && !(option->state & State_Enabled || option->state & State_On) && (option->state & State_AutoRaise)) + break; + // don't draw a frame for dock widget buttons, unless we are hovering + if (widget && widget->inherits("QDockWidgetTitleButton") && !(option->state & State_MouseOver)) + break; + + GtkStateType state = gtkPainter.gtkState(option); + if (option->state & State_On || option->state & State_Sunken) + state = GTK_STATE_ACTIVE; + GtkWidget *gtkButton = isTool ? d->gtkWidget("GtkToolButton.GtkButton") : d->gtkWidget("GtkButton"); + gint focusWidth, focusPad; + gboolean interiorFocus = false; + d->gtk_widget_style_get (gtkButton, + "focus-line-width", &focusWidth, + "focus-padding", &focusPad, + "interior-focus", &interiorFocus, NULL); + + style = gtkButton->style; + + QRect buttonRect = option->rect; + + QString key; + if (isDefault) { + key += QLS("def"); + GTK_WIDGET_SET_FLAGS(gtkButton, GTK_HAS_DEFAULT); + gtkPainter.paintBox(gtkButton, "buttondefault", buttonRect, state, GTK_SHADOW_IN, + style, isDefault ? QLS("d") : QString()); + } + + bool hasFocus = option->state & State_HasFocus; + + if (hasFocus) { + key += QLS("def"); + GTK_WIDGET_SET_FLAGS(gtkButton, GTK_HAS_FOCUS); + } + + if (!interiorFocus) + buttonRect = buttonRect.adjusted(focusWidth, focusWidth, -focusWidth, -focusWidth); + + GtkShadowType shadow = (option->state & State_Sunken || option->state & State_On ) ? + GTK_SHADOW_IN : GTK_SHADOW_OUT; + + gtkPainter.paintBox(gtkButton, "button", buttonRect, state, shadow, + style, key); + if (isDefault) + GTK_WIDGET_UNSET_FLAGS(gtkButton, GTK_HAS_DEFAULT); + if (hasFocus) + GTK_WIDGET_UNSET_FLAGS(gtkButton, GTK_HAS_FOCUS); + } + break; + + case PE_IndicatorRadioButton: { + GtkShadowType shadow = GTK_SHADOW_OUT; + GtkStateType state = gtkPainter.gtkState(option); + + if (option->state & State_Sunken) + state = GTK_STATE_ACTIVE; + + if (option->state & State_NoChange) + shadow = GTK_SHADOW_ETCHED_IN; + else if (option->state & State_On) + shadow = GTK_SHADOW_IN; + else + shadow = GTK_SHADOW_OUT; + + GtkWidget *gtkRadioButton = d->gtkWidget("GtkRadioButton"); + gint spacing; + d->gtk_widget_style_get(gtkRadioButton, "indicator-spacing", &spacing, NULL); + QRect buttonRect = option->rect.adjusted(spacing, spacing, -spacing, -spacing); + gtkPainter.setClipRect(option->rect); + // ### Note: Ubuntulooks breaks when the proper widget is passed + // Murrine engine requires a widget not to get RGBA check - warnings + GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton"); + QString key(QLS("radiobutton")); + if (option->state & State_HasFocus) { // Themes such as Nodoka check this flag + key += QLatin1Char('f'); + GTK_WIDGET_SET_FLAGS(gtkCheckButton, GTK_HAS_FOCUS); + } + gtkPainter.paintOption(gtkCheckButton , buttonRect, state, shadow, gtkRadioButton->style, key); + if (option->state & State_HasFocus) + GTK_WIDGET_UNSET_FLAGS(gtkCheckButton, GTK_HAS_FOCUS); + } + break; + + case PE_IndicatorCheckBox: { + GtkShadowType shadow = GTK_SHADOW_OUT; + GtkStateType state = gtkPainter.gtkState(option); + + if (option->state & State_Sunken) + state = GTK_STATE_ACTIVE; + + if (option->state & State_NoChange) + shadow = GTK_SHADOW_ETCHED_IN; + else if (option->state & State_On) + shadow = GTK_SHADOW_IN; + else + shadow = GTK_SHADOW_OUT; + + int spacing; + + GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton"); + QString key(QLS("checkbutton")); + if (option->state & State_HasFocus) { // Themes such as Nodoka checks this flag + key += QLatin1Char('f'); + GTK_WIDGET_SET_FLAGS(gtkCheckButton, GTK_HAS_FOCUS); + } + + // Some styles such as aero-clone assume they can paint in the spacing area + gtkPainter.setClipRect(option->rect); + + d->gtk_widget_style_get(gtkCheckButton, "indicator-spacing", &spacing, NULL); + + QRect checkRect = option->rect.adjusted(spacing, spacing, -spacing, -spacing); + + gtkPainter.paintCheckbox(gtkCheckButton, checkRect, state, shadow, gtkCheckButton->style, + key); + if (option->state & State_HasFocus) + GTK_WIDGET_UNSET_FLAGS(gtkCheckButton, GTK_HAS_FOCUS); + + } + break; + +#ifndef QT_NO_TABBAR + + case PE_FrameTabBarBase: + if (const QStyleOptionTabBarBase *tbb + = qstyleoption_cast(option)) { + QRect tabRect = tbb->rect; + painter->save(); + painter->setPen(QPen(option->palette.dark().color().dark(110), 0)); + switch (tbb->shape) { + + case QTabBar::RoundedNorth: + painter->drawLine(tabRect.topLeft(), tabRect.topRight()); + break; + + case QTabBar::RoundedWest: + painter->drawLine(tabRect.left(), tabRect.top(), tabRect.left(), tabRect.bottom()); + break; + + case QTabBar::RoundedSouth: + painter->drawLine(tbb->rect.left(), tbb->rect.bottom(), + tabRect.right(), tabRect.bottom()); + break; + + case QTabBar::RoundedEast: + painter->drawLine(tabRect.topRight(), tabRect.bottomRight()); + break; + + case QTabBar::TriangularNorth: + case QTabBar::TriangularEast: + case QTabBar::TriangularWest: + case QTabBar::TriangularSouth: + painter->restore(); + QWindowsStyle::drawPrimitive(element, option, painter, widget); + return; + } + + painter->restore(); + } + return; + +#endif // QT_NO_TABBAR + + case PE_Widget: + break; + + default: + QCleanlooksStyle::drawPrimitive(element, option, painter, widget); + } +} + +/*! + \reimp +*/ +void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + + QPainter *painter, const QWidget *widget) const +{ + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) { + QCleanlooksStyle::drawComplexControl(control, option, painter, widget); + return; + } + + GtkStyle* style = d->gtkStyle(); + QGtkPainter gtkPainter(painter); + QColor button = option->palette.button().color(); + QColor dark; + QColor grooveColor; + QColor darkOutline; + dark.setHsv(button.hue(), + qMin(255, (int)(button.saturation()*1.9)), + qMin(255, (int)(button.value()*0.7))); + grooveColor.setHsv(button.hue(), + qMin(255, (int)(button.saturation()*2.6)), + qMin(255, (int)(button.value()*0.9))); + darkOutline.setHsv(button.hue(), + qMin(255, (int)(button.saturation()*3.0)), + qMin(255, (int)(button.value()*0.6))); + + QColor alphaCornerColor; + + if (widget) + alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), darkOutline); + else + alphaCornerColor = mergedColors(option->palette.background().color(), darkOutline); + + switch (control) { + + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(option)) { + // Since this is drawn by metacity and not Gtk we + // have to rely on Cleanlooks for a fallback + QStyleOptionTitleBar copyOpt = *tb; + QPalette pal = copyOpt.palette; + // Bg color is closer to the window selection than + // the base selection color + GdkColor gdkBg = style->bg[GTK_STATE_SELECTED]; + QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); + pal.setBrush(QPalette::Active, QPalette::Highlight, bgColor); + copyOpt.palette = pal; + QCleanlooksStyle::drawComplexControl(control, ©Opt, painter, widget); + } + break; + +#ifndef QT_NO_GROUPBOX + + case CC_GroupBox: + painter->save(); + + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(option)) { + QRect textRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget); + QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxCheckBox, widget); + // Draw title + + if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) { + // Draw prelight background + GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton"); + + if (option->state & State_MouseOver) { + QRect bgRect = textRect | checkBoxRect; + gtkPainter.paintFlatBox(gtkCheckButton, "checkbutton", bgRect.adjusted(0, 0, 0, -2), + GTK_STATE_PRELIGHT, GTK_SHADOW_ETCHED_OUT, gtkCheckButton->style); + } + + if (!groupBox->text.isEmpty()) { + int alignment = int(groupBox->textAlignment); + if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, option, widget)) + alignment |= Qt::TextHideMnemonic; + QColor textColor = groupBox->textColor; // Note: custom textColor is currently ignored + int labelState = GTK_STATE_INSENSITIVE; + + if (option->state & State_Enabled) + labelState = (option->state & State_MouseOver) ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL; + + GdkColor gdkText = gtkCheckButton->style->fg[labelState]; + textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + painter->setPen(textColor); + QFont font = painter->font(); + font.setBold(true); + painter->setFont(font); + painter->drawText(textRect, Qt::TextShowMnemonic | Qt::AlignLeft| alignment, groupBox->text); + + if (option->state & State_HasFocus) + gtkPainter.paintFocus( NULL, "tab", textRect.adjusted(-4, -1, 0, -3), GTK_STATE_ACTIVE, style); + } + } + + if (groupBox->subControls & SC_GroupBoxCheckBox) { + QStyleOptionButton box; + box.QStyleOption::operator=(*groupBox); + box.rect = checkBoxRect; + proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget); + } + } + + painter->restore(); + break; +#endif // QT_NO_GROUPBOX + +#ifndef QT_NO_COMBOBOX + + case CC_ComboBox: + // See: http://live.gnome.org/GnomeArt/Tutorials/GtkThemes/GtkComboBox + // and http://live.gnome.org/GnomeArt/Tutorials/GtkThemes/GtkComboBoxEntry + if (const QStyleOptionComboBox *comboBox = qstyleoption_cast(option)) { + bool sunken = comboBox->state & State_On; // play dead, if combobox has no items + BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("cb-%0-%1").arg(sunken).arg(comboBox->editable)); + QGtkPainter gtkCachedPainter(p); + gtkCachedPainter.setUsePixmapCache(false); // cached externally + + bool isEnabled = (comboBox->state & State_Enabled); + bool focus = isEnabled && (comboBox->state & State_HasFocus); + GtkStateType state = gtkPainter.gtkState(option); + int appears_as_list = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, comboBox, widget); + QStyleOptionComboBox comboBoxCopy = *comboBox; + comboBoxCopy.rect = option->rect; + + bool reverse = (option->direction == Qt::RightToLeft); + QRect rect = option->rect; + QRect arrowButtonRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy, + SC_ComboBoxArrow, widget); + + GtkShadowType shadow = (option->state & State_Sunken || option->state & State_On ) ? + GTK_SHADOW_IN : GTK_SHADOW_OUT; + const QHashableLatin1Literal comboBoxPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry") : QHashableLatin1Literal("GtkComboBox"); + + // We use the gtk widget to position arrows and separators for us + GtkWidget *gtkCombo = d->gtkWidget(comboBoxPath); + GtkAllocation geometry = {0, 0, option->rect.width(), option->rect.height()}; + d->gtk_widget_set_direction(gtkCombo, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + d->gtk_widget_size_allocate(gtkCombo, &geometry); + + QHashableLatin1Literal buttonPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton") + : QHashableLatin1Literal("GtkComboBox.GtkToggleButton"); + GtkWidget *gtkToggleButton = d->gtkWidget(buttonPath); + d->gtk_widget_set_direction(gtkToggleButton, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + if (gtkToggleButton && (appears_as_list || comboBox->editable)) { + if (focus) + GTK_WIDGET_SET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS); + // Draw the combo box as a line edit with a button next to it + if (comboBox->editable || appears_as_list) { + GtkStateType frameState = (state == GTK_STATE_PRELIGHT) ? GTK_STATE_NORMAL : state; + QHashableLatin1Literal entryPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry.GtkEntry") : QHashableLatin1Literal("GtkComboBox.GtkFrame"); + GtkWidget *gtkEntry = d->gtkWidget(entryPath); + d->gtk_widget_set_direction(gtkEntry, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + QRect frameRect = option->rect; + + if (reverse) + frameRect.setLeft(arrowButtonRect.right()); + else + frameRect.setRight(arrowButtonRect.left()); + + // Fill the line edit background + // We could have used flat_box with "entry_bg" but that is probably not worth the overhead + uint resolve_mask = option->palette.resolve(); + int xt = gtkEntry->style->xthickness; + int yt = gtkEntry->style->ythickness; + QRect contentRect = frameRect.adjusted(xt, yt, -xt, -yt); + // Required for inner blue highlight with clearlooks + if (focus) + GTK_WIDGET_SET_FLAGS(gtkEntry, GTK_HAS_FOCUS); + + if (widget && widget->testAttribute(Qt::WA_SetPalette) && + resolve_mask & (1 << QPalette::Base)) // Palette overridden by user + p->fillRect(contentRect, option->palette.base().color()); + else { + gtkCachedPainter.paintFlatBox(gtkEntry, "entry_bg", contentRect, + option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, + GTK_SHADOW_NONE, gtkEntry->style, entryPath.toString() + QString::number(focus)); + } + + gtkCachedPainter.paintShadow(gtkEntry, comboBox->editable ? "entry" : "frame", frameRect, frameState, + GTK_SHADOW_IN, gtkEntry->style, entryPath.toString() + + QString::number(focus) + QString::number(comboBox->editable) + + QString::number(option->direction)); + if (focus) + GTK_WIDGET_UNSET_FLAGS(gtkEntry, GTK_HAS_FOCUS); + } + + GtkStateType buttonState = GTK_STATE_NORMAL; + + if (!(option->state & State_Enabled)) + buttonState = GTK_STATE_INSENSITIVE; + else if (option->state & State_Sunken || option->state & State_On) + buttonState = GTK_STATE_ACTIVE; + else if (option->state & State_MouseOver && comboBox->activeSubControls & SC_ComboBoxArrow) + buttonState = GTK_STATE_PRELIGHT; + + Q_ASSERT(gtkToggleButton); + gtkCachedPainter.paintBox( gtkToggleButton, "button", arrowButtonRect, buttonState, + shadow, gtkToggleButton->style, buttonPath.toString() + + QString::number(focus) + QString::number(option->direction)); + if (focus) + GTK_WIDGET_UNSET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS); + } else { + // Draw combo box as a button + QRect buttonRect = option->rect; + + if (focus) // Clearlooks actually check the widget for the default state + GTK_WIDGET_SET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS); + gtkCachedPainter.paintBox(gtkToggleButton, "button", + buttonRect, state, + shadow, gtkToggleButton->style, + buttonPath.toString() + QString::number(focus)); + if (focus) + GTK_WIDGET_UNSET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS); + + + // Draw the separator between label and arrows + QHashableLatin1Literal vSeparatorPath = comboBox->editable + ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton.GtkHBox.GtkVSeparator") + : QHashableLatin1Literal("GtkComboBox.GtkToggleButton.GtkHBox.GtkVSeparator"); + + if (GtkWidget *gtkVSeparator = d->gtkWidget(vSeparatorPath)) { + QRect vLineRect(gtkVSeparator->allocation.x, + gtkVSeparator->allocation.y, + gtkVSeparator->allocation.width, + gtkVSeparator->allocation.height); + + gtkCachedPainter.paintVline( gtkVSeparator, "vseparator", + vLineRect, state, gtkVSeparator->style, + 0, vLineRect.height(), 0, vSeparatorPath.toString()); + + + gint interiorFocus = true; + d->gtk_widget_style_get(gtkToggleButton, "interior-focus", &interiorFocus, NULL); + int xt = interiorFocus ? gtkToggleButton->style->xthickness : 0; + int yt = interiorFocus ? gtkToggleButton->style->ythickness : 0; + if (focus && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) + gtkCachedPainter.paintFocus(gtkToggleButton, "button", + option->rect.adjusted(xt, yt, -xt, -yt), + option->state & State_Sunken ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL, + gtkToggleButton->style); + } + } + + if (comboBox->subControls & SC_ComboBoxArrow) { + if (!isEnabled) + state = GTK_STATE_INSENSITIVE; + else if (sunken) + state = GTK_STATE_ACTIVE; + else if (option->state & State_MouseOver) + state = GTK_STATE_PRELIGHT; + else + state = GTK_STATE_NORMAL; + + QHashableLatin1Literal arrowPath(""); + if (comboBox->editable) { + if (appears_as_list) + arrowPath = QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton.GtkArrow"); + else + arrowPath = QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton.GtkHBox.GtkArrow"); + } else { + if (appears_as_list) + arrowPath = QHashableLatin1Literal("GtkComboBox.GtkToggleButton.GtkArrow"); + else + arrowPath = QHashableLatin1Literal("GtkComboBox.GtkToggleButton.GtkHBox.GtkArrow"); + } + + GtkWidget *gtkArrow = d->gtkWidget(arrowPath); + gfloat scale = 0.7; + gint minSize = 15; + QRect arrowWidgetRect; + + if (gtkArrow && !d->gtk_check_version(2, 12, 0)) { + d->gtk_widget_style_get(gtkArrow, "arrow-scaling", &scale, NULL); + d->gtk_widget_style_get(gtkCombo, "arrow-size", &minSize, NULL); + } + if (gtkArrow) { + arrowWidgetRect = QRect(gtkArrow->allocation.x, gtkArrow->allocation.y, + gtkArrow->allocation.width, gtkArrow->allocation.height); + style = gtkArrow->style; + } + + // Note that for some reason the arrow-size is not properly respected with Hildon + // Hence we enforce the minimum "arrow-size" ourselves + int arrowSize = qMax(qMin(rect.height() - gtkCombo->style->ythickness * 2, minSize), + qMin(arrowWidgetRect.width(), arrowWidgetRect.height())); + QRect arrowRect(0, 0, static_cast(arrowSize * scale), static_cast(arrowSize * scale)); + + arrowRect.moveCenter(arrowWidgetRect.center()); + + if (sunken) { + int xoff, yoff; + const QHashableLatin1Literal toggleButtonPath = comboBox->editable + ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton") + : QHashableLatin1Literal("GtkComboBox.GtkToggleButton"); + + GtkWidget *gtkButton = d->gtkWidget(toggleButtonPath); + d->gtk_widget_style_get(gtkButton, "child-displacement-x", &xoff, NULL); + d->gtk_widget_style_get(gtkButton, "child-displacement-y", &yoff, NULL); + arrowRect = arrowRect.adjusted(xoff, yoff, xoff, yoff); + } + + // Some styles such as Nimbus paint outside the arrowRect + // hence we have provide the whole widget as the cliprect + if (gtkArrow) { + gtkCachedPainter.setClipRect(option->rect); + gtkCachedPainter.paintArrow( gtkArrow, "arrow", arrowRect, + GTK_ARROW_DOWN, state, GTK_SHADOW_NONE, TRUE, + style, arrowPath.toString() + QString::number(option->direction)); + } + } + END_STYLE_PIXMAPCACHE; + } + break; +#endif // QT_NO_COMBOBOX +#ifndef QT_NO_TOOLBUTTON + + case CC_ToolButton: + if (const QStyleOptionToolButton *toolbutton + = qstyleoption_cast(option)) { + QRect button, menuarea; + button = proxy()->subControlRect(control, toolbutton, SC_ToolButton, widget); + menuarea = proxy()->subControlRect(control, toolbutton, SC_ToolButtonMenu, widget); + State bflags = toolbutton->state & ~(State_Sunken | State_MouseOver); + + if (bflags & State_AutoRaise) + if (!(bflags & State_MouseOver)) + bflags &= ~State_Raised; + + State mflags = bflags; + + if (toolbutton->state & State_Sunken) { + if (toolbutton->activeSubControls & SC_ToolButton) + bflags |= State_Sunken; + if (toolbutton->activeSubControls & SC_ToolButtonMenu) + mflags |= State_Sunken; + } else if (toolbutton->state & State_MouseOver) { + if (toolbutton->activeSubControls & SC_ToolButton) + bflags |= State_MouseOver; + if (toolbutton->activeSubControls & SC_ToolButtonMenu) + mflags |= State_MouseOver; + } + + QStyleOption tool(0); + + tool.palette = toolbutton->palette; + + if (toolbutton->subControls & SC_ToolButton) { + if (bflags & (State_Sunken | State_On | State_Raised | State_MouseOver)) { + tool.rect = button; + tool.state = bflags; + proxy()->drawPrimitive(PE_PanelButtonTool, &tool, painter, widget); + } + } + + bool drawMenuArrow = toolbutton->features & QStyleOptionToolButton::HasMenu && + !(toolbutton->features & QStyleOptionToolButton::MenuButtonPopup); + int popupArrowSize = drawMenuArrow ? 7 : 0; + + if (toolbutton->state & State_HasFocus) { + QStyleOptionFocusRect fr; + fr.QStyleOption::operator=(*toolbutton); + fr.rect = proxy()->subControlRect(CC_ToolButton, toolbutton, SC_ToolButton, widget); + fr.rect.adjust(1, 1, -1, -1); + proxy()->drawPrimitive(PE_FrameFocusRect, &fr, painter, widget); + } + + QStyleOptionToolButton label = *toolbutton; + label.state = bflags; + GtkWidget *gtkButton = d->gtkWidget("GtkToolButton.GtkButton"); + QPalette pal = toolbutton->palette; + if (option->state & State_Enabled && + option->state & State_MouseOver && !(widget && widget->testAttribute(Qt::WA_SetPalette))) { + GdkColor gdkText = gtkButton->style->fg[GTK_STATE_PRELIGHT]; + QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + pal.setBrush(QPalette::All, QPalette::ButtonText, textColor); + label.palette = pal; + } + label.rect = button.adjusted(style->xthickness, style->ythickness, + -style->xthickness - popupArrowSize, -style->ythickness); + proxy()->drawControl(CE_ToolButtonLabel, &label, painter, widget); + + if (toolbutton->subControls & SC_ToolButtonMenu) { + tool.rect = menuarea; + tool.state = mflags; + if ((mflags & State_Enabled && (mflags & (State_Sunken | State_Raised | State_MouseOver))) || !(mflags & State_AutoRaise)) + proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, painter, widget); + + proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget); + + } else if (drawMenuArrow) { + QRect ir = toolbutton->rect; + QStyleOptionToolButton newBtn = *toolbutton; + newBtn.rect = QRect(ir.right() - popupArrowSize - style->xthickness - 3, ir.height()/2 - 1, popupArrowSize, popupArrowSize); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget); + } + } + break; + +#endif // QT_NO_TOOLBUTTON +#ifndef QT_NO_SCROLLBAR + + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast(option)) { + GtkWidget *gtkHScrollBar = d->gtkWidget("GtkHScrollbar"); + GtkWidget *gtkVScrollBar = d->gtkWidget("GtkVScrollbar"); + + // Fill background in case the scrollbar is partially transparent + painter->fillRect(option->rect, option->palette.background()); + + QRect rect = scrollBar->rect; + QRect scrollBarSubLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget); + QRect scrollBarAddLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget); + QRect scrollBarSlider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget); + QRect grooveRect = proxy()->subControlRect(control, scrollBar, SC_ScrollBarGroove, widget); + bool horizontal = scrollBar->orientation == Qt::Horizontal; + GtkWidget * scrollbarWidget = horizontal ? gtkHScrollBar : gtkVScrollBar; + style = scrollbarWidget->style; + gboolean trough_under_steppers = true; + gboolean trough_side_details = false; + gboolean activate_slider = false; + gboolean stepper_size = 14; + gint trough_border = 1; + if (!d->gtk_check_version(2, 10, 0)) { + d->gtk_widget_style_get((GtkWidget*)(scrollbarWidget), + "trough-border", &trough_border, + "trough-side-details", &trough_side_details, + "trough-under-steppers", &trough_under_steppers, + "activate-slider", &activate_slider, + "stepper-size", &stepper_size, NULL); + } + if (trough_under_steppers) { + scrollBarAddLine.adjust(trough_border, trough_border, -trough_border, -trough_border); + scrollBarSubLine.adjust(trough_border, trough_border, -trough_border, -trough_border); + scrollBarSlider.adjust(horizontal ? -trough_border : 0, horizontal ? 0 : -trough_border, + horizontal ? trough_border : 0, horizontal ? 0 : trough_border); + } + + // Some styles check the position of scrollbars in order to determine + // if lines should be painted when the scrollbar is in max or min positions. + int maximum = 2; + int fakePos = 0; + bool reverse = (option->direction == Qt::RightToLeft); + if (scrollBar->minimum == scrollBar->maximum) + maximum = 0; + if (scrollBar->sliderPosition == scrollBar->maximum) + fakePos = maximum; + else if (scrollBar->sliderPosition > scrollBar->minimum) + fakePos = maximum - 1; + + + GtkRange *range = (GtkRange*)(horizontal ? gtkHScrollBar : gtkVScrollBar); + GtkAdjustment *adjustment = d->gtk_range_get_adjustment(range); + + if (adjustment) { + d->gtk_adjustment_configure(adjustment, fakePos, 0, maximum, 0, 0, 0); + } else { + adjustment = (GtkAdjustment*)d->gtk_adjustment_new(fakePos, 0, maximum, 0, 0, 0); + d->gtk_range_set_adjustment(range, adjustment); + } + + if (scrollBar->subControls & SC_ScrollBarGroove) { + GtkStateType state = GTK_STATE_ACTIVE; + + if (!(option->state & State_Enabled)) + state = GTK_STATE_INSENSITIVE; + + if (trough_under_steppers) + grooveRect = option->rect; + + gtkPainter.paintBox( scrollbarWidget, "trough", grooveRect, state, GTK_SHADOW_IN, style); + } + + //paint slider + if (scrollBar->subControls & SC_ScrollBarSlider) { + GtkStateType state = GTK_STATE_NORMAL; + + if (!(option->state & State_Enabled)) + state = GTK_STATE_INSENSITIVE; + else if (activate_slider && + option->state & State_Sunken && (scrollBar->activeSubControls & SC_ScrollBarSlider)) + state = GTK_STATE_ACTIVE; + else if (option->state & State_MouseOver && (scrollBar->activeSubControls & SC_ScrollBarSlider)) + state = GTK_STATE_PRELIGHT; + + GtkShadowType shadow = GTK_SHADOW_OUT; + + if (trough_under_steppers) { + if (!horizontal) + scrollBarSlider.adjust(trough_border, 0, -trough_border, 0); + else + scrollBarSlider.adjust(0, trough_border, 0, -trough_border); + } + + gtkPainter.paintSlider( scrollbarWidget, "slider", scrollBarSlider, state, shadow, style, + + horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, QString(QLS("%0%1")).arg(fakePos).arg(maximum)); + } + + if (scrollBar->subControls & SC_ScrollBarAddLine) { + gtkVScrollBar->allocation.y = scrollBarAddLine.top(); + gtkVScrollBar->allocation.height = scrollBarAddLine.height() - rect.height() + 6; + gtkHScrollBar->allocation.x = scrollBarAddLine.right(); + gtkHScrollBar->allocation.width = scrollBarAddLine.width() - rect.width(); + + GtkShadowType shadow = GTK_SHADOW_OUT; + GtkStateType state = GTK_STATE_NORMAL; + + if (!(option->state & State_Enabled) || (fakePos == maximum)) + state = GTK_STATE_INSENSITIVE; + else if (option->state & State_Sunken && (scrollBar->activeSubControls & SC_ScrollBarAddLine)) { + state = GTK_STATE_ACTIVE; + shadow = GTK_SHADOW_IN; + + } else if (option->state & State_MouseOver && (scrollBar->activeSubControls & SC_ScrollBarAddLine)) + state = GTK_STATE_PRELIGHT; + + gtkPainter.paintBox( scrollbarWidget, + horizontal ? "hscrollbar" : "vscrollbar", scrollBarAddLine, + state, shadow, style, QLS("add")); + + gtkPainter.paintArrow( scrollbarWidget, horizontal ? "hscrollbar" : "vscrollbar", scrollBarAddLine.adjusted(4, 4, -4, -4), + horizontal ? (reverse ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT) : + GTK_ARROW_DOWN, state, GTK_SHADOW_NONE, FALSE, style); + } + + if (scrollBar->subControls & SC_ScrollBarSubLine) { + gtkVScrollBar->allocation.y = 0; + gtkVScrollBar->allocation.height = scrollBarSubLine.height(); + gtkHScrollBar->allocation.x = 0; + gtkHScrollBar->allocation.width = scrollBarSubLine.width(); + + GtkShadowType shadow = GTK_SHADOW_OUT; + GtkStateType state = GTK_STATE_NORMAL; + + if (!(option->state & State_Enabled) || (fakePos == 0)) + state = GTK_STATE_INSENSITIVE; + else if (option->state & State_Sunken && (scrollBar->activeSubControls & SC_ScrollBarSubLine)) { + shadow = GTK_SHADOW_IN; + state = GTK_STATE_ACTIVE; + + } else if (option->state & State_MouseOver && (scrollBar->activeSubControls & SC_ScrollBarSubLine)) + state = GTK_STATE_PRELIGHT; + + gtkPainter.paintBox(scrollbarWidget, horizontal ? "hscrollbar" : "vscrollbar", scrollBarSubLine, + state, shadow, style, QLS("sub")); + + gtkPainter.paintArrow(scrollbarWidget, horizontal ? "hscrollbar" : "vscrollbar", scrollBarSubLine.adjusted(4, 4, -4, -4), + horizontal ? (reverse ? GTK_ARROW_RIGHT : GTK_ARROW_LEFT) : + GTK_ARROW_UP, state, GTK_SHADOW_NONE, FALSE, style); + } + } + break; + +#endif //QT_NO_SCROLLBAR +#ifndef QT_NO_SPINBOX + + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { + + GtkWidget *gtkSpinButton = spinBox->buttonSymbols == QAbstractSpinBox::NoButtons + ? d->gtkWidget("GtkEntry") + : d->gtkWidget("GtkSpinButton"); + bool isEnabled = (spinBox->state & State_Enabled); + bool hover = isEnabled && (spinBox->state & State_MouseOver); + bool sunken = (spinBox->state & State_Sunken); + bool upIsActive = (spinBox->activeSubControls == SC_SpinBoxUp); + bool downIsActive = (spinBox->activeSubControls == SC_SpinBoxDown); + bool reverse = (spinBox->direction == Qt::RightToLeft); + + QRect editArea = option->rect; + QRect editRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxEditField, widget); + QRect upRect, downRect, buttonRect; + if (spinBox->buttonSymbols != QAbstractSpinBox::NoButtons) { + upRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget); + downRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget); + + //### Move this to subControlRect + upRect.setTop(option->rect.top()); + + if (reverse) + upRect.setLeft(option->rect.left()); + else + upRect.setRight(option->rect.right()); + + downRect.setBottom(option->rect.bottom()); + + if (reverse) + downRect.setLeft(option->rect.left()); + else + downRect.setRight(option->rect.right()); + + buttonRect = upRect | downRect; + + if (reverse) + editArea.setLeft(upRect.right()); + else + editArea.setRight(upRect.left()); + } + if (spinBox->frame) { + GtkShadowType shadow = GTK_SHADOW_OUT; + GtkStateType state = gtkPainter.gtkState(option); + + if (!(option->state & State_Enabled)) + state = GTK_STATE_INSENSITIVE; + else if (option->state & State_HasFocus) + state = GTK_STATE_NORMAL; + else if (state == GTK_STATE_PRELIGHT) + state = GTK_STATE_NORMAL; + + shadow = GTK_SHADOW_IN; + style = gtkPainter.getStyle(gtkSpinButton); + + + QString key; + + if (option->state & State_HasFocus) { + key += QLatin1Char('f'); + GTK_WIDGET_SET_FLAGS(gtkSpinButton, GTK_HAS_FOCUS); + } + + uint resolve_mask = option->palette.resolve(); + + if (resolve_mask & (1 << QPalette::Base)) // Palette overridden by user + painter->fillRect(editRect, option->palette.base().color()); + else + gtkPainter.paintFlatBox(gtkSpinButton, "entry_bg", editArea.adjusted(style->xthickness, style->ythickness, + -style->xthickness, -style->ythickness), + option->state & State_Enabled ? + GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, GTK_SHADOW_NONE, style, key); + + gtkPainter.paintShadow(gtkSpinButton, "entry", editArea, state, GTK_SHADOW_IN, gtkSpinButton->style, key); + if (spinBox->buttonSymbols != QAbstractSpinBox::NoButtons) { + gtkPainter.paintBox(gtkSpinButton, "spinbutton", buttonRect, state, GTK_SHADOW_IN, style, key); + + upRect.setSize(downRect.size()); + if (!(option->state & State_Enabled)) + gtkPainter.paintBox( gtkSpinButton, "spinbutton_up", upRect, GTK_STATE_INSENSITIVE, GTK_SHADOW_IN, style, key); + else if (upIsActive && sunken) + gtkPainter.paintBox( gtkSpinButton, "spinbutton_up", upRect, GTK_STATE_ACTIVE, GTK_SHADOW_IN, style, key); + else if (upIsActive && hover) + gtkPainter.paintBox( gtkSpinButton, "spinbutton_up", upRect, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, style, key); + else + gtkPainter.paintBox( gtkSpinButton, "spinbutton_up", upRect, GTK_STATE_NORMAL, GTK_SHADOW_OUT, style, key); + + if (!(option->state & State_Enabled)) + gtkPainter.paintBox( gtkSpinButton, "spinbutton_down", downRect, GTK_STATE_INSENSITIVE, GTK_SHADOW_IN, style, key); + else if (downIsActive && sunken) + gtkPainter.paintBox( gtkSpinButton, "spinbutton_down", downRect, GTK_STATE_ACTIVE, GTK_SHADOW_IN, style, key); + else if (downIsActive && hover) + gtkPainter.paintBox( gtkSpinButton, "spinbutton_down", downRect, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, style, key); + else + gtkPainter.paintBox( gtkSpinButton, "spinbutton_down", downRect, GTK_STATE_NORMAL, GTK_SHADOW_OUT, style, key); + + if (option->state & State_HasFocus) + GTK_WIDGET_UNSET_FLAGS(gtkSpinButton, GTK_HAS_FOCUS); + } + } + + if (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) { + int centerX = upRect.center().x(); + int centerY = upRect.center().y(); + // plus/minus + + if (spinBox->activeSubControls == SC_SpinBoxUp && sunken) { + painter->drawLine(1 + centerX - 2, 1 + centerY, 1 + centerX + 2, 1 + centerY); + painter->drawLine(1 + centerX, 1 + centerY - 2, 1 + centerX, 1 + centerY + 2); + + } else { + painter->drawLine(centerX - 2, centerY, centerX + 2, centerY); + painter->drawLine(centerX, centerY - 2, centerX, centerY + 2); + } + centerX = downRect.center().x(); + centerY = downRect.center().y(); + + if (spinBox->activeSubControls == SC_SpinBoxDown && sunken) { + painter->drawLine(1 + centerX - 2, 1 + centerY, 1 + centerX + 2, 1 + centerY); + } else { + painter->drawLine(centerX - 2, centerY, centerX + 2, centerY); + } + + } else if (spinBox->buttonSymbols == QAbstractSpinBox::UpDownArrows) { + int size = d->getSpinboxArrowSize(); + int w = size / 2 - 1; + w -= w % 2 - 1; // force odd + int h = (w + 1)/2; + QRect arrowRect(0, 0, w, h); + arrowRect.moveCenter(upRect.center()); + // arrows + GtkStateType state = GTK_STATE_NORMAL; + + if (!(option->state & State_Enabled) || !(spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled)) + state = GTK_STATE_INSENSITIVE; + + gtkPainter.paintArrow( gtkSpinButton, "spinbutton", arrowRect, GTK_ARROW_UP, state, + GTK_SHADOW_NONE, FALSE, style); + + arrowRect.moveCenter(downRect.center()); + + if (!(option->state & State_Enabled) || !(spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled)) + state = GTK_STATE_INSENSITIVE; + + gtkPainter.paintArrow( gtkSpinButton, "spinbutton", arrowRect, GTK_ARROW_DOWN, state, + GTK_SHADOW_NONE, FALSE, style); + } + } + break; + +#endif // QT_NO_SPINBOX + +#ifndef QT_NO_SLIDER + + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + GtkWidget *hScaleWidget = d->gtkWidget("GtkHScale"); + GtkWidget *vScaleWidget = d->gtkWidget("GtkVScale"); + + QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget); + QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget); + + bool horizontal = slider->orientation == Qt::Horizontal; + bool ticksAbove = slider->tickPosition & QSlider::TicksAbove; + bool ticksBelow = slider->tickPosition & QSlider::TicksBelow; + + QBrush oldBrush = painter->brush(); + QPen oldPen = painter->pen(); + + QColor shadowAlpha(Qt::black); + shadowAlpha.setAlpha(10); + QColor highlightAlpha(Qt::white); + highlightAlpha.setAlpha(80); + + QGtkStylePrivate::gtk_widget_set_direction(hScaleWidget, slider->upsideDown ? + GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + GtkWidget *scaleWidget = horizontal ? hScaleWidget : vScaleWidget; + style = scaleWidget->style; + + if ((option->subControls & SC_SliderGroove) && groove.isValid()) { + + GtkRange *range = (GtkRange*)scaleWidget; + GtkAdjustment *adjustment = d->gtk_range_get_adjustment(range); + if (adjustment) { + d->gtk_adjustment_configure(adjustment, + slider->sliderPosition, + slider->minimum, + slider->maximum, + slider->singleStep, + slider->singleStep, + slider->pageStep); + } else { + adjustment = (GtkAdjustment*)d->gtk_adjustment_new(slider->sliderPosition, + slider->minimum, + slider->maximum, + slider->singleStep, + slider->singleStep, + slider->pageStep); + d->gtk_range_set_adjustment(range, adjustment); + } + + int outerSize; + d->gtk_range_set_inverted(range, !horizontal); + d->gtk_widget_style_get(scaleWidget, "trough-border", &outerSize, NULL); + outerSize++; + + GtkStateType state = gtkPainter.gtkState(option); + int focusFrameMargin = 2; + QRect grooveRect = option->rect.adjusted(focusFrameMargin, outerSize + focusFrameMargin, + -focusFrameMargin, -outerSize - focusFrameMargin); + + gboolean trough_side_details = false; // Indicates if the upper or lower scale background differs + if (!d->gtk_check_version(2, 10, 0)) + d->gtk_widget_style_get((GtkWidget*)(scaleWidget), "trough-side-details", &trough_side_details, NULL); + + if (!trough_side_details) { + gtkPainter.paintBox( scaleWidget, "trough", grooveRect, state, + GTK_SHADOW_IN, style, QString(QLS("p%0")).arg(slider->sliderPosition)); + } else { + QRect upperGroove = grooveRect; + QRect lowerGroove = grooveRect; + + if (horizontal) { + if (slider->upsideDown) { + lowerGroove.setLeft(handle.center().x()); + upperGroove.setRight(handle.center().x()); + } else { + upperGroove.setLeft(handle.center().x()); + lowerGroove.setRight(handle.center().x()); + } + } else { + if (!slider->upsideDown) { + lowerGroove.setBottom(handle.center().y()); + upperGroove.setTop(handle.center().y()); + } else { + upperGroove.setBottom(handle.center().y()); + lowerGroove.setTop(handle.center().y()); + } + } + + gtkPainter.paintBox( scaleWidget, "trough-upper", upperGroove, state, + GTK_SHADOW_IN, style, QString(QLS("p%0")).arg(slider->sliderPosition)); + gtkPainter.paintBox( scaleWidget, "trough-lower", lowerGroove, state, + GTK_SHADOW_IN, style, QString(QLS("p%0")).arg(slider->sliderPosition)); + } + } + + if (option->subControls & SC_SliderTickmarks) { + painter->setPen(darkOutline); + int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget); + int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget); + int interval = slider->tickInterval; + + if (interval <= 0) { + interval = slider->singleStep; + + if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval, + available) + - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, + 0, available) < 3) + interval = slider->pageStep; + } + + if (interval <= 0) + interval = 1; + + int v = slider->minimum; + int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); + while (v <= slider->maximum + 1) { + if (v == slider->maximum + 1 && interval == 1) + break; + const int v_ = qMin(v, slider->maximum); + int pos = sliderPositionFromValue(slider->minimum, slider->maximum, + v_, (horizontal + ? slider->rect.width() + : slider->rect.height()) - len, + slider->upsideDown) + len / 2; + int extra = 2 - ((v_ == slider->minimum || v_ == slider->maximum) ? 1 : 0); + if (horizontal) { + if (ticksAbove) + painter->drawLine(pos, slider->rect.top() + extra, + pos, slider->rect.top() + tickSize); + if (ticksBelow) + painter->drawLine(pos, slider->rect.bottom() - extra, + pos, slider->rect.bottom() - tickSize); + + } else { + if (ticksAbove) + painter->drawLine(slider->rect.left() + extra, pos, + slider->rect.left() + tickSize, pos); + if (ticksBelow) + painter->drawLine(slider->rect.right() - extra, pos, + slider->rect.right() - tickSize, pos); + } + + // In the case where maximum is max int + int nextInterval = v + interval; + if (nextInterval < v) + break; + v = nextInterval; + } + } + + // Draw slider handle + if (option->subControls & SC_SliderHandle) { + GtkShadowType shadow = GTK_SHADOW_OUT; + GtkStateType state = GTK_STATE_NORMAL; + + if (!(option->state & State_Enabled)) + state = GTK_STATE_INSENSITIVE; + else if (option->state & State_MouseOver && option->activeSubControls & SC_SliderHandle) + state = GTK_STATE_PRELIGHT; + + bool horizontal = option->state & State_Horizontal; + + if (slider->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*slider); + fropt.rect = slider->rect.adjusted(-1, -1 ,1, 1); + + if (horizontal) { + fropt.rect.setTop(handle.top() - 3); + fropt.rect.setBottom(handle.bottom() + 4); + + } else { + fropt.rect.setLeft(handle.left() - 3); + fropt.rect.setRight(handle.right() + 3); + } + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + gtkPainter.paintSlider( scaleWidget, horizontal ? "hscale" : "vscale", handle, state, shadow, style, + + horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL); + } + painter->setBrush(oldBrush); + painter->setPen(oldPen); + } + break; + +#endif // QT_NO_SLIDER + + default: + QCleanlooksStyle::drawComplexControl(control, option, painter, widget); + + break; + } +} + + +/*! + \reimp +*/ +void QGtkStyle::drawControl(ControlElement element, + const QStyleOption *option, + QPainter *painter, + const QWidget *widget) const +{ + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) { + QCleanlooksStyle::drawControl(element, option, painter, widget); + return; + } + + GtkStyle* style = d->gtkStyle(); + QGtkPainter gtkPainter(painter); + + switch (element) { + case CE_ProgressBarLabel: + if (const QStyleOptionProgressBar *bar = qstyleoption_cast(option)) { + GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar"); + if (!gtkProgressBar) + return; + + QRect leftRect; + QRect rect = bar->rect; + GdkColor gdkText = gtkProgressBar->style->fg[GTK_STATE_NORMAL]; + QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + gdkText = gtkProgressBar->style->fg[GTK_STATE_PRELIGHT]; + QColor alternateTextColor= QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + + painter->save(); + bool vertical = false, inverted = false; + if (const QStyleOptionProgressBarV2 *bar2 = qstyleoption_cast(option)) { + vertical = (bar2->orientation == Qt::Vertical); + inverted = bar2->invertedAppearance; + } + if (vertical) + rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height + const int progressIndicatorPos = (bar->progress - qreal(bar->minimum)) * rect.width() / + qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum); + if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width()) + leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height()); + if (vertical) + leftRect.translate(rect.width() - progressIndicatorPos, 0); + + bool flip = (!vertical && (((bar->direction == Qt::RightToLeft) && !inverted) || + ((bar->direction == Qt::LeftToRight) && inverted))); + + QRegion rightRect = rect; + rightRect = rightRect.subtracted(leftRect); + painter->setClipRegion(rightRect); + painter->setPen(flip ? alternateTextColor : textColor); + painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); + if (!leftRect.isNull()) { + painter->setPen(flip ? textColor : alternateTextColor); + painter->setClipRect(leftRect); + painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); + } + painter->restore(); + } + break; + case CE_PushButtonLabel: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + QRect ir = button->rect; + uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic; + QPoint buttonShift; + + if (option->state & State_Sunken) + buttonShift = QPoint(pixelMetric(PM_ButtonShiftHorizontal, option, widget), + proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget)); + + if (proxy()->styleHint(SH_UnderlineShortcut, button, widget)) + tf |= Qt::TextShowMnemonic; + else + tf |= Qt::TextHideMnemonic; + + if (!button->icon.isNull()) { + //Center both icon and text + QPoint point; + + QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled; + if (mode == QIcon::Normal && button->state & State_HasFocus) + mode = QIcon::Active; + + QIcon::State state = QIcon::Off; + + if (button->state & State_On) + state = QIcon::On; + + QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state); + int w = pixmap.width(); + int h = pixmap.height(); + + if (!button->text.isEmpty()) + w += button->fontMetrics.boundingRect(option->rect, tf, button->text).width() + 4; + + point = QPoint(ir.x() + ir.width() / 2 - w / 2, + ir.y() + ir.height() / 2 - h / 2); + + if (button->direction == Qt::RightToLeft) + point.rx() += pixmap.width(); + + painter->drawPixmap(visualPos(button->direction, button->rect, point + buttonShift), pixmap); + + if (button->direction == Qt::RightToLeft) + ir.translate(-point.x() - 2, 0); + else + ir.translate(point.x() + pixmap.width() + 2, 0); + + // left-align text if there is + if (!button->text.isEmpty()) + tf |= Qt::AlignLeft; + + } else { + tf |= Qt::AlignHCenter; + } + + ir.translate(buttonShift); + + if (button->features & QStyleOptionButton::HasMenu) + ir = ir.adjusted(0, 0, -pixelMetric(PM_MenuButtonIndicator, button, widget), 0); + + GtkWidget *gtkButton = d->gtkWidget("GtkButton"); + QPalette pal = button->palette; + int labelState = GTK_STATE_INSENSITIVE; + if (option->state & State_Enabled) + labelState = (option->state & State_MouseOver && !(option->state & State_Sunken)) ? + GTK_STATE_PRELIGHT : GTK_STATE_NORMAL; + + GdkColor gdkText = gtkButton->style->fg[labelState]; + QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + pal.setBrush(QPalette::ButtonText, textColor); + proxy()->drawItemText(painter, ir, tf, pal, (button->state & State_Enabled), + button->text, QPalette::ButtonText); + } + break; + + case CE_RadioButton: // Fall through + case CE_CheckBox: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + bool isRadio = (element == CE_RadioButton); + + // Draw prelight background + GtkWidget *gtkRadioButton = d->gtkWidget("GtkRadioButton"); + + if (option->state & State_MouseOver) { + gtkPainter.paintFlatBox(gtkRadioButton, "checkbutton", option->rect, + GTK_STATE_PRELIGHT, GTK_SHADOW_ETCHED_OUT, gtkRadioButton->style); + } + + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator + : SE_CheckBoxIndicator, btn, widget); + proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox, + &subopt, painter, widget); + subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents + : SE_CheckBoxContents, btn, widget); + // Get label text color + QPalette pal = subopt.palette; + int labelState = GTK_STATE_INSENSITIVE; + if (option->state & State_Enabled) + labelState = (option->state & State_MouseOver) ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL; + + GdkColor gdkText = gtkRadioButton->style->fg[labelState]; + QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + pal.setBrush(QPalette::WindowText, textColor); + subopt.palette = pal; + proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget); + + if (btn->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*btn); + fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect + : SE_CheckBoxFocusRect, btn, widget); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + } + break; + +#ifndef QT_NO_COMBOBOX + + case CE_ComboBoxLabel: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(option)) { + QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget); + bool appearsAsList = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, cb, widget); + painter->save(); + painter->setClipRect(editRect); + + if (!cb->currentIcon.isNull()) { + QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal + : QIcon::Disabled; + QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode); + QRect iconRect(editRect); + iconRect.setWidth(cb->iconSize.width() + 4); + + iconRect = alignedRect(cb->direction, + Qt::AlignLeft | Qt::AlignVCenter, + iconRect.size(), editRect); + + if (cb->editable) + painter->fillRect(iconRect, option->palette.brush(QPalette::Base)); + + proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); + + if (cb->direction == Qt::RightToLeft) + editRect.translate(-4 - cb->iconSize.width(), 0); + else + editRect.translate(cb->iconSize.width() + 4, 0); + } + + if (!cb->currentText.isEmpty() && !cb->editable) { + GtkWidget *gtkCombo = d->gtkWidget("GtkComboBox"); + QPalette pal = cb->palette; + int labelState = GTK_STATE_INSENSITIVE; + + if (option->state & State_Enabled) + labelState = (option->state & State_MouseOver && !appearsAsList) ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL; + + GdkColor gdkText = gtkCombo->style->fg[labelState]; + + QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + + pal.setBrush(QPalette::ButtonText, textColor); + + proxy()->drawItemText(painter, editRect.adjusted(1, 0, -1, 0), + visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter), + pal, cb->state & State_Enabled, cb->currentText, QPalette::ButtonText); + } + + painter->restore(); + } + break; + +#endif // QT_NO_COMBOBOX + + case CE_DockWidgetTitle: + painter->save(); + if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast(option)) { + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(dwOpt); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + + QRect rect = dwOpt->rect; + QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, option, widget).adjusted(-2, 0, -2, 0); + QRect r = rect.adjusted(0, 0, -1, -1); + if (verticalTitleBar) + r.adjust(0, 0, 0, -1); + + if (verticalTitleBar) { + QRect r = rect; + QSize s = r.size(); + s.transpose(); + r.setSize(s); + + titleRect = QRect(r.left() + rect.bottom() + - titleRect.bottom(), + r.top() + titleRect.left() - rect.left(), + titleRect.height(), titleRect.width()); + + painter->translate(r.left(), r.top() + r.width()); + painter->rotate(-90); + painter->translate(-r.left(), -r.top()); + + rect = r; + } + + if (!dwOpt->title.isEmpty()) { + QString titleText + = painter->fontMetrics().elidedText(dwOpt->title, + Qt::ElideRight, titleRect.width()); + proxy()->drawItemText(painter, + titleRect, + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette, + dwOpt->state & State_Enabled, titleText, + QPalette::WindowText); + } + } + painter->restore(); + break; + + + + case CE_HeaderSection: + painter->save(); + + // Draws the header in tables. + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + Q_UNUSED(header); + GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView"); + // Get the middle column + GtkTreeViewColumn *column = d->gtk_tree_view_get_column((GtkTreeView*)gtkTreeView, 1); + Q_ASSERT(column); + + GtkWidget *gtkTreeHeader = column->button; + GtkStateType state = gtkPainter.gtkState(option); + GtkShadowType shadow = GTK_SHADOW_OUT; + + if (option->state & State_Sunken) + shadow = GTK_SHADOW_IN; + + gtkPainter.paintBox(gtkTreeHeader, "button", option->rect.adjusted(-1, 0, 0, 0), state, shadow, gtkTreeHeader->style); + } + + painter->restore(); + break; + +#ifndef QT_NO_SIZEGRIP + + case CE_SizeGrip: { + GtkWidget *gtkStatusbar = d->gtkWidget("GtkStatusbar.GtkFrame"); + QRect gripRect = option->rect.adjusted(0, 0, -gtkStatusbar->style->xthickness, -gtkStatusbar->style->ythickness); + gtkPainter.paintResizeGrip( gtkStatusbar, "statusbar", gripRect, GTK_STATE_NORMAL, + GTK_SHADOW_OUT, QApplication::isRightToLeft() ? + GDK_WINDOW_EDGE_SOUTH_WEST : GDK_WINDOW_EDGE_SOUTH_EAST, + gtkStatusbar->style); + } + break; + +#endif // QT_NO_SIZEGRIP + + case CE_MenuBarEmptyArea: { + GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar"); + GdkColor gdkBg = gtkMenubar->style->bg[GTK_STATE_NORMAL]; // Theme can depend on transparency + painter->fillRect(option->rect, QColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8)); + if (widget) { // See CE_MenuBarItem + QRect menuBarRect = widget->rect(); + QPixmap pixmap(menuBarRect.size()); + pixmap.fill(Qt::transparent); + QPainter pmPainter(&pixmap); + QGtkPainter gtkMenuBarPainter(&pmPainter); + GtkShadowType shadow_type; + d->gtk_widget_style_get(gtkMenubar, "shadow-type", &shadow_type, NULL); + gtkMenuBarPainter.paintBox( gtkMenubar, "menubar", menuBarRect, + GTK_STATE_NORMAL, shadow_type, gtkMenubar->style); + pmPainter.end(); + painter->drawPixmap(option->rect, pixmap, option->rect); + } + } + break; + + case CE_MenuBarItem: + painter->save(); + + if (const QStyleOptionMenuItem *mbi = qstyleoption_cast(option)) { + GtkWidget *gtkMenubarItem = d->gtkWidget("GtkMenuBar.GtkMenuItem"); + GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar"); + + style = gtkMenubarItem->style; + + if (widget) { + // Since Qt does not currently allow filling the entire background + // we use a hack for this by making a complete menubar each time and + // paint with the correct offset inside it. Pixmap caching should resolve + // most of the performance penalty. + QRect menuBarRect = widget->rect(); + QPixmap pixmap(menuBarRect.size()); + pixmap.fill(Qt::transparent); + QPainter pmPainter(&pixmap); + QGtkPainter menubarPainter(&pmPainter); + GtkShadowType shadow_type; + d->gtk_widget_style_get(gtkMenubar, "shadow-type", &shadow_type, NULL); + GdkColor gdkBg = gtkMenubar->style->bg[GTK_STATE_NORMAL]; // Theme can depend on transparency + painter->fillRect(option->rect, QColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8)); + menubarPainter.paintBox(gtkMenubar, "menubar", menuBarRect, + GTK_STATE_NORMAL, shadow_type, gtkMenubar->style); + pmPainter.end(); + painter->drawPixmap(option->rect, pixmap, option->rect); + } + + QStyleOptionMenuItem item = *mbi; + bool act = mbi->state & State_Selected && mbi->state & State_Sunken; + bool dis = !(mbi->state & State_Enabled); + item.rect = mbi->rect; + GdkColor gdkText = gtkMenubarItem->style->fg[dis ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL]; + GdkColor gdkHText = gtkMenubarItem->style->fg[GTK_STATE_PRELIGHT]; + QColor normalTextColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + QColor highlightedTextColor = QColor(gdkHText.red>>8, gdkHText.green>>8, gdkHText.blue>>8); + item.palette.setBrush(QPalette::HighlightedText, highlightedTextColor); + item.palette.setBrush(QPalette::Text, normalTextColor); + item.palette.setBrush(QPalette::ButtonText, normalTextColor); + QCommonStyle::drawControl(element, &item, painter, widget); + + if (act) { + GtkShadowType shadowType = GTK_SHADOW_NONE; + d->gtk_widget_style_get (gtkMenubarItem, "selected-shadow-type", &shadowType, NULL); + gtkPainter.paintBox(gtkMenubarItem, "menuitem", option->rect.adjusted(0, 0, 0, 3), + GTK_STATE_PRELIGHT, shadowType, gtkMenubarItem->style); + //draw text + QPalette::ColorRole textRole = dis ? QPalette::Text : QPalette::HighlightedText; + uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + + if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget)) + alignment |= Qt::TextHideMnemonic; + + proxy()->drawItemText(painter, item.rect, alignment, item.palette, mbi->state & State_Enabled, mbi->text, textRole); + } + } + painter->restore(); + break; + + case CE_Splitter: { + GtkWidget *gtkWindow = d->gtkWidget("GtkWindow"); // The Murrine Engine currently assumes a widget is passed + gtkPainter.paintHandle(gtkWindow, "splitter", option->rect, gtkPainter.gtkState(option), GTK_SHADOW_NONE, + !(option->state & State_Horizontal) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, + style); + } + break; + +#ifndef QT_NO_TOOLBAR + + case CE_ToolBar: + if (const QStyleOptionToolBar *toolbar = qstyleoption_cast(option)) { + // Reserve the beveled appearance only for mainwindow toolbars + if (!(widget && qobject_cast (widget->parentWidget()))) + break; + + QRect rect = option->rect; + // There is a 1 pixel gap between toolbar lines in some styles (i.e Human) + if (toolbar->positionWithinLine != QStyleOptionToolBar::End) + rect.adjust(0, 0, 1, 0); + + GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar"); + GtkShadowType shadow_type = GTK_SHADOW_NONE; + d->gtk_widget_style_get(gtkToolbar, "shadow-type", &shadow_type, NULL); + gtkPainter.paintBox( gtkToolbar, "toolbar", rect, + GTK_STATE_NORMAL, shadow_type, gtkToolbar->style); + } + break; + +#endif // QT_NO_TOOLBAR + + case CE_MenuItem: + painter->save(); + + // Draws one item in a popup menu. + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast(option)) { + const int windowsItemFrame = 2; // menu item frame width + const int windowsItemHMargin = 3; // menu item hor text margin + const int windowsItemVMargin = 26; // menu item ver text margin + const int windowsRightBorder = 15; // right border on windows + GtkWidget *gtkMenuItem = menuItem->checked ? d->gtkWidget("GtkMenu.GtkCheckMenuItem") : + d->gtkWidget("GtkMenu.GtkMenuItem"); + + style = gtkPainter.getStyle(gtkMenuItem); + QColor shadow = option->palette.dark().color(); + + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + GtkWidget *gtkMenuSeparator = d->gtkWidget("GtkMenu.GtkSeparatorMenuItem"); + painter->setPen(shadow.lighter(106)); + gboolean wide_separators = 0; + gint separator_height = 0; + guint horizontal_padding = 3; + QRect separatorRect = option->rect; + if (!d->gtk_check_version(2, 10, 0)) { + d->gtk_widget_style_get(gtkMenuSeparator, + "wide-separators", &wide_separators, + "separator-height", &separator_height, + "horizontal-padding", &horizontal_padding, + NULL); + } + separatorRect.setHeight(option->rect.height() - 2 * gtkMenuSeparator->style->ythickness); + separatorRect.setWidth(option->rect.width() - 2 * (horizontal_padding + gtkMenuSeparator->style->xthickness)); + separatorRect.moveCenter(option->rect.center()); + if (wide_separators) + gtkPainter.paintBox( gtkMenuSeparator, "hseparator", + separatorRect, GTK_STATE_NORMAL, GTK_SHADOW_NONE, gtkMenuSeparator->style); + else + gtkPainter.paintHline( gtkMenuSeparator, "hseparator", + separatorRect, GTK_STATE_NORMAL, gtkMenuSeparator->style, + 0, option->rect.right() - 1, 1); + painter->restore(); + break; + } + + bool selected = menuItem->state & State_Selected && menuItem->state & State_Enabled; + + if (selected) { + QRect rect = option->rect; +#ifndef QT_NO_COMBOBOX + if (qobject_cast(widget)) + rect = option->rect; +#endif + gtkPainter.paintBox( gtkMenuItem, "menuitem", rect, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, style); + } + + bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable; + bool checked = menuItem->checked; + bool enabled = menuItem->state & State_Enabled; + bool ignoreCheckMark = false; + + gint checkSize; + d->gtk_widget_style_get(d->gtkWidget("GtkMenu.GtkCheckMenuItem"), "indicator-size", &checkSize, NULL); + + int checkcol = qMax(menuItem->maxIconWidth, qMax(20, checkSize)); + +#ifndef QT_NO_COMBOBOX + + if (qobject_cast(widget)) + ignoreCheckMark = true; // Ignore the checkmarks provided by the QComboMenuDelegate + +#endif + if (!ignoreCheckMark) { + // Check + QRect checkRect(option->rect.left() + 7, option->rect.center().y() - checkSize/2 + 1, checkSize, checkSize); + checkRect = visualRect(menuItem->direction, menuItem->rect, checkRect); + + if (checkable && menuItem->icon.isNull()) { + // Some themes such as aero-clone draw slightly outside the paint rect + int spacing = 1; // ### Consider using gtkCheckBox : "indicator-spacing" instead + + if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) { + // Radio button + GtkShadowType shadow = GTK_SHADOW_OUT; + GtkStateType state = gtkPainter.gtkState(option); + + if (selected) + state = GTK_STATE_PRELIGHT; + if (checked) + shadow = GTK_SHADOW_IN; + + gtkPainter.setClipRect(checkRect.adjusted(-spacing, -spacing, spacing, spacing)); + gtkPainter.paintOption(gtkMenuItem, checkRect.translated(-spacing, -spacing), state, shadow, + gtkMenuItem->style, QLS("option")); + gtkPainter.setClipRect(QRect()); + + } else { + // Check box + if (menuItem->icon.isNull()) { + GtkShadowType shadow = GTK_SHADOW_OUT; + GtkStateType state = gtkPainter.gtkState(option); + + if (selected) + state = GTK_STATE_PRELIGHT; + if (checked) + shadow = GTK_SHADOW_IN; + + gtkPainter.setClipRect(checkRect.adjusted(-spacing, -spacing, -spacing, -spacing)); + gtkPainter.paintCheckbox(gtkMenuItem, checkRect.translated(-spacing, -spacing), state, shadow, + gtkMenuItem->style, QLS("check")); + gtkPainter.setClipRect(QRect()); + } + } + } + + } else { + // Ignore checkmark + if (menuItem->icon.isNull()) + checkcol = 0; + else + checkcol = menuItem->maxIconWidth; + } + + bool dis = !(menuItem->state & State_Enabled); + bool act = menuItem->state & State_Selected; + const QStyleOption *opt = option; + const QStyleOptionMenuItem *menuitem = menuItem; + QPainter *p = painter; + QRect vCheckRect = visualRect(opt->direction, menuitem->rect, + QRect(menuitem->rect.x() + 3, menuitem->rect.y(), + checkcol, menuitem->rect.height())); + + if (!menuItem->icon.isNull()) { + QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; + + if (act && !dis) + mode = QIcon::Active; + + QPixmap pixmap; + int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize, option, widget); + QSize iconSize(smallIconSize, smallIconSize); + +#ifndef QT_NO_COMBOBOX + if (const QComboBox *combo = qobject_cast(widget)) + iconSize = combo->iconSize(); + +#endif // QT_NO_COMBOBOX + if (checked) + pixmap = menuItem->icon.pixmap(iconSize, mode, QIcon::On); + else + pixmap = menuItem->icon.pixmap(iconSize, mode); + + int pixw = pixmap.width(); + int pixh = pixmap.height(); + QRect pmr(0, 0, pixw, pixh); + pmr.moveCenter(vCheckRect.center() - QPoint(0, 1)); + painter->setPen(menuItem->palette.text().color()); + if (!ignoreCheckMark && checkable && checked) { + QStyleOption opt = *option; + + if (act) { + QColor activeColor = mergedColors(option->palette.background().color(), + option->palette.highlight().color()); + opt.palette.setBrush(QPalette::Button, activeColor); + } + opt.state |= State_Sunken; + opt.rect = vCheckRect; + proxy()->drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget); + } + painter->drawPixmap(pmr.topLeft(), pixmap); + } + + GdkColor gdkText = gtkMenuItem->style->fg[GTK_STATE_NORMAL]; + GdkColor gdkDText = gtkMenuItem->style->fg[GTK_STATE_INSENSITIVE]; + GdkColor gdkHText = gtkMenuItem->style->fg[GTK_STATE_PRELIGHT]; + uint resolve_mask = option->palette.resolve(); + QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + QColor disabledTextColor = QColor(gdkDText.red>>8, gdkDText.green>>8, gdkDText.blue>>8); + if (resolve_mask & (1 << QPalette::ButtonText)) { + textColor = option->palette.buttonText().color(); + disabledTextColor = option->palette.brush(QPalette::Disabled, QPalette::ButtonText).color(); + } + + QColor highlightedTextColor = QColor(gdkHText.red>>8, gdkHText.green>>8, gdkHText.blue>>8); + if (resolve_mask & (1 << QPalette::HighlightedText)) { + highlightedTextColor = option->palette.highlightedText().color(); + } + + if (selected) + painter->setPen(highlightedTextColor); + else + painter->setPen(textColor); + + int x, y, w, h; + menuitem->rect.getRect(&x, &y, &w, &h); + int tab = menuitem->tabWidth; + int xm = windowsItemFrame + checkcol + windowsItemHMargin; + int xpos = menuitem->rect.x() + xm + 1; + QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); + QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect); + QString s = menuitem->text; + + if (!s.isEmpty()) { // Draw text + p->save(); + int t = s.indexOf(QLatin1Char('\t')); + int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + + if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget)) + text_flags |= Qt::TextHideMnemonic; + + // Draw shortcut right aligned + text_flags |= Qt::AlignRight; + + if (t >= 0) { + int rightMargin = 12; // Hardcode for now + QRect vShortcutRect = visualRect(opt->direction, menuitem->rect, + QRect(textRect.topRight(), QPoint(menuitem->rect.right() - rightMargin, textRect.bottom()))); + + if (dis) + p->setPen(disabledTextColor); + p->drawText(vShortcutRect, text_flags , s.mid(t + 1)); + s = s.left(t); + } + + text_flags &= ~Qt::AlignRight; + text_flags |= Qt::AlignLeft; + QFont font = menuitem->font; + if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) + font.setBold(true); + p->setFont(font); + + if (dis) + p->setPen(disabledTextColor); + p->drawText(vTextRect, text_flags, s.left(t)); + p->restore(); + } + + // Arrow + if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow + + QFontMetrics fm(menuitem->font); + int arrow_size = fm.ascent() + fm.descent() - 2 * gtkMenuItem->style->ythickness; + gfloat arrow_scaling = 0.8; + int extra = 0; + if (!d->gtk_check_version(2, 16, 0)) { + // "arrow-scaling" is actually hardcoded and fails on hardy (see gtk+-2.12/gtkmenuitem.c) + // though the current documentation states otherwise + d->gtk_widget_style_get(gtkMenuItem, "arrow-scaling", &arrow_scaling, NULL); + // in versions < 2.16 ythickness was previously subtracted from the arrow_size + extra = 2 * gtkMenuItem->style->ythickness; + } + + int horizontal_padding; + d->gtk_widget_style_get(gtkMenuItem, "horizontal-padding", &horizontal_padding, NULL); + + const int dim = static_cast(arrow_size * arrow_scaling) + extra; + int xpos = menuItem->rect.left() + menuItem->rect.width() - horizontal_padding - dim; + QRect vSubMenuRect = visualRect(option->direction, menuItem->rect, + QRect(xpos, menuItem->rect.top() + + menuItem->rect.height() / 2 - dim / 2, dim, dim)); + GtkStateType state = enabled ? (act ? GTK_STATE_PRELIGHT: GTK_STATE_NORMAL) : GTK_STATE_INSENSITIVE; + GtkShadowType shadowType = (state == GTK_STATE_PRELIGHT) ? GTK_SHADOW_OUT : GTK_SHADOW_IN; + gtkPainter.paintArrow(gtkMenuItem, "menuitem", vSubMenuRect, QApplication::isRightToLeft() ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT, state, + shadowType, FALSE, style); + } + } + painter->restore(); + break; + + case CE_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + GtkWidget *gtkButton = d->gtkWidget("GtkButton"); + proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget); + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); + gint interiorFocus = true; + d->gtk_widget_style_get(gtkButton, "interior-focus", &interiorFocus, NULL); + int xt = interiorFocus ? gtkButton->style->xthickness : 0; + int yt = interiorFocus ? gtkButton->style->ythickness : 0; + + if (btn->features & QStyleOptionButton::Flat && btn->state & State_HasFocus) + // The normal button focus rect does not work well for flat buttons in Clearlooks + proxy()->drawPrimitive(PE_FrameFocusRect, option, painter, widget); + else if (btn->state & State_HasFocus) + gtkPainter.paintFocus(gtkButton, "button", + option->rect.adjusted(xt, yt, -xt, -yt), + btn->state & State_Sunken ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL, + gtkButton->style); + + proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget); + } + break; + +#ifndef QT_NO_TABBAR + + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { + GtkWidget *gtkNotebook = d->gtkWidget("GtkNotebook"); + style = gtkPainter.getStyle(gtkNotebook); + + QRect rect = option->rect; + GtkShadowType shadow = GTK_SHADOW_OUT; + GtkStateType state = GTK_STATE_ACTIVE; + if (tab->state & State_Selected) + state = GTK_STATE_NORMAL; + + bool selected = (tab->state & State_Selected); + bool first = false, last = false; + if (widget) { + // This is most accurate and avoids resizing tabs while moving + first = tab->rect.left() == widget->rect().left(); + last = tab->rect.right() == widget->rect().right(); + } else if (option->direction == Qt::RightToLeft) { + bool tmp = first; + first = last; + last = tmp; + } + int topIndent = 3; + int bottomIndent = 1; + int tabOverlap = 1; + painter->save(); + + switch (tab->shape) { + case QTabBar::RoundedNorth: + if (!selected) + rect.adjust(first ? 0 : -tabOverlap, topIndent, last ? 0 : tabOverlap, -bottomIndent); + gtkPainter.paintExtention( gtkNotebook, "tab", rect, + state, shadow, GTK_POS_BOTTOM, style); + break; + + case QTabBar::RoundedSouth: + if (!selected) + rect.adjust(first ? 0 : -tabOverlap, 0, last ? 0 : tabOverlap, -topIndent); + gtkPainter.paintExtention( gtkNotebook, "tab", rect.adjusted(0, 1, 0, 0), + state, shadow, GTK_POS_TOP, style); + break; + + case QTabBar::RoundedWest: + if (!selected) + rect.adjust(topIndent, 0, -bottomIndent, 0); + gtkPainter.paintExtention( gtkNotebook, "tab", rect, state, shadow, GTK_POS_RIGHT, style); + break; + + case QTabBar::RoundedEast: + if (!selected) + rect.adjust(bottomIndent, 0, -topIndent, 0); + gtkPainter.paintExtention( gtkNotebook, "tab", rect, state, shadow, GTK_POS_LEFT, style); + break; + + default: + QCleanlooksStyle::drawControl(element, option, painter, widget); + break; + } + + painter->restore(); + } + + break; + +#endif //QT_NO_TABBAR + + case CE_ProgressBarGroove: + if (const QStyleOptionProgressBar *bar = qstyleoption_cast(option)) { + Q_UNUSED(bar); + GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar"); + GtkStateType state = gtkPainter.gtkState(option); + gtkPainter.paintBox( gtkProgressBar, "trough", option->rect, state, GTK_SHADOW_IN, gtkProgressBar->style); + } + + break; + + case CE_ProgressBarContents: + if (const QStyleOptionProgressBar *bar = qstyleoption_cast(option)) { + GtkStateType state = option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE; + GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar"); + style = gtkProgressBar->style; + gtkPainter.paintBox( gtkProgressBar, "trough", option->rect, state, GTK_SHADOW_IN, style); + int xt = style->xthickness; + int yt = style->ythickness; + QRect rect = bar->rect.adjusted(xt, yt, -xt, -yt); + bool vertical = false; + bool inverted = false; + bool indeterminate = (bar->minimum == 0 && bar->maximum == 0); + // Get extra style options if version 2 + + if (const QStyleOptionProgressBarV2 *bar2 = qstyleoption_cast(option)) { + vertical = (bar2->orientation == Qt::Vertical); + inverted = bar2->invertedAppearance; + } + + // If the orientation is vertical, we use a transform to rotate + // the progress bar 90 degrees clockwise. This way we can use the + // same rendering code for both orientations. + if (vertical) { + rect.translate(xt, -yt * 2); + rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // Flip width and height + QTransform m = QTransform::fromTranslate(rect.height(), 0); + m.rotate(90.0); + painter->setTransform(m); + } + + int maxWidth = rect.width(); + int minWidth = 4; + + qint64 progress = (qint64)qMax(bar->progress, bar->minimum); // Workaround for bug in QProgressBar + double vc6_workaround = ((progress - qint64(bar->minimum)) / double(qint64(bar->maximum) - qint64(bar->minimum))) * maxWidth; + int progressBarWidth = (int(vc6_workaround) > minWidth ) ? int(vc6_workaround) : minWidth; + int width = indeterminate ? maxWidth : progressBarWidth; + bool reverse = (!vertical && (bar->direction == Qt::RightToLeft)) || vertical; + + if (inverted) + reverse = !reverse; + + int maximum = 2; + int fakePos = 0; + if (bar->minimum == bar->maximum) + maximum = 0; + if (bar->progress == bar->maximum) + fakePos = maximum; + else if (bar->progress > bar->minimum) + fakePos = maximum - 1; + + d->gtk_progress_configure((GtkProgress*)gtkProgressBar, fakePos, 0, maximum); + + QRect progressBar; + + if (!indeterminate) { + if (!reverse) + progressBar.setRect(rect.left(), rect.top(), width, rect.height()); + else + progressBar.setRect(rect.right() - width, rect.top(), width, rect.height()); + + } else { + Q_D(const QGtkStyle); + int slideWidth = ((rect.width() - 4) * 2) / 3; + int step = ((d->animateStep * slideWidth) / d->animationFps) % slideWidth; + if ((((d->animateStep * slideWidth) / d->animationFps) % (2 * slideWidth)) >= slideWidth) + step = slideWidth - step; + progressBar.setRect(rect.left() + step, rect.top(), slideWidth / 2, rect.height()); + } + + QString key = QString(QLS("%0")).arg(fakePos); + if (inverted) { + key += QLatin1String("inv"); + gtkPainter.setFlipHorizontal(true); + } + gtkPainter.paintBox( gtkProgressBar, "bar", progressBar, GTK_STATE_SELECTED, GTK_SHADOW_OUT, style, key); + } + + break; + + default: + QCleanlooksStyle::drawControl(element, option, painter, widget); + } +} + +/*! + \reimp +*/ +QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, + SubControl subControl, const QWidget *widget) const +{ + Q_D(const QGtkStyle); + + QRect rect = QWindowsStyle::subControlRect(control, option, subControl, widget); + if (!d->isThemeAvailable()) + return QCleanlooksStyle::subControlRect(control, option, subControl, widget); + + switch (control) { + case CC_TitleBar: + return QCleanlooksStyle::subControlRect(control, option, subControl, widget); + + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + // Reserve space for outside focus rect + QStyleOptionSlider sliderCopy = *slider; + sliderCopy.rect = option->rect.adjusted(2, 2, -2, -2); + return QCleanlooksStyle::subControlRect(control, &sliderCopy, subControl, widget); + } + + break; + +#ifndef QT_NO_GROUPBOX + + case CC_GroupBox: + if (qstyleoption_cast(option)) { + rect = option->rect.adjusted(0, groupBoxTopMargin, 0, -groupBoxBottomMargin); + int topMargin = 0; + int topHeight = 0; + topHeight = 10; + QRect frameRect = rect; + frameRect.setTop(topMargin); + + if (subControl == SC_GroupBoxFrame) + return rect; + else if (subControl == SC_GroupBoxContents) { + int margin = 0; + int leftMarginExtension = 8; + return frameRect.adjusted(leftMarginExtension + margin, margin + topHeight + groupBoxTitleMargin, -margin, -margin); + } + + if (const QGroupBox *groupBoxWidget = qobject_cast(widget)) { + //Prepare metrics for a bold font + QFont font = widget->font(); + font.setBold(true); + QFontMetrics fontMetrics(font); + QSize textRect = fontMetrics.boundingRect(groupBoxWidget->title()).size() + QSize(4, 4); + int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget); + int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget); + + if (subControl == SC_GroupBoxCheckBox) { + rect.setWidth(indicatorWidth); + rect.setHeight(indicatorHeight); + rect.moveTop((textRect.height() - indicatorHeight) / 2); + + } else if (subControl == SC_GroupBoxLabel) { + if (groupBoxWidget->isCheckable()) + rect.adjust(indicatorWidth + 4, 0, 0, 0); + rect.setSize(textRect); + } + rect = visualRect(option->direction, option->rect, rect); + } + } + + return rect; + +#endif +#ifndef QT_NO_SPINBOX + + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(option)) { + GtkWidget *gtkSpinButton = d->gtkWidget("GtkSpinButton"); + int center = spinbox->rect.height() / 2; + int xt = spinbox->frame ? gtkSpinButton->style->xthickness : 0; + int yt = spinbox->frame ? gtkSpinButton->style->ythickness : 0; + int y = yt; + + QSize bs; + bs.setHeight(qMax(8, spinbox->rect.height()/2 - y)); + bs.setWidth(d->getSpinboxArrowSize()); + int x, lx, rx; + x = spinbox->rect.width() - y - bs.width() + 2; + lx = xt; + rx = x - xt; + + switch (subControl) { + + case SC_SpinBoxUp: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + rect = QRect(x, xt, bs.width(), center - yt); + break; + + case SC_SpinBoxDown: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + rect = QRect(x, center, bs.width(), spinbox->rect.bottom() - center - yt + 1); + break; + + case SC_SpinBoxEditField: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + rect = QRect(lx, yt, spinbox->rect.width() - 2*xt, spinbox->rect.height() - 2*yt); + else + rect = QRect(lx, yt, rx - qMax(xt - 1, 0), spinbox->rect.height() - 2*yt); + break; + + case SC_SpinBoxFrame: + rect = spinbox->rect; + + default: + break; + } + + rect = visualRect(spinbox->direction, spinbox->rect, rect); + } + + break; + +#endif // Qt_NO_SPINBOX +#ifndef QT_NO_COMBOBOX + + case CC_ComboBox: + if (const QStyleOptionComboBox *box = qstyleoption_cast(option)) { + // We employ the gtk widget to position arrows and separators for us + GtkWidget *gtkCombo = box->editable ? d->gtkWidget("GtkComboBoxEntry") + : d->gtkWidget("GtkComboBox"); + d->gtk_widget_set_direction(gtkCombo, (option->direction == Qt::RightToLeft) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + GtkAllocation geometry = {0, 0, qMax(0, option->rect.width()), qMax(0, option->rect.height())}; + d->gtk_widget_size_allocate(gtkCombo, &geometry); + int appears_as_list = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, option, widget); + QHashableLatin1Literal arrowPath("GtkComboBoxEntry.GtkToggleButton"); + if (!box->editable) { + if (appears_as_list) + arrowPath = "GtkComboBox.GtkToggleButton"; + else + arrowPath = "GtkComboBox.GtkToggleButton.GtkHBox.GtkArrow"; + } + + GtkWidget *arrowWidget = d->gtkWidget(arrowPath); + if (!arrowWidget) + return QCleanlooksStyle::subControlRect(control, option, subControl, widget); + + QRect buttonRect(option->rect.left() + arrowWidget->allocation.x, + option->rect.top() + arrowWidget->allocation.y, + arrowWidget->allocation.width, arrowWidget->allocation.height); + + switch (subControl) { + + case SC_ComboBoxArrow: // Note: this indicates the arrowbutton for editable combos + rect = buttonRect; + break; + + case SC_ComboBoxEditField: { + rect = visualRect(option->direction, option->rect, rect); + int xMargin = box->editable ? 1 : 4, yMargin = 2; + rect.setRect(option->rect.left() + gtkCombo->style->xthickness + xMargin, + option->rect.top() + gtkCombo->style->ythickness + yMargin, + option->rect.width() - buttonRect.width() - 2*(gtkCombo->style->xthickness + xMargin), + option->rect.height() - 2*(gtkCombo->style->ythickness + yMargin)); + rect = visualRect(option->direction, option->rect, rect); + break; + } + + default: + break; + } + } + + break; + +#endif // QT_NO_COMBOBOX + + default: + break; + } + + return rect; +} + +/*! + \reimp +*/ +QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const +{ + Q_D(const QGtkStyle); + + QSize newSize = QCleanlooksStyle::sizeFromContents(type, option, size, widget); + if (!d->isThemeAvailable()) + return newSize; + + switch (type) { + + case CT_ToolButton: + if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast(option)) { + GtkWidget *gtkButton = d->gtkWidget("GtkToolButton.GtkButton"); + newSize = size + QSize(2 * gtkButton->style->xthickness, 2 + 2 * gtkButton->style->ythickness); + if (widget && qobject_cast(widget->parentWidget())) { + QSize minSize(0, 25); + if (toolbutton->toolButtonStyle != Qt::ToolButtonTextOnly) + minSize = toolbutton->iconSize + QSize(12, 12); + newSize = newSize.expandedTo(minSize); + } + + if (toolbutton->features & QStyleOptionToolButton::HasMenu) + newSize += QSize(6, 0); + } + break; + case CT_MenuItem: + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast(option)) { + int textMargin = 8; + + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + GtkWidget *gtkMenuSeparator = d->gtkWidget("GtkMenu.GtkSeparatorMenuItem"); + GtkRequisition sizeReq = {0, 0}; + d->gtk_widget_size_request(gtkMenuSeparator, &sizeReq); + newSize = QSize(size.width(), sizeReq.height); + break; + } + + GtkWidget *gtkMenuItem = d->gtkWidget("GtkMenu.GtkCheckMenuItem"); + GtkStyle* style = gtkMenuItem->style; + + // Note we get the perfect height for the default font since we + // set a fake text label on the gtkMenuItem + // But if custom fonts are used on the widget we need a minimum size + GtkRequisition sizeReq = {0, 0}; + d->gtk_widget_size_request(gtkMenuItem, &sizeReq); + newSize.setHeight(qMax(newSize.height() - 4, sizeReq.height)); + newSize += QSize(textMargin + style->xthickness - 1, 0); + + // Cleanlooks assumes a check column of 20 pixels so we need to + // expand it a bit + gint checkSize; + d->gtk_widget_style_get(gtkMenuItem, "indicator-size", &checkSize, NULL); + newSize.setWidth(newSize.width() + qMax(0, checkSize - 20)); + } + + break; + + case CT_SpinBox: + // QSpinBox does some nasty things that depends on CT_LineEdit + newSize = size + QSize(0, -d->gtkWidget("GtkSpinButton")->style->ythickness * 2); + break; + + case CT_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + GtkWidget *gtkButton = d->gtkWidget("GtkButton"); + gint focusPadding, focusWidth; + d->gtk_widget_style_get(gtkButton, "focus-padding", &focusPadding, NULL); + d->gtk_widget_style_get(gtkButton, "focus-line-width", &focusWidth, NULL); + newSize = size; + newSize += QSize(2*gtkButton->style->xthickness + 4, 2*gtkButton->style->ythickness); + newSize += QSize(2*(focusWidth + focusPadding + 2), 2*(focusWidth + focusPadding)); + + GtkWidget *gtkButtonBox = d->gtkWidget("GtkHButtonBox"); + gint minWidth = 85, minHeight = 0; + d->gtk_widget_style_get(gtkButtonBox, "child-min-width", &minWidth, + "child-min-height", &minHeight, NULL); + if (!btn->text.isEmpty() && newSize.width() < minWidth) + newSize.setWidth(minWidth); + if (newSize.height() < minHeight) + newSize.setHeight(minHeight); + } + + break; + + case CT_Slider: { + GtkWidget *gtkSlider = d->gtkWidget("GtkHScale"); + newSize = size + QSize(2*gtkSlider->style->xthickness, 2*gtkSlider->style->ythickness); + } + break; + + case CT_LineEdit: { + GtkWidget *gtkEntry = d->gtkWidget("GtkEntry"); + newSize = size + QSize(2*gtkEntry->style->xthickness, 2 + 2*gtkEntry->style->ythickness); + } + break; + + case CT_ItemViewItem: + newSize += QSize(0, 2); + break; + + case CT_ComboBox: + if (const QStyleOptionComboBox *combo = qstyleoption_cast(option)) { + GtkWidget *gtkCombo = d->gtkWidget("GtkComboBox"); + QRect arrowButtonRect = proxy()->subControlRect(CC_ComboBox, combo, SC_ComboBoxArrow, widget); + newSize = size + QSize(12 + arrowButtonRect.width() + 2*gtkCombo->style->xthickness, 4 + 2*gtkCombo->style->ythickness); + + if (!(widget && qobject_cast(widget->parentWidget()))) + newSize += QSize(0, 2); + } + break; + + case CT_GroupBox: + newSize += QSize(4, groupBoxBottomMargin + groupBoxTopMargin + groupBoxTitleMargin); // Add some space below the groupbox + break; + + case CT_TabBarTab: + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { + if (!tab->icon.isNull()) + newSize += QSize(6, 0); + } + newSize += QSize(1, 1); + break; + + default: + break; + } + + return newSize; +} + + +/*! \reimp */ +QPixmap QGtkStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, + const QWidget *widget) const +{ + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) + return QCleanlooksStyle::standardPixmap(sp, option, widget); + + QPixmap pixmap; + switch (sp) { + + case SP_TitleBarNormalButton: { + QImage restoreButton((const char **)dock_widget_restore_xpm); + QColor alphaCorner = restoreButton.color(2); + alphaCorner.setAlpha(80); + restoreButton.setColor(2, alphaCorner.rgba()); + alphaCorner.setAlpha(180); + restoreButton.setColor(4, alphaCorner.rgba()); + return QPixmap::fromImage(restoreButton); + } + break; + + case SP_TitleBarCloseButton: // Fall through + case SP_DockWidgetCloseButton: { + + QImage closeButton((const char **)dock_widget_close_xpm); + QColor alphaCorner = closeButton.color(2); + alphaCorner.setAlpha(80); + closeButton.setColor(2, alphaCorner.rgba()); + return QPixmap::fromImage(closeButton); + } + break; + + case SP_DialogDiscardButton: + return QGtkPainter::getIcon(GTK_STOCK_DELETE); + case SP_DialogOkButton: + return QGtkPainter::getIcon(GTK_STOCK_OK); + case SP_DialogCancelButton: + return QGtkPainter::getIcon(GTK_STOCK_CANCEL); + case SP_DialogYesButton: + return QGtkPainter::getIcon(GTK_STOCK_YES); + case SP_DialogNoButton: + return QGtkPainter::getIcon(GTK_STOCK_NO); + case SP_DialogOpenButton: + return QGtkPainter::getIcon(GTK_STOCK_OPEN); + case SP_DialogCloseButton: + return QGtkPainter::getIcon(GTK_STOCK_CLOSE); + case SP_DialogApplyButton: + return QGtkPainter::getIcon(GTK_STOCK_APPLY); + case SP_DialogSaveButton: + return QGtkPainter::getIcon(GTK_STOCK_SAVE); + case SP_MessageBoxWarning: + return QGtkPainter::getIcon(GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); + case SP_MessageBoxQuestion: + return QGtkPainter::getIcon(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); + case SP_MessageBoxInformation: + return QGtkPainter::getIcon(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); + case SP_MessageBoxCritical: + return QGtkPainter::getIcon(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG); + default: + return QCleanlooksStyle::standardPixmap(sp, option, widget); + } + return pixmap; +} + +/*! + \internal +*/ +QIcon QGtkStyle::standardIconImplementation(StandardPixmap standardIcon, + const QStyleOption *option, + const QWidget *widget) const +{ + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) + return QCleanlooksStyle::standardIconImplementation(standardIcon, option, widget); + switch (standardIcon) { + case SP_DialogDiscardButton: + return QGtkPainter::getIcon(GTK_STOCK_DELETE); + case SP_DialogOkButton: + return QGtkPainter::getIcon(GTK_STOCK_OK); + case SP_DialogCancelButton: + return QGtkPainter::getIcon(GTK_STOCK_CANCEL); + case SP_DialogYesButton: + return QGtkPainter::getIcon(GTK_STOCK_YES); + case SP_DialogNoButton: + return QGtkPainter::getIcon(GTK_STOCK_NO); + case SP_DialogOpenButton: + return QGtkPainter::getIcon(GTK_STOCK_OPEN); + case SP_DialogCloseButton: + return QGtkPainter::getIcon(GTK_STOCK_CLOSE); + case SP_DialogApplyButton: + return QGtkPainter::getIcon(GTK_STOCK_APPLY); + case SP_DialogSaveButton: + return QGtkPainter::getIcon(GTK_STOCK_SAVE); + case SP_MessageBoxWarning: + return QGtkPainter::getIcon(GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); + case SP_MessageBoxQuestion: + return QGtkPainter::getIcon(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); + case SP_MessageBoxInformation: + return QGtkPainter::getIcon(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); + case SP_MessageBoxCritical: + return QGtkPainter::getIcon(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG); + default: + return QCleanlooksStyle::standardIconImplementation(standardIcon, option, widget); + } +} + + +/*! \reimp */ +QRect QGtkStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const +{ + Q_D(const QGtkStyle); + + QRect r = QCleanlooksStyle::subElementRect(element, option, widget); + if (!d->isThemeAvailable()) + return r; + + switch (element) { + case SE_ProgressBarLabel: + case SE_ProgressBarContents: + case SE_ProgressBarGroove: + return option->rect; + case SE_PushButtonContents: + if (!d->gtk_check_version(2, 10, 0)) { + GtkWidget *gtkButton = d->gtkWidget("GtkButton"); + GtkBorder *border = 0; + d->gtk_widget_style_get(gtkButton, "inner-border", &border, NULL); + if (border) { + r = option->rect.adjusted(border->left, border->top, -border->right, -border->bottom); + d->gtk_border_free(border); + } else { + r = option->rect.adjusted(1, 1, -1, -1); + } + r = visualRect(option->direction, option->rect, r); + } + break; + default: + break; + } + + return r; +} + +/*! + \reimp +*/ +QRect QGtkStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const +{ + return QCleanlooksStyle::itemPixmapRect(r, flags, pixmap); +} + +/*! + \reimp +*/ +void QGtkStyle::drawItemPixmap(QPainter *painter, const QRect &rect, + int alignment, const QPixmap &pixmap) const +{ + QCleanlooksStyle::drawItemPixmap(painter, rect, alignment, pixmap); +} + +/*! + \reimp +*/ +QStyle::SubControl QGtkStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *w) const +{ + return QCleanlooksStyle::hitTestComplexControl(cc, opt, pt, w); +} + +/*! + \reimp +*/ +QPixmap QGtkStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *opt) const +{ + return QCleanlooksStyle::generatedIconPixmap(iconMode, pixmap, opt); +} + +/*! + \reimp +*/ +void QGtkStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal, + bool enabled, const QString& text, QPalette::ColorRole textRole) const +{ + return QCleanlooksStyle::drawItemText(painter, rect, alignment, pal, enabled, text, textRole); +} + +QT_END_NAMESPACE + +#endif //!defined(QT_NO_STYLE_QGTK) diff --git a/src/widgets/styles/qgtkstyle.h b/src/widgets/styles/qgtkstyle.h new file mode 100644 index 0000000000..616ce24509 --- /dev/null +++ b/src/widgets/styles/qgtkstyle.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGTKSTYLE_H +#define QGTKSTYLE_H + +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_STYLE_GTK) + +class QPainterPath; +class QGtkStylePrivate; + +class Q_GUI_EXPORT QGtkStyle : public QCleanlooksStyle +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGtkStyle) + +public: + QGtkStyle(); + QGtkStyle(QGtkStylePrivate &dd); + + ~QGtkStyle(); + + QPalette standardPalette() const; + + void drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const; + void drawControl(ControlElement control, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const; + void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const; + void drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, + const QPixmap &pixmap) const; + void drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal, + bool enabled, const QString& text, QPalette::ColorRole textRole) const; + + int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, + const QWidget *widget = 0) const; + int styleHint(StyleHint hint, const QStyleOption *option, + const QWidget *widget, QStyleHintReturn *returnData) const; + + QStyle::SubControl hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *w) const; + + QRect subControlRect(ComplexControl control, const QStyleOptionComplex *option, + SubControl subControl, const QWidget *widget) const; + QRect subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *w) const; + QRect itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const; + + + QSize sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const; + QPixmap standardPixmap(StandardPixmap sp, const QStyleOption *option, + const QWidget *widget) const; + QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *opt) const; + + void polish(QWidget *widget); + void polish(QApplication *app); + void polish(QPalette &palette); + + void unpolish(QWidget *widget); + void unpolish(QApplication *app); + + static bool getGConfBool(const QString &key, bool fallback = 0); + static QString getGConfString(const QString &key, const QString &fallback = QString()); + + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget = 0) const; +}; + +#endif //!defined(QT_NO_STYLE_QGTK) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif //QGTKSTYLE_H diff --git a/src/widgets/styles/qgtkstyle_p.cpp b/src/widgets/styles/qgtkstyle_p.cpp new file mode 100644 index 0000000000..d7c53c9a91 --- /dev/null +++ b/src/widgets/styles/qgtkstyle_p.cpp @@ -0,0 +1,1146 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgtkstyle_p.h" + +// This file is responsible for resolving all GTK functions we use +// dynamically. This is done to avoid link-time dependancy on GTK +// as well as crashes occurring due to usage of the GTK_QT engines +// +// Additionally we create a map of common GTK widgets that we can pass +// to the GTK theme engine as many engines resort to querying the +// actual widget pointers for details that are not covered by the +// state flags + +#include +#if !defined(QT_NO_STYLE_GTK) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +static bool displayDepth = -1; +Q_GLOBAL_STATIC(QGtkStyleUpdateScheduler, styleScheduler) + +Ptr_gtk_container_forall QGtkStylePrivate::gtk_container_forall = 0; +Ptr_gtk_init QGtkStylePrivate::gtk_init = 0; +Ptr_gtk_style_attach QGtkStylePrivate::gtk_style_attach = 0; +Ptr_gtk_window_new QGtkStylePrivate::gtk_window_new = 0; +Ptr_gtk_widget_destroy QGtkStylePrivate::gtk_widget_destroy = 0; +Ptr_gtk_widget_realize QGtkStylePrivate::gtk_widget_realize = 0; +Ptr_gtk_widget_set_default_direction QGtkStylePrivate::gtk_widget_set_default_direction = 0; +Ptr_gtk_widget_modify_color QGtkStylePrivate::gtk_widget_modify_fg = 0; +Ptr_gtk_widget_modify_color QGtkStylePrivate::gtk_widget_modify_bg = 0; +Ptr_gtk_arrow_new QGtkStylePrivate::gtk_arrow_new = 0; +Ptr_gtk_menu_item_new_with_label QGtkStylePrivate::gtk_menu_item_new_with_label = 0; +Ptr_gtk_check_menu_item_new_with_label QGtkStylePrivate::gtk_check_menu_item_new_with_label = 0; +Ptr_gtk_menu_bar_new QGtkStylePrivate::gtk_menu_bar_new = 0; +Ptr_gtk_menu_new QGtkStylePrivate::gtk_menu_new = 0; +Ptr_gtk_button_new QGtkStylePrivate::gtk_button_new = 0; +Ptr_gtk_tool_button_new QGtkStylePrivate::gtk_tool_button_new = 0; +Ptr_gtk_hbutton_box_new QGtkStylePrivate::gtk_hbutton_box_new = 0; +Ptr_gtk_check_button_new QGtkStylePrivate::gtk_check_button_new = 0; +Ptr_gtk_radio_button_new QGtkStylePrivate::gtk_radio_button_new = 0; +Ptr_gtk_spin_button_new QGtkStylePrivate::gtk_spin_button_new = 0; +Ptr_gtk_frame_new QGtkStylePrivate::gtk_frame_new = 0; +Ptr_gtk_expander_new QGtkStylePrivate::gtk_expander_new = 0; +Ptr_gtk_statusbar_new QGtkStylePrivate::gtk_statusbar_new = 0; +Ptr_gtk_entry_new QGtkStylePrivate::gtk_entry_new = 0; +Ptr_gtk_hscale_new QGtkStylePrivate::gtk_hscale_new = 0; +Ptr_gtk_vscale_new QGtkStylePrivate::gtk_vscale_new = 0; +Ptr_gtk_hscrollbar_new QGtkStylePrivate::gtk_hscrollbar_new = 0; +Ptr_gtk_vscrollbar_new QGtkStylePrivate::gtk_vscrollbar_new = 0; +Ptr_gtk_scrolled_window_new QGtkStylePrivate::gtk_scrolled_window_new = 0; +Ptr_gtk_notebook_new QGtkStylePrivate::gtk_notebook_new = 0; +Ptr_gtk_toolbar_new QGtkStylePrivate::gtk_toolbar_new = 0; +Ptr_gtk_toolbar_insert QGtkStylePrivate::gtk_toolbar_insert = 0; +Ptr_gtk_separator_tool_item_new QGtkStylePrivate::gtk_separator_tool_item_new = 0; +Ptr_gtk_tree_view_new QGtkStylePrivate::gtk_tree_view_new = 0; +Ptr_gtk_combo_box_new QGtkStylePrivate::gtk_combo_box_new = 0; +Ptr_gtk_combo_box_entry_new QGtkStylePrivate::gtk_combo_box_entry_new = 0; +Ptr_gtk_progress_bar_new QGtkStylePrivate::gtk_progress_bar_new = 0; +Ptr_gtk_container_add QGtkStylePrivate::gtk_container_add = 0; +Ptr_gtk_menu_shell_append QGtkStylePrivate::gtk_menu_shell_append = 0; +Ptr_gtk_progress_configure QGtkStylePrivate::gtk_progress_configure = 0; +Ptr_gtk_range_get_adjustment QGtkStylePrivate::gtk_range_get_adjustment = 0; +Ptr_gtk_range_set_adjustment QGtkStylePrivate::gtk_range_set_adjustment = 0; +Ptr_gtk_range_set_inverted QGtkStylePrivate::gtk_range_set_inverted = 0; +Ptr_gtk_icon_factory_lookup_default QGtkStylePrivate::gtk_icon_factory_lookup_default = 0; +Ptr_gtk_icon_theme_get_default QGtkStylePrivate::gtk_icon_theme_get_default = 0; +Ptr_gtk_widget_style_get QGtkStylePrivate::gtk_widget_style_get = 0; +Ptr_gtk_icon_set_render_icon QGtkStylePrivate::gtk_icon_set_render_icon = 0; +Ptr_gtk_fixed_new QGtkStylePrivate::gtk_fixed_new = 0; +Ptr_gtk_tree_view_column_new QGtkStylePrivate::gtk_tree_view_column_new = 0; +Ptr_gtk_tree_view_get_column QGtkStylePrivate::gtk_tree_view_get_column = 0; +Ptr_gtk_tree_view_append_column QGtkStylePrivate::gtk_tree_view_append_column = 0; +Ptr_gtk_paint_check QGtkStylePrivate::gtk_paint_check = 0; +Ptr_gtk_paint_box QGtkStylePrivate::gtk_paint_box = 0; +Ptr_gtk_paint_box_gap QGtkStylePrivate::gtk_paint_box_gap = 0; +Ptr_gtk_paint_flat_box QGtkStylePrivate::gtk_paint_flat_box = 0; +Ptr_gtk_paint_option QGtkStylePrivate::gtk_paint_option = 0; +Ptr_gtk_paint_extension QGtkStylePrivate::gtk_paint_extension = 0; +Ptr_gtk_paint_slider QGtkStylePrivate::gtk_paint_slider = 0; +Ptr_gtk_paint_shadow QGtkStylePrivate::gtk_paint_shadow = 0; +Ptr_gtk_paint_resize_grip QGtkStylePrivate::gtk_paint_resize_grip = 0; +Ptr_gtk_paint_focus QGtkStylePrivate::gtk_paint_focus = 0; +Ptr_gtk_paint_arrow QGtkStylePrivate::gtk_paint_arrow = 0; +Ptr_gtk_paint_handle QGtkStylePrivate::gtk_paint_handle = 0; +Ptr_gtk_paint_expander QGtkStylePrivate::gtk_paint_expander = 0; +Ptr_gtk_adjustment_configure QGtkStylePrivate::gtk_adjustment_configure = 0; +Ptr_gtk_adjustment_new QGtkStylePrivate::gtk_adjustment_new = 0; +Ptr_gtk_paint_hline QGtkStylePrivate::gtk_paint_hline = 0; +Ptr_gtk_paint_vline QGtkStylePrivate::gtk_paint_vline = 0; +Ptr_gtk_menu_item_set_submenu QGtkStylePrivate::gtk_menu_item_set_submenu = 0; +Ptr_gtk_settings_get_default QGtkStylePrivate::gtk_settings_get_default = 0; +Ptr_gtk_separator_menu_item_new QGtkStylePrivate::gtk_separator_menu_item_new = 0; +Ptr_gtk_widget_size_allocate QGtkStylePrivate::gtk_widget_size_allocate = 0; +Ptr_gtk_widget_size_request QGtkStylePrivate::gtk_widget_size_request = 0; +Ptr_gtk_widget_set_direction QGtkStylePrivate::gtk_widget_set_direction = 0; +Ptr_gtk_widget_path QGtkStylePrivate::gtk_widget_path = 0; +Ptr_gtk_container_get_type QGtkStylePrivate::gtk_container_get_type = 0; +Ptr_gtk_window_get_type QGtkStylePrivate::gtk_window_get_type = 0; +Ptr_gtk_widget_get_type QGtkStylePrivate::gtk_widget_get_type = 0; +Ptr_gtk_rc_get_style_by_paths QGtkStylePrivate::gtk_rc_get_style_by_paths = 0; +Ptr_gtk_check_version QGtkStylePrivate::gtk_check_version = 0; +Ptr_gtk_border_free QGtkStylePrivate::gtk_border_free = 0; +Ptr_pango_font_description_get_size QGtkStylePrivate::pango_font_description_get_size = 0; +Ptr_pango_font_description_get_weight QGtkStylePrivate::pango_font_description_get_weight = 0; +Ptr_pango_font_description_get_family QGtkStylePrivate::pango_font_description_get_family = 0; +Ptr_pango_font_description_get_style QGtkStylePrivate::pango_font_description_get_style = 0; + +Ptr_gtk_file_filter_new QGtkStylePrivate::gtk_file_filter_new = 0; +Ptr_gtk_file_filter_set_name QGtkStylePrivate::gtk_file_filter_set_name = 0; +Ptr_gtk_file_filter_add_pattern QGtkStylePrivate::gtk_file_filter_add_pattern = 0; +Ptr_gtk_file_chooser_add_filter QGtkStylePrivate::gtk_file_chooser_add_filter = 0; +Ptr_gtk_file_chooser_set_filter QGtkStylePrivate::gtk_file_chooser_set_filter = 0; +Ptr_gtk_file_chooser_get_filter QGtkStylePrivate::gtk_file_chooser_get_filter = 0; +Ptr_gtk_file_chooser_dialog_new QGtkStylePrivate::gtk_file_chooser_dialog_new = 0; +Ptr_gtk_file_chooser_set_current_folder QGtkStylePrivate::gtk_file_chooser_set_current_folder = 0; +Ptr_gtk_file_chooser_get_filename QGtkStylePrivate::gtk_file_chooser_get_filename = 0; +Ptr_gtk_file_chooser_get_filenames QGtkStylePrivate::gtk_file_chooser_get_filenames = 0; +Ptr_gtk_file_chooser_set_current_name QGtkStylePrivate::gtk_file_chooser_set_current_name = 0; +Ptr_gtk_dialog_run QGtkStylePrivate::gtk_dialog_run = 0; +Ptr_gtk_file_chooser_set_filename QGtkStylePrivate::gtk_file_chooser_set_filename = 0; + +Ptr_gdk_pixbuf_get_pixels QGtkStylePrivate::gdk_pixbuf_get_pixels = 0; +Ptr_gdk_pixbuf_get_width QGtkStylePrivate::gdk_pixbuf_get_width = 0; +Ptr_gdk_pixbuf_get_height QGtkStylePrivate::gdk_pixbuf_get_height = 0; +Ptr_gdk_pixmap_new QGtkStylePrivate::gdk_pixmap_new = 0; +Ptr_gdk_pixbuf_new QGtkStylePrivate::gdk_pixbuf_new = 0; +Ptr_gdk_pixbuf_get_from_drawable QGtkStylePrivate::gdk_pixbuf_get_from_drawable = 0; +Ptr_gdk_draw_rectangle QGtkStylePrivate::gdk_draw_rectangle = 0; +Ptr_gdk_pixbuf_unref QGtkStylePrivate::gdk_pixbuf_unref = 0; +Ptr_gdk_drawable_unref QGtkStylePrivate::gdk_drawable_unref = 0; +Ptr_gdk_drawable_get_depth QGtkStylePrivate::gdk_drawable_get_depth = 0; +Ptr_gdk_color_free QGtkStylePrivate::gdk_color_free = 0; +Ptr_gdk_x11_window_set_user_time QGtkStylePrivate::gdk_x11_window_set_user_time = 0; +Ptr_gdk_x11_drawable_get_xid QGtkStylePrivate::gdk_x11_drawable_get_xid = 0; +Ptr_gdk_x11_drawable_get_xdisplay QGtkStylePrivate::gdk_x11_drawable_get_xdisplay = 0; + +Ptr_gconf_client_get_default QGtkStylePrivate::gconf_client_get_default = 0; +Ptr_gconf_client_get_string QGtkStylePrivate::gconf_client_get_string = 0; +Ptr_gconf_client_get_bool QGtkStylePrivate::gconf_client_get_bool = 0; + +Ptr_gnome_icon_lookup_sync QGtkStylePrivate::gnome_icon_lookup_sync = 0; +Ptr_gnome_vfs_init QGtkStylePrivate::gnome_vfs_init = 0; + +typedef int (*x11ErrorHandler)(Display*, XErrorEvent*); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGtkStylePrivate*); + +QT_BEGIN_NAMESPACE + +static void gtkStyleSetCallback(GtkWidget*) +{ + qRegisterMetaType(); + + // We have to let this function return and complete the event + // loop to ensure that all gtk widgets have been styled before + // updating + QMetaObject::invokeMethod(styleScheduler(), "updateTheme", Qt::QueuedConnection); +} + +static void update_toolbar_style(GtkWidget *gtkToolBar, GParamSpec *, gpointer) +{ + GtkToolbarStyle toolbar_style = GTK_TOOLBAR_ICONS; + g_object_get(gtkToolBar, "toolbar-style", &toolbar_style, NULL); + QWidgetList widgets = QApplication::allWidgets(); + for (int i = 0; i < widgets.size(); ++i) { + QWidget *widget = widgets.at(i); + if (qobject_cast(widget)) { + QEvent event(QEvent::StyleChange); + QApplication::sendEvent(widget, &event); + } + } +} + +static QHashableLatin1Literal classPath(GtkWidget *widget) +{ + char *class_path; + QGtkStylePrivate::gtk_widget_path (widget, NULL, &class_path, NULL); + + char *copy = class_path; + if (strncmp(copy, "GtkWindow.", 10) == 0) + copy += 10; + if (strncmp(copy, "GtkFixed.", 9) == 0) + copy += 9; + + copy = strdup(copy); + + g_free(class_path); + + return QHashableLatin1Literal::fromData(copy); +} + + + +bool QGtkStyleFilter::eventFilter(QObject *obj, QEvent *e) +{ + if (e->type() == QEvent::ApplicationPaletteChange) { + // Only do this the first time since this will also + // generate applicationPaletteChange events + if (!qt_app_palettes_hash() || qt_app_palettes_hash()->isEmpty()) { + stylePrivate->applyCustomPaletteHash(); + } + } + return QObject::eventFilter(obj, e); +} + +QList QGtkStylePrivate::instances; +QGtkStylePrivate::WidgetMap *QGtkStylePrivate::widgetMap = 0; + +QGtkStylePrivate::QGtkStylePrivate() + : QCleanlooksStylePrivate() + , filter(this) +{ + instances.append(this); +} + +QGtkStylePrivate::~QGtkStylePrivate() +{ + instances.removeOne(this); +} + +void QGtkStylePrivate::init() +{ + resolveGtk(); + initGtkWidgets(); +} + +GtkWidget* QGtkStylePrivate::gtkWidget(const QHashableLatin1Literal &path) +{ + GtkWidget *widget = gtkWidgetMap()->value(path); + if (!widget) { + // Theme might have rearranged widget internals + widget = gtkWidgetMap()->value(path); + } + return widget; +} + +GtkStyle* QGtkStylePrivate::gtkStyle(const QHashableLatin1Literal &path) +{ + if (GtkWidget *w = gtkWidgetMap()->value(path)) + return w->style; + return 0; +} + +/*! \internal + * Get references to gtk functions after we dynamically load the library. + */ +void QGtkStylePrivate::resolveGtk() const +{ + // enforce the "0" suffix, so we'll open libgtk-x11-2.0.so.0 + QLibrary libgtk(QLS("gtk-x11-2.0"), 0, 0); + + gtk_init = (Ptr_gtk_init)libgtk.resolve("gtk_init"); + gtk_window_new = (Ptr_gtk_window_new)libgtk.resolve("gtk_window_new"); + gtk_style_attach = (Ptr_gtk_style_attach)libgtk.resolve("gtk_style_attach"); + gtk_widget_destroy = (Ptr_gtk_widget_destroy)libgtk.resolve("gtk_widget_destroy"); + gtk_widget_realize = (Ptr_gtk_widget_realize)libgtk.resolve("gtk_widget_realize"); + + gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)libgtk.resolve("gtk_file_chooser_set_current_folder"); + gtk_file_filter_new = (Ptr_gtk_file_filter_new)libgtk.resolve("gtk_file_filter_new"); + gtk_file_filter_set_name = (Ptr_gtk_file_filter_set_name)libgtk.resolve("gtk_file_filter_set_name"); + gtk_file_filter_add_pattern = (Ptr_gtk_file_filter_add_pattern)libgtk.resolve("gtk_file_filter_add_pattern"); + gtk_file_chooser_add_filter = (Ptr_gtk_file_chooser_add_filter)libgtk.resolve("gtk_file_chooser_add_filter"); + gtk_file_chooser_set_filter = (Ptr_gtk_file_chooser_set_filter)libgtk.resolve("gtk_file_chooser_set_filter"); + gtk_file_chooser_get_filter = (Ptr_gtk_file_chooser_get_filter)libgtk.resolve("gtk_file_chooser_get_filter"); + gtk_file_chooser_dialog_new = (Ptr_gtk_file_chooser_dialog_new)libgtk.resolve("gtk_file_chooser_dialog_new"); + gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)libgtk.resolve("gtk_file_chooser_set_current_folder"); + gtk_file_chooser_get_filename = (Ptr_gtk_file_chooser_get_filename)libgtk.resolve("gtk_file_chooser_get_filename"); + gtk_file_chooser_get_filenames = (Ptr_gtk_file_chooser_get_filenames)libgtk.resolve("gtk_file_chooser_get_filenames"); + gtk_file_chooser_set_current_name = (Ptr_gtk_file_chooser_set_current_name)libgtk.resolve("gtk_file_chooser_set_current_name"); + gtk_dialog_run = (Ptr_gtk_dialog_run)libgtk.resolve("gtk_dialog_run"); + gtk_file_chooser_set_filename = (Ptr_gtk_file_chooser_set_filename)libgtk.resolve("gtk_file_chooser_set_filename"); + + gdk_pixbuf_get_pixels = (Ptr_gdk_pixbuf_get_pixels)libgtk.resolve("gdk_pixbuf_get_pixels"); + gdk_pixbuf_get_width = (Ptr_gdk_pixbuf_get_width)libgtk.resolve("gdk_pixbuf_get_width"); + gdk_pixbuf_get_height = (Ptr_gdk_pixbuf_get_height)libgtk.resolve("gdk_pixbuf_get_height"); + gdk_pixmap_new = (Ptr_gdk_pixmap_new)libgtk.resolve("gdk_pixmap_new"); + gdk_pixbuf_new = (Ptr_gdk_pixbuf_new)libgtk.resolve("gdk_pixbuf_new"); + gdk_pixbuf_get_from_drawable = (Ptr_gdk_pixbuf_get_from_drawable)libgtk.resolve("gdk_pixbuf_get_from_drawable"); + gdk_draw_rectangle = (Ptr_gdk_draw_rectangle)libgtk.resolve("gdk_draw_rectangle"); + gdk_pixbuf_unref = (Ptr_gdk_pixbuf_unref)libgtk.resolve("gdk_pixbuf_unref"); + gdk_drawable_unref = (Ptr_gdk_drawable_unref)libgtk.resolve("gdk_drawable_unref"); + gdk_drawable_get_depth = (Ptr_gdk_drawable_get_depth)libgtk.resolve("gdk_drawable_get_depth"); + gdk_color_free = (Ptr_gdk_color_free)libgtk.resolve("gdk_color_free"); + gdk_x11_window_set_user_time = (Ptr_gdk_x11_window_set_user_time)libgtk.resolve("gdk_x11_window_set_user_time"); + gdk_x11_drawable_get_xid = (Ptr_gdk_x11_drawable_get_xid)libgtk.resolve("gdk_x11_drawable_get_xid"); + gdk_x11_drawable_get_xdisplay = (Ptr_gdk_x11_drawable_get_xdisplay)libgtk.resolve("gdk_x11_drawable_get_xdisplay"); + + gtk_widget_set_default_direction = (Ptr_gtk_widget_set_default_direction)libgtk.resolve("gtk_widget_set_default_direction"); + gtk_widget_modify_fg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_fg"); + gtk_widget_modify_bg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_bg"); + gtk_arrow_new = (Ptr_gtk_arrow_new)libgtk.resolve("gtk_arrow_new"); + gtk_menu_item_new_with_label = (Ptr_gtk_menu_item_new_with_label)libgtk.resolve("gtk_menu_item_new_with_label"); + gtk_check_menu_item_new_with_label = (Ptr_gtk_check_menu_item_new_with_label)libgtk.resolve("gtk_check_menu_item_new_with_label"); + gtk_menu_bar_new = (Ptr_gtk_menu_bar_new)libgtk.resolve("gtk_menu_bar_new"); + gtk_menu_new = (Ptr_gtk_menu_new)libgtk.resolve("gtk_menu_new"); + gtk_toolbar_new = (Ptr_gtk_toolbar_new)libgtk.resolve("gtk_toolbar_new"); + gtk_separator_tool_item_new = (Ptr_gtk_separator_tool_item_new)libgtk.resolve("gtk_separator_tool_item_new"); + gtk_toolbar_insert = (Ptr_gtk_toolbar_insert)libgtk.resolve("gtk_toolbar_insert"); + gtk_button_new = (Ptr_gtk_button_new)libgtk.resolve("gtk_button_new"); + gtk_tool_button_new = (Ptr_gtk_tool_button_new)libgtk.resolve("gtk_tool_button_new"); + gtk_hbutton_box_new = (Ptr_gtk_hbutton_box_new)libgtk.resolve("gtk_hbutton_box_new"); + gtk_check_button_new = (Ptr_gtk_check_button_new)libgtk.resolve("gtk_check_button_new"); + gtk_radio_button_new = (Ptr_gtk_radio_button_new)libgtk.resolve("gtk_radio_button_new"); + gtk_notebook_new = (Ptr_gtk_notebook_new)libgtk.resolve("gtk_notebook_new"); + gtk_progress_bar_new = (Ptr_gtk_progress_bar_new)libgtk.resolve("gtk_progress_bar_new"); + gtk_spin_button_new = (Ptr_gtk_spin_button_new)libgtk.resolve("gtk_spin_button_new"); + gtk_hscale_new = (Ptr_gtk_hscale_new)libgtk.resolve("gtk_hscale_new"); + gtk_vscale_new = (Ptr_gtk_vscale_new)libgtk.resolve("gtk_vscale_new"); + gtk_hscrollbar_new = (Ptr_gtk_hscrollbar_new)libgtk.resolve("gtk_hscrollbar_new"); + gtk_vscrollbar_new = (Ptr_gtk_vscrollbar_new)libgtk.resolve("gtk_vscrollbar_new"); + gtk_scrolled_window_new = (Ptr_gtk_scrolled_window_new)libgtk.resolve("gtk_scrolled_window_new"); + gtk_menu_shell_append = (Ptr_gtk_menu_shell_append)libgtk.resolve("gtk_menu_shell_append"); + gtk_entry_new = (Ptr_gtk_entry_new)libgtk.resolve("gtk_entry_new"); + gtk_tree_view_new = (Ptr_gtk_tree_view_new)libgtk.resolve("gtk_tree_view_new"); + gtk_combo_box_new = (Ptr_gtk_combo_box_new)libgtk.resolve("gtk_combo_box_new"); + gtk_progress_configure = (Ptr_gtk_progress_configure)libgtk.resolve("gtk_progress_configure"); + gtk_range_get_adjustment = (Ptr_gtk_range_get_adjustment)libgtk.resolve("gtk_range_get_adjustment"); + gtk_range_set_adjustment = (Ptr_gtk_range_set_adjustment)libgtk.resolve("gtk_range_set_adjustment"); + gtk_range_set_inverted = (Ptr_gtk_range_set_inverted)libgtk.resolve("gtk_range_set_inverted"); + gtk_container_add = (Ptr_gtk_container_add)libgtk.resolve("gtk_container_add"); + gtk_icon_factory_lookup_default = (Ptr_gtk_icon_factory_lookup_default)libgtk.resolve("gtk_icon_factory_lookup_default"); + gtk_icon_theme_get_default = (Ptr_gtk_icon_theme_get_default)libgtk.resolve("gtk_icon_theme_get_default"); + gtk_widget_style_get = (Ptr_gtk_widget_style_get)libgtk.resolve("gtk_widget_style_get"); + gtk_icon_set_render_icon = (Ptr_gtk_icon_set_render_icon)libgtk.resolve("gtk_icon_set_render_icon"); + gtk_fixed_new = (Ptr_gtk_fixed_new)libgtk.resolve("gtk_fixed_new"); + gtk_tree_view_column_new = (Ptr_gtk_tree_view_column_new)libgtk.resolve("gtk_tree_view_column_new"); + gtk_tree_view_append_column= (Ptr_gtk_tree_view_append_column )libgtk.resolve("gtk_tree_view_append_column"); + gtk_tree_view_get_column = (Ptr_gtk_tree_view_get_column )libgtk.resolve("gtk_tree_view_get_column"); + gtk_paint_check = (Ptr_gtk_paint_check)libgtk.resolve("gtk_paint_check"); + gtk_paint_box = (Ptr_gtk_paint_box)libgtk.resolve("gtk_paint_box"); + gtk_paint_flat_box = (Ptr_gtk_paint_flat_box)libgtk.resolve("gtk_paint_flat_box"); + gtk_paint_check = (Ptr_gtk_paint_check)libgtk.resolve("gtk_paint_check"); + gtk_paint_box = (Ptr_gtk_paint_box)libgtk.resolve("gtk_paint_box"); + gtk_paint_resize_grip = (Ptr_gtk_paint_resize_grip)libgtk.resolve("gtk_paint_resize_grip"); + gtk_paint_focus = (Ptr_gtk_paint_focus)libgtk.resolve("gtk_paint_focus"); + gtk_paint_shadow = (Ptr_gtk_paint_shadow)libgtk.resolve("gtk_paint_shadow"); + gtk_paint_slider = (Ptr_gtk_paint_slider)libgtk.resolve("gtk_paint_slider"); + gtk_paint_expander = (Ptr_gtk_paint_expander)libgtk.resolve("gtk_paint_expander"); + gtk_paint_handle = (Ptr_gtk_paint_handle)libgtk.resolve("gtk_paint_handle"); + gtk_paint_option = (Ptr_gtk_paint_option)libgtk.resolve("gtk_paint_option"); + gtk_paint_arrow = (Ptr_gtk_paint_arrow)libgtk.resolve("gtk_paint_arrow"); + gtk_paint_box_gap = (Ptr_gtk_paint_box_gap)libgtk.resolve("gtk_paint_box_gap"); + gtk_paint_extension = (Ptr_gtk_paint_extension)libgtk.resolve("gtk_paint_extension"); + gtk_paint_hline = (Ptr_gtk_paint_hline)libgtk.resolve("gtk_paint_hline"); + gtk_paint_vline = (Ptr_gtk_paint_vline)libgtk.resolve("gtk_paint_vline"); + gtk_adjustment_configure = (Ptr_gtk_adjustment_configure)libgtk.resolve("gtk_adjustment_configure"); + gtk_adjustment_new = (Ptr_gtk_adjustment_new)libgtk.resolve("gtk_adjustment_new"); + gtk_menu_item_set_submenu = (Ptr_gtk_menu_item_set_submenu)libgtk.resolve("gtk_menu_item_set_submenu"); + gtk_settings_get_default = (Ptr_gtk_settings_get_default)libgtk.resolve("gtk_settings_get_default"); + gtk_separator_menu_item_new = (Ptr_gtk_separator_menu_item_new)libgtk.resolve("gtk_separator_menu_item_new"); + gtk_frame_new = (Ptr_gtk_frame_new)libgtk.resolve("gtk_frame_new"); + gtk_expander_new = (Ptr_gtk_expander_new)libgtk.resolve("gtk_expander_new"); + gtk_statusbar_new = (Ptr_gtk_statusbar_new)libgtk.resolve("gtk_statusbar_new"); + gtk_combo_box_entry_new = (Ptr_gtk_combo_box_entry_new)libgtk.resolve("gtk_combo_box_entry_new"); + gtk_container_forall = (Ptr_gtk_container_forall)libgtk.resolve("gtk_container_forall"); + gtk_widget_size_allocate =(Ptr_gtk_widget_size_allocate)libgtk.resolve("gtk_widget_size_allocate"); + gtk_widget_size_request =(Ptr_gtk_widget_size_request)libgtk.resolve("gtk_widget_size_request"); + gtk_widget_set_direction =(Ptr_gtk_widget_set_direction)libgtk.resolve("gtk_widget_set_direction"); + gtk_widget_path =(Ptr_gtk_widget_path)libgtk.resolve("gtk_widget_path"); + gtk_container_get_type =(Ptr_gtk_container_get_type)libgtk.resolve("gtk_container_get_type"); + gtk_window_get_type =(Ptr_gtk_window_get_type)libgtk.resolve("gtk_window_get_type"); + gtk_widget_get_type =(Ptr_gtk_widget_get_type)libgtk.resolve("gtk_widget_get_type"); + + gtk_rc_get_style_by_paths =(Ptr_gtk_rc_get_style_by_paths)libgtk.resolve("gtk_rc_get_style_by_paths"); + gtk_check_version =(Ptr_gtk_check_version)libgtk.resolve("gtk_check_version"); + gtk_border_free =(Ptr_gtk_border_free)libgtk.resolve("gtk_border_free"); + pango_font_description_get_size = (Ptr_pango_font_description_get_size)libgtk.resolve("pango_font_description_get_size"); + pango_font_description_get_weight = (Ptr_pango_font_description_get_weight)libgtk.resolve("pango_font_description_get_weight"); + pango_font_description_get_family = (Ptr_pango_font_description_get_family)libgtk.resolve("pango_font_description_get_family"); + pango_font_description_get_style = (Ptr_pango_font_description_get_style)libgtk.resolve("pango_font_description_get_style"); + + gnome_icon_lookup_sync = (Ptr_gnome_icon_lookup_sync)QLibrary::resolve(QLS("gnomeui-2"), 0, "gnome_icon_lookup_sync"); + gnome_vfs_init= (Ptr_gnome_vfs_init)QLibrary::resolve(QLS("gnomevfs-2"), 0, "gnome_vfs_init"); +} + +/* \internal + * Initializes a number of gtk menu widgets. + * The widgets are cached. + */ +void QGtkStylePrivate::initGtkMenu() const +{ + // Create menubar + GtkWidget *gtkMenuBar = QGtkStylePrivate::gtk_menu_bar_new(); + setupGtkWidget(gtkMenuBar); + + GtkWidget *gtkMenuBarItem = QGtkStylePrivate::gtk_menu_item_new_with_label("X"); + gtk_menu_shell_append((GtkMenuShell*)(gtkMenuBar), gtkMenuBarItem); + gtk_widget_realize(gtkMenuBarItem); + + // Create menu + GtkWidget *gtkMenu = QGtkStylePrivate::gtk_menu_new(); + gtk_menu_item_set_submenu((GtkMenuItem*)(gtkMenuBarItem), gtkMenu); + gtk_widget_realize(gtkMenu); + + GtkWidget *gtkMenuItem = QGtkStylePrivate::gtk_menu_item_new_with_label("X"); + gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkMenuItem); + gtk_widget_realize(gtkMenuItem); + + GtkWidget *gtkCheckMenuItem = QGtkStylePrivate::gtk_check_menu_item_new_with_label("X"); + gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkCheckMenuItem); + gtk_widget_realize(gtkCheckMenuItem); + + GtkWidget *gtkMenuSeparator = QGtkStylePrivate::gtk_separator_menu_item_new(); + gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkMenuSeparator); + + addAllSubWidgets(gtkMenuBar); + addAllSubWidgets(gtkMenu); +} + + +void QGtkStylePrivate::initGtkTreeview() const +{ + GtkWidget *gtkTreeView = gtk_tree_view_new(); + gtk_tree_view_append_column((GtkTreeView*)gtkTreeView, gtk_tree_view_column_new()); + gtk_tree_view_append_column((GtkTreeView*)gtkTreeView, gtk_tree_view_column_new()); + gtk_tree_view_append_column((GtkTreeView*)gtkTreeView, gtk_tree_view_column_new()); + addWidget(gtkTreeView); +} + + +/* \internal + * Initializes a number of gtk widgets that we can later on use to determine some of our styles. + * The widgets are cached. + */ +void QGtkStylePrivate::initGtkWidgets() const +{ + // From gtkmain.c + uid_t ruid = getuid (); + uid_t rgid = getgid (); + uid_t euid = geteuid (); + uid_t egid = getegid (); + if (ruid != euid || rgid != egid) { + qWarning("\nThis process is currently running setuid or setgid.\nGTK+ does not allow this " + "therefore Qt cannot use the GTK+ integration.\nTry launching your app using \'gksudo\', " + "\'kdesudo\' or a similar tool.\n\n" + "See http://www.gtk.org/setuid.html for more information.\n"); + return; + } + + static QString themeName; + if (!gtkWidgetMap()->contains("GtkWindow") && themeName.isEmpty()) { + themeName = getThemeName(); + + if (themeName.isEmpty()) { + qWarning("QGtkStyle was unable to detect the current GTK+ theme."); + return; + } else if (themeName == QLS("Qt") || themeName == QLS("Qt4")) { + // Due to namespace conflicts with Qt3 and obvious recursion with Qt4, + // we cannot support the GTK_Qt Gtk engine + qWarning("QGtkStyle cannot be used together with the GTK_Qt engine."); + return; + } + } + + if (QGtkStylePrivate::gtk_init) { + // Gtk will set the Qt error handler so we have to reset it afterwards + x11ErrorHandler qt_x_errhandler = XSetErrorHandler(0); + QGtkStylePrivate::gtk_init (NULL, NULL); + XSetErrorHandler(qt_x_errhandler); + + // make a window + GtkWidget* gtkWindow = QGtkStylePrivate::gtk_window_new(GTK_WINDOW_POPUP); + QGtkStylePrivate::gtk_widget_realize(gtkWindow); + if (displayDepth == -1) + displayDepth = QGtkStylePrivate::gdk_drawable_get_depth(gtkWindow->window); + QHashableLatin1Literal widgetPath = QHashableLatin1Literal::fromData(strdup("GtkWindow")); + removeWidgetFromMap(widgetPath); + gtkWidgetMap()->insert(widgetPath, gtkWindow); + + + // Make all other widgets. respect the text direction + if (qApp->layoutDirection() == Qt::RightToLeft) + QGtkStylePrivate::gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL); + + if (!gtkWidgetMap()->contains("GtkButton")) { + GtkWidget *gtkButton = QGtkStylePrivate::gtk_button_new(); + addWidget(gtkButton); + g_signal_connect(gtkButton, "style-set", G_CALLBACK(gtkStyleSetCallback), 0); + addWidget(QGtkStylePrivate::gtk_tool_button_new(NULL, "Qt")); + addWidget(QGtkStylePrivate::gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE)); + addWidget(QGtkStylePrivate::gtk_hbutton_box_new()); + addWidget(QGtkStylePrivate::gtk_check_button_new()); + addWidget(QGtkStylePrivate::gtk_radio_button_new(NULL)); + addWidget(QGtkStylePrivate::gtk_combo_box_new()); + addWidget(QGtkStylePrivate::gtk_combo_box_entry_new()); + addWidget(QGtkStylePrivate::gtk_entry_new()); + addWidget(QGtkStylePrivate::gtk_frame_new(NULL)); + addWidget(QGtkStylePrivate::gtk_expander_new("")); + addWidget(QGtkStylePrivate::gtk_statusbar_new()); + addWidget(QGtkStylePrivate::gtk_hscale_new((GtkAdjustment*)(QGtkStylePrivate::gtk_adjustment_new(1, 0, 1, 0, 0, 0)))); + addWidget(QGtkStylePrivate::gtk_hscrollbar_new(NULL)); + addWidget(QGtkStylePrivate::gtk_scrolled_window_new(NULL, NULL)); + + initGtkMenu(); + addWidget(QGtkStylePrivate::gtk_notebook_new()); + addWidget(QGtkStylePrivate::gtk_progress_bar_new()); + addWidget(QGtkStylePrivate::gtk_spin_button_new((GtkAdjustment*) + (QGtkStylePrivate::gtk_adjustment_new(1, 0, 1, 0, 0, 0)), 0.1, 3)); + GtkWidget *toolbar = gtk_toolbar_new(); + g_signal_connect (toolbar, "notify::toolbar-style", G_CALLBACK (update_toolbar_style), toolbar); + gtk_toolbar_insert((GtkToolbar*)toolbar, gtk_separator_tool_item_new(), -1); + addWidget(toolbar); + initGtkTreeview(); + addWidget(gtk_vscale_new((GtkAdjustment*)(QGtkStylePrivate::gtk_adjustment_new(1, 0, 1, 0, 0, 0)))); + addWidget(gtk_vscrollbar_new(NULL)); + } + else // Rebuild map + { + // When styles change subwidgets can get rearranged + // as with the combo box. We need to update the widget map + // to reflect this; + QHash oldMap = *gtkWidgetMap(); + gtkWidgetMap()->clear(); + QHashIterator it(oldMap); + while (it.hasNext()) { + it.next(); + if (!strchr(it.key().data(), '.')) { + addAllSubWidgets(it.value()); + } + free(const_cast(it.key().data())); + } + } + } else { + qWarning("QGtkStyle could not resolve GTK. Make sure you have installed the proper libraries."); + } +} + +/*! \internal + * destroys all previously buffered widgets. + */ +void QGtkStylePrivate::cleanupGtkWidgets() +{ + if (!widgetMap) + return; + if (widgetMap->contains("GtkWindow")) // Gtk will destroy all children + gtk_widget_destroy(widgetMap->value("GtkWindow")); + for (QHash::const_iterator it = widgetMap->constBegin(); + it != widgetMap->constEnd(); ++it) + free(const_cast(it.key().data())); +} + +static bool resolveGConf() +{ + if (!QGtkStylePrivate::gconf_client_get_default) { + QGtkStylePrivate::gconf_client_get_default = (Ptr_gconf_client_get_default)QLibrary::resolve(QLS("gconf-2"), 4, "gconf_client_get_default"); + QGtkStylePrivate::gconf_client_get_string = (Ptr_gconf_client_get_string)QLibrary::resolve(QLS("gconf-2"), 4, "gconf_client_get_string"); + QGtkStylePrivate::gconf_client_get_bool = (Ptr_gconf_client_get_bool)QLibrary::resolve(QLS("gconf-2"), 4, "gconf_client_get_bool"); + } + return (QGtkStylePrivate::gconf_client_get_default !=0); +} + +QString QGtkStylePrivate::getGConfString(const QString &value, const QString &fallback) +{ + QString retVal = fallback; + if (resolveGConf()) { + g_type_init(); + GConfClient* client = gconf_client_get_default(); + GError *err = 0; + char *str = gconf_client_get_string(client, qPrintable(value), &err); + if (!err) { + retVal = QString::fromUtf8(str); + g_free(str); + } + g_object_unref(client); + if (err) + g_error_free (err); + } + return retVal; +} + +bool QGtkStylePrivate::getGConfBool(const QString &key, bool fallback) +{ + bool retVal = fallback; + if (resolveGConf()) { + g_type_init(); + GConfClient* client = gconf_client_get_default(); + GError *err = 0; + bool result = gconf_client_get_bool(client, qPrintable(key), &err); + g_object_unref(client); + if (!err) + retVal = result; + else + g_error_free (err); + } + return retVal; +} + +QString QGtkStylePrivate::getThemeName() +{ + QString themeName; + // We try to parse the gtkrc file first + // primarily to avoid resolving Gtk functions if + // the KDE 3 "Qt" style is currently in use + QString rcPaths = QString::fromLocal8Bit(qgetenv("GTK2_RC_FILES")); + if (!rcPaths.isEmpty()) { + QStringList paths = rcPaths.split(QLS(":")); + foreach (const QString &rcPath, paths) { + if (!rcPath.isEmpty()) { + QFile rcFile(rcPath); + if (rcFile.exists() && rcFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&rcFile); + while(!in.atEnd()) { + QString line = in.readLine(); + if (line.contains(QLS("gtk-theme-name"))) { + line = line.right(line.length() - line.indexOf(QLatin1Char('=')) - 1); + line.remove(QLatin1Char('\"')); + line = line.trimmed(); + themeName = line; + break; + } + } + } + } + if (!themeName.isEmpty()) + break; + } + } + + // Fall back to gconf + if (themeName.isEmpty() && resolveGConf()) + themeName = getGConfString(QLS("/desktop/gnome/interface/gtk_theme")); + + return themeName; +} + +// Get size of the arrow controls in a GtkSpinButton +int QGtkStylePrivate::getSpinboxArrowSize() const +{ + const int MIN_ARROW_WIDTH = 6; + GtkWidget *spinButton = gtkWidget("GtkSpinButton"); + GtkStyle *style = spinButton->style; + gint size = pango_font_description_get_size (style->font_desc); + gint arrow_size; + arrow_size = qMax(PANGO_PIXELS (size), MIN_ARROW_WIDTH) + style->xthickness; + arrow_size += arrow_size%2 + 1; + return arrow_size; +} + + +bool QGtkStylePrivate::isKDE4Session() +{ + static int version = -1; + if (version == -1) + version = qgetenv("KDE_SESSION_VERSION").toInt(); + return (version == 4); +} + +void QGtkStylePrivate::applyCustomPaletteHash() +{ + QPalette menuPal = gtkWidgetPalette("GtkMenu"); + GdkColor gdkBg = gtkWidget("GtkMenu")->style->bg[GTK_STATE_NORMAL]; + QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); + menuPal.setBrush(QPalette::Base, bgColor); + menuPal.setBrush(QPalette::Window, bgColor); + qApp->setPalette(menuPal, "QMenu"); + + QPalette toolbarPal = gtkWidgetPalette("GtkToolbar"); + qApp->setPalette(toolbarPal, "QToolBar"); + + QPalette menuBarPal = gtkWidgetPalette("GtkMenuBar"); + qApp->setPalette(menuBarPal, "QMenuBar"); +} + +/*! \internal + * Returns the gtk Widget that should be used to determine text foreground and background colors. +*/ +GtkWidget* QGtkStylePrivate::getTextColorWidget() const +{ + return gtkWidget("GtkEntry"); +} + +void QGtkStylePrivate::setupGtkWidget(GtkWidget* widget) +{ + if (Q_GTK_IS_WIDGET(widget)) { + static GtkWidget* protoLayout = 0; + if (!protoLayout) { + protoLayout = QGtkStylePrivate::gtk_fixed_new(); + QGtkStylePrivate::gtk_container_add((GtkContainer*)(gtkWidgetMap()->value("GtkWindow")), protoLayout); + } + Q_ASSERT(protoLayout); + + if (!widget->parent && !GTK_WIDGET_TOPLEVEL(widget)) + QGtkStylePrivate::gtk_container_add((GtkContainer*)(protoLayout), widget); + QGtkStylePrivate::gtk_widget_realize(widget); + } +} + +void QGtkStylePrivate::removeWidgetFromMap(const QHashableLatin1Literal &path) +{ + WidgetMap *map = gtkWidgetMap(); + WidgetMap::iterator it = map->find(path); + if (it != map->end()) { + free(const_cast(it.key().data())); + map->erase(it); + } +} + +void QGtkStylePrivate::addWidgetToMap(GtkWidget *widget) +{ + if (Q_GTK_IS_WIDGET(widget)) { + gtk_widget_realize(widget); + QHashableLatin1Literal widgetPath = classPath(widget); + + removeWidgetFromMap(widgetPath); + gtkWidgetMap()->insert(widgetPath, widget); +#ifdef DUMP_GTK_WIDGET_TREE + qWarning("Inserted Gtk Widget: %s", widgetPath.data()); +#endif + } + } + +void QGtkStylePrivate::addAllSubWidgets(GtkWidget *widget, gpointer v) +{ + Q_UNUSED(v); + addWidgetToMap(widget); + if (GTK_CHECK_TYPE ((widget), gtk_container_get_type())) + gtk_container_forall((GtkContainer*)widget, addAllSubWidgets, NULL); +} + +// Updates window/windowtext palette based on the indicated gtk widget +QPalette QGtkStylePrivate::gtkWidgetPalette(const QHashableLatin1Literal >kWidgetName) const +{ + GtkWidget *gtkWidget = QGtkStylePrivate::gtkWidget(gtkWidgetName); + Q_ASSERT(gtkWidget); + QPalette pal = QApplication::palette(); + GdkColor gdkBg = gtkWidget->style->bg[GTK_STATE_NORMAL]; + GdkColor gdkText = gtkWidget->style->fg[GTK_STATE_NORMAL]; + GdkColor gdkDisabledText = gtkWidget->style->fg[GTK_STATE_INSENSITIVE]; + QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); + QColor textColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + QColor disabledTextColor(gdkDisabledText.red>>8, gdkDisabledText.green>>8, gdkDisabledText.blue>>8); + pal.setBrush(QPalette::Window, bgColor); + pal.setBrush(QPalette::Button, bgColor); + pal.setBrush(QPalette::All, QPalette::WindowText, textColor); + pal.setBrush(QPalette::Disabled, QPalette::WindowText, disabledTextColor); + pal.setBrush(QPalette::All, QPalette::ButtonText, textColor); + pal.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledTextColor); + return pal; +} + + +void QGtkStyleUpdateScheduler::updateTheme() +{ + static QString oldTheme(QLS("qt_not_set")); + QPixmapCache::clear(); + + QFont font = QGtkStylePrivate::getThemeFont(); + if (QApplication::font() != font) + qApp->setFont(font); + + if (oldTheme != QGtkStylePrivate::getThemeName()) { + oldTheme = QGtkStylePrivate::getThemeName(); + QPalette newPalette = qApp->style()->standardPalette(); + QApplicationPrivate::setSystemPalette(newPalette); + QApplication::setPalette(newPalette); + if (!QGtkStylePrivate::instances.isEmpty()) { + QGtkStylePrivate::instances.last()->initGtkWidgets(); + QGtkStylePrivate::instances.last()->applyCustomPaletteHash(); + } + QList widgets = QApplication::allWidgets(); + // Notify all widgets that size metrics might have changed + foreach (QWidget *widget, widgets) { + QEvent e(QEvent::StyleChange); + QApplication::sendEvent(widget, &e); + } + } + QIconLoader::instance()->updateSystemTheme(); +} + +void QGtkStylePrivate::addWidget(GtkWidget *widget) +{ + if (widget) { + setupGtkWidget(widget); + addAllSubWidgets(widget); + } +} + + +// Fetch the application font from the pango font description +// contained in the theme. +QFont QGtkStylePrivate::getThemeFont() +{ + QFont font; + GtkStyle *style = gtkStyle(); + if (style && qApp->desktopSettingsAware()) + { + PangoFontDescription *gtk_font = style->font_desc; + font.setPointSizeF((float)(pango_font_description_get_size(gtk_font))/PANGO_SCALE); + + QString family = QString::fromLatin1(pango_font_description_get_family(gtk_font)); + if (!family.isEmpty()) + font.setFamily(family); + + int weight = pango_font_description_get_weight(gtk_font); + if (weight >= PANGO_WEIGHT_HEAVY) + font.setWeight(QFont::Black); + else if (weight >= PANGO_WEIGHT_BOLD) + font.setWeight(QFont::Bold); + else if (weight >= PANGO_WEIGHT_SEMIBOLD) + font.setWeight(QFont::DemiBold); + else if (weight >= PANGO_WEIGHT_NORMAL) + font.setWeight(QFont::Normal); + else + font.setWeight(QFont::Light); + + PangoStyle fontstyle = pango_font_description_get_style(gtk_font); + if (fontstyle == PANGO_STYLE_ITALIC) + font.setStyle(QFont::StyleItalic); + else if (fontstyle == PANGO_STYLE_OBLIQUE) + font.setStyle(QFont::StyleOblique); + else + font.setStyle(QFont::StyleNormal); + } + return font; +} + + +// ----------- Native file dialogs ----------- + +// Extract filter list from expressions of type: foo (*.a *.b *.c)" +QStringList QGtkStylePrivate::extract_filter(const QString &rawFilter) +{ + QString result = rawFilter; + QRegExp r(QString::fromLatin1("^([^()]*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$")); + int index = r.indexIn(result); + if (index >= 0) + result = r.cap(2); + return result.split(QLatin1Char(' ')); +} + +extern QStringList qt_make_filter_list(const QString &filter); + +void QGtkStylePrivate::setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, + const QString &dir, const QString &filter, QString *selectedFilter, + QFileDialog::Options options, bool isSaveDialog, + QMap *filterMap) +{ + g_object_set(gtkFileChooser, "do-overwrite-confirmation", gboolean(!(options & QFileDialog::DontConfirmOverwrite)), NULL); + g_object_set(gtkFileChooser, "local_only", gboolean(true), NULL); + if (!filter.isEmpty()) { + QStringList filters = qt_make_filter_list(filter); + foreach (const QString &rawfilter, filters) { + GtkFileFilter *gtkFilter = QGtkStylePrivate::gtk_file_filter_new (); + QString name = rawfilter.left(rawfilter.indexOf(QLatin1Char('('))); + QStringList extensions = extract_filter(rawfilter); + QGtkStylePrivate::gtk_file_filter_set_name(gtkFilter, qPrintable(name.isEmpty() ? extensions.join(QLS(", ")) : name)); + + foreach (const QString &fileExtension, extensions) { + // Note Gtk file dialogs are by default case sensitive + // and only supports basic glob syntax so we + // rewrite .xyz to .[xX][yY][zZ] + QString caseInsensitive; + for (int i = 0 ; i < fileExtension.length() ; ++i) { + QChar ch = fileExtension.at(i); + if (ch.isLetter()) { + caseInsensitive.append( + QLatin1Char('[') + + ch.toLower() + + ch.toUpper() + + QLatin1Char(']')); + } else { + caseInsensitive.append(ch); + } + } + QGtkStylePrivate::gtk_file_filter_add_pattern (gtkFilter, qPrintable(caseInsensitive)); + + } + if (filterMap) + filterMap->insert(gtkFilter, rawfilter); + QGtkStylePrivate::gtk_file_chooser_add_filter((GtkFileChooser*)gtkFileChooser, gtkFilter); + if (selectedFilter && (rawfilter == *selectedFilter)) + QGtkStylePrivate::gtk_file_chooser_set_filter((GtkFileChooser*)gtkFileChooser, gtkFilter); + } + } + + // Using the currently active window is not entirely correct, however + // it gives more sensible behavior for applications that do not provide a + // parent + QWidget *modalFor = parent ? parent->window() : qApp->activeWindow(); + if (modalFor) { + QGtkStylePrivate::gtk_widget_realize(gtkFileChooser); // Creates X window + XSetTransientForHint(QGtkStylePrivate::gdk_x11_drawable_get_xdisplay(gtkFileChooser->window), + QGtkStylePrivate::gdk_x11_drawable_get_xid(gtkFileChooser->window), + modalFor->winId()); + QGtkStylePrivate::gdk_x11_window_set_user_time (gtkFileChooser->window, QX11Info::appUserTime()); + + } + + QFileInfo fileinfo(dir); + if (dir.isEmpty()) + fileinfo.setFile(QDir::currentPath()); + fileinfo.makeAbsolute(); + if (fileinfo.isDir()) { + QGtkStylePrivate::gtk_file_chooser_set_current_folder((GtkFileChooser*)gtkFileChooser, qPrintable(dir)); + } else if (isSaveDialog) { + QGtkStylePrivate::gtk_file_chooser_set_current_folder((GtkFileChooser*)gtkFileChooser, qPrintable(fileinfo.absolutePath())); + QGtkStylePrivate::gtk_file_chooser_set_current_name((GtkFileChooser*)gtkFileChooser, qPrintable(fileinfo.fileName())); + } else { + QGtkStylePrivate::gtk_file_chooser_set_filename((GtkFileChooser*)gtkFileChooser, qPrintable(dir)); + } +} + +QString QGtkStylePrivate::openFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options) +{ + QMap filterMap; + GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), + NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, false, &filterMap); + + QWidget modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + QString filename; + if (QGtkStylePrivate::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { + char *gtk_filename = QGtkStylePrivate::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); + filename = QString::fromUtf8(gtk_filename); + g_free (gtk_filename); + if (selectedFilter) { + GtkFileFilter *gtkFilter = QGtkStylePrivate::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); + *selectedFilter = filterMap.value(gtkFilter); + } + } + + QApplicationPrivate::leaveModal(&modal_widget); + gtk_widget_destroy (gtkFileChooser); + return filename; +} + + +QString QGtkStylePrivate::openDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options) +{ + QMap filterMap; + GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), + NULL, + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + setupGtkFileChooser(gtkFileChooser, parent, dir, QString(), 0, options); + QWidget modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + QString filename; + if (QGtkStylePrivate::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { + char *gtk_filename = QGtkStylePrivate::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); + filename = QString::fromUtf8(gtk_filename); + g_free (gtk_filename); + } + + QApplicationPrivate::leaveModal(&modal_widget); + gtk_widget_destroy (gtkFileChooser); + return filename; +} + +QStringList QGtkStylePrivate::openFilenames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options) +{ + QStringList filenames; + QMap filterMap; + GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), + NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, false, &filterMap); + g_object_set(gtkFileChooser, "select-multiple", gboolean(true), NULL); + + QWidget modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + if (gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { + GSList *gtk_file_names = QGtkStylePrivate::gtk_file_chooser_get_filenames((GtkFileChooser*)gtkFileChooser); + for (GSList *iterator = gtk_file_names ; iterator; iterator = iterator->next) + filenames << QString::fromUtf8((const char*)iterator->data); + g_slist_free(gtk_file_names); + if (selectedFilter) { + GtkFileFilter *gtkFilter = QGtkStylePrivate::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); + *selectedFilter = filterMap.value(gtkFilter); + } + } + + QApplicationPrivate::leaveModal(&modal_widget); + gtk_widget_destroy (gtkFileChooser); + return filenames; +} + +QString QGtkStylePrivate::saveFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options) +{ + QMap filterMap; + GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), + NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, true, &filterMap); + + QWidget modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + QString filename; + if (QGtkStylePrivate::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { + char *gtk_filename = QGtkStylePrivate::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); + filename = QString::fromUtf8(gtk_filename); + g_free (gtk_filename); + if (selectedFilter) { + GtkFileFilter *gtkFilter = QGtkStylePrivate::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); + *selectedFilter = filterMap.value(gtkFilter); + } + } + + QApplicationPrivate::leaveModal(&modal_widget); + gtk_widget_destroy (gtkFileChooser); + return filename; +} + +QIcon QGtkStylePrivate::getFilesystemIcon(const QFileInfo &info) +{ + QIcon icon; + if (gnome_vfs_init && gnome_icon_lookup_sync) { + gnome_vfs_init(); + GtkIconTheme *theme = gtk_icon_theme_get_default(); + QByteArray fileurl = QUrl::fromLocalFile(info.absoluteFilePath()).toEncoded(); + char * icon_name = gnome_icon_lookup_sync(theme, + NULL, + fileurl.data(), + NULL, + GNOME_ICON_LOOKUP_FLAGS_NONE, + NULL); + QString iconName = QString::fromUtf8(icon_name); + g_free(icon_name); + if (iconName.startsWith(QLatin1Char('/'))) + return QIcon(iconName); + return QIcon::fromTheme(iconName); + } + return icon; +} + +bool operator==(const QHashableLatin1Literal &l1, const QHashableLatin1Literal &l2) +{ + return l1.size() == l2.size() || qstrcmp(l1.data(), l2.data()) == 0; +} + +// copied from qHash.cpp +uint qHash(const QHashableLatin1Literal &key) +{ + int n = key.size(); + const uchar *p = reinterpret_cast(key.data()); + uint h = 0; + uint g; + + while (n--) { + h = (h << 4) + *p++; + if ((g = (h & 0xf0000000)) != 0) + h ^= g >> 23; + h &= ~g; + } + return h; +} + +QT_END_NAMESPACE + +#endif // !defined(QT_NO_STYLE_GTK) diff --git a/src/widgets/styles/qgtkstyle_p.h b/src/widgets/styles/qgtkstyle_p.h new file mode 100644 index 0000000000..15a98c8257 --- /dev/null +++ b/src/widgets/styles/qgtkstyle_p.h @@ -0,0 +1,531 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGTKSTYLE_P_H +#define QGTKSTYLE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#if !defined(QT_NO_STYLE_GTK) + +#include +#include +#include + +#include + +#include +#include + +#undef signals // Collides with GTK stymbols +#include + +typedef unsigned long XID; + +#undef GTK_OBJECT_FLAGS +#define GTK_OBJECT_FLAGS(obj)(((GtkObject*)(obj))->flags) +#define Q_GTK_IS_WIDGET(widget) widget && GTK_CHECK_TYPE ((widget), QGtkStylePrivate::gtk_widget_get_type()) + +#define QLS(x) QLatin1String(x) + +QT_BEGIN_NAMESPACE + +// ### Qt 4.7 - merge with QLatin1Literal +class QHashableLatin1Literal +{ +public: + int size() const { return m_size; } + const char *data() const { return m_data; } + +#ifdef __SUNPRO_CC + QHashableLatin1Literal(const char* str) + : m_size(strlen(str)), m_data(str) {} +#else + template + QHashableLatin1Literal(const char (&str)[N]) + : m_size(N - 1), m_data(str) {} +#endif + + QHashableLatin1Literal(const QHashableLatin1Literal &other) + : m_size(other.m_size), m_data(other.m_data) + {} + + QHashableLatin1Literal &operator=(const QHashableLatin1Literal &other) + { + if (this == &other) + return *this; + *const_cast(&m_size) = other.m_size; + *const_cast(&m_data) = const_cast(other.m_data); + return *this; + } + + QString toString() const { return QString::fromLatin1(m_data, m_size); } + + static QHashableLatin1Literal fromData(const char *str) + { + return QHashableLatin1Literal(str, qstrlen(str)); + } + +private: + QHashableLatin1Literal(const char *str, int length) + : m_size(length), m_data(str) + {} + + const int m_size; + const char *m_data; +}; + +bool operator==(const QHashableLatin1Literal &l1, const QHashableLatin1Literal &l2); +inline bool operator!=(const QHashableLatin1Literal &l1, const QHashableLatin1Literal &l2) { return !operator==(l1, l2); } +uint qHash(const QHashableLatin1Literal &key); + +QT_END_NAMESPACE + +class GConf; +class GConfClient; + +typedef GConfClient* (*Ptr_gconf_client_get_default)(); +typedef char* (*Ptr_gconf_client_get_string)(GConfClient*, const char*, GError **); +typedef bool (*Ptr_gconf_client_get_bool)(GConfClient*, const char*, GError **); + +typedef void (*Ptr_gtk_init)(int *, char ***); +typedef GtkWidget* (*Ptr_gtk_window_new) (GtkWindowType); +typedef GtkStyle* (*Ptr_gtk_style_attach)(GtkStyle *, GdkWindow *); +typedef void (*Ptr_gtk_widget_destroy) (GtkWidget *); +typedef void (*Ptr_gtk_widget_realize) (GtkWidget *); +typedef void (*Ptr_gtk_widget_set_default_direction) (GtkTextDirection); +typedef void (*Ptr_gtk_widget_modify_color)(GtkWidget *widget, GtkStateType state, const GdkColor *color); +typedef GtkWidget* (*Ptr_gtk_arrow_new)(GtkArrowType, GtkShadowType); +typedef GtkWidget* (*Ptr_gtk_menu_item_new_with_label)(const gchar *); +typedef GtkWidget* (*Ptr_gtk_separator_menu_item_new)(void); +typedef GtkWidget* (*Ptr_gtk_check_menu_item_new_with_label)(const gchar *); +typedef GtkWidget* (*Ptr_gtk_menu_bar_new)(void); +typedef GtkWidget* (*Ptr_gtk_menu_new)(void); +typedef GtkWidget* (*Ptr_gtk_combo_box_entry_new)(void); +typedef GtkWidget* (*Ptr_gtk_toolbar_new)(void); +typedef GtkWidget* (*Ptr_gtk_spin_button_new)(GtkAdjustment*, double, int); +typedef GtkWidget* (*Ptr_gtk_button_new)(void); +typedef GtkWidget* (*Ptr_gtk_tool_button_new)(GtkWidget *, const gchar *); +typedef GtkWidget* (*Ptr_gtk_hbutton_box_new)(void); +typedef GtkWidget* (*Ptr_gtk_check_button_new)(void); +typedef GtkWidget* (*Ptr_gtk_radio_button_new)(GSList *); +typedef GtkWidget* (*Ptr_gtk_notebook_new)(void); +typedef GtkWidget* (*Ptr_gtk_progress_bar_new)(void); +typedef GtkWidget* (*Ptr_gtk_hscale_new)(GtkAdjustment*); +typedef GtkWidget* (*Ptr_gtk_vscale_new)(GtkAdjustment*); +typedef GtkWidget* (*Ptr_gtk_hscrollbar_new)(GtkAdjustment*); +typedef GtkWidget* (*Ptr_gtk_vscrollbar_new)(GtkAdjustment*); +typedef GtkWidget* (*Ptr_gtk_scrolled_window_new)(GtkAdjustment*, GtkAdjustment*); +typedef gchar* (*Ptr_gtk_check_version)(guint, guint, guint); +typedef GtkToolItem* (*Ptr_gtk_separator_tool_item_new) (void); +typedef GtkWidget* (*Ptr_gtk_entry_new)(void); +typedef GtkWidget* (*Ptr_gtk_tree_view_new)(void); +typedef GtkTreeViewColumn* (*Ptr_gtk_tree_view_get_column)(GtkTreeView *, gint); +typedef GtkWidget* (*Ptr_gtk_combo_box_new)(void); +typedef GtkWidget* (*Ptr_gtk_frame_new)(const gchar *); +typedef GtkWidget* (*Ptr_gtk_expander_new)(const gchar*); +typedef GtkWidget* (*Ptr_gtk_statusbar_new)(void); +typedef GtkSettings* (*Ptr_gtk_settings_get_default)(void); +typedef GtkAdjustment* (*Ptr_gtk_range_get_adjustment)(GtkRange *); +typedef void (*Ptr_gtk_range_set_adjustment)(GtkRange *, GtkAdjustment *); +typedef void (*Ptr_gtk_progress_configure)(GtkProgress *, double, double, double); +typedef void (*Ptr_gtk_range_set_inverted)(GtkRange*, bool); +typedef void (*Ptr_gtk_container_add)(GtkContainer *container, GtkWidget *widget); +typedef GtkIconSet* (*Ptr_gtk_icon_factory_lookup_default) (const gchar*); +typedef GtkIconTheme* (*Ptr_gtk_icon_theme_get_default) (void); +typedef void (*Ptr_gtk_widget_style_get)(GtkWidget *, const gchar *first_property_name, ...); +typedef GtkTreeViewColumn* (*Ptr_gtk_tree_view_column_new)(void); +typedef GtkWidget* (*Ptr_gtk_fixed_new)(void); +typedef GdkPixbuf* (*Ptr_gtk_icon_set_render_icon)(GtkIconSet *, GtkStyle *, GtkTextDirection, GtkStateType, GtkIconSize, GtkWidget *,const char *); +typedef void (*Ptr_gtk_tree_view_append_column) (GtkTreeView*, GtkTreeViewColumn*); +typedef void (*Ptr_gtk_paint_check) (GtkStyle*,GdkWindow*, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, gint , gint , gint , gint); +typedef void (*Ptr_gtk_paint_box) (GtkStyle*,GdkWindow*, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, gint , gint , gint , gint); +typedef void (*Ptr_gtk_paint_box_gap) (GtkStyle*,GdkWindow*, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, gint, gint, gint , gint, GtkPositionType, gint gap_x, gint gap_width); +typedef void (*Ptr_gtk_paint_resize_grip) (GtkStyle*,GdkWindow*, GtkStateType, const GdkRectangle *, GtkWidget *, const gchar *, GdkWindowEdge, gint , gint , gint , gint); +typedef void (*Ptr_gtk_paint_focus) (GtkStyle*,GdkWindow*, GtkStateType, const GdkRectangle *, GtkWidget *, const gchar *, gint , gint , gint , gint); +typedef void (*Ptr_gtk_paint_shadow) (GtkStyle*,GdkWindow*, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, gint , gint , gint , gint); +typedef void (*Ptr_gtk_paint_slider) (GtkStyle*,GdkWindow*, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, gint , gint , gint , gint, GtkOrientation); +typedef void (*Ptr_gtk_paint_expander) (GtkStyle*,GdkWindow*, GtkStateType, const GdkRectangle *, GtkWidget *, const gchar *, gint , gint , GtkExpanderStyle ); +typedef void (*Ptr_gtk_paint_handle) (GtkStyle*,GdkWindow*, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, gint , gint , gint , gint, GtkOrientation); +typedef void (*Ptr_gtk_paint_arrow) (GtkStyle*,GdkWindow*, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, GtkArrowType, gboolean, gint , gint , gint , gint); +typedef void (*Ptr_gtk_paint_option) (GtkStyle*,GdkWindow*, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, gint , gint , gint , gint); +typedef void (*Ptr_gtk_paint_flat_box) (GtkStyle*,GdkWindow*, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, gint , gint , gint , gint); +typedef void (*Ptr_gtk_paint_extension) (GtkStyle *, GdkWindow *, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, gint, gint, gint, gint, GtkPositionType); +typedef void (*Ptr_gtk_adjustment_configure) (GtkAdjustment *, double, double, double, double, double, double); +typedef GtkObject* (*Ptr_gtk_adjustment_new) (double, double, double, double, double, double); +typedef void (*Ptr_gtk_paint_hline) (GtkStyle *, GdkWindow *, GtkStateType, const GdkRectangle *, GtkWidget *, const gchar *, gint, gint, gint y); +typedef void (*Ptr_gtk_paint_vline) (GtkStyle *, GdkWindow *, GtkStateType, const GdkRectangle *, GtkWidget *, const gchar *, gint, gint, gint); +typedef void (*Ptr_gtk_menu_item_set_submenu) (GtkMenuItem *, GtkWidget *); +typedef void (*Ptr_gtk_container_forall) (GtkContainer *, GtkCallback, gpointer); +typedef void (*Ptr_gtk_widget_size_allocate) (GtkWidget *, GtkAllocation*); +typedef void (*Ptr_gtk_widget_size_request) (GtkWidget *widget, GtkRequisition *requisition); +typedef void (*Ptr_gtk_widget_set_direction) (GtkWidget *, GtkTextDirection); +typedef void (*Ptr_gtk_widget_path) (GtkWidget *, guint *, gchar **, gchar**); + +typedef void (*Ptr_gtk_toolbar_insert) (GtkToolbar *toolbar, GtkToolItem *item, int pos); +typedef void (*Ptr_gtk_menu_shell_append)(GtkMenuShell *, GtkWidget *); +typedef GtkType (*Ptr_gtk_container_get_type) (void); +typedef GtkType (*Ptr_gtk_window_get_type) (void); +typedef GtkType (*Ptr_gtk_widget_get_type) (void); +typedef GtkStyle* (*Ptr_gtk_rc_get_style_by_paths) (GtkSettings *, const char *, const char *, GType); +typedef gint (*Ptr_pango_font_description_get_size) (const PangoFontDescription *); +typedef PangoWeight (*Ptr_pango_font_description_get_weight) (const PangoFontDescription *); +typedef const char* (*Ptr_pango_font_description_get_family) (const PangoFontDescription *); +typedef PangoStyle (*Ptr_pango_font_description_get_style) (const PangoFontDescription *desc); +typedef gboolean (*Ptr_gtk_file_chooser_set_current_folder)(GtkFileChooser *, const gchar *); +typedef GtkFileFilter* (*Ptr_gtk_file_filter_new)(void); +typedef void (*Ptr_gtk_file_filter_set_name)(GtkFileFilter *, const gchar *); +typedef void (*Ptr_gtk_file_filter_add_pattern)(GtkFileFilter *filter, const gchar *pattern); +typedef void (*Ptr_gtk_file_chooser_add_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); +typedef void (*Ptr_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); +typedef GtkFileFilter* (*Ptr_gtk_file_chooser_get_filter)(GtkFileChooser *chooser); +typedef gchar* (*Ptr_gtk_file_chooser_get_filename)(GtkFileChooser *chooser); +typedef GSList* (*Ptr_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); +typedef GtkWidget* (*Ptr_gtk_file_chooser_dialog_new)(const gchar *title, + GtkWindow *parent, + GtkFileChooserAction action, + const gchar *first_button_text, + ...); +typedef void (*Ptr_gtk_file_chooser_set_current_name) (GtkFileChooser *, const gchar *); +typedef gboolean (*Ptr_gtk_file_chooser_set_filename) (GtkFileChooser *chooser, const gchar *name); +typedef gint (*Ptr_gtk_dialog_run) (GtkDialog*); +typedef void (*Ptr_gtk_border_free)(GtkBorder *); + +typedef guchar* (*Ptr_gdk_pixbuf_get_pixels) (const GdkPixbuf *pixbuf); +typedef int (*Ptr_gdk_pixbuf_get_width) (const GdkPixbuf *pixbuf); +typedef void (*Ptr_gdk_color_free) (const GdkColor *); +typedef int (*Ptr_gdk_pixbuf_get_height) (const GdkPixbuf *pixbuf); +typedef GdkPixbuf* (*Ptr_gdk_pixbuf_get_from_drawable) (GdkPixbuf *dest, GdkDrawable *src, + GdkColormap *cmap, int src_x, + int src_y, int dest_x, int dest_y, + int width, int height); +typedef GdkPixmap* (*Ptr_gdk_pixmap_new) (GdkDrawable *drawable, gint width, gint height, gint depth); +typedef GdkPixbuf* (*Ptr_gdk_pixbuf_new) (GdkColorspace colorspace, gboolean has_alpha, + int bits_per_sample, int width, int height); +typedef void (*Ptr_gdk_draw_rectangle) (GdkDrawable *drawable, GdkGC *gc, + gboolean filled, gint x, gint y, gint width, gint height); +typedef void (*Ptr_gdk_pixbuf_unref)(GdkPixbuf *); +typedef void (*Ptr_gdk_drawable_unref)(GdkDrawable *); +typedef gint (*Ptr_gdk_drawable_get_depth)(GdkDrawable *); +typedef void (*Ptr_gdk_x11_window_set_user_time) (GdkWindow *window, guint32); +typedef XID (*Ptr_gdk_x11_drawable_get_xid) (GdkDrawable *); +typedef Display* (*Ptr_gdk_x11_drawable_get_xdisplay) ( GdkDrawable *); + + +QT_BEGIN_NAMESPACE + +typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, + const QString &filter, QString *selectedFilter, QFileDialog::Options options); +typedef QString (*_qt_filedialog_open_filename_hook) (QWidget * parent, const QString &caption, const QString &dir, + const QString &filter, QString *selectedFilter, QFileDialog::Options options); +typedef QString (*_qt_filedialog_save_filename_hook) (QWidget * parent, const QString &caption, const QString &dir, + const QString &filter, QString *selectedFilter, QFileDialog::Options options); +typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, + QFileDialog::Options options); + +extern Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook; +extern Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook; +extern Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook; +extern Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook; + +class QGtkStylePrivate; + +class QGtkStyleFilter : public QObject +{ +public: + QGtkStyleFilter(QGtkStylePrivate* sp) + : stylePrivate(sp) + {} +private: + QGtkStylePrivate* stylePrivate; + bool eventFilter(QObject *obj, QEvent *e); +}; + +typedef enum { + GNOME_ICON_LOOKUP_FLAGS_NONE = 0, + GNOME_ICON_LOOKUP_FLAGS_EMBEDDING_TEXT = 1<<0, + GNOME_ICON_LOOKUP_FLAGS_SHOW_SMALL_IMAGES_AS_THEMSELVES = 1<<1, + GNOME_ICON_LOOKUP_FLAGS_ALLOW_SVG_AS_THEMSELVES = 1<<2 +} GnomeIconLookupFlags; + +typedef enum { + GNOME_ICON_LOOKUP_RESULT_FLAGS_NONE = 0, + GNOME_ICON_LOOKUP_RESULT_FLAGS_THUMBNAIL = 1<<0 +} GnomeIconLookupResultFlags; + +struct GnomeThumbnailFactory; +typedef gboolean (*Ptr_gnome_vfs_init) (void); +typedef char* (*Ptr_gnome_icon_lookup_sync) ( + GtkIconTheme *icon_theme, + GnomeThumbnailFactory *, + const char *file_uri, + const char *custom_icon, + GnomeIconLookupFlags flags, + GnomeIconLookupResultFlags *result); + +class QGtkStylePrivate : public QCleanlooksStylePrivate +{ + Q_DECLARE_PUBLIC(QGtkStyle) +public: + QGtkStylePrivate(); + ~QGtkStylePrivate(); + + QGtkStyleFilter filter; + + static GtkWidget* gtkWidget(const QHashableLatin1Literal &path); + static GtkStyle* gtkStyle(const QHashableLatin1Literal &path = QHashableLatin1Literal("GtkWindow")); + + virtual void resolveGtk() const; + virtual void initGtkMenu() const; + virtual void initGtkTreeview() const; + virtual void initGtkWidgets() const; + + static void cleanupGtkWidgets(); + + static bool isKDE4Session(); + void applyCustomPaletteHash(); + static QFont getThemeFont(); + static bool isThemeAvailable() { return gtkStyle() != 0; } + + static bool getGConfBool(const QString &key, bool fallback = 0); + static QString getGConfString(const QString &key, const QString &fallback = QString()); + + static QString getThemeName(); + virtual int getSpinboxArrowSize() const; + + static void setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, + const QString &dir, const QString &filter, QString *selectedFilter, + QFileDialog::Options options, bool isSaveDialog = false, + QMap *filterMap = 0); + + static QString openFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options); + static QString saveFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options); + static QString openDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options); + static QStringList openFilenames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options); + static QIcon getFilesystemIcon(const QFileInfo &); + + static Ptr_gtk_container_forall gtk_container_forall; + static Ptr_gtk_init gtk_init; + static Ptr_gtk_style_attach gtk_style_attach; + static Ptr_gtk_window_new gtk_window_new; + static Ptr_gtk_widget_destroy gtk_widget_destroy; + static Ptr_gtk_widget_realize gtk_widget_realize; + static Ptr_gtk_widget_set_default_direction gtk_widget_set_default_direction; + static Ptr_gtk_widget_modify_color gtk_widget_modify_fg; + static Ptr_gtk_widget_modify_color gtk_widget_modify_bg; + static Ptr_gtk_menu_item_new_with_label gtk_menu_item_new_with_label; + static Ptr_gtk_arrow_new gtk_arrow_new; + static Ptr_gtk_check_menu_item_new_with_label gtk_check_menu_item_new_with_label; + static Ptr_gtk_menu_bar_new gtk_menu_bar_new; + static Ptr_gtk_menu_new gtk_menu_new; + static Ptr_gtk_expander_new gtk_expander_new; + static Ptr_gtk_button_new gtk_button_new; + static Ptr_gtk_tool_button_new gtk_tool_button_new; + static Ptr_gtk_hbutton_box_new gtk_hbutton_box_new; + static Ptr_gtk_check_button_new gtk_check_button_new; + static Ptr_gtk_radio_button_new gtk_radio_button_new; + static Ptr_gtk_spin_button_new gtk_spin_button_new; + static Ptr_gtk_separator_tool_item_new gtk_separator_tool_item_new; + static Ptr_gtk_toolbar_insert gtk_toolbar_insert; + static Ptr_gtk_frame_new gtk_frame_new; + static Ptr_gtk_statusbar_new gtk_statusbar_new; + static Ptr_gtk_entry_new gtk_entry_new; + static Ptr_gtk_hscale_new gtk_hscale_new; + static Ptr_gtk_vscale_new gtk_vscale_new; + static Ptr_gtk_hscrollbar_new gtk_hscrollbar_new; + static Ptr_gtk_vscrollbar_new gtk_vscrollbar_new; + static Ptr_gtk_scrolled_window_new gtk_scrolled_window_new; + static Ptr_gtk_notebook_new gtk_notebook_new; + static Ptr_gtk_toolbar_new gtk_toolbar_new; + static Ptr_gtk_tree_view_new gtk_tree_view_new; + static Ptr_gtk_tree_view_get_column gtk_tree_view_get_column; + static Ptr_gtk_combo_box_new gtk_combo_box_new; + static Ptr_gtk_combo_box_entry_new gtk_combo_box_entry_new; + static Ptr_gtk_progress_bar_new gtk_progress_bar_new; + static Ptr_gtk_container_add gtk_container_add; + static Ptr_gtk_menu_shell_append gtk_menu_shell_append; + static Ptr_gtk_progress_configure gtk_progress_configure; + static Ptr_gtk_range_get_adjustment gtk_range_get_adjustment; + static Ptr_gtk_range_set_adjustment gtk_range_set_adjustment; + static Ptr_gtk_range_set_inverted gtk_range_set_inverted; + static Ptr_gtk_icon_factory_lookup_default gtk_icon_factory_lookup_default; + static Ptr_gtk_icon_theme_get_default gtk_icon_theme_get_default; + static Ptr_gtk_widget_style_get gtk_widget_style_get; + static Ptr_gtk_icon_set_render_icon gtk_icon_set_render_icon; + static Ptr_gtk_fixed_new gtk_fixed_new; + static Ptr_gtk_tree_view_column_new gtk_tree_view_column_new; + static Ptr_gtk_tree_view_append_column gtk_tree_view_append_column; + static Ptr_gtk_paint_check gtk_paint_check; + static Ptr_gtk_paint_box gtk_paint_box; + static Ptr_gtk_paint_box_gap gtk_paint_box_gap; + static Ptr_gtk_paint_flat_box gtk_paint_flat_box; + static Ptr_gtk_paint_option gtk_paint_option; + static Ptr_gtk_paint_extension gtk_paint_extension; + static Ptr_gtk_paint_slider gtk_paint_slider; + static Ptr_gtk_paint_shadow gtk_paint_shadow; + static Ptr_gtk_paint_resize_grip gtk_paint_resize_grip; + static Ptr_gtk_paint_focus gtk_paint_focus; + static Ptr_gtk_paint_arrow gtk_paint_arrow; + static Ptr_gtk_paint_handle gtk_paint_handle; + static Ptr_gtk_paint_expander gtk_paint_expander; + static Ptr_gtk_adjustment_configure gtk_adjustment_configure; + static Ptr_gtk_adjustment_new gtk_adjustment_new; + static Ptr_gtk_paint_vline gtk_paint_vline; + static Ptr_gtk_paint_hline gtk_paint_hline; + static Ptr_gtk_menu_item_set_submenu gtk_menu_item_set_submenu; + static Ptr_gtk_settings_get_default gtk_settings_get_default; + static Ptr_gtk_separator_menu_item_new gtk_separator_menu_item_new; + static Ptr_gtk_widget_size_allocate gtk_widget_size_allocate; + static Ptr_gtk_widget_size_request gtk_widget_size_request; + static Ptr_gtk_widget_set_direction gtk_widget_set_direction; + static Ptr_gtk_widget_path gtk_widget_path; + static Ptr_gtk_container_get_type gtk_container_get_type; + static Ptr_gtk_window_get_type gtk_window_get_type; + static Ptr_gtk_widget_get_type gtk_widget_get_type; + static Ptr_gtk_rc_get_style_by_paths gtk_rc_get_style_by_paths; + static Ptr_gtk_check_version gtk_check_version; + static Ptr_gtk_border_free gtk_border_free; + + static Ptr_pango_font_description_get_size pango_font_description_get_size; + static Ptr_pango_font_description_get_weight pango_font_description_get_weight; + static Ptr_pango_font_description_get_family pango_font_description_get_family; + static Ptr_pango_font_description_get_style pango_font_description_get_style; + + static Ptr_gtk_file_filter_new gtk_file_filter_new; + static Ptr_gtk_file_filter_set_name gtk_file_filter_set_name; + static Ptr_gtk_file_filter_add_pattern gtk_file_filter_add_pattern; + static Ptr_gtk_file_chooser_add_filter gtk_file_chooser_add_filter; + static Ptr_gtk_file_chooser_set_filter gtk_file_chooser_set_filter; + static Ptr_gtk_file_chooser_get_filter gtk_file_chooser_get_filter; + static Ptr_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new; + static Ptr_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder; + static Ptr_gtk_file_chooser_get_filename gtk_file_chooser_get_filename; + static Ptr_gtk_file_chooser_get_filenames gtk_file_chooser_get_filenames; + static Ptr_gtk_file_chooser_set_current_name gtk_file_chooser_set_current_name; + static Ptr_gtk_dialog_run gtk_dialog_run; + static Ptr_gtk_file_chooser_set_filename gtk_file_chooser_set_filename; + + static Ptr_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels; + static Ptr_gdk_pixbuf_get_width gdk_pixbuf_get_width; + static Ptr_gdk_pixbuf_get_height gdk_pixbuf_get_height; + static Ptr_gdk_pixmap_new gdk_pixmap_new; + static Ptr_gdk_pixbuf_new gdk_pixbuf_new; + static Ptr_gdk_pixbuf_get_from_drawable gdk_pixbuf_get_from_drawable; + static Ptr_gdk_draw_rectangle gdk_draw_rectangle; + static Ptr_gdk_pixbuf_unref gdk_pixbuf_unref; + static Ptr_gdk_drawable_unref gdk_drawable_unref; + static Ptr_gdk_drawable_get_depth gdk_drawable_get_depth; + static Ptr_gdk_color_free gdk_color_free; + static Ptr_gdk_x11_window_set_user_time gdk_x11_window_set_user_time; + static Ptr_gdk_x11_drawable_get_xid gdk_x11_drawable_get_xid; + static Ptr_gdk_x11_drawable_get_xdisplay gdk_x11_drawable_get_xdisplay; + + static Ptr_gconf_client_get_default gconf_client_get_default; + static Ptr_gconf_client_get_string gconf_client_get_string; + static Ptr_gconf_client_get_bool gconf_client_get_bool; + + static Ptr_gnome_icon_lookup_sync gnome_icon_lookup_sync; + static Ptr_gnome_vfs_init gnome_vfs_init; + + virtual QPalette gtkWidgetPalette(const QHashableLatin1Literal >kWidgetName) const; + +protected: + typedef QHash WidgetMap; + + static inline void destroyWidgetMap() + { + cleanupGtkWidgets(); + delete widgetMap; + widgetMap = 0; + } + + static inline WidgetMap *gtkWidgetMap() + { + if (!widgetMap) { + widgetMap = new WidgetMap(); + qAddPostRoutine(destroyWidgetMap); + } + return widgetMap; + } + + static QStringList extract_filter(const QString &rawFilter); + + virtual GtkWidget* getTextColorWidget() const; + static void setupGtkWidget(GtkWidget* widget); + static void addWidgetToMap(GtkWidget* widget); + static void addAllSubWidgets(GtkWidget *widget, gpointer v = 0); + static void addWidget(GtkWidget *widget); + static void removeWidgetFromMap(const QHashableLatin1Literal &path); + + virtual void init(); + +private: + static QList instances; + static WidgetMap *widgetMap; + friend class QGtkStyleUpdateScheduler; +}; + +// Helper to ensure that we have polished all our gtk widgets +// before updating our own palettes +class QGtkStyleUpdateScheduler : public QObject +{ + Q_OBJECT +public slots: + void updateTheme(); +}; + +QT_END_NAMESPACE + +#endif // !QT_NO_STYLE_GTK +#endif // QGTKSTYLE_P_H diff --git a/src/widgets/styles/qmacstyle.qdoc b/src/widgets/styles/qmacstyle.qdoc new file mode 100644 index 0000000000..2f42d7156b --- /dev/null +++ b/src/widgets/styles/qmacstyle.qdoc @@ -0,0 +1,247 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of this +** file. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +/*! + \class QMacStyle + \brief The QMacStyle class provides a Mac OS X style using the Apple Appearance Manager. + + \ingroup appearance + + This class is implemented as a wrapper to the HITheme + APIs, allowing applications to be styled according to the current + theme in use on Mac OS X. This is done by having primitives + in QStyle implemented in terms of what Mac OS X would normally theme. + + \warning This style is only available on Mac OS X because it relies on the + HITheme APIs. + + There are additional issues that should be taken + into consideration to make an application compatible with the + \link http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/index.html + Apple Human Interface Guidelines \endlink. Some of these issues are outlined + below. + + \list + + \i Layout - The restrictions on window layout are such that some + aspects of layout that are style-dependent cannot be achieved + using QLayout. Changes are being considered (and feedback would be + appreciated) to make layouts QStyle-able. Some of the restrictions + involve horizontal and vertical widget alignment and widget size + (covered below). + + \i Widget size - Mac OS X allows widgets to have specific fixed sizes. Qt + does not fully implement this behavior so as to maintain cross-platform + compatibility. As a result some widgets sizes may be inappropriate (and + subsequently not rendered correctly by the HITheme APIs).The + QWidget::sizeHint() will return the appropriate size for many + managed widgets (widgets enumerated in \l QStyle::ContentsType). + + \i Effects - QMacStyle uses HITheme for performing most of the drawing, but + also uses emulation in a few cases where HITheme does not provide the + required functionality (for example, tab bars on Panther, the toolbar + separator, etc). We tried to make the emulation as close to the original as + possible. Please report any issues you see in effects or non-standard + widgets. + + \endlist + + There are other issues that need to be considered in the feel of + your application (including the general color scheme to match the + Aqua colors). The Guidelines mentioned above will remain current + with new advances and design suggestions for Mac OS X. + + Note that the functions provided by QMacStyle are + reimplementations of QStyle functions; see QStyle for their + documentation. + + \img qmacstyle.png + \sa QWindowsXPStyle, QWindowsStyle, QPlastiqueStyle, QCDEStyle, QMotifStyle +*/ + + +/*! + \enum QMacStyle::WidgetSizePolicy + + \value SizeSmall + \value SizeLarge + \value SizeMini + \value SizeDefault + \omitvalue SizeNone +*/ + +/*! \fn QMacStyle::QMacStyle() + Constructs a QMacStyle object. +*/ + +/*! \fn QMacStyle::~QMacStyle() + Destructs a QMacStyle object. +*/ + +/*! \fn void QMacStyle::polish(QPalette &pal) + \reimp +*/ + +/*! \fn void QMacStyle::polish(QApplication *) + \reimp +*/ + +/*! \fn void QMacStyle::unpolish(QApplication *) + \reimp +*/ + +/*! \fn void QMacStyle::polish(QWidget* w) + \reimp +*/ + +/*! \fn void QMacStyle::unpolish(QWidget* w) + \reimp +*/ + +/*! \fn int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const + \reimp +*/ + +/*! \fn QPalette QMacStyle::standardPalette() const + \reimp +*/ + +/*! \fn int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w, QStyleHintReturn *hret) const + \reimp +*/ + +/*! \fn QPixmap QMacStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const + \reimp +*/ + +/*! \fn QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const + \reimp +*/ + +/*! + \enum QMacStyle::FocusRectPolicy + + This type is used to signify a widget's focus rectangle policy. + + \value FocusEnabled show a focus rectangle when the widget has focus. + \value FocusDisabled never show a focus rectangle for the widget. + \value FocusDefault show a focus rectangle when the widget has + focus and the widget is a QSpinWidget, QDateTimeEdit, QLineEdit, + QListBox, QListView, editable QTextEdit, or one of their + subclasses. +*/ + +/*! \fn void QMacStyle::setFocusRectPolicy(QWidget *w, FocusRectPolicy policy) + \obsolete + Sets the focus rectangle policy of \a w. The \a policy can be one of + \l{QMacStyle::FocusRectPolicy}. + + This is now simply an interface to the Qt::WA_MacShowFocusRect attribute and the + FocusDefault value does nothing anymore. If you want to set a widget back + to its default value, you must save the old value of the attribute before + you change it. + + \sa focusRectPolicy() QWidget::setAttribute() +*/ + +/*! \fn QMacStyle::FocusRectPolicy QMacStyle::focusRectPolicy(const QWidget *w) + \obsolete + Returns the focus rectangle policy for the widget \a w. + + The focus rectangle policy can be one of \l{QMacStyle::FocusRectPolicy}. + + In 4.3 and up this function will simply test for the + Qt::WA_MacShowFocusRect attribute and will never return + QMacStyle::FocusDefault. + + \sa setFocusRectPolicy(), QWidget::testAttribute() +*/ + +/*! \fn void QMacStyle::setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy) + + \obsolete + + Call QWidget::setAttribute() with Qt::WA_MacMiniSize, Qt::WA_MacSmallSize, + or Qt::WA_MacNormalSize instead. +*/ + +/*! \fn QMacStyle::WidgetSizePolicy QMacStyle::widgetSizePolicy(const QWidget *widget) + \obsolete + + Call QWidget::testAttribute() with Qt::WA_MacMiniSize, Qt::WA_MacSmallSize, + or Qt::WA_MacNormalSize instead. +*/ + +/*! \fn void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const + + \reimp +*/ + +/*! \fn void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p, const QWidget *w) const + + \reimp +*/ + +/*! \fn QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *widget) const + + \reimp +*/ + +/*! \fn void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const + \reimp +*/ + +/*! \fn QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, const QPoint &pt, const QWidget *widget) const + \reimp +*/ + +/*! \fn QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const + \reimp +*/ + +/*! \fn QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &csz, const QWidget *widget) const + \reimp +*/ + +/*! \fn void QMacStyle::drawItemText(QPainter *p, const QRect &r, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole) const + \reimp +*/ + +/*! \fn bool QMacStyle::event(QEvent *e) + \reimp +*/ + +/*! \fn QIcon QMacStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt, const QWidget *widget) const + \internal +*/ + +/*! \fn int QMacStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget) const + + \internal +*/ + diff --git a/src/widgets/styles/qmacstyle_mac.h b/src/widgets/styles/qmacstyle_mac.h new file mode 100644 index 0000000000..78a25ce9b2 --- /dev/null +++ b/src/widgets/styles/qmacstyle_mac.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMACSTYLE_MAC_H +#define QMACSTYLE_MAC_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) + +class QPalette; + +#if defined(QT_PLUGIN) +#define Q_GUI_EXPORT_STYLE_MAC +#else +#define Q_GUI_EXPORT_STYLE_MAC Q_GUI_EXPORT +#endif + +class QPushButton; +class QStyleOptionButton; +class QMacStylePrivate; +class Q_GUI_EXPORT_STYLE_MAC QMacStyle : public QWindowsStyle +{ + Q_OBJECT +public: + QMacStyle(); + virtual ~QMacStyle(); + + void polish(QWidget *w); + void unpolish(QWidget *w); + + void polish(QApplication*); + void unpolish(QApplication*); + + void polish(QPalette &pal); + + void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const; + void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const; + QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const; + void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, + const QWidget *w = 0) const; + SubControl hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *w = 0) const; + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, + const QWidget *w = 0) const; + QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, + const QSize &contentsSize, const QWidget *w = 0) const; + + int pixelMetric(PixelMetric pm, const QStyleOption *opt = 0, const QWidget *widget = 0) const; + + QPalette standardPalette() const; + + virtual int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0, + QStyleHintReturn *shret = 0) const; + + enum FocusRectPolicy { FocusEnabled, FocusDisabled, FocusDefault }; + static void setFocusRectPolicy(QWidget *w, FocusRectPolicy policy); + static FocusRectPolicy focusRectPolicy(const QWidget *w); + + enum WidgetSizePolicy { SizeSmall, SizeLarge, SizeMini, SizeDefault +#ifdef QT3_SUPPORT + , SizeNone = SizeDefault +#endif + }; + static void setWidgetSizePolicy(const QWidget *w, WidgetSizePolicy policy); + static WidgetSizePolicy widgetSizePolicy(const QWidget *w); + + QPixmap standardPixmap(StandardPixmap sp, const QStyleOption *opt, + const QWidget *widget = 0) const; + + QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *opt) const; + + virtual void drawItemText(QPainter *p, const QRect &r, int flags, const QPalette &pal, + bool enabled, const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const; + + bool event(QEvent *e); + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt = 0, + const QWidget *widget = 0) const; + int layoutSpacingImplementation(QSizePolicy::ControlType control1, + QSizePolicy::ControlType control2, + Qt::Orientation orientation, + const QStyleOption *option = 0, + const QWidget *widget = 0) const; + +private: + Q_DISABLE_COPY(QMacStyle) + + QMacStylePrivate *d; + + friend bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option); +}; + +#endif // Q_WS_MAC + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMACSTYLE_H diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm new file mode 100644 index 0000000000..2d21628488 --- /dev/null +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -0,0 +1,6042 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + Note: The qdoc comments for QMacStyle are contained in + .../doc/src/qstyles.qdoc. +*/ + +#include "qmacstyle_mac.h" + +#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) +#define QMAC_QAQUASTYLE_SIZE_CONSTRAIN +//#define DEBUG_SIZE_CONSTRAINT + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qmacstyle_mac_p.h" +#include + +QT_BEGIN_NAMESPACE + +// The following constants are used for adjusting the size +// of push buttons so that they are drawn inside their bounds. +const int QMacStylePrivate::PushButtonLeftOffset = 6; +const int QMacStylePrivate::PushButtonTopOffset = 4; +const int QMacStylePrivate::PushButtonRightOffset = 12; +const int QMacStylePrivate::PushButtonBottomOffset = 12; +const int QMacStylePrivate::MiniButtonH = 26; +const int QMacStylePrivate::SmallButtonH = 30; +const int QMacStylePrivate::BevelButtonW = 50; +const int QMacStylePrivate::BevelButtonH = 22; +const int QMacStylePrivate::PushButtonContentPadding = 6; + +// These colors specify the titlebar gradient colors on +// Leopard. Ideally we should get them from the system. +static const QColor titlebarGradientActiveBegin(220, 220, 220); +static const QColor titlebarGradientActiveEnd(151, 151, 151); +static const QColor titlebarSeparatorLineActive(111, 111, 111); +static const QColor titlebarGradientInactiveBegin(241, 241, 241); +static const QColor titlebarGradientInactiveEnd(207, 207, 207); +static const QColor titlebarSeparatorLineInactive(131, 131, 131); + +// Gradient colors used for the dock widget title bar and +// non-unifed tool bar bacground. +static const QColor mainWindowGradientBegin(240, 240, 240); +static const QColor mainWindowGradientEnd(200, 200, 200); + +static const int DisclosureOffset = 4; + +// Resolve these at run-time, since the functions was moved in Leopard. +typedef HIRect * (*PtrHIShapeGetBounds)(HIShapeRef, HIRect *); +static PtrHIShapeGetBounds ptrHIShapeGetBounds = 0; + +static int closeButtonSize = 12; + +extern QRegion qt_mac_convert_mac_region(RgnHandle); //qregion_mac.cpp + +static bool isVerticalTabs(const QTabBar::Shape shape) { + return (shape == QTabBar::RoundedEast + || shape == QTabBar::TriangularEast + || shape == QTabBar::RoundedWest + || shape == QTabBar::TriangularWest); +} + +void drawTabCloseButton(QPainter *p, bool hover, bool active, bool selected) +{ + // draw background circle + p->setRenderHints(QPainter::Antialiasing); + QRect rect(0, 0, closeButtonSize, closeButtonSize); + QColor background; + if (hover) { + background = QColor(124, 124, 124); + } else { + if (active) { + if (selected) + background = QColor(104, 104, 104); + else + background = QColor(83, 83, 83); + } else { + if (selected) + background = QColor(144, 144, 144); + else + background = QColor(114, 114, 114); + } + } + p->setPen(Qt::transparent); + p->setBrush(background); + p->drawEllipse(rect); + + // draw cross + int min = 3; + int max = 9; + QPen crossPen; + crossPen.setColor(QColor(194, 194, 194)); + crossPen.setWidthF(1.3); + crossPen.setCapStyle(Qt::FlatCap); + p->setPen(crossPen); + p->drawLine(min, min, max, max); + p->drawLine(min, max, max, min); +} + +QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect) +{ + if (isVerticalTabs(shape)) { + int newX, newY, newRot; + if (shape == QTabBar::RoundedEast + || shape == QTabBar::TriangularEast) { + newX = tabRect.width(); + newY = tabRect.y(); + newRot = 90; + } else { + newX = 0; + newY = tabRect.y() + tabRect.height(); + newRot = -90; + } + tabRect.setRect(0, 0, tabRect.height(), tabRect.width()); + QMatrix m; + m.translate(newX, newY); + m.rotate(newRot); + p->setMatrix(m, true); + } + return tabRect; +} + +void drawTabShape(QPainter *p, const QStyleOptionTabV3 *tabOpt) +{ + QRect r = tabOpt->rect; + p->translate(tabOpt->rect.x(), tabOpt->rect.y()); + r.moveLeft(0); + r.moveTop(0); + QRect tabRect = rotateTabPainter(p, tabOpt->shape, r); + + int width = tabRect.width(); + int height = 20; + bool active = (tabOpt->state & QStyle::State_Active); + bool selected = (tabOpt->state & QStyle::State_Selected); + + if (selected) { + QRect rect(1, 0, width - 2, height); + + // fill body + if (active) { + int d = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ? 16 : 0; + p->fillRect(rect, QColor(151 + d, 151 + d, 151 + d)); + } else { + int d = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ? 9 : 0; + QLinearGradient gradient(rect.topLeft(), rect.bottomLeft()); + gradient.setColorAt(0, QColor(207 + d, 207 + d, 207 + d)); + gradient.setColorAt(0.5, QColor(206 + d, 206 + d, 206 + d)); + gradient.setColorAt(1, QColor(201 + d, 201 + d, 201 + d)); + p->fillRect(rect, gradient); + } + + // draw border + QColor borderSides; + QColor borderBottom; + if (active) { + borderSides = QColor(88, 88, 88); + borderBottom = QColor(88, 88, 88); + } else { + borderSides = QColor(121, 121, 121); + borderBottom = QColor(116, 116, 116); + } + + p->setPen(borderSides); + + int bottom = height; + // left line + p->drawLine(0, 1, 0, bottom-2); + // right line + p->drawLine(width-1, 1, width-1, bottom-2); + + // bottom line + if (active) { + p->setPen(QColor(168, 168, 168)); + p->drawLine(3, bottom-1, width-3, bottom-1); + } + p->setPen(borderBottom); + p->drawLine(2, bottom, width-2, bottom); + + int w = 3; + QRectF rectangleLeft(1, height - w, w, w); + QRectF rectangleRight(width - 2, height - 1, w, w); + int startAngle = 180 * 16; + int spanAngle = 90 * 16; + p->setRenderHint(QPainter::Antialiasing); + p->drawArc(rectangleLeft, startAngle, spanAngle); + p->drawArc(rectangleRight, startAngle, -spanAngle); + } else { + // when the mouse is over non selected tabs they get a new color + bool hover = (tabOpt->state & QStyle::State_MouseOver); + if (hover) { + QRect rect(1, 2, width - 1, height - 1); + p->fillRect(rect, QColor(110, 110, 110)); + } + + // seperator lines between tabs + bool west = (tabOpt->shape == QTabBar::RoundedWest || tabOpt->shape == QTabBar::TriangularWest); + bool drawOnRight = !west; + if ((!drawOnRight && tabOpt->selectedPosition != QStyleOptionTab::NextIsSelected) + || (drawOnRight && tabOpt->selectedPosition != QStyleOptionTab::NextIsSelected)) { + QColor borderColor; + QColor borderHighlightColor; + if (active) { + borderColor = QColor(64, 64, 64); + borderHighlightColor = QColor(140, 140, 140); + } else { + borderColor = QColor(135, 135, 135); + borderHighlightColor = QColor(178, 178, 178); + } + + int x = drawOnRight ? width : 0; + + // tab seperator line + p->setPen(borderColor); + p->drawLine(x, 2, x, height + 1); + + // tab seperator highlight + p->setPen(borderHighlightColor); + p->drawLine(x-1, 2, x-1, height + 1); + p->drawLine(x+1, 2, x+1, height + 1); + } + } +} + +void drawTabBase(QPainter *p, const QStyleOptionTabBarBaseV2 *tbb, const QWidget *w) +{ + QRect r = tbb->rect; + if (isVerticalTabs(tbb->shape)) { + r.setWidth(w->width()); + } else { + r.setHeight(w->height()); + } + QRect tabRect = rotateTabPainter(p, tbb->shape, r); + int width = tabRect.width(); + int height = tabRect.height(); + bool active = (tbb->state & QStyle::State_Active); + + // top border lines + QColor borderHighlightTop; + QColor borderTop; + if (active) { + borderTop = QColor(64, 64, 64); + borderHighlightTop = QColor(174, 174, 174); + } else { + borderTop = QColor(135, 135, 135); + borderHighlightTop = QColor(207, 207, 207); + } + p->setPen(borderHighlightTop); + p->drawLine(tabRect.x(), 0, width, 0); + p->setPen(borderTop); + p->drawLine(tabRect.x(), 1, width, 1); + + // center block + QRect centralRect(tabRect.x(), 2, width, height - 2); + if (active) { + QColor mainColor = QColor(120, 120, 120); + p->fillRect(centralRect, mainColor); + } else { + QLinearGradient gradient(centralRect.topLeft(), centralRect.bottomLeft()); + gradient.setColorAt(0, QColor(165, 165, 165)); + gradient.setColorAt(0.5, QColor(164, 164, 164)); + gradient.setColorAt(1, QColor(158, 158, 158)); + p->fillRect(centralRect, gradient); + } + + // bottom border lines + QColor borderHighlightBottom; + QColor borderBottom; + if (active) { + borderHighlightBottom = QColor(153, 153, 153); + borderBottom = QColor(64, 64, 64); + } else { + borderHighlightBottom = QColor(177, 177, 177); + borderBottom = QColor(127, 127, 127); + } + p->setPen(borderHighlightBottom); + p->drawLine(tabRect.x(), height - 2, width, height - 2); + p->setPen(borderBottom); + p->drawLine(tabRect.x(), height - 1, width, height - 1); +} + +static int getControlSize(const QStyleOption *option, const QWidget *widget) +{ + if (option) { + if (option->state & (QStyle::State_Small | QStyle::State_Mini)) + return (option->state & QStyle::State_Mini) ? QAquaSizeMini : QAquaSizeSmall; + } else if (widget) { + switch (QMacStyle::widgetSizePolicy(widget)) { + case QMacStyle::SizeSmall: + return QAquaSizeSmall; + case QMacStyle::SizeMini: + return QAquaSizeMini; + default: + break; + } + } + return QAquaSizeLarge; +} + + +static inline bool isTreeView(const QWidget *widget) +{ + return (widget && widget->parentWidget() && + (qobject_cast(widget->parentWidget()) +#ifdef QT3_SUPPORT + || widget->parentWidget()->inherits("Q3ListView") +#endif + )); +} + +QString qt_mac_removeMnemonics(const QString &original) +{ + QString returnText(original.size(), 0); + int finalDest = 0; + int currPos = 0; + int l = original.length(); + while (l) { + if (original.at(currPos) == QLatin1Char('&') + && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) { + ++currPos; + --l; + if (l == 0) + break; + } + returnText[finalDest] = original.at(currPos); + ++currPos; + ++finalDest; + --l; + } + returnText.truncate(finalDest); + return returnText; +} + +static inline ThemeTabDirection getTabDirection(QTabBar::Shape shape) +{ + ThemeTabDirection ttd; + switch (shape) { + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + ttd = kThemeTabSouth; + break; + default: // Added to remove the warning, since all values are taken care of, really! + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + ttd = kThemeTabNorth; + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + ttd = kThemeTabWest; + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + ttd = kThemeTabEast; + break; + } + return ttd; +} + +QT_BEGIN_INCLUDE_NAMESPACE +#include "moc_qmacstyle_mac.cpp" +#include "moc_qmacstyle_mac_p.cpp" +QT_END_INCLUDE_NAMESPACE + +/***************************************************************************** + External functions + *****************************************************************************/ +extern CGContextRef qt_mac_cg_context(const QPaintDevice *); //qpaintdevice_mac.cpp +extern QRegion qt_mac_convert_mac_region(HIShapeRef); //qregion_mac.cpp +void qt_mac_dispose_rgn(RgnHandle r); //qregion_mac.cpp +extern QPaintDevice *qt_mac_safe_pdev; //qapplication_mac.cpp + +/***************************************************************************** + QMacCGStyle globals + *****************************************************************************/ +const int qt_mac_hitheme_version = 0; //the HITheme version we speak +const int macItemFrame = 2; // menu item frame width +const int macItemHMargin = 3; // menu item hor text margin +const int macItemVMargin = 2; // menu item ver text margin +const int macRightBorder = 12; // right border on mac +const ThemeWindowType QtWinType = kThemeDocumentWindow; // Window type we use for QTitleBar. +QPixmap *qt_mac_backgroundPattern = 0; // stores the standard widget background. + +/***************************************************************************** + QMacCGStyle utility functions + *****************************************************************************/ +static inline int qt_mac_hitheme_tab_version() +{ + return 1; +} + +static inline HIRect qt_hirectForQRect(const QRect &convertRect, const QRect &rect = QRect()) +{ + return CGRectMake(convertRect.x() + rect.x(), convertRect.y() + rect.y(), + convertRect.width() - rect.width(), convertRect.height() - rect.height()); +} + +static inline const QRect qt_qrectForHIRect(const HIRect &hirect) +{ + return QRect(QPoint(int(hirect.origin.x), int(hirect.origin.y)), + QSize(int(hirect.size.width), int(hirect.size.height))); +} + +inline bool qt_mac_is_metal(const QWidget *w) +{ + for (; w; w = w->parentWidget()) { + if (w->testAttribute(Qt::WA_MacBrushedMetal)) + return true; + if (w->isWindow() && w->testAttribute(Qt::WA_WState_Created)) { // If not created will fall through to the opaque check and be fine anyway. + return macWindowIsTextured(qt_mac_window_for(w)); + } + if (w->d_func()->isOpaque) + break; + } + return false; +} + +static int qt_mac_aqua_get_metric(ThemeMetric met) +{ + SInt32 ret; + GetThemeMetric(met, &ret); + return ret; +} + +static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg, QSize szHint, + QAquaWidgetSize sz) +{ + QSize ret(-1, -1); + if (sz != QAquaSizeSmall && sz != QAquaSizeLarge && sz != QAquaSizeMini) { + qDebug("Not sure how to return this..."); + return ret; + } + if ((widg && widg->testAttribute(Qt::WA_SetFont)) || !QApplication::desktopSettingsAware()) { + // If you're using a custom font and it's bigger than the default font, + // then no constraints for you. If you are smaller, we can try to help you out + QFont font = qt_app_fonts_hash()->value(widg->metaObject()->className(), QFont()); + if (widg->font().pointSize() > font.pointSize()) + return ret; + } + + if (ct == QStyle::CT_CustomBase && widg) { + if (qobject_cast(widg)) + ct = QStyle::CT_PushButton; + else if (qobject_cast(widg)) + ct = QStyle::CT_RadioButton; + else if (qobject_cast(widg)) + ct = QStyle::CT_CheckBox; + else if (qobject_cast(widg)) + ct = QStyle::CT_ComboBox; + else if (qobject_cast(widg)) + ct = QStyle::CT_ToolButton; + else if (qobject_cast(widg)) + ct = QStyle::CT_Slider; + else if (qobject_cast(widg)) + ct = QStyle::CT_ProgressBar; + else if (qobject_cast(widg)) + ct = QStyle::CT_LineEdit; + else if (qobject_cast(widg) +#ifdef QT3_SUPPORT + || widg->inherits("Q3Header") +#endif + ) + ct = QStyle::CT_HeaderSection; + else if (qobject_cast(widg) +#ifdef QT3_SUPPORT + || widg->inherits("Q3MenuBar") +#endif + ) + ct = QStyle::CT_MenuBar; + else if (qobject_cast(widg)) + ct = QStyle::CT_SizeGrip; + else + return ret; + } + + switch (ct) { + case QStyle::CT_PushButton: { + const QPushButton *psh = qobject_cast(widg); + // If this comparison is false, then the widget was not a push button. + // This is bad and there's very little we can do since we were requested to find a + // sensible size for a widget that pretends to be a QPushButton but is not. + if(psh) { + QString buttonText = qt_mac_removeMnemonics(psh->text()); + if (buttonText.contains(QLatin1Char('\n'))) + ret = QSize(-1, -1); + else if (sz == QAquaSizeLarge) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight)); + else if (sz == QAquaSizeSmall) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPushButtonHeight)); + else if (sz == QAquaSizeMini) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPushButtonHeight)); + + if (!psh->icon().isNull()){ + // If the button got an icon, and the icon is larger than the + // button, we can't decide on a default size + ret.setWidth(-1); + if (ret.height() < psh->iconSize().height()) + ret.setHeight(-1); + } + else if (buttonText == QLatin1String("OK") || buttonText == QLatin1String("Cancel")){ + // Aqua Style guidelines restrict the size of OK and Cancel buttons to 68 pixels. + // However, this doesn't work for German, therefore only do it for English, + // I suppose it would be better to do some sort of lookups for languages + // that like to have really long words. + ret.setWidth(77 - 8); + } + } else { + // The only sensible thing to do is to return whatever the style suggests... + if (sz == QAquaSizeLarge) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight)); + else if (sz == QAquaSizeSmall) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPushButtonHeight)); + else if (sz == QAquaSizeMini) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPushButtonHeight)); + else + // Since there's no default size we return the large size... + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight)); + } +#if 0 //Not sure we are applying the rules correctly for RadioButtons/CheckBoxes --Sam + } else if (ct == QStyle::CT_RadioButton) { + QRadioButton *rdo = static_cast(widg); + // Exception for case where multiline radio button text requires no size constrainment + if (rdo->text().find('\n') != -1) + return ret; + if (sz == QAquaSizeLarge) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricRadioButtonHeight)); + else if (sz == QAquaSizeSmall) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallRadioButtonHeight)); + else if (sz == QAquaSizeMini) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniRadioButtonHeight)); + } else if (ct == QStyle::CT_CheckBox) { + if (sz == QAquaSizeLarge) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricCheckBoxHeight)); + else if (sz == QAquaSizeSmall) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallCheckBoxHeight)); + else if (sz == QAquaSizeMini) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniCheckBoxHeight)); +#endif + break; + } + case QStyle::CT_SizeGrip: + if (sz == QAquaSizeLarge || sz == QAquaSizeSmall) { + HIRect r; + HIPoint p = { 0, 0 }; + HIThemeGrowBoxDrawInfo gbi; + gbi.version = 0; + gbi.state = kThemeStateActive; + gbi.kind = kHIThemeGrowBoxKindNormal; + gbi.direction = QApplication::isRightToLeft() ? kThemeGrowLeft | kThemeGrowDown + : kThemeGrowRight | kThemeGrowDown; + gbi.size = sz == QAquaSizeSmall ? kHIThemeGrowBoxSizeSmall : kHIThemeGrowBoxSizeNormal; + if (HIThemeGetGrowBoxBounds(&p, &gbi, &r) == noErr) + ret = QSize(r.size.width, r.size.height); + } + break; + case QStyle::CT_ComboBox: + switch (sz) { + case QAquaSizeLarge: + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPopupButtonHeight)); + break; + case QAquaSizeSmall: + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPopupButtonHeight)); + break; + case QAquaSizeMini: + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPopupButtonHeight)); + break; + default: + break; + } + break; + case QStyle::CT_ToolButton: + if (sz == QAquaSizeSmall) { + int width = 0, height = 0; + if (szHint == QSize(-1, -1)) { //just 'guess'.. + const QToolButton *bt = qobject_cast(widg); + // If this conversion fails then the widget was not what it claimed to be. + if(bt) { + if (!bt->icon().isNull()) { + QSize iconSize = bt->iconSize(); + QSize pmSize = bt->icon().actualSize(QSize(32, 32), QIcon::Normal); + width = qMax(width, qMax(iconSize.width(), pmSize.width())); + height = qMax(height, qMax(iconSize.height(), pmSize.height())); + } + if (!bt->text().isNull() && bt->toolButtonStyle() != Qt::ToolButtonIconOnly) { + int text_width = bt->fontMetrics().width(bt->text()), + text_height = bt->fontMetrics().height(); + if (bt->toolButtonStyle() == Qt::ToolButtonTextUnderIcon) { + width = qMax(width, text_width); + height += text_height; + } else { + width += text_width; + width = qMax(height, text_height); + } + } + } else { + // Let's return the size hint... + width = szHint.width(); + height = szHint.height(); + } + } else { + width = szHint.width(); + height = szHint.height(); + } + width = qMax(20, width + 5); //border + height = qMax(20, height + 5); //border + ret = QSize(width, height); + } + break; + case QStyle::CT_Slider: { + int w = -1; + const QSlider *sld = qobject_cast(widg); + // If this conversion fails then the widget was not what it claimed to be. + if(sld) { + if (sz == QAquaSizeLarge) { + if (sld->orientation() == Qt::Horizontal) { + w = qt_mac_aqua_get_metric(kThemeMetricHSliderHeight); + if (sld->tickPosition() != QSlider::NoTicks) + w += qt_mac_aqua_get_metric(kThemeMetricHSliderTickHeight); + } else { + w = qt_mac_aqua_get_metric(kThemeMetricVSliderWidth); + if (sld->tickPosition() != QSlider::NoTicks) + w += qt_mac_aqua_get_metric(kThemeMetricVSliderTickWidth); + } + } else if (sz == QAquaSizeSmall) { + if (sld->orientation() == Qt::Horizontal) { + w = qt_mac_aqua_get_metric(kThemeMetricSmallHSliderHeight); + if (sld->tickPosition() != QSlider::NoTicks) + w += qt_mac_aqua_get_metric(kThemeMetricSmallHSliderTickHeight); + } else { + w = qt_mac_aqua_get_metric(kThemeMetricSmallVSliderWidth); + if (sld->tickPosition() != QSlider::NoTicks) + w += qt_mac_aqua_get_metric(kThemeMetricSmallVSliderTickWidth); + } + } else if (sz == QAquaSizeMini) { + if (sld->orientation() == Qt::Horizontal) { + w = qt_mac_aqua_get_metric(kThemeMetricMiniHSliderHeight); + if (sld->tickPosition() != QSlider::NoTicks) + w += qt_mac_aqua_get_metric(kThemeMetricMiniHSliderTickHeight); + } else { + w = qt_mac_aqua_get_metric(kThemeMetricMiniVSliderWidth); + if (sld->tickPosition() != QSlider::NoTicks) + w += qt_mac_aqua_get_metric(kThemeMetricMiniVSliderTickWidth); + } + } + } else { + // This is tricky, we were requested to find a size for a slider which is not + // a slider. We don't know if this is vertical or horizontal or if we need to + // have tick marks or not. + // For this case we will return an horizontal slider without tick marks. + w = qt_mac_aqua_get_metric(kThemeMetricHSliderHeight); + w += qt_mac_aqua_get_metric(kThemeMetricHSliderTickHeight); + } + if (sld->orientation() == Qt::Horizontal) + ret.setHeight(w); + else + ret.setWidth(w); + break; + } + case QStyle::CT_ProgressBar: { + int finalValue = -1; + Qt::Orientation orient = Qt::Horizontal; + if (const QProgressBar *pb = qobject_cast(widg)) + orient = pb->orientation(); + + if (sz == QAquaSizeLarge) + finalValue = qt_mac_aqua_get_metric(kThemeMetricLargeProgressBarThickness) + + qt_mac_aqua_get_metric(kThemeMetricProgressBarShadowOutset); + else + finalValue = qt_mac_aqua_get_metric(kThemeMetricNormalProgressBarThickness) + + qt_mac_aqua_get_metric(kThemeMetricSmallProgressBarShadowOutset); + if (orient == Qt::Horizontal) + ret.setHeight(finalValue); + else + ret.setWidth(finalValue); + break; + } + case QStyle::CT_LineEdit: + if (!widg || !qobject_cast(widg->parentWidget())) { + //should I take into account the font dimentions of the lineedit? -Sam + if (sz == QAquaSizeLarge) + ret = QSize(-1, 22); + else + ret = QSize(-1, 19); + } + break; + case QStyle::CT_HeaderSection: + if (isTreeView(widg)) + ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricListHeaderHeight)); + break; + case QStyle::CT_MenuBar: + if (sz == QAquaSizeLarge) { +#ifndef QT_MAC_USE_COCOA + SInt16 size; + if (!GetThemeMenuBarHeight(&size)) + ret = QSize(-1, size); +#else + ret = QSize(-1, [[NSApp mainMenu] menuBarHeight]); + // In the qt_mac_set_native_menubar(false) case, + // we come it here with a zero-height main menu, + // preventing the in-window menu from displaying. + // Use 22 pixels for the height, by observation. + if (ret.height() <= 0) + ret.setHeight(22); +#endif + } + break; + default: + break; + } + return ret; +} + + +#if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT) +static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSize small, QSize mini) +{ + if (large == QSize(-1, -1)) { + if (small != QSize(-1, -1)) + return QAquaSizeSmall; + if (mini != QSize(-1, -1)) + return QAquaSizeMini; + return QAquaSizeUnknown; + } else if (small == QSize(-1, -1)) { + if (mini != QSize(-1, -1)) + return QAquaSizeMini; + return QAquaSizeLarge; + } else if (mini == QSize(-1, -1)) { + return QAquaSizeLarge; + } + +#ifndef QT_NO_MAINWINDOW + if (qobject_cast(widg->window()) || !qgetenv("QWIDGET_ALL_SMALL").isNull()) { + //if (small.width() != -1 || small.height() != -1) + return QAquaSizeSmall; + } else if (!qgetenv("QWIDGET_ALL_MINI").isNull()) { + return QAquaSizeMini; + } +#endif + +#if 0 + /* Figure out which size we're closer to, I just hacked this in, I haven't + tested it as it would probably look pretty strange to have some widgets + big and some widgets small in the same window?? -Sam */ + int large_delta=0; + if (large.width() != -1) { + int delta = large.width() - widg->width(); + large_delta += delta * delta; + } + if (large.height() != -1) { + int delta = large.height() - widg->height(); + large_delta += delta * delta; + } + int small_delta=0; + if (small.width() != -1) { + int delta = small.width() - widg->width(); + small_delta += delta * delta; + } + if (small.height() != -1) { + int delta = small.height() - widg->height(); + small_delta += delta * delta; + } + int mini_delta=0; + if (mini.width() != -1) { + int delta = mini.width() - widg->width(); + mini_delta += delta * delta; + } + if (mini.height() != -1) { + int delta = mini.height() - widg->height(); + mini_delta += delta * delta; + } + if (mini_delta < small_delta && mini_delta < large_delta) + return QAquaSizeMini; + else if (small_delta < large_delta) + return QAquaSizeSmall; +#endif + return QAquaSizeLarge; +} +#endif + +QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, const QWidget *widg, + QStyle::ContentsType ct, QSize szHint, QSize *insz) const +{ +#if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT) + if (option) { + if (option->state & QStyle::State_Small) + return QAquaSizeSmall; + if (option->state & QStyle::State_Mini) + return QAquaSizeMini; + } + + if (!widg) { + if (insz) + *insz = QSize(); + if (!qgetenv("QWIDGET_ALL_SMALL").isNull()) + return QAquaSizeSmall; + if (!qgetenv("QWIDGET_ALL_MINI").isNull()) + return QAquaSizeMini; + return QAquaSizeUnknown; + } + QSize large = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeLarge), + small = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeSmall), + mini = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeMini); + bool guess_size = false; + QAquaWidgetSize ret = QAquaSizeUnknown; + QMacStyle::WidgetSizePolicy wsp = q->widgetSizePolicy(widg); + if (wsp == QMacStyle::SizeDefault) + guess_size = true; + else if (wsp == QMacStyle::SizeMini) + ret = QAquaSizeMini; + else if (wsp == QMacStyle::SizeSmall) + ret = QAquaSizeSmall; + else if (wsp == QMacStyle::SizeLarge) + ret = QAquaSizeLarge; + if (guess_size) + ret = qt_aqua_guess_size(widg, large, small, mini); + + QSize *sz = 0; + if (ret == QAquaSizeSmall) + sz = &small; + else if (ret == QAquaSizeLarge) + sz = &large; + else if (ret == QAquaSizeMini) + sz = &mini; + if (insz) + *insz = sz ? *sz : QSize(-1, -1); +#ifdef DEBUG_SIZE_CONSTRAINT + if (sz) { + const char *size_desc = "Unknown"; + if (sz == &small) + size_desc = "Small"; + else if (sz == &large) + size_desc = "Large"; + else if (sz == &mini) + size_desc = "Mini"; + qDebug("%s - %s: %s taken (%d, %d) [%d, %d]", + widg ? widg->objectName().toLatin1().constData() : "*Unknown*", + widg ? widg->metaObject()->className() : "*Unknown*", size_desc, widg->width(), widg->height(), + sz->width(), sz->height()); + } +#endif + return ret; +#else + if (insz) + *insz = QSize(); + Q_UNUSED(widg); + Q_UNUSED(ct); + Q_UNUSED(szHint); + return QAquaSizeUnknown; +#endif +} + +/** + Returns the free space awailable for contents inside the + button (and not the size of the contents itself) +*/ +HIRect QMacStylePrivate::pushButtonContentBounds(const QStyleOptionButton *btn, + const HIThemeButtonDrawInfo *bdi) const +{ + HIRect outerBounds = qt_hirectForQRect(btn->rect); + // Adjust the bounds to correct for + // carbon not calculating the content bounds fully correct + if (bdi->kind == kThemePushButton || bdi->kind == kThemePushButtonSmall){ + outerBounds.origin.y += QMacStylePrivate::PushButtonTopOffset; + outerBounds.size.height -= QMacStylePrivate::PushButtonBottomOffset; + } else if (bdi->kind == kThemePushButtonMini) { + outerBounds.origin.y += QMacStylePrivate::PushButtonTopOffset; + } + + HIRect contentBounds; + HIThemeGetButtonContentBounds(&outerBounds, bdi, &contentBounds); + return contentBounds; +} + +/** + Calculates the size of the button contents. + This includes both the text and the icon. +*/ +QSize QMacStylePrivate::pushButtonSizeFromContents(const QStyleOptionButton *btn) const +{ + QSize csz(0, 0); + QSize iconSize = btn->icon.isNull() ? QSize(0, 0) + : (btn->iconSize + QSize(QMacStylePrivate::PushButtonContentPadding, 0)); + QRect textRect = btn->text.isEmpty() ? QRect(0, 0, 1, 1) + : btn->fontMetrics.boundingRect(QRect(), Qt::AlignCenter, btn->text); + csz.setWidth(iconSize.width() + textRect.width() + + ((btn->features & QStyleOptionButton::HasMenu) + ? q->proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, 0) : 0)); + csz.setHeight(qMax(iconSize.height(), textRect.height())); + return csz; +} + +/** + Checks if the actual contents of btn fits inside the free content bounds of + 'buttonKindToCheck'. Meant as a helper function for 'initHIThemePushButton' + for determining which button kind to use for drawing. +*/ +bool QMacStylePrivate::contentFitsInPushButton(const QStyleOptionButton *btn, + HIThemeButtonDrawInfo *bdi, + ThemeButtonKind buttonKindToCheck) const +{ + ThemeButtonKind tmp = bdi->kind; + bdi->kind = buttonKindToCheck; + QSize contentSize = pushButtonSizeFromContents(btn); + QRect freeContentRect = qt_qrectForHIRect(pushButtonContentBounds(btn, bdi)); + bdi->kind = tmp; + return freeContentRect.contains(QRect(freeContentRect.x(), freeContentRect.y(), + contentSize.width(), contentSize.height())); +} + +/** + Creates a HIThemeButtonDrawInfo structure that specifies the correct button + kind and other details to use for drawing the given push button. Which + button kind depends on the size of the button, the size of the contents, + explicit user style settings, etc. +*/ +void QMacStylePrivate::initHIThemePushButton(const QStyleOptionButton *btn, + const QWidget *widget, + const ThemeDrawState tds, + HIThemeButtonDrawInfo *bdi) const +{ + bool drawColorless = btn->palette.currentColorGroup() == QPalette::Active; + ThemeDrawState tdsModified = tds; + if (btn->state & QStyle::State_On) + tdsModified = kThemeStatePressed; + bdi->version = qt_mac_hitheme_version; + bdi->state = tdsModified; + bdi->value = kThemeButtonOff; + + if (drawColorless && tdsModified == kThemeStateInactive) + bdi->state = kThemeStateActive; + if (btn->state & QStyle::State_HasFocus) + bdi->adornment = kThemeAdornmentFocus; + else + bdi->adornment = kThemeAdornmentNone; + + + if (btn->features & (QStyleOptionButton::Flat)) { + bdi->kind = kThemeBevelButton; + } else { + switch (aquaSizeConstrain(btn, widget)) { + case QAquaSizeSmall: + bdi->kind = kThemePushButtonSmall; + break; + case QAquaSizeMini: + bdi->kind = kThemePushButtonMini; + break; + case QAquaSizeLarge: + // ... We should honor if the user is explicit about using the + // large button. But right now Qt will specify the large button + // as default rather than QAquaSizeUnknown. + // So we treat it like QAquaSizeUnknown + // to get the dynamic choosing of button kind. + case QAquaSizeUnknown: + // Choose the button kind that closest match the button rect, but at the + // same time displays the button contents without clipping. + bdi->kind = kThemeBevelButton; + if (btn->rect.width() >= QMacStylePrivate::BevelButtonW && btn->rect.height() >= QMacStylePrivate::BevelButtonH){ + if (widget && widget->testAttribute(Qt::WA_MacVariableSize)) { + if (btn->rect.height() <= QMacStylePrivate::MiniButtonH){ + if (contentFitsInPushButton(btn, bdi, kThemePushButtonMini)) + bdi->kind = kThemePushButtonMini; + } else if (btn->rect.height() <= QMacStylePrivate::SmallButtonH){ + if (contentFitsInPushButton(btn, bdi, kThemePushButtonSmall)) + bdi->kind = kThemePushButtonSmall; + } else if (contentFitsInPushButton(btn, bdi, kThemePushButton)) { + bdi->kind = kThemePushButton; + } + } else { + bdi->kind = kThemePushButton; + } + } + } + } +} + +bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option) +{ + QMacStyle *macStyle = qobject_cast(pushButton->style()); + if (!macStyle) + return false; + HIThemeButtonDrawInfo bdi; + macStyle->d->initHIThemePushButton(option, pushButton, kThemeStateActive, &bdi); + return bdi.kind == kThemeBevelButton; +} + +/** + Creates a HIThemeButtonDrawInfo structure that specifies the correct button + kind and other details to use for drawing the given combobox. Which button + kind depends on the size of the combo, wether or not it is editable, + explicit user style settings, etc. +*/ +void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi, + const QWidget *widget, const ThemeDrawState &tds) +{ + bdi->version = qt_mac_hitheme_version; + bdi->adornment = kThemeAdornmentArrowLeftArrow; + bdi->value = kThemeButtonOff; + if (combo->state & QStyle::State_HasFocus) + bdi->adornment = kThemeAdornmentFocus; + bool drawColorless = combo->palette.currentColorGroup() == QPalette::Active && tds == kThemeStateInactive; + if (combo->activeSubControls & QStyle::SC_ComboBoxArrow) + bdi->state = kThemeStatePressed; + else if (drawColorless) + bdi->state = kThemeStateActive; + else + bdi->state = tds; + + QAquaWidgetSize aSize = aquaSizeConstrain(combo, widget); + switch (aSize) { + case QAquaSizeMini: + bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxMini) + : ThemeButtonKind(kThemePopupButtonMini); + break; + case QAquaSizeSmall: + bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxSmall) + : ThemeButtonKind(kThemePopupButtonSmall); + break; + case QAquaSizeUnknown: + case QAquaSizeLarge: + // Unless the user explicitly specified large buttons, determine the + // kind by looking at the combox size. + // ... specifying small and mini-buttons it not a current feature of + // Qt (e.g. QWidget::getAttribute(WA_ButtonSize)). But when it is, add + // an extra check here before using the mini and small buttons. + int h = combo->rect.size().height(); + if (combo->editable){ + if (h < 21) + bdi->kind = kThemeComboBoxMini; + else if (h < 26) + bdi->kind = kThemeComboBoxSmall; + else + bdi->kind = kThemeComboBox; + } else { + // Even if we specify that we want the kThemePopupButton, Carbon + // will use the kThemePopupButtonSmall if the size matches. So we + // do the same size check explicit to have the size of the inner + // text field be correct. Therefore, do this even if the user specifies + // the use of LargeButtons explicit. + if (h < 21) + bdi->kind = kThemePopupButtonMini; + else if (h < 26) + bdi->kind = kThemePopupButtonSmall; + else + bdi->kind = kThemePopupButton; + } + break; + } +} + +/** + Carbon draws comboboxes (and other views) outside the rect given as argument. Use this function to obtain + the corresponding inner rect for drawing the same combobox so that it stays inside the given outerBounds. +*/ +HIRect QMacStylePrivate::comboboxInnerBounds(const HIRect &outerBounds, int buttonKind) +{ + HIRect innerBounds = outerBounds; + // Carbon draw parts of the view outside the rect. + // So make the rect a bit smaller to compensate + // (I wish HIThemeGetButtonBackgroundBounds worked) + switch (buttonKind){ + case kThemePopupButton: + innerBounds.origin.x += 2; + innerBounds.origin.y += 3; + innerBounds.size.width -= 5; + innerBounds.size.height -= 6; + break; + case kThemePopupButtonSmall: + innerBounds.origin.x += 3; + innerBounds.origin.y += 3; + innerBounds.size.width -= 6; + innerBounds.size.height -= 7; + break; + case kThemePopupButtonMini: + innerBounds.origin.x += 2; + innerBounds.origin.y += 2; + innerBounds.size.width -= 5; + innerBounds.size.height -= 6; + break; + case kThemeComboBox: + innerBounds.origin.x += 3; + innerBounds.origin.y += 3; + innerBounds.size.width -= 6; + innerBounds.size.height -= 6; + break; + case kThemeComboBoxSmall: + innerBounds.origin.x += 3; + innerBounds.origin.y += 3; + innerBounds.size.width -= 7; + innerBounds.size.height -= 8; + break; + case kThemeComboBoxMini: + innerBounds.origin.x += 3; + innerBounds.origin.y += 3; + innerBounds.size.width -= 4; + innerBounds.size.height -= 8; + break; + default: + break; + } + return innerBounds; +} + +/** + Inside a combobox Qt places a line edit widget. The size of this widget should depend on the kind + of combobox we choose to draw. This function calculates and returns this size. +*/ +QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi) +{ + QRect ret = outerBounds; + switch (bdi.kind){ + case kThemeComboBox: + ret.adjust(5, 8, -21, -4); + break; + case kThemeComboBoxSmall: + ret.adjust(4, 5, -18, 0); + ret.setHeight(16); + break; + case kThemeComboBoxMini: + ret.adjust(4, 5, -16, 0); + ret.setHeight(13); + break; + case kThemePopupButton: + ret.adjust(10, 3, -23, -3); + break; + case kThemePopupButtonSmall: + ret.adjust(9, 3, -20, -3); + break; + case kThemePopupButtonMini: + ret.adjust(8, 3, -19, 0); + ret.setHeight(13); + break; + } + return ret; +} + +/** + Carbon comboboxes don't scale (sight). If the size of the combo suggest a scaled version, + create it manually by drawing a small Carbon combo onto a pixmap (use pixmap cache), chop + it up, and copy it back onto the widget. Othervise, draw the combobox supplied by Carbon directly. +*/ +void QMacStylePrivate::drawCombobox(const HIRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p) +{ + if (!(bdi.kind == kThemeComboBox && outerBounds.size.height > 28)){ + // We have an unscaled combobox, or popup-button; use Carbon directly. + HIRect innerBounds = QMacStylePrivate::comboboxInnerBounds(outerBounds, bdi.kind); + HIThemeDrawButton(&innerBounds, &bdi, QMacCGContext(p), kHIThemeOrientationNormal, 0); + } else { + QPixmap buffer; + QString key = QString(QLatin1String("$qt_cbox%1-%2")).arg(int(bdi.state)).arg(int(bdi.adornment)); + if (!QPixmapCache::find(key, buffer)) { + HIRect innerBoundsSmallCombo = {{3, 3}, {29, 25}}; + buffer = QPixmap(35, 28); + buffer.fill(Qt::transparent); + QPainter buffPainter(&buffer); + HIThemeDrawButton(&innerBoundsSmallCombo, &bdi, QMacCGContext(&buffPainter), kHIThemeOrientationNormal, 0); + buffPainter.end(); + QPixmapCache::insert(key, buffer); + } + + const int bwidth = 20; + const int fwidth = 10; + const int fheight = 10; + int w = qRound(outerBounds.size.width); + int h = qRound(outerBounds.size.height); + int bstart = w - bwidth; + int blower = fheight + 1; + int flower = h - fheight; + int sheight = flower - fheight; + int center = qRound(outerBounds.size.height + outerBounds.origin.y) / 2; + + // Draw upper and lower gap + p->drawPixmap(fwidth, 0, bstart - fwidth, fheight, buffer, fwidth, 0, 1, fheight); + p->drawPixmap(fwidth, flower, bstart - fwidth, fheight, buffer, fwidth, buffer.height() - fheight, 1, fheight); + // Draw left and right gap. Right gap is drawn top and bottom separatly + p->drawPixmap(0, fheight, fwidth, sheight, buffer, 0, fheight, fwidth, 1); + p->drawPixmap(bstart, fheight, bwidth, center - fheight, buffer, buffer.width() - bwidth, fheight - 1, bwidth, 1); + p->drawPixmap(bstart, center, bwidth, sheight / 2, buffer, buffer.width() - bwidth, fheight + 6, bwidth, 1); + // Draw arrow + p->drawPixmap(bstart, center - 4, bwidth - 3, 6, buffer, buffer.width() - bwidth, fheight, bwidth - 3, 6); + // Draw corners + p->drawPixmap(0, 0, fwidth, fheight, buffer, 0, 0, fwidth, fheight); + p->drawPixmap(bstart, 0, bwidth, fheight, buffer, buffer.width() - bwidth, 0, bwidth, fheight); + p->drawPixmap(0, flower, fwidth, fheight, buffer, 0, buffer.height() - fheight, fwidth, fheight); + p->drawPixmap(bstart, h - blower, bwidth, blower, buffer, buffer.width() - bwidth, buffer.height() - blower, bwidth, blower); + } +} + +/** + Carbon tableheaders don't scale (sight). So create it manually by drawing a small Carbon header + onto a pixmap (use pixmap cache), chop it up, and copy it back onto the widget. +*/ +void QMacStylePrivate::drawTableHeader(const HIRect &outerBounds, + bool drawTopBorder, bool drawLeftBorder, const HIThemeButtonDrawInfo &bdi, QPainter *p) +{ + static SInt32 headerHeight = 0; + static OSStatus err = GetThemeMetric(kThemeMetricListHeaderHeight, &headerHeight); + Q_UNUSED(err); + + QPixmap buffer; + QString key = QString(QLatin1String("$qt_tableh%1-%2-%3")).arg(int(bdi.state)).arg(int(bdi.adornment)).arg(int(bdi.value)); + if (!QPixmapCache::find(key, buffer)) { + HIRect headerNormalRect = {{0., 0.}, {16., CGFloat(headerHeight)}}; + buffer = QPixmap(headerNormalRect.size.width, headerNormalRect.size.height); + buffer.fill(Qt::transparent); + QPainter buffPainter(&buffer); + HIThemeDrawButton(&headerNormalRect, &bdi, QMacCGContext(&buffPainter), kHIThemeOrientationNormal, 0); + buffPainter.end(); + QPixmapCache::insert(key, buffer); + } + const int buttonw = qRound(outerBounds.size.width); + const int buttonh = qRound(outerBounds.size.height); + const int framew = 1; + const int frameh_n = 4; + const int frameh_s = 3; + const int transh = buffer.height() - frameh_n - frameh_s; + int center = buttonh - frameh_s - int(transh / 2.0f) + 1; // Align bottom; + + int skipTopBorder = 0; + if (!drawTopBorder) + skipTopBorder = 1; + + p->translate(outerBounds.origin.x, outerBounds.origin.y); + + p->drawPixmap(QRect(QRect(0, -skipTopBorder, buttonw - framew , frameh_n)), buffer, QRect(framew, 0, 1, frameh_n)); + p->drawPixmap(QRect(0, buttonh - frameh_s, buttonw - framew, frameh_s), buffer, QRect(framew, buffer.height() - frameh_s, 1, frameh_s)); + // Draw upper and lower center blocks + p->drawPixmap(QRect(0, frameh_n - skipTopBorder, buttonw - framew, center - frameh_n + skipTopBorder), buffer, QRect(framew, frameh_n, 1, 1)); + p->drawPixmap(QRect(0, center, buttonw - framew, buttonh - center - frameh_s), buffer, QRect(framew, buffer.height() - frameh_s, 1, 1)); + // Draw right center block borders + p->drawPixmap(QRect(buttonw - framew, frameh_n - skipTopBorder, framew, center - frameh_n), buffer, QRect(buffer.width() - framew, frameh_n, framew, 1)); + p->drawPixmap(QRect(buttonw - framew, center, framew, buttonh - center - 1), buffer, QRect(buffer.width() - framew, buffer.height() - frameh_s, framew, 1)); + // Draw right corners + p->drawPixmap(QRect(buttonw - framew, -skipTopBorder, framew, frameh_n), buffer, QRect(buffer.width() - framew, 0, framew, frameh_n)); + p->drawPixmap(QRect(buttonw - framew, buttonh - frameh_s, framew, frameh_s), buffer, QRect(buffer.width() - framew, buffer.height() - frameh_s, framew, frameh_s)); + // Draw center transition block + p->drawPixmap(QRect(0, center - qRound(transh / 2.0f), buttonw - framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(framew, frameh_n + 1, 1, transh)); + // Draw right center transition block border + p->drawPixmap(QRect(buttonw - framew, center - qRound(transh / 2.0f), framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(buffer.width() - framew, frameh_n + 1, framew, transh)); + if (drawLeftBorder){ + // Draw left center block borders + p->drawPixmap(QRect(0, frameh_n - skipTopBorder, framew, center - frameh_n + skipTopBorder), buffer, QRect(0, frameh_n, framew, 1)); + p->drawPixmap(QRect(0, center, framew, buttonh - center - 1), buffer, QRect(0, buffer.height() - frameh_s, framew, 1)); + // Draw left corners + p->drawPixmap(QRect(0, -skipTopBorder, framew, frameh_n), buffer, QRect(0, 0, framew, frameh_n)); + p->drawPixmap(QRect(0, buttonh - frameh_s, framew, frameh_s), buffer, QRect(0, buffer.height() - frameh_s, framew, frameh_s)); + // Draw left center transition block border + p->drawPixmap(QRect(0, center - qRound(transh / 2.0f), framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(0, frameh_n + 1, framew, transh)); + } + + p->translate(-outerBounds.origin.x, -outerBounds.origin.y); +} + +/* + Returns cutoff sizes for scroll bars. + thumbIndicatorCutoff is the smallest size where the thumb indicator is drawn. + scrollButtonsCutoff is the smallest size where the up/down buttons is drawn. +*/ +enum ScrollBarCutoffType { thumbIndicatorCutoff = 0, scrollButtonsCutoff = 1 }; +static int scrollButtonsCutoffSize(ScrollBarCutoffType cutoffType, QMacStyle::WidgetSizePolicy widgetSize) +{ + // Mini scroll bars do not exist as of version 10.4. + if (widgetSize == QMacStyle::SizeMini) + return 0; + + const int sizeIndex = (widgetSize == QMacStyle::SizeSmall) ? 1 : 0; + static const int sizeTable[2][2] = { { 61, 56 }, { 49, 44 } }; + return sizeTable[sizeIndex][cutoffType]; +} + +void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider, + HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe) +{ + memset(tdi, 0, sizeof(HIThemeTrackDrawInfo)); // We don't get it all for some reason or another... + tdi->version = qt_mac_hitheme_version; + tdi->reserved = 0; + tdi->filler1 = 0; + bool isScrollbar = (cc == QStyle::CC_ScrollBar); + switch (aquaSizeConstrain(0, needToRemoveMe)) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + if (isScrollbar) + tdi->kind = kThemeMediumScrollBar; + else + tdi->kind = kThemeMediumSlider; + break; + case QAquaSizeMini: + if (isScrollbar) + tdi->kind = kThemeSmallScrollBar; // should be kThemeMiniScrollBar, but not implemented + else + tdi->kind = kThemeMiniSlider; + break; + case QAquaSizeSmall: + if (isScrollbar) + tdi->kind = kThemeSmallScrollBar; + else + tdi->kind = kThemeSmallSlider; + break; + } + tdi->bounds = qt_hirectForQRect(slider->rect); + tdi->min = slider->minimum; + tdi->max = slider->maximum; + tdi->value = slider->sliderPosition; + tdi->attributes = kThemeTrackShowThumb; + if (slider->upsideDown) + tdi->attributes |= kThemeTrackRightToLeft; + if (slider->orientation == Qt::Horizontal) { + tdi->attributes |= kThemeTrackHorizontal; + if (isScrollbar && slider->direction == Qt::RightToLeft) { + if (!slider->upsideDown) + tdi->attributes |= kThemeTrackRightToLeft; + else + tdi->attributes &= ~kThemeTrackRightToLeft; + } + } + + // Tiger broke reverse scroll bars so put them back and "fake it" + if (isScrollbar && (tdi->attributes & kThemeTrackRightToLeft)) { + tdi->attributes &= ~kThemeTrackRightToLeft; + tdi->value = tdi->max - slider->sliderPosition; + } + + tdi->enableState = (slider->state & QStyle::State_Enabled) ? kThemeTrackActive + : kThemeTrackDisabled; + if (!(slider->state & QStyle::State_Active)) + tdi->enableState = kThemeTrackInactive; + if (!isScrollbar) { + if (slider->state & QStyle::QStyle::State_HasFocus) + tdi->attributes |= kThemeTrackHasFocus; + if (slider->tickPosition == QSlider::NoTicks || slider->tickPosition == QSlider::TicksBothSides) + tdi->trackInfo.slider.thumbDir = kThemeThumbPlain; + else if (slider->tickPosition == QSlider::TicksAbove) + tdi->trackInfo.slider.thumbDir = kThemeThumbUpward; + else + tdi->trackInfo.slider.thumbDir = kThemeThumbDownward; + } else { + tdi->trackInfo.scrollbar.viewsize = slider->pageStep; + } +} +#endif + +QMacStylePrivate::QMacStylePrivate(QMacStyle *style) + : timerID(-1), progressFrame(0), q(style), mouseDown(false) +{ + defaultButtonStart = CFAbsoluteTimeGetCurrent(); + memset(&buttonState, 0, sizeof(ButtonState)); + + if (ptrHIShapeGetBounds == 0) { + QLibrary library(QLatin1String("/System/Library/Frameworks/Carbon.framework/Carbon")); + library.setLoadHints(QLibrary::ExportExternalSymbolsHint); + ptrHIShapeGetBounds = reinterpret_cast(library.resolve("HIShapeGetBounds")); + } + +} + +bool QMacStylePrivate::animatable(QMacStylePrivate::Animates as, const QWidget *w) const +{ + if (!w) + return false; + + if (as == AquaPushButton) { + QPushButton *pb = const_cast(static_cast(w)); + if (w->window()->isActiveWindow() && pb && !mouseDown) { + if (static_cast(w) != defaultButton) { + // Changed on its own, update the value. + const_cast(this)->stopAnimate(as, defaultButton); + const_cast(this)->startAnimate(as, pb); + } + return true; + } + } else if (as == AquaProgressBar) { + if (progressBars.contains((const_cast(w)))) + return true; + } + return false; +} + +void QMacStylePrivate::stopAnimate(QMacStylePrivate::Animates as, QWidget *w) +{ + if (as == AquaPushButton && defaultButton) { + QPushButton *tmp = defaultButton; + defaultButton = 0; + tmp->update(); + } else if (as == AquaProgressBar) { + progressBars.removeAll(w); + } +} + +void QMacStylePrivate::startAnimate(QMacStylePrivate::Animates as, QWidget *w) +{ + if (as == AquaPushButton) + defaultButton = static_cast(w); + else if (as == AquaProgressBar) + progressBars.append(w); + startAnimationTimer(); +} + +void QMacStylePrivate::startAnimationTimer() +{ + if ((defaultButton || !progressBars.isEmpty()) && timerID <= -1) + timerID = startTimer(animateSpeed(AquaListViewItemOpen)); +} + +bool QMacStylePrivate::addWidget(QWidget *w) +{ + //already knew of it + if (static_cast(w) == defaultButton + || progressBars.contains(static_cast(w))) + return false; + + if (QPushButton *btn = qobject_cast(w)) { + btn->installEventFilter(this); + if (btn->isDefault() || (btn->autoDefault() && btn->hasFocus())) + startAnimate(AquaPushButton, btn); + return true; + } else { + bool isProgressBar = (qobject_cast(w) +#ifdef QT3_SUPPORT + || w->inherits("Q3ProgressBar") +#endif + ); + if (isProgressBar) { + w->installEventFilter(this); + startAnimate(AquaProgressBar, w); + return true; + } + } + if (w->isWindow()) { + w->installEventFilter(this); + return true; + } + return false; +} + +void QMacStylePrivate::removeWidget(QWidget *w) +{ + QPushButton *btn = qobject_cast(w); + if (btn && btn == defaultButton) { + stopAnimate(AquaPushButton, btn); + } else if (qobject_cast(w) +#ifdef QT3_SUPPORT + || w->inherits("Q3ProgressBar") +#endif + ) { + stopAnimate(AquaProgressBar, w); + } +} + +ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) +{ + ThemeDrawState tds = kThemeStateActive; + if (flags & QStyle::State_Sunken) { + tds = kThemeStatePressed; + } else if (flags & QStyle::State_Active) { + if (!(flags & QStyle::State_Enabled)) + tds = kThemeStateUnavailable; + } else { + if (flags & QStyle::State_Enabled) + tds = kThemeStateInactive; + else + tds = kThemeStateUnavailableInactive; + } + return tds; +} + +void QMacStylePrivate::timerEvent(QTimerEvent *) +{ + int animated = 0; + if (defaultButton && defaultButton->isEnabled() && defaultButton->window()->isActiveWindow() + && defaultButton->isVisibleTo(0) && (defaultButton->isDefault() + || (defaultButton->autoDefault() && defaultButton->hasFocus())) + && doAnimate(AquaPushButton)) { + ++animated; + defaultButton->update(); + } + if (!progressBars.isEmpty()) { + int i = 0; + while (i < progressBars.size()) { + QWidget *maybeProgress = progressBars.at(i); + if (!maybeProgress) { + progressBars.removeAt(i); + } else { + if (QProgressBar *pb = qobject_cast(maybeProgress)) { + if (pb->maximum() == 0 || (pb->value() > 0 && pb->value() < pb->maximum())) { + if (doAnimate(AquaProgressBar)) + pb->update(); + } + } +#ifdef QT3_SUPPORT + else { + // Watch me now... + QVariant progress = maybeProgress->property("progress"); + QVariant totalSteps = maybeProgress->property("totalSteps"); + if (progress.isValid() && totalSteps.isValid()) { + int intProgress = progress.toInt(); + int intTotalSteps = totalSteps.toInt(); + if (intTotalSteps == 0 || intProgress > 0 && intProgress < intTotalSteps) { + if (doAnimate(AquaProgressBar)) + maybeProgress->update(); + } + } + } +#endif + ++i; + } + } + if (i > 0) { + ++progressFrame; + animated += i; + } + } + if (animated <= 0) { + killTimer(timerID); + timerID = -1; + } +} + +bool QMacStylePrivate::eventFilter(QObject *o, QEvent *e) +{ + //animate + if (QProgressBar *pb = qobject_cast(o)) { + switch (e->type()) { + default: + break; + case QEvent::Show: + if (!progressBars.contains(pb)) + startAnimate(AquaProgressBar, pb); + break; + case QEvent::Destroy: + case QEvent::Hide: + progressBars.removeAll(pb); + } + } else if (QPushButton *btn = qobject_cast(o)) { + switch (e->type()) { + default: + break; + case QEvent::FocusIn: + if (btn->autoDefault()) + startAnimate(AquaPushButton, btn); + break; + case QEvent::Destroy: + case QEvent::Hide: + if (btn == defaultButton) + stopAnimate(AquaPushButton, btn); + break; + case QEvent::MouseButtonPress: + // It is very confusing to keep the button pulsing, so just stop the animation. + if (static_cast(e)->button() == Qt::LeftButton) + mouseDown = true; + stopAnimate(AquaPushButton, btn); + break; + case QEvent::MouseButtonRelease: + if (static_cast(e)->button() == Qt::LeftButton) + mouseDown = false; + // fall through + case QEvent::FocusOut: + case QEvent::Show: + case QEvent::WindowActivate: { + QList list = btn->window()->findChildren(); + for (int i = 0; i < list.size(); ++i) { + QPushButton *pBtn = list.at(i); + if ((e->type() == QEvent::FocusOut + && (pBtn->isDefault() || (pBtn->autoDefault() && pBtn->hasFocus())) + && pBtn != btn) + || ((e->type() == QEvent::Show || e->type() == QEvent::MouseButtonRelease + || e->type() == QEvent::WindowActivate) + && pBtn->isDefault())) { + if (pBtn->window()->isActiveWindow()) { + startAnimate(AquaPushButton, pBtn); + } + break; + } + } + break; } + } + } + return false; +} + +bool QMacStylePrivate::doAnimate(QMacStylePrivate::Animates as) +{ + if (as == AquaPushButton) { + } else if (as == AquaProgressBar) { + // something for later... + } else if (as == AquaListViewItemOpen) { + // To be revived later... + } + return true; +} + +void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi, + QPainter *p, const QStyleOption *opt) const +{ + int xoff = 0, + yoff = 0, + extraWidth = 0, + extraHeight = 0, + finalyoff = 0; + + const QStyleOptionComboBox *combo = qstyleoption_cast(opt); + int width = int(macRect.size.width) + extraWidth; + int height = int(macRect.size.height) + extraHeight; + + if (width <= 0 || height <= 0) + return; // nothing to draw + + QString key = QLatin1String("$qt_mac_style_ctb_") + QString::number(bdi->kind) + QLatin1Char('_') + + QString::number(bdi->value) + QLatin1Char('_') + QString::number(width) + + QLatin1Char('_') + QString::number(height); + QPixmap pm; + if (!QPixmapCache::find(key, pm)) { + QPixmap activePixmap(width, height); + activePixmap.fill(Qt::transparent); + { + if (combo){ + // Carbon combos don't scale. Therefore we draw it + // ourselves, if a scaled version is needed. + QPainter tmpPainter(&activePixmap); + QMacStylePrivate::drawCombobox(macRect, *bdi, &tmpPainter); + } + else { + QMacCGContext cg(&activePixmap); + HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height); + HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0); + } + } + + if (!combo && bdi->value == kThemeButtonOff) { + pm = activePixmap; + } else if (combo) { + QImage image = activePixmap.toImage(); + + for (int y = 0; y < height; ++y) { + QRgb *scanLine = reinterpret_cast(image.scanLine(y)); + + for (int x = 0; x < width; ++x) { + QRgb &pixel = scanLine[x]; + + int darkest = qRed(pixel); + int mid = qGreen(pixel); + int lightest = qBlue(pixel); + + if (darkest > mid) + qSwap(darkest, mid); + if (mid > lightest) + qSwap(mid, lightest); + if (darkest > mid) + qSwap(darkest, mid); + + int gray = (mid + 2 * lightest) / 3; + pixel = qRgba(gray, gray, gray, qAlpha(pixel)); + } + } + pm = QPixmap::fromImage(image); + } else { + QImage activeImage = activePixmap.toImage(); + QImage colorlessImage; + { + QPixmap colorlessPixmap(width, height); + colorlessPixmap.fill(Qt::transparent); + + QMacCGContext cg(&colorlessPixmap); + HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height); + int oldValue = bdi->value; + bdi->value = kThemeButtonOff; + HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0); + bdi->value = oldValue; + colorlessImage = colorlessPixmap.toImage(); + } + + for (int y = 0; y < height; ++y) { + QRgb *colorlessScanLine = reinterpret_cast(colorlessImage.scanLine(y)); + const QRgb *activeScanLine = reinterpret_cast(activeImage.scanLine(y)); + + for (int x = 0; x < width; ++x) { + QRgb &colorlessPixel = colorlessScanLine[x]; + QRgb activePixel = activeScanLine[x]; + + if (activePixel != colorlessPixel) { + int max = qMax(qMax(qRed(activePixel), qGreen(activePixel)), + qBlue(activePixel)); + QRgb newPixel = qRgba(max, max, max, qAlpha(activePixel)); + if (qGray(newPixel) < qGray(colorlessPixel) + || qAlpha(newPixel) > qAlpha(colorlessPixel)) + colorlessPixel = newPixel; + } + } + } + pm = QPixmap::fromImage(colorlessImage); + } + QPixmapCache::insert(key, pm); + } + p->drawPixmap(int(macRect.origin.x), int(macRect.origin.y) + finalyoff, width, height, pm); +} + +QMacStyle::QMacStyle() + : QWindowsStyle() +{ + d = new QMacStylePrivate(this); +} + +QMacStyle::~QMacStyle() +{ + delete qt_mac_backgroundPattern; + qt_mac_backgroundPattern = 0; + delete d; +} + +/*! \internal + Generates the standard widget background pattern. +*/ +QPixmap QMacStylePrivate::generateBackgroundPattern() const +{ + QPixmap px(4, 4); + QMacCGContext cg(&px); + HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationNormal); + const CGRect cgRect = CGRectMake(0, 0, px.width(), px.height()); + CGContextFillRect(cg, cgRect); + return px; +} + +/*! \internal + Fills the given \a rect with the pattern stored in \a brush. As an optimization, + HIThemeSetFill us used directly if we are filling with the standard background. +*/ +void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush) +{ + QPoint dummy; + const QPaintDevice *target = painter->device(); + const QPaintDevice *redirected = QPainter::redirected(target, &dummy); + const bool usePainter = redirected && redirected != target; + + if (!usePainter && qt_mac_backgroundPattern + && qt_mac_backgroundPattern->cacheKey() == brush.texture().cacheKey()) { + + painter->setClipRegion(rgn); + + QCFType cg = qt_mac_cg_context(target); + CGContextSaveGState(cg); + HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationInverted); + + const QVector &rects = rgn.rects(); + for (int i = 0; i < rects.size(); ++i) { + const QRect rect(rects.at(i)); + // Anchor the pattern to the top so it stays put when the window is resized. + CGContextSetPatternPhase(cg, CGSizeMake(rect.width(), rect.height())); + CGRect mac_rect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); + CGContextFillRect(cg, mac_rect); + } + + CGContextRestoreGState(cg); + } else { + const QRect rect(rgn.boundingRect()); + painter->setClipRegion(rgn); + painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); + } +} + +void QMacStyle::polish(QPalette &pal) +{ + if (!qt_mac_backgroundPattern) { + if (!qApp) + return; + qt_mac_backgroundPattern = new QPixmap(d->generateBackgroundPattern()); + } + + QColor pc(Qt::black); + pc = qcolorForTheme(kThemeBrushDialogBackgroundActive); + QBrush background(pc, *qt_mac_backgroundPattern); + pal.setBrush(QPalette::All, QPalette::Window, background); + pal.setBrush(QPalette::All, QPalette::Button, background); + + QCFString theme; + const OSErr err = CopyThemeIdentifier(&theme); + if (err == noErr && CFStringCompare(theme, kThemeAppearanceAquaGraphite, 0) == kCFCompareEqualTo) { + pal.setBrush(QPalette::All, QPalette::AlternateBase, QColor(240, 240, 240)); + } else { + pal.setBrush(QPalette::All, QPalette::AlternateBase, QColor(237, 243, 254)); + } +} + +void QMacStyle::polish(QApplication *) +{ +} + +void QMacStyle::unpolish(QApplication *) +{ +} + +void QMacStyle::polish(QWidget* w) +{ + d->addWidget(w); + if (qt_mac_is_metal(w) && !w->testAttribute(Qt::WA_SetPalette)) { + // Set a clear brush so that the metal shines through. + QPalette pal = w->palette(); + QBrush background(Qt::transparent); + pal.setBrush(QPalette::All, QPalette::Window, background); + pal.setBrush(QPalette::All, QPalette::Button, background); + w->setPalette(pal); + w->setAttribute(Qt::WA_SetPalette, false); + } + + if (qobject_cast(w) || qobject_cast(w)) { + w->setWindowOpacity(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 ? 0.985 : 0.94); + if (!w->testAttribute(Qt::WA_SetPalette)) { + QPixmap px(64, 64); + px.fill(Qt::white); + HIThemeMenuDrawInfo mtinfo; + mtinfo.version = qt_mac_hitheme_version; + mtinfo.menuType = kThemeMenuTypePopUp; + HIRect rect = CGRectMake(0, 0, px.width(), px.height()); + HIThemeDrawMenuBackground(&rect, &mtinfo, QCFType(qt_mac_cg_context(&px)), + kHIThemeOrientationNormal); + QPalette pal = w->palette(); + QBrush background(px); + pal.setBrush(QPalette::All, QPalette::Window, background); + pal.setBrush(QPalette::All, QPalette::Button, background); + w->setPalette(pal); + w->setAttribute(Qt::WA_SetPalette, false); + } + } + + if (QTabBar *tb = qobject_cast(w)) { + if (tb->documentMode()) { + w->setAttribute(Qt::WA_Hover); + w->setFont(qt_app_fonts_hash()->value("QSmallFont", QFont())); + QPalette p = w->palette(); + p.setColor(QPalette::WindowText, QColor(17, 17, 17)); + w->setPalette(p); + } + } + + QWindowsStyle::polish(w); + + if (QRubberBand *rubber = qobject_cast(w)) { + rubber->setWindowOpacity(0.25); + rubber->setAttribute(Qt::WA_PaintOnScreen, false); + rubber->setAttribute(Qt::WA_NoSystemBackground, false); + } +} + +void QMacStyle::unpolish(QWidget* w) +{ + d->removeWidget(w); + if ((qobject_cast(w) || qt_mac_is_metal(w)) && !w->testAttribute(Qt::WA_SetPalette)) { + QPalette pal = qApp->palette(w); + w->setPalette(pal); + w->setAttribute(Qt::WA_SetPalette, false); + w->setWindowOpacity(1.0); + } + + if (QComboBox *combo = qobject_cast(w)) { + if (!combo->isEditable()) { + if (QWidget *widget = combo->findChild()) + widget->setWindowOpacity(1.0); + } + } + + if (QRubberBand *rubber = ::qobject_cast(w)) { + rubber->setWindowOpacity(1.0); + rubber->setAttribute(Qt::WA_PaintOnScreen, true); + rubber->setAttribute(Qt::WA_NoSystemBackground, true); + } + + if (QFocusFrame *frame = qobject_cast(w)) + frame->setAttribute(Qt::WA_NoSystemBackground, true); + + QWindowsStyle::unpolish(w); +} + +int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const +{ + int controlSize = getControlSize(opt, widget); + SInt32 ret = 0; + + switch (metric) { + case PM_TabCloseIndicatorWidth: + case PM_TabCloseIndicatorHeight: + ret = closeButtonSize; + break; + case PM_ToolBarIconSize: + ret = proxy()->pixelMetric(PM_LargeIconSize); + break; + case PM_FocusFrameVMargin: + case PM_FocusFrameHMargin: + GetThemeMetric(kThemeMetricFocusRectOutset, &ret); + break; + case PM_DialogButtonsSeparator: + ret = -5; + break; + case PM_DialogButtonsButtonHeight: { + QSize sz; + ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz); + if (sz == QSize(-1, -1)) + ret = 32; + else + ret = sz.height(); + break; } + case PM_CheckListButtonSize: { + switch (d->aquaSizeConstrain(opt, widget)) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + GetThemeMetric(kThemeMetricCheckBoxWidth, &ret); + break; + case QAquaSizeMini: + GetThemeMetric(kThemeMetricMiniCheckBoxWidth, &ret); + break; + case QAquaSizeSmall: + GetThemeMetric(kThemeMetricSmallCheckBoxWidth, &ret); + break; + } + break; } + case PM_DialogButtonsButtonWidth: { + QSize sz; + ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz); + if (sz == QSize(-1, -1)) + ret = 70; + else + ret = sz.width(); + break; } + + case PM_MenuBarHMargin: + ret = 8; + break; + + case PM_MenuBarVMargin: + ret = 0; + break; + + case QStyle::PM_MenuDesktopFrameWidth: + ret = 5; + break; + + case PM_CheckBoxLabelSpacing: + case PM_RadioButtonLabelSpacing: + ret = 2; + break; + case PM_MenuScrollerHeight: +#if 0 + SInt16 ash, asw; + GetThemeMenuItemExtra(kThemeMenuItemScrollUpArrow, &ash, &asw); + ret = ash; +#else + ret = 15; // I hate having magic numbers in here... +#endif + break; + case PM_DefaultFrameWidth: +#ifndef QT_NO_MAINWINDOW + if (widget && (widget->isWindow() || !widget->parentWidget() + || (qobject_cast(widget->parentWidget()) + && static_cast(widget->parentWidget())->centralWidget() == widget)) + && (qobject_cast(widget) +#ifdef QT3_SUPPORT + || widget->inherits("QScrollView") +#endif + || widget->inherits("QWorkspaceChild"))) + ret = 0; + else +#endif + // The combo box popup has no frame. + if (qstyleoption_cast(opt) != 0) + ret = 0; + // Frame of mac style line edits is two pixels on top and one on the bottom + else if (qobject_cast(widget) != 0) + ret = 2; + else + ret = 1; + break; + case PM_MaximumDragDistance: + ret = -1; + break; + case PM_ScrollBarSliderMin: + ret = 24; + break; + case PM_SpinBoxFrameWidth: + GetThemeMetric(kThemeMetricEditTextFrameOutset, &ret); + switch (d->aquaSizeConstrain(opt, widget)) { + default: + ret += 2; + break; + case QAquaSizeMini: + ret += 1; + break; + } + break; + case PM_ButtonShiftHorizontal: + case PM_ButtonShiftVertical: + ret = 0; + break; + case PM_SliderLength: + ret = 17; + break; + case PM_ButtonDefaultIndicator: + ret = 0; + break; + case PM_TitleBarHeight: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(opt)) { + HIThemeWindowDrawInfo wdi; + wdi.version = qt_mac_hitheme_version; + wdi.state = kThemeStateActive; + wdi.windowType = QtWinType; + if (tb->titleBarState) + wdi.attributes = kThemeWindowHasFullZoom | kThemeWindowHasCloseBox + | kThemeWindowHasCollapseBox; + else if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + wdi.attributes = kThemeWindowHasCloseBox; + else + wdi.attributes = 0; + wdi.titleHeight = tb->rect.height(); + wdi.titleWidth = tb->rect.width(); + QCFType region; + HIRect hirect = qt_hirectForQRect(tb->rect); + if (hirect.size.width <= 0) + hirect.size.width = 100; + if (hirect.size.height <= 0) + hirect.size.height = 30; + + HIThemeGetWindowShape(&hirect, &wdi, kWindowTitleBarRgn, ®ion); + HIRect rect; + ptrHIShapeGetBounds(region, &rect); + ret = int(rect.size.height); + ret += 4; + } + break; + case PM_TabBarTabVSpace: + ret = 4; + break; + case PM_TabBarTabShiftHorizontal: + case PM_TabBarTabShiftVertical: + ret = 0; + break; + case PM_TabBarBaseHeight: + ret = 0; + break; + case PM_TabBarTabOverlap: + ret = 0; + break; + case PM_TabBarBaseOverlap: + switch (d->aquaSizeConstrain(opt, widget)) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + ret = 11; + break; + case QAquaSizeSmall: + ret = 8; + break; + case QAquaSizeMini: + ret = 7; + break; + } + break; + case PM_ScrollBarExtent: { + switch (d->aquaSizeConstrain(opt, widget)) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + GetThemeMetric(kThemeMetricScrollBarWidth, &ret); + break; + case QAquaSizeMini: + case QAquaSizeSmall: + GetThemeMetric(kThemeMetricSmallScrollBarWidth, &ret); + break; + } + break; } + case PM_IndicatorHeight: { + switch (d->aquaSizeConstrain(opt, widget)) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + GetThemeMetric(kThemeMetricCheckBoxHeight, &ret); + break; + case QAquaSizeMini: + GetThemeMetric(kThemeMetricMiniCheckBoxHeight, &ret); + break; + case QAquaSizeSmall: + GetThemeMetric(kThemeMetricSmallCheckBoxHeight, &ret); + break; + } + break; } + case PM_IndicatorWidth: { + switch (d->aquaSizeConstrain(opt, widget)) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + GetThemeMetric(kThemeMetricCheckBoxWidth, &ret); + break; + case QAquaSizeMini: + GetThemeMetric(kThemeMetricMiniCheckBoxWidth, &ret); + break; + case QAquaSizeSmall: + GetThemeMetric(kThemeMetricSmallCheckBoxWidth, &ret); + break; + } + ++ret; + break; } + case PM_ExclusiveIndicatorHeight: { + switch (d->aquaSizeConstrain(opt, widget)) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + GetThemeMetric(kThemeMetricRadioButtonHeight, &ret); + break; + case QAquaSizeMini: + GetThemeMetric(kThemeMetricMiniRadioButtonHeight, &ret); + break; + case QAquaSizeSmall: + GetThemeMetric(kThemeMetricSmallRadioButtonHeight, &ret); + break; + } + break; } + case PM_ExclusiveIndicatorWidth: { + switch (d->aquaSizeConstrain(opt, widget)) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + GetThemeMetric(kThemeMetricRadioButtonWidth, &ret); + break; + case QAquaSizeMini: + GetThemeMetric(kThemeMetricMiniRadioButtonWidth, &ret); + break; + case QAquaSizeSmall: + GetThemeMetric(kThemeMetricSmallRadioButtonWidth, &ret); + break; + } + ++ret; + break; } + case PM_MenuVMargin: + ret = 4; + break; + case PM_MenuPanelWidth: + ret = 0; + break; + case PM_ToolTipLabelFrameWidth: + ret = 0; + break; + case PM_SizeGripSize: { + QAquaWidgetSize aSize; + if (widget && widget->window()->windowType() == Qt::Tool) + aSize = QAquaSizeSmall; + else + aSize = QAquaSizeLarge; + const QSize size = qt_aqua_get_known_size(CT_SizeGrip, widget, QSize(), aSize); + ret = size.width(); + break; } + case PM_MdiSubWindowFrameWidth: + ret = 1; + break; + case PM_DockWidgetFrameWidth: + ret = 2; + break; + case PM_DockWidgetTitleMargin: + ret = 0; + break; + case PM_DockWidgetSeparatorExtent: + ret = 1; + break; + case PM_ToolBarHandleExtent: + ret = 11; + break; + case PM_ToolBarItemMargin: + ret = 0; + break; + case PM_ToolBarItemSpacing: + ret = 4; + break; + case PM_SplitterWidth: + ret = qMax(7, QApplication::globalStrut().width()); + break; + case PM_LayoutLeftMargin: + case PM_LayoutTopMargin: + case PM_LayoutRightMargin: + case PM_LayoutBottomMargin: + { + bool isWindow = false; + if (opt) { + isWindow = (opt->state & State_Window); + } else if (widget) { + isWindow = widget->isWindow(); + } + + if (isWindow) { + bool isMetal = widget && widget->testAttribute(Qt::WA_MacBrushedMetal); + if (isMetal) { + if (metric == PM_LayoutTopMargin) { + return_SIZE(9 /* AHIG */, 6 /* guess */, 6 /* guess */); + } else if (metric == PM_LayoutBottomMargin) { + return_SIZE(18 /* AHIG */, 15 /* guess */, 13 /* guess */); + } else { + return_SIZE(14 /* AHIG */, 11 /* guess */, 9 /* guess */); + } + } else { + /* + AHIG would have (20, 8, 10) here but that makes + no sense. It would also have 14 for the top margin + but this contradicts both Builder and most + applications. + */ + return_SIZE(20, 10, 10); // AHIG + } + } else { + // hack to detect QTabWidget + if (widget && widget->parentWidget() + && widget->parentWidget()->sizePolicy().controlType() == QSizePolicy::TabWidget) { + if (metric == PM_LayoutTopMargin) { + /* + Builder would have 14 (= 20 - 6) instead of 12, + but that makes the tab look disproportionate. + */ + return_SIZE(12, 6, 6); // guess + } else { + return_SIZE(20 /* Builder */, 8 /* guess */, 8 /* guess */); + } + } else { + /* + Child margins are highly inconsistent in AHIG and Builder. + */ + return_SIZE(12, 8, 6); // guess + } + } + } + case PM_LayoutHorizontalSpacing: + case PM_LayoutVerticalSpacing: + return -1; + case QStyle::PM_TabBarTabHSpace: + switch (d->aquaSizeConstrain(opt, widget)) { + case QAquaSizeLarge: + case QAquaSizeUnknown: + ret = QWindowsStyle::pixelMetric(metric, opt, widget); + break; + case QAquaSizeSmall: + ret = 20; + break; + case QAquaSizeMini: + ret = 16; + break; + } + break; + case PM_MenuHMargin: + ret = 0; + break; + case PM_ToolBarFrameWidth: + ret = 1; + if (widget) { + if (QMainWindow * mainWindow = qobject_cast(widget->parent())) + if (mainWindow->unifiedTitleAndToolBarOnMac()) + ret = 0; + } + break; + default: + ret = QWindowsStyle::pixelMetric(metric, opt, widget); + break; + } + return ret; +} + +QPalette QMacStyle::standardPalette() const +{ + QPalette pal = QWindowsStyle::standardPalette(); + pal.setColor(QPalette::Disabled, QPalette::Dark, QColor(191, 191, 191)); + pal.setColor(QPalette::Active, QPalette::Dark, QColor(191, 191, 191)); + pal.setColor(QPalette::Inactive, QPalette::Dark, QColor(191, 191, 191)); + return pal; +} + +int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w, + QStyleHintReturn *hret) const +{ + SInt32 ret = 0; + switch (sh) { + case SH_Menu_SelectionWrap: + ret = false; + break; + case SH_Menu_KeyboardSearch: + ret = true; + break; + case SH_Menu_SpaceActivatesItem: + ret = true; + break; + case SH_Slider_AbsoluteSetButtons: + ret = Qt::LeftButton|Qt::MidButton; + break; + case SH_Slider_PageSetButtons: + ret = 0; + break; + case SH_ScrollBar_ContextMenu: + ret = false; + break; + case SH_TitleBar_AutoRaise: + ret = true; + break; + case SH_Menu_AllowActiveAndDisabled: + ret = false; + break; + case SH_Menu_SubMenuPopupDelay: + ret = 100; + break; + case SH_ScrollBar_LeftClickAbsolutePosition: { + extern bool qt_scrollbar_jump_to_pos; //qapplication_mac.cpp + if(QApplication::keyboardModifiers() & Qt::AltModifier) + ret = !qt_scrollbar_jump_to_pos; + else + ret = qt_scrollbar_jump_to_pos; + break; } + case SH_TabBar_PreferNoArrows: + ret = true; + break; + case SH_LineEdit_PasswordCharacter: + ret = kBulletUnicode; + break; + /* + case SH_DialogButtons_DefaultButton: + ret = QDialogButtons::Reject; + break; + */ + case SH_Menu_SloppySubMenus: + ret = true; + break; + case SH_GroupBox_TextLabelVerticalAlignment: + ret = Qt::AlignTop; + break; + case SH_ScrollView_FrameOnlyAroundContents: + if (w && (w->isWindow() || !w->parentWidget() || w->parentWidget()->isWindow()) + && (w->inherits("QWorkspaceChild") +#ifdef QT3_SUPPORT + || w->inherits("QScrollView") +#endif + )) + ret = true; + else + ret = QWindowsStyle::styleHint(sh, opt, w, hret); + break; + case SH_Menu_FillScreenWithScroll: + ret = false; + break; + case SH_Menu_Scrollable: + ret = true; + break; + case SH_RichText_FullWidthSelection: + ret = true; + break; + case SH_BlinkCursorWhenTextSelected: + ret = false; + break; + case SH_ScrollBar_StopMouseOverSlider: + ret = true; + break; + case SH_Q3ListViewExpand_SelectMouseType: + ret = QEvent::MouseButtonRelease; + break; + case SH_TabBar_SelectMouseType: + if (const QStyleOptionTabBarBaseV2 *opt2 = qstyleoption_cast(opt)) { + ret = opt2->documentMode ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; + } else { + ret = QEvent::MouseButtonRelease; + } + break; + case SH_ComboBox_Popup: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(opt)) + ret = !cmb->editable; + else + ret = 0; + break; + case SH_Workspace_FillSpaceOnMaximize: + ret = true; + break; + case SH_Widget_ShareActivation: + ret = true; + break; + case SH_Header_ArrowAlignment: + ret = Qt::AlignRight; + break; + case SH_TabBar_Alignment: { + if (const QTabWidget *tab = qobject_cast(w)) { + if (tab->documentMode()) { + ret = Qt::AlignLeft; + break; + } + } + if (const QTabBar *tab = qobject_cast(w)) { + if (tab->documentMode()) { + ret = Qt::AlignLeft; + break; + } + } + ret = Qt::AlignCenter; + } break; + case SH_UnderlineShortcut: + ret = false; + break; + case SH_ToolTipLabel_Opacity: + ret = 242; // About 95% + break; + case SH_Button_FocusPolicy: + ret = Qt::TabFocus; + break; + case SH_EtchDisabledText: + ret = false; + break; + case SH_FocusFrame_Mask: { + ret = true; + if(QStyleHintReturnMask *mask = qstyleoption_cast(hret)) { + const uchar fillR = 192, fillG = 191, fillB = 190; + QImage img; + + QSize pixmapSize = opt->rect.size(); + if (pixmapSize.isValid()) { + QPixmap pix(pixmapSize); + pix.fill(QColor(fillR, fillG, fillB)); + QPainter pix_paint(&pix); + proxy()->drawControl(CE_FocusFrame, opt, &pix_paint, w); + pix_paint.end(); + img = pix.toImage(); + } + + const QRgb *sptr = (QRgb*)img.bits(), *srow; + const int sbpl = img.bytesPerLine(); + const int w = sbpl/4, h = img.height(); + + QImage img_mask(img.width(), img.height(), QImage::Format_ARGB32); + QRgb *dptr = (QRgb*)img_mask.bits(), *drow; + const int dbpl = img_mask.bytesPerLine(); + + for (int y = 0; y < h; ++y) { + srow = sptr+((y*sbpl)/4); + drow = dptr+((y*dbpl)/4); + for (int x = 0; x < w; ++x) { + const int diff = (((qRed(*srow)-fillR)*(qRed(*srow)-fillR)) + + ((qGreen(*srow)-fillG)*((qGreen(*srow)-fillG))) + + ((qBlue(*srow)-fillB)*((qBlue(*srow)-fillB)))); + (*drow++) = (diff < 100) ? 0xffffffff : 0xff000000; + ++srow; + } + } + QBitmap qmask = QBitmap::fromImage(img_mask); + mask->region = QRegion(qmask); + } + break; } + case SH_TitleBar_NoBorder: + ret = 1; + break; + case SH_RubberBand_Mask: + ret = 0; + break; + case SH_ComboBox_LayoutDirection: + ret = Qt::LeftToRight; + break; + case SH_ItemView_EllipsisLocation: + ret = Qt::AlignHCenter; + break; + case SH_ItemView_ShowDecorationSelected: + ret = true; + break; + case SH_TitleBar_ModifyNotification: + ret = false; + break; + case SH_ScrollBar_RollBetweenButtons: + ret = true; + break; + case SH_WindowFrame_Mask: + ret = 1; + if (QStyleHintReturnMask *mask = qstyleoption_cast(hret)) { + mask->region = opt->rect; + mask->region -= QRect(opt->rect.left(), opt->rect.top(), 5, 1); + mask->region -= QRect(opt->rect.left(), opt->rect.top() + 1, 3, 1); + mask->region -= QRect(opt->rect.left(), opt->rect.top() + 2, 2, 1); + mask->region -= QRect(opt->rect.left(), opt->rect.top() + 3, 1, 2); + + mask->region -= QRect(opt->rect.right() - 4, opt->rect.top(), 5, 1); + mask->region -= QRect(opt->rect.right() - 2, opt->rect.top() + 1, 3, 1); + mask->region -= QRect(opt->rect.right() - 1, opt->rect.top() + 2, 2, 1); + mask->region -= QRect(opt->rect.right() , opt->rect.top() + 3, 1, 2); + } + break; + case SH_TabBar_ElideMode: + ret = Qt::ElideRight; + break; + case SH_DialogButtonLayout: + ret = QDialogButtonBox::MacLayout; + break; + case SH_FormLayoutWrapPolicy: + ret = QFormLayout::DontWrapRows; + break; + case SH_FormLayoutFieldGrowthPolicy: + ret = QFormLayout::FieldsStayAtSizeHint; + break; + case SH_FormLayoutFormAlignment: + ret = Qt::AlignHCenter | Qt::AlignTop; + break; + case SH_FormLayoutLabelAlignment: + ret = Qt::AlignRight; + break; + case SH_ComboBox_PopupFrameStyle: + ret = QFrame::NoFrame | QFrame::Plain; + break; + case SH_MessageBox_TextInteractionFlags: + ret = Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard; + break; + case SH_SpellCheckUnderlineStyle: + ret = QTextCharFormat::DashUnderline; + break; + case SH_MessageBox_CenterButtons: + ret = false; + break; + case SH_MenuBar_AltKeyNavigation: + ret = false; + break; + case SH_ItemView_MovementWithoutUpdatingSelection: + ret = false; + break; + case SH_FocusFrame_AboveWidget: + ret = true; + break; + case SH_WizardStyle: + ret = QWizard::MacStyle; + break; + case SH_ItemView_ArrowKeysNavigateIntoChildren: + ret = false; + break; + case SH_Menu_FlashTriggeredItem: + ret = true; + break; + case SH_Menu_FadeOutOnHide: + ret = true; + break; + case SH_Menu_Mask: + if (opt) { + if (QStyleHintReturnMask *mask = qstyleoption_cast(hret)) { + ret = true; + HIRect menuRect = CGRectMake(opt->rect.x(), opt->rect.y() + 4, + opt->rect.width(), opt->rect.height() - 8); + HIThemeMenuDrawInfo mdi; + mdi.version = 0; + if (w && qobject_cast(w->parentWidget())) + mdi.menuType = kThemeMenuTypeHierarchical; + else + mdi.menuType = kThemeMenuTypePopUp; + QCFType shape; + HIThemeGetMenuBackgroundShape(&menuRect, &mdi, &shape); + mask->region = QRegion::fromHIShapeRef(shape); + } + } + break; + case SH_ItemView_PaintAlternatingRowColorsForEmptyArea: + ret = true; + break; + case SH_TabBar_CloseButtonPosition: + ret = QTabBar::LeftSide; + break; + case SH_DockWidget_ButtonsHaveFrame: + ret = false; + break; + default: + ret = QWindowsStyle::styleHint(sh, opt, w, hret); + break; + } + return ret; +} + +QPixmap QMacStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *opt) const +{ + switch (iconMode) { + case QIcon::Disabled: { + QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); + int imgh = img.height(); + int imgw = img.width(); + QRgb pixel; + for (int y = 0; y < imgh; ++y) { + for (int x = 0; x < imgw; ++x) { + pixel = img.pixel(x, y); + img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), + qAlpha(pixel) / 2)); + } + } + return QPixmap::fromImage(img); + } + default: + ; + } + return QWindowsStyle::generatedIconPixmap(iconMode, pixmap, opt); +} + + +QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget) const +{ + // The default implementation of QStyle::standardIconImplementation() is to call standardPixmap() + // I don't want infinite recursion so if we do get in that situation, just return the Window's + // standard pixmap instead (since there is no mac-specific icon then). This should be fine until + // someone changes how Windows standard + // pixmap works. + static bool recursionGuard = false; + + if (recursionGuard) + return QWindowsStyle::standardPixmap(standardPixmap, opt, widget); + + recursionGuard = true; + QIcon icon = standardIconImplementation(standardPixmap, opt, widget); + recursionGuard = false; + int size; + switch (standardPixmap) { + default: + size = 32; + break; + case SP_MessageBoxCritical: + case SP_MessageBoxQuestion: + case SP_MessageBoxInformation: + case SP_MessageBoxWarning: + size = 64; + break; + } + return icon.pixmap(size, size); +} + +void QMacStyle::setFocusRectPolicy(QWidget *w, FocusRectPolicy policy) +{ + switch (policy) { + case FocusDefault: + break; + case FocusEnabled: + case FocusDisabled: + w->setAttribute(Qt::WA_MacShowFocusRect, policy == FocusEnabled); + break; + } +} + +QMacStyle::FocusRectPolicy QMacStyle::focusRectPolicy(const QWidget *w) +{ + return w->testAttribute(Qt::WA_MacShowFocusRect) ? FocusEnabled : FocusDisabled; +} + +void QMacStyle::setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy) +{ + QWidget *wadget = const_cast(widget); + wadget->setAttribute(Qt::WA_MacNormalSize, policy == SizeLarge); + wadget->setAttribute(Qt::WA_MacSmallSize, policy == SizeSmall); + wadget->setAttribute(Qt::WA_MacMiniSize, policy == SizeMini); +} + +QMacStyle::WidgetSizePolicy QMacStyle::widgetSizePolicy(const QWidget *widget) +{ + while (widget) { + if (widget->testAttribute(Qt::WA_MacMiniSize)) { + return SizeMini; + } else if (widget->testAttribute(Qt::WA_MacSmallSize)) { + return SizeSmall; + } else if (widget->testAttribute(Qt::WA_MacNormalSize)) { + return SizeLarge; + } + widget = widget->parentWidget(); + } + return SizeDefault; +} + +void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *w) const +{ + ThemeDrawState tds = d->getDrawState(opt->state); + QMacCGContext cg(p); + switch (pe) { + case PE_IndicatorArrowUp: + case PE_IndicatorArrowDown: + case PE_IndicatorArrowRight: + case PE_IndicatorArrowLeft: { + p->save(); + p->setRenderHint(QPainter::Antialiasing); + int xOffset = opt->direction == Qt::LeftToRight ? 2 : -1; + QMatrix matrix; + matrix.translate(opt->rect.center().x() + xOffset, opt->rect.center().y() + 2); + QPainterPath path; + switch(pe) { + default: + case PE_IndicatorArrowDown: + break; + case PE_IndicatorArrowUp: + matrix.rotate(180); + break; + case PE_IndicatorArrowLeft: + matrix.rotate(90); + break; + case PE_IndicatorArrowRight: + matrix.rotate(-90); + break; + } + path.moveTo(0, 5); + path.lineTo(-4, -3); + path.lineTo(4, -3); + p->setMatrix(matrix); + p->setPen(Qt::NoPen); + p->setBrush(QColor(0, 0, 0, 135)); + p->drawPath(path); + p->restore(); + break; } + case PE_FrameTabBarBase: + if (const QStyleOptionTabBarBaseV2 *tbb + = qstyleoption_cast(opt)) { + if (tbb->documentMode) { + p->save(); + drawTabBase(p, tbb, w); + p->restore(); + return; + } + + QRegion region(tbb->rect); + region -= tbb->tabBarRect; + p->save(); + p->setClipRegion(region); + QStyleOptionTabWidgetFrame twf; + twf.QStyleOption::operator=(*tbb); + twf.shape = tbb->shape; + switch (getTabDirection(twf.shape)) { + case kThemeTabNorth: + twf.rect = twf.rect.adjusted(0, 0, 0, 10); + break; + case kThemeTabSouth: + twf.rect = twf.rect.adjusted(0, -10, 0, 0); + break; + case kThemeTabWest: + twf.rect = twf.rect.adjusted(0, 0, 10, 0); + break; + case kThemeTabEast: + twf.rect = twf.rect.adjusted(0, -10, 0, 0); + break; + } + proxy()->drawPrimitive(PE_FrameTabWidget, &twf, p, w); + p->restore(); + } + break; + case PE_PanelTipLabel: + p->fillRect(opt->rect, opt->palette.brush(QPalette::ToolTipBase)); + break; + case PE_FrameGroupBox: + if (const QStyleOptionFrame *groupBox = qstyleoption_cast(opt)) { + const QStyleOptionFrameV2 *frame2 = qstyleoption_cast(opt); + if (frame2 && frame2->features & QStyleOptionFrameV2::Flat) { + QWindowsStyle::drawPrimitive(pe, groupBox, p, w); + } else { + HIThemeGroupBoxDrawInfo gdi; + gdi.version = qt_mac_hitheme_version; + gdi.state = tds; + if (w && qobject_cast(w->parentWidget())) + gdi.kind = kHIThemeGroupBoxKindSecondary; + else + gdi.kind = kHIThemeGroupBoxKindPrimary; + HIRect hirect = qt_hirectForQRect(opt->rect); + HIThemeDrawGroupBox(&hirect, &gdi, cg, kHIThemeOrientationNormal); + } + } + break; + case PE_IndicatorToolBarSeparator: { + QPainterPath path; + if (opt->state & State_Horizontal) { + int xpoint = opt->rect.center().x(); + path.moveTo(xpoint + 0.5, opt->rect.top() + 1); + path.lineTo(xpoint + 0.5, opt->rect.bottom()); + } else { + int ypoint = opt->rect.center().y(); + path.moveTo(opt->rect.left() + 2 , ypoint + 0.5); + path.lineTo(opt->rect.right() + 1, ypoint + 0.5); + } + QPainterPathStroker theStroker; + theStroker.setCapStyle(Qt::FlatCap); + theStroker.setDashPattern(QVector() << 1 << 2); + path = theStroker.createStroke(path); + p->fillPath(path, QColor(0, 0, 0, 119)); + } + break; + case PE_FrameWindow: + break; + case PE_IndicatorDockWidgetResizeHandle: { + // The docwidget resize handle is drawn as a one-pixel wide line. + p->save(); + if (opt->state & State_Horizontal) { + p->setPen(QColor(160, 160, 160)); + p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); + } else { + p->setPen(QColor(145, 145, 145)); + p->drawLine(opt->rect.topRight(), opt->rect.bottomRight()); + } + p->restore(); + } break; + case PE_IndicatorToolBarHandle: { + p->save(); + QPainterPath path; + int x = opt->rect.x() + 6; + int y = opt->rect.y() + 5; + static const int RectHeight = 2; + if (opt->state & State_Horizontal) { + while (y < opt->rect.height() - RectHeight - 6) { + path.moveTo(x, y); + path.addRect(x, y, RectHeight, RectHeight); + y += 6; + } + } else { + while (x < opt->rect.width() - RectHeight - 6) { + path.moveTo(x, y); + path.addRect(x, y, RectHeight, RectHeight); + x += 6; + } + } + p->setPen(Qt::NoPen); + QColor dark = opt->palette.dark().color(); + dark.setAlphaF(0.75); + QColor light = opt->palette.light().color(); + light.setAlphaF(0.6); + p->fillPath(path, light); + p->save(); + p->translate(1, 1); + p->fillPath(path, dark); + p->restore(); + p->translate(3, 3); + p->fillPath(path, light); + p->translate(1, 1); + p->fillPath(path, dark); + p->restore(); + + break; + } + case PE_IndicatorHeaderArrow: + if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { + // In HITheme, up is down, down is up and hamburgers eat people. + if (header->sortIndicator != QStyleOptionHeader::None) + proxy()->drawPrimitive( + (header->sortIndicator == QStyleOptionHeader::SortDown) ? + PE_IndicatorArrowUp : PE_IndicatorArrowDown, header, p, w); + } + break; + case PE_IndicatorMenuCheckMark: { + const int checkw = 8; + const int checkh = 8; + const int xoff = qMax(0, (opt->rect.width() - checkw) / 2); + const int yoff = qMax(0, (opt->rect.width() - checkh) / 2); + const int x1 = xoff + opt->rect.x(); + const int y1 = yoff + opt->rect.y() + checkw/2; + const int x2 = xoff + opt->rect.x() + checkw/4; + const int y2 = yoff + opt->rect.y() + checkh; + const int x3 = xoff + opt->rect.x() + checkw; + const int y3 = yoff + opt->rect.y(); + + QVector a(2); + a << QLineF(x1, y1, x2, y2); + a << QLineF(x2, y2, x3, y3); + if (opt->palette.currentColorGroup() == QPalette::Active) + p->setPen(QPen(Qt::white, 3)); + else + p->setPen(QPen(QColor(100, 100, 100), 3)); + p->save(); + p->setRenderHint(QPainter::Antialiasing); + p->drawLines(a); + p->restore(); + break; } + case PE_IndicatorViewItemCheck: + case PE_Q3CheckListExclusiveIndicator: + case PE_Q3CheckListIndicator: + case PE_IndicatorRadioButton: + case PE_IndicatorCheckBox: { + bool drawColorless = (!(opt->state & State_Active)) + && opt->palette.currentColorGroup() == QPalette::Active; + HIThemeButtonDrawInfo bdi; + bdi.version = qt_mac_hitheme_version; + bdi.state = tds; + if (drawColorless && tds == kThemeStateInactive) + bdi.state = kThemeStateActive; + bdi.adornment = kThemeDrawIndicatorOnly; + if (opt->state & State_HasFocus) + bdi.adornment |= kThemeAdornmentFocus; + bool isRadioButton = (pe == PE_Q3CheckListExclusiveIndicator + || pe == PE_IndicatorRadioButton); + switch (d->aquaSizeConstrain(opt, w)) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + if (isRadioButton) + bdi.kind = kThemeRadioButton; + else + bdi.kind = kThemeCheckBox; + break; + case QAquaSizeMini: + if (isRadioButton) + bdi.kind = kThemeMiniRadioButton; + else + bdi.kind = kThemeMiniCheckBox; + break; + case QAquaSizeSmall: + if (isRadioButton) + bdi.kind = kThemeSmallRadioButton; + else + bdi.kind = kThemeSmallCheckBox; + break; + } + if (opt->state & State_NoChange) + bdi.value = kThemeButtonMixed; + else if (opt->state & State_On) + bdi.value = kThemeButtonOn; + else + bdi.value = kThemeButtonOff; + HIRect macRect; + if (pe == PE_Q3CheckListExclusiveIndicator || pe == PE_Q3CheckListIndicator) + macRect = qt_hirectForQRect(opt->rect); + else + macRect = qt_hirectForQRect(opt->rect); + if (!drawColorless) + HIThemeDrawButton(&macRect, &bdi, cg, kHIThemeOrientationNormal, 0); + else + d->drawColorlessButton(macRect, &bdi, p, opt); + break; } + case PE_FrameFocusRect: + // Use the our own focus widget stuff. + break; + case PE_IndicatorBranch: { + if (!(opt->state & State_Children)) + break; + HIThemeButtonDrawInfo bi; + bi.version = qt_mac_hitheme_version; + bi.state = tds; + if (tds == kThemeStateInactive && opt->palette.currentColorGroup() == QPalette::Active) + bi.state = kThemeStateActive; + if (opt->state & State_Sunken) + bi.state |= kThemeStatePressed; + bi.kind = kThemeDisclosureButton; + if (opt->state & State_Open) + bi.value = kThemeDisclosureDown; + else + bi.value = opt->direction == Qt::LeftToRight ? kThemeDisclosureRight : kThemeDisclosureLeft; + bi.adornment = kThemeAdornmentNone; + HIRect hirect = qt_hirectForQRect(opt->rect.adjusted(DisclosureOffset,0,-DisclosureOffset,0)); + HIThemeDrawButton(&hirect, &bi, cg, kHIThemeOrientationNormal, 0); + break; } + + case PE_Frame: { + QPen oldPen = p->pen(); + p->setPen(opt->palette.base().color().darker(140)); + p->drawRect(opt->rect.adjusted(0, 0, -1, -1)); + p->setPen(opt->palette.base().color().darker(180)); + p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); + p->setPen(oldPen); + break; } + + case PE_FrameLineEdit: + if (const QStyleOptionFrame *frame = qstyleoption_cast(opt)) { + if (frame->state & State_Sunken) { + QColor baseColor(frame->palette.background().color()); + HIThemeFrameDrawInfo fdi; + fdi.version = qt_mac_hitheme_version; + fdi.state = tds; + SInt32 frame_size; + if (pe == PE_FrameLineEdit) { + fdi.kind = kHIThemeFrameTextFieldSquare; + GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size); + if ((frame->state & State_ReadOnly) || !(frame->state & State_Enabled)) + fdi.state = kThemeStateInactive; + } else { + baseColor = QColor(150, 150, 150); //hardcoded since no query function --Sam + fdi.kind = kHIThemeFrameListBox; + GetThemeMetric(kThemeMetricListBoxFrameOutset, &frame_size); + } + fdi.isFocused = (frame->state & State_HasFocus); + int lw = frame->lineWidth; + if (lw <= 0) + lw = proxy()->pixelMetric(PM_DefaultFrameWidth, frame, w); + { //clear to base color + p->save(); + p->setPen(QPen(baseColor, lw)); + p->setBrush(Qt::NoBrush); + p->drawRect(frame->rect); + p->restore(); + } + HIRect hirect = qt_hirectForQRect(frame->rect, + QRect(frame_size, frame_size, + frame_size * 2, frame_size * 2)); + + HIThemeDrawFrame(&hirect, &fdi, cg, kHIThemeOrientationNormal); + } else { + QWindowsStyle::drawPrimitive(pe, opt, p, w); + } + } + break; + case PE_PanelLineEdit: + QWindowsStyle::drawPrimitive(pe, opt, p, w); + // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit). + // Focus frame is drawn outside the rectangle passed in the option-rect. + if (const QStyleOptionFrame *panel = qstyleoption_cast(opt)) { + if ((opt->state & State_HasFocus) && !qobject_cast(w)) { + int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin); + int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin); + QStyleOptionFrame focusFrame = *panel; + focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin); + drawControl(CE_FocusFrame, &focusFrame, p, w); + } + } + + break; + case PE_FrameTabWidget: + if (const QStyleOptionTabWidgetFrame *twf + = qstyleoption_cast(opt)) { + HIRect hirect = qt_hirectForQRect(twf->rect); + HIThemeTabPaneDrawInfo tpdi; + tpdi.version = qt_mac_hitheme_tab_version(); + tpdi.state = tds; + tpdi.direction = getTabDirection(twf->shape); + tpdi.size = kHIThemeTabSizeNormal; + tpdi.kind = kHIThemeTabKindNormal; + tpdi.adornment = kHIThemeTabPaneAdornmentNormal; + HIThemeDrawTabPane(&hirect, &tpdi, cg, kHIThemeOrientationNormal); + } + break; + case PE_PanelScrollAreaCorner: { + const QBrush brush(opt->palette.brush(QPalette::Base)); + p->fillRect(opt->rect, brush); + p->setPen(QPen(QColor(217, 217, 217))); + p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); + p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); + } break; + case PE_FrameStatusBarItem: + break; + case PE_IndicatorTabClose: { + bool hover = (opt->state & State_MouseOver); + bool selected = (opt->state & State_Selected); + bool active = (opt->state & State_Active); + drawTabCloseButton(p, hover, active, selected); + } break; + case PE_PanelStatusBar: { + if (QSysInfo::MacintoshVersion <= QSysInfo::MV_10_4) { + QWindowsStyle::drawPrimitive(pe, opt, p, w); + break; + } + // Use the Leopard style only if the status bar is the status bar for a + // QMainWindow with a unifed toolbar. + if (w == 0 || w->parent() == 0 || qobject_cast(w->parent()) == 0 || + qobject_cast(w->parent())->unifiedTitleAndToolBarOnMac() == false ) { + QWindowsStyle::drawPrimitive(pe, opt, p, w); + break; + } + + // Fill the status bar with the titlebar gradient. + QLinearGradient linearGrad(0, opt->rect.top(), 0, opt->rect.bottom()); + if (opt->state & QStyle::State_Active) { + linearGrad.setColorAt(0, titlebarGradientActiveBegin); + linearGrad.setColorAt(1, titlebarGradientActiveEnd); + } else { + linearGrad.setColorAt(0, titlebarGradientInactiveBegin); + linearGrad.setColorAt(1, titlebarGradientInactiveEnd); + } + p->fillRect(opt->rect, linearGrad); + + // Draw the black separator line at the top of the status bar. + if (opt->state & QStyle::State_Active) + p->setPen(titlebarSeparatorLineActive); + else + p->setPen(titlebarSeparatorLineInactive); + p->drawLine(opt->rect.left(), opt->rect.top(), opt->rect.right(), opt->rect.top()); + + break; + } + + default: + QWindowsStyle::drawPrimitive(pe, opt, p, w); + break; + } +} + +static inline QPixmap darkenPixmap(const QPixmap &pixmap) +{ + QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); + int imgh = img.height(); + int imgw = img.width(); + int h, s, v, a; + QRgb pixel; + for (int y = 0; y < imgh; ++y) { + for (int x = 0; x < imgw; ++x) { + pixel = img.pixel(x, y); + a = qAlpha(pixel); + QColor hsvColor(pixel); + hsvColor.getHsv(&h, &s, &v); + s = qMin(100, s * 2); + v = v / 2; + hsvColor.setHsv(h, s, v); + pixel = hsvColor.rgb(); + img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), a)); + } + } + return QPixmap::fromImage(img); +} + + + +void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p, + const QWidget *w) const +{ + ThemeDrawState tds = d->getDrawState(opt->state); + QMacCGContext cg(p); + switch (ce) { + case CE_HeaderSection: + if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { + HIThemeButtonDrawInfo bdi; + bdi.version = qt_mac_hitheme_version; + State flags = header->state; + QRect ir = header->rect; + bdi.kind = kThemeListHeaderButton; + bdi.adornment = kThemeAdornmentNone; + bdi.state = kThemeStateActive; + + if (flags & State_On) + bdi.value = kThemeButtonOn; + else + bdi.value = kThemeButtonOff; + + if (header->orientation == Qt::Horizontal){ + switch (header->position) { + case QStyleOptionHeader::Beginning: + ir.adjust(-1, -1, 0, 0); + break; + case QStyleOptionHeader::Middle: + ir.adjust(-1, -1, 0, 0); + break; + case QStyleOptionHeader::OnlyOneSection: + case QStyleOptionHeader::End: + ir.adjust(-1, -1, 1, 0); + break; + default: + break; + } + + if (header->position != QStyleOptionHeader::Beginning + && header->position != QStyleOptionHeader::OnlyOneSection) { + bdi.adornment = header->direction == Qt::LeftToRight + ? kThemeAdornmentHeaderButtonLeftNeighborSelected + : kThemeAdornmentHeaderButtonRightNeighborSelected; + } + } + + if (flags & State_Active) { + if (!(flags & State_Enabled)) + bdi.state = kThemeStateUnavailable; + else if (flags & State_Sunken) + bdi.state = kThemeStatePressed; + } else { + if (flags & State_Enabled) + bdi.state = kThemeStateInactive; + else + bdi.state = kThemeStateUnavailableInactive; + } + + if (header->sortIndicator != QStyleOptionHeader::None) { + bdi.value = kThemeButtonOn; + if (header->sortIndicator == QStyleOptionHeader::SortDown) + bdi.adornment = kThemeAdornmentHeaderButtonSortUp; + } + if (flags & State_HasFocus) + bdi.adornment = kThemeAdornmentFocus; + + ir = visualRect(header->direction, header->rect, ir); + HIRect bounds = qt_hirectForQRect(ir); + + bool noVerticalHeader = true; + if (w) + if (const QTableView *table = qobject_cast(w->parentWidget())) + noVerticalHeader = !table->verticalHeader()->isVisible(); + + bool drawTopBorder = header->orientation == Qt::Horizontal; + bool drawLeftBorder = header->orientation == Qt::Vertical + || header->position == QStyleOptionHeader::OnlyOneSection + || (header->position == QStyleOptionHeader::Beginning && noVerticalHeader); + d->drawTableHeader(bounds, drawTopBorder, drawLeftBorder, bdi, p); + } + break; + case CE_HeaderLabel: + if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { + QRect textr = header->rect; + if (!header->icon.isNull()) { + QIcon::Mode mode = QIcon::Disabled; + if (opt->state & State_Enabled) + mode = QIcon::Normal; + QPixmap pixmap = header->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), mode); + + QRect pixr = header->rect; + pixr.setY(header->rect.center().y() - (pixmap.height() - 1) / 2); + proxy()->drawItemPixmap(p, pixr, Qt::AlignVCenter, pixmap); + textr.translate(pixmap.width() + 2, 0); + } + + proxy()->drawItemText(p, textr, header->textAlignment | Qt::AlignVCenter, header->palette, + header->state & State_Enabled, header->text, QPalette::ButtonText); + } + break; + case CE_ToolButtonLabel: + if (const QStyleOptionToolButton *tb = qstyleoption_cast(opt)) { + QStyleOptionToolButton myTb = *tb; + myTb.state &= ~State_AutoRaise; + if (w && qobject_cast(w->parentWidget())) { + QRect cr = tb->rect; + int shiftX = 0; + int shiftY = 0; + bool needText = false; + int alignment = 0; + bool down = tb->state & (State_Sunken | State_On); + if (down) { + shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, w); + shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, tb, w); + } + // The down state is special for QToolButtons in a toolbar on the Mac + // The text is a bit bolder and gets a drop shadow and the icons are also darkened. + // This doesn't really fit into any particular case in QIcon, so we + // do the majority of the work ourselves. + if (!(tb->features & QStyleOptionToolButton::Arrow)) { + Qt::ToolButtonStyle tbstyle = tb->toolButtonStyle; + if (tb->icon.isNull() && !tb->text.isEmpty()) + tbstyle = Qt::ToolButtonTextOnly; + + switch (tbstyle) { + case Qt::ToolButtonTextOnly: { + needText = true; + alignment = Qt::AlignCenter; + break; } + case Qt::ToolButtonIconOnly: + case Qt::ToolButtonTextBesideIcon: + case Qt::ToolButtonTextUnderIcon: { + QRect pr = cr; + QIcon::Mode iconMode = (tb->state & State_Enabled) ? QIcon::Normal + : QIcon::Disabled; + QIcon::State iconState = (tb->state & State_On) ? QIcon::On + : QIcon::Off; + QPixmap pixmap = tb->icon.pixmap(tb->rect.size().boundedTo(tb->iconSize), iconMode, iconState); + + // Draw the text if it's needed. + if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) { + needText = true; + if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { + QMainWindow *mw = qobject_cast(w->window()); + if (mw && mw->unifiedTitleAndToolBarOnMac()) { + pr.setHeight(pixmap.size().height()); + cr.adjust(0, pr.bottom() + 1, 0, 1); + } else { + pr.setHeight(pixmap.size().height() + 6); + cr.adjust(0, pr.bottom(), 0, -3); + } + alignment |= Qt::AlignCenter; + } else { + pr.setWidth(pixmap.width() + 8); + cr.adjust(pr.right(), 0, 0, 0); + alignment |= Qt::AlignLeft | Qt::AlignVCenter; + } + } + if (opt->state & State_Sunken) { + pr.translate(shiftX, shiftY); + pixmap = darkenPixmap(pixmap); + } + proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pixmap); + break; } + default: + Q_ASSERT(false); + break; + } + + if (needText) { + QPalette pal = tb->palette; + QPalette::ColorRole role = QPalette::NoRole; + if (!proxy()->styleHint(SH_UnderlineShortcut, tb, w)) + alignment |= Qt::TextHideMnemonic; + if (down) + cr.translate(shiftX, shiftY); + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 + && (tbstyle == Qt::ToolButtonTextOnly + || (tbstyle != Qt::ToolButtonTextOnly && !down))) { + QPen pen = p->pen(); + QColor light = down ? Qt::black : Qt::white; + light.setAlphaF(0.375f); + p->setPen(light); + p->drawText(cr.adjusted(0, 1, 0, 1), alignment, tb->text); + p->setPen(pen); + if (down && tbstyle == Qt::ToolButtonTextOnly) { + pal = QApplication::palette("QMenu"); + pal.setCurrentColorGroup(tb->palette.currentColorGroup()); + role = QPalette::HighlightedText; + } + } + proxy()->drawItemText(p, cr, alignment, pal, + tb->state & State_Enabled, tb->text, role); + if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5 && + (tb->state & State_Sunken)) { + // Draw a "drop shadow" in earlier versions. + proxy()->drawItemText(p, cr.adjusted(0, 1, 0, 1), alignment, + tb->palette, tb->state & State_Enabled, tb->text); + } + } + } else { + QWindowsStyle::drawControl(ce, &myTb, p, w); + } + } else { + QWindowsStyle::drawControl(ce, &myTb, p, w); + } + } + break; + case CE_ToolBoxTabShape: + QCommonStyle::drawControl(ce, opt, p, w); + break; + case CE_PushButtonBevel: + if (const QStyleOptionButton *btn = ::qstyleoption_cast(opt)) { + if (!(btn->state & (State_Raised | State_Sunken | State_On))) + break; + + if (btn->features & QStyleOptionButton::CommandLinkButton) { + QWindowsStyle::drawControl(ce, opt, p, w); + break; + } + + HIThemeButtonDrawInfo bdi; + d->initHIThemePushButton(btn, w, tds, &bdi); + if (btn->features & QStyleOptionButton::DefaultButton + && d->animatable(QMacStylePrivate::AquaPushButton, w)) { + bdi.adornment |= kThemeAdornmentDefault; + bdi.animation.time.start = d->defaultButtonStart; + bdi.animation.time.current = CFAbsoluteTimeGetCurrent(); + if (d->timerID <= -1) + QMetaObject::invokeMethod(d, "startAnimationTimer", Qt::QueuedConnection); + } + // Unlike Carbon, we want the button to always be drawn inside its bounds. + // Therefore, make the button a bit smaller, so that even if it got focus, + // the focus 'shadow' will be inside. + HIRect newRect = qt_hirectForQRect(btn->rect); + if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) { + newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset; + newRect.origin.y += QMacStylePrivate::PushButtonTopOffset; + newRect.size.width -= QMacStylePrivate::PushButtonRightOffset; + newRect.size.height -= QMacStylePrivate::PushButtonBottomOffset; + } else if (bdi.kind == kThemePushButtonMini) { + newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset - 2; + newRect.origin.y += QMacStylePrivate::PushButtonTopOffset; + newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4; + } + HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); + + if (btn->features & QStyleOptionButton::HasMenu) { + int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); + QRect ir = btn->rect; + HIRect arrowRect = CGRectMake(ir.right() - mbi - QMacStylePrivate::PushButtonRightOffset, + ir.height() / 2 - 4, mbi, ir.height() / 2); + bool drawColorless = btn->palette.currentColorGroup() == QPalette::Active; + if (drawColorless && tds == kThemeStateInactive) + tds = kThemeStateActive; + + HIThemePopupArrowDrawInfo pdi; + pdi.version = qt_mac_hitheme_version; + pdi.state = tds; + pdi.orientation = kThemeArrowDown; + if (arrowRect.size.width < 8.) + pdi.size = kThemeArrow5pt; + else + pdi.size = kThemeArrow9pt; + HIThemeDrawPopupArrow(&arrowRect, &pdi, cg, kHIThemeOrientationNormal); + } + } + break; + case CE_PushButtonLabel: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + // We really don't want the label to be drawn the same as on + // windows style if it has an icon and text, then it should be more like a + // tab. So, cheat a little here. However, if it *is* only an icon + // the windows style works great, so just use that implementation. + bool hasMenu = btn->features & QStyleOptionButton::HasMenu; + bool hasIcon = !btn->icon.isNull(); + bool hasText = !btn->text.isEmpty(); + if (!hasIcon && !hasMenu) { + // ### this is really overly difficult, simplify. + // It basically tries to get the right font for "small" and "mini" icons. + QFont oldFont = p->font(); + QFont newFont = qt_app_fonts_hash()->value("QPushButton", QFont()); + ThemeFontID themeId = kThemePushButtonFont; + if (oldFont == newFont) { // Yes, use HITheme to draw the text for small sizes. + switch (d->aquaSizeConstrain(opt, w)) { + default: + break; + case QAquaSizeSmall: + themeId = kThemeSmallSystemFont; + break; + case QAquaSizeMini: + themeId = kThemeMiniSystemFont; + break; + } + } + if (themeId == kThemePushButtonFont) { + QWindowsStyle::drawControl(ce, btn, p, w); + } else { + p->save(); + CGContextSetShouldAntialias(cg, true); + CGContextSetShouldSmoothFonts(cg, true); + HIThemeTextInfo tti; + tti.version = qt_mac_hitheme_version; + tti.state = tds; + QColor textColor = btn->palette.buttonText().color(); + CGFloat colorComp[] = { textColor.redF(), textColor.greenF(), + textColor.blueF(), textColor.alphaF() }; + CGContextSetFillColorSpace(cg, QCoreGraphicsPaintEngine::macGenericColorSpace()); + CGContextSetFillColor(cg, colorComp); + tti.fontID = themeId; + tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; + tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; + tti.options = kHIThemeTextBoxOptionNone; + tti.truncationPosition = kHIThemeTextTruncationNone; + tti.truncationMaxLines = 1 + btn->text.count(QLatin1Char('\n')); + QCFString buttonText = qt_mac_removeMnemonics(btn->text); + QRect r = btn->rect; + HIRect bounds = qt_hirectForQRect(r); + HIThemeDrawTextBox(buttonText, &bounds, &tti, + cg, kHIThemeOrientationNormal); + p->restore(); + } + } else { + if (hasIcon && !hasText) { + QWindowsStyle::drawControl(ce, btn, p, w); + } else { + QRect freeContentRect = btn->rect; + QRect textRect = itemTextRect( + btn->fontMetrics, freeContentRect, Qt::AlignCenter, btn->state & State_Enabled, btn->text); + if (hasMenu) + textRect.adjust(-1, 0, -1, 0); + // Draw the icon: + if (hasIcon) { + int contentW = textRect.width(); + if (hasMenu) + contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4; + QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled; + if (mode == QIcon::Normal && btn->state & State_HasFocus) + mode = QIcon::Active; + // Decide if the icon is should be on or off: + QIcon::State state = QIcon::Off; + if (btn->state & State_On) + state = QIcon::On; + QPixmap pixmap = btn->icon.pixmap(btn->iconSize, mode, state); + contentW += pixmap.width() + QMacStylePrivate::PushButtonContentPadding; + int iconLeftOffset = freeContentRect.x() + (freeContentRect.width() - contentW) / 2; + int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmap.height()) / 2; + QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmap.width(), pixmap.height()); + QRect visualIconDestRect = visualRect(btn->direction, freeContentRect, iconDestRect); + proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap); + int newOffset = iconDestRect.x() + iconDestRect.width() + + QMacStylePrivate::PushButtonContentPadding - textRect.x(); + textRect.adjust(newOffset, 0, newOffset, 0); + } + // Draw the text: + if (hasText) { + textRect = visualRect(btn->direction, freeContentRect, textRect); + proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn->palette, + (btn->state & State_Enabled), btn->text, QPalette::ButtonText); + } + } + } + } + break; + case CE_ComboBoxLabel: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { + QStyleOptionComboBox comboCopy = *cb; + comboCopy.direction = Qt::LeftToRight; + QWindowsStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w); + } + break; + case CE_TabBarTabShape: + if (const QStyleOptionTab *tabOpt = qstyleoption_cast(opt)) { + + if (const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast(opt)) { + if (tabOptV3->documentMode) { + p->save(); + QRect tabRect = tabOptV3->rect; + drawTabShape(p, tabOptV3); + p->restore(); + return; + } + } + HIThemeTabDrawInfo tdi; + tdi.version = 1; + tdi.style = kThemeTabNonFront; + tdi.direction = getTabDirection(tabOpt->shape); + switch (d->aquaSizeConstrain(opt, w)) { + default: + case QAquaSizeUnknown: + case QAquaSizeLarge: + tdi.size = kHIThemeTabSizeNormal; + break; + case QAquaSizeSmall: + tdi.size = kHIThemeTabSizeSmall; + break; + case QAquaSizeMini: + tdi.size = kHIThemeTabSizeMini; + break; + } + bool verticalTabs = tdi.direction == kThemeTabWest || tdi.direction == kThemeTabEast; + QRect tabRect = tabOpt->rect; + + bool selected = tabOpt->state & State_Selected; + if (selected) { + if (!(tabOpt->state & State_Active)) + tdi.style = kThemeTabFrontUnavailable; + else if (!(tabOpt->state & State_Enabled)) + tdi.style = kThemeTabFrontInactive; + else + tdi.style = kThemeTabFront; + } else if (!(tabOpt->state & State_Active)) { + tdi.style = kThemeTabNonFrontUnavailable; + } else if (!(tabOpt->state & State_Enabled)) { + tdi.style = kThemeTabNonFrontInactive; + } else if (tabOpt->state & State_Sunken) { + tdi.style = kThemeTabFrontInactive; // (should be kThemeTabNonFrontPressed) + } + if (tabOpt->state & State_HasFocus) + tdi.adornment = kHIThemeTabAdornmentFocus; + else + tdi.adornment = kHIThemeTabAdornmentNone; + tdi.kind = kHIThemeTabKindNormal; + if (!verticalTabs) + tabRect.setY(tabRect.y() - 1); + else + tabRect.setX(tabRect.x() - 1); + QStyleOptionTab::TabPosition tp = tabOpt->position; + QStyleOptionTab::SelectedPosition sp = tabOpt->selectedPosition; + if (tabOpt->direction == Qt::RightToLeft && !verticalTabs) { + if (sp == QStyleOptionTab::NextIsSelected) + sp = QStyleOptionTab::PreviousIsSelected; + else if (sp == QStyleOptionTab::PreviousIsSelected) + sp = QStyleOptionTab::NextIsSelected; + switch (tp) { + case QStyleOptionTab::Beginning: + tp = QStyleOptionTab::End; + break; + case QStyleOptionTab::End: + tp = QStyleOptionTab::Beginning; + break; + default: + break; + } + } + bool stretchTabs = (!verticalTabs && tabRect.height() > 22) || (verticalTabs && tabRect.width() > 22); + + switch (tp) { + case QStyleOptionTab::Beginning: + tdi.position = kHIThemeTabPositionFirst; + if (sp != QStyleOptionTab::NextIsSelected || stretchTabs) + tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator; + break; + case QStyleOptionTab::Middle: + tdi.position = kHIThemeTabPositionMiddle; + if (selected) + tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator; + if (sp != QStyleOptionTab::NextIsSelected || stretchTabs) // Also when we're selected. + tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator; + break; + case QStyleOptionTab::End: + tdi.position = kHIThemeTabPositionLast; + if (selected) + tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator; + break; + case QStyleOptionTab::OnlyOneTab: + tdi.position = kHIThemeTabPositionOnly; + break; + } + // HITheme doesn't stretch its tabs. Therefore we have to cheat and do the job ourselves. + if (stretchTabs) { + HIRect hirect = CGRectMake(0, 0, 23, 23); + QPixmap pm(23, 23); + pm.fill(Qt::transparent); + { + QMacCGContext pmcg(&pm); + HIThemeDrawTab(&hirect, &tdi, pmcg, kHIThemeOrientationNormal, 0); + } + QStyleHelper::drawBorderPixmap(pm, p, tabRect, 7, 7, 7, 7); + } else { + HIRect hirect = qt_hirectForQRect(tabRect); + HIThemeDrawTab(&hirect, &tdi, cg, kHIThemeOrientationNormal, 0); + } + } + break; + case CE_TabBarTabLabel: + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + QStyleOptionTabV3 myTab = *tab; + ThemeTabDirection ttd = getTabDirection(myTab.shape); + bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; + + // Check to see if we use have the same as the system font + // (QComboMenuItem is internal and should never be seen by the + // outside world, unless they read the source, in which case, it's + // their own fault). + bool nonDefaultFont = p->font() != qt_app_fonts_hash()->value("QComboMenuItem"); + if (verticalTabs || nonDefaultFont || !tab->icon.isNull() + || !myTab.leftButtonSize.isNull() || !myTab.rightButtonSize.isNull()) { + int heightOffset = 0; + if (verticalTabs) { + heightOffset = -1; + } else if (nonDefaultFont) { + if (p->fontMetrics().height() == myTab.rect.height()) + heightOffset = 2; + } + myTab.rect.setHeight(myTab.rect.height() + heightOffset); + + if (myTab.documentMode) { + p->save(); + rotateTabPainter(p, myTab.shape, myTab.rect); + + QPalette np = tab->palette; + np.setColor(QPalette::WindowText, QColor(255, 255, 255, 75)); + QRect nr = subElementRect(SE_TabBarTabText, opt, w); + nr.moveTop(-1); + int alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextHideMnemonic; + proxy()->drawItemText(p, nr, alignment, np, tab->state & State_Enabled, + tab->text, QPalette::WindowText); + p->restore(); + } + + QCommonStyle::drawControl(ce, &myTab, p, w); + } else { + p->save(); + CGContextSetShouldAntialias(cg, true); + CGContextSetShouldSmoothFonts(cg, true); + HIThemeTextInfo tti; + tti.version = qt_mac_hitheme_version; + tti.state = tds; + QColor textColor = myTab.palette.windowText().color(); + CGFloat colorComp[] = { textColor.redF(), textColor.greenF(), + textColor.blueF(), textColor.alphaF() }; + CGContextSetFillColorSpace(cg, QCoreGraphicsPaintEngine::macGenericColorSpace()); + CGContextSetFillColor(cg, colorComp); + switch (d->aquaSizeConstrain(opt, w)) { + default: + case QAquaSizeUnknown: + case QAquaSizeLarge: + tti.fontID = kThemeSystemFont; + break; + case QAquaSizeSmall: + tti.fontID = kThemeSmallSystemFont; + break; + case QAquaSizeMini: + tti.fontID = kThemeMiniSystemFont; + break; + } + tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; + tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; + tti.options = verticalTabs ? kHIThemeTextBoxOptionStronglyVertical : kHIThemeTextBoxOptionNone; + tti.truncationPosition = kHIThemeTextTruncationNone; + tti.truncationMaxLines = 1 + myTab.text.count(QLatin1Char('\n')); + QCFString tabText = qt_mac_removeMnemonics(myTab.text); + QRect r = myTab.rect.adjusted(0, 0, 0, -1); + HIRect bounds = qt_hirectForQRect(r); + HIThemeDrawTextBox(tabText, &bounds, &tti, cg, kHIThemeOrientationNormal); + p->restore(); + } + } + break; + case CE_DockWidgetTitle: + if (const QDockWidget *dockWidget = qobject_cast(w)) { + bool floating = dockWidget->isFloating(); + if (floating) { + ThemeDrawState tds = d->getDrawState(opt->state); + HIThemeWindowDrawInfo wdi; + wdi.version = qt_mac_hitheme_version; + wdi.state = tds; + wdi.windowType = kThemeMovableDialogWindow; + wdi.titleHeight = opt->rect.height(); + wdi.titleWidth = opt->rect.width(); + wdi.attributes = 0; + + HIRect titleBarRect; + HIRect tmpRect = qt_hirectForQRect(opt->rect); + { + QCFType titleRegion; + QRect newr = opt->rect.adjusted(0, 0, 2, 0); + HIThemeGetWindowShape(&tmpRect, &wdi, kWindowTitleBarRgn, &titleRegion); + ptrHIShapeGetBounds(titleRegion, &tmpRect); + newr.translate(newr.x() - int(tmpRect.origin.x), newr.y() - int(tmpRect.origin.y)); + titleBarRect = qt_hirectForQRect(newr); + } + QMacCGContext cg(p); + HIThemeDrawWindowFrame(&titleBarRect, &wdi, cg, kHIThemeOrientationNormal, 0); + } else { + // fill title bar background + QLinearGradient linearGrad(0, opt->rect.top(), 0, opt->rect.bottom()); + linearGrad.setColorAt(0, mainWindowGradientBegin); + linearGrad.setColorAt(1, mainWindowGradientEnd); + p->fillRect(opt->rect, linearGrad); + + // draw horizontal lines at top and bottom + p->save(); + p->setPen(mainWindowGradientBegin.lighter(114)); + p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); + p->setPen(mainWindowGradientEnd.darker(114)); + p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight()); + p->restore(); + } + } + + // Draw the text... + if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast(opt)) { + if (!dwOpt->title.isEmpty()) { + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(dwOpt); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + + QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, opt, w); + if (verticalTitleBar) { + QRect rect = dwOpt->rect; + QRect r = rect; + QSize s = r.size(); + s.transpose(); + r.setSize(s); + + titleRect = QRect(r.left() + rect.bottom() + - titleRect.bottom(), + r.top() + titleRect.left() - rect.left(), + titleRect.height(), titleRect.width()); + + p->translate(r.left(), r.top() + r.width()); + p->rotate(-90); + p->translate(-r.left(), -r.top()); + } + + QFont oldFont = p->font(); + p->setFont(qt_app_fonts_hash()->value("QToolButton", p->font())); + QString text = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, + titleRect.width()); + drawItemText(p, titleRect, + Qt::AlignCenter | Qt::TextShowMnemonic, dwOpt->palette, + dwOpt->state & State_Enabled, text, + QPalette::WindowText); + p->setFont(oldFont); + } + } + break; + case CE_FocusFrame: { + int xOff = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, w) + 1; + int yOff = proxy()->pixelMetric(PM_FocusFrameVMargin, opt, w) + 1; + HIRect hirect = CGRectMake(xOff+opt->rect.x(), yOff+opt->rect.y(), opt->rect.width() - 2 * xOff, + opt->rect.height() - 2 * yOff); + HIThemeDrawFocusRect(&hirect, true, QMacCGContext(p), kHIThemeOrientationNormal); + break; } + case CE_MenuItem: + case CE_MenuEmptyArea: + if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { + p->fillRect(mi->rect, opt->palette.background()); + QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, w); + int tabwidth = mi->tabWidth; + int maxpmw = mi->maxIconWidth; + bool active = mi->state & State_Selected; + bool enabled = mi->state & State_Enabled; + HIRect menuRect = qt_hirectForQRect(mi->menuRect); + HIRect itemRect = qt_hirectForQRect(mi->rect); + HIThemeMenuItemDrawInfo mdi; + mdi.version = qt_mac_hitheme_version; + mdi.itemType = kThemeMenuItemPlain; + if (!mi->icon.isNull()) + mdi.itemType |= kThemeMenuItemHasIcon; + if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) + mdi.itemType |= kThemeMenuItemHierarchical | kThemeMenuItemHierBackground; + else + mdi.itemType |= kThemeMenuItemPopUpBackground; + if (enabled) + mdi.state = kThemeMenuActive; + else + mdi.state = kThemeMenuDisabled; + if (active) + mdi.state |= kThemeMenuSelected; + QRect contentRect; + if (mi->menuItemType == QStyleOptionMenuItem::Separator) { + // First arg should be &menurect, but wacky stuff happens then. + HIThemeDrawMenuSeparator(&itemRect, &itemRect, &mdi, + cg, kHIThemeOrientationNormal); + break; + } else { + HIRect cr; + bool needAlpha = mi->palette.color(QPalette::Button) == Qt::transparent; + if (needAlpha) { + needAlpha = true; + CGContextSaveGState(cg); + CGContextSetAlpha(cg, 0.0); + } + HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, + cg, kHIThemeOrientationNormal, &cr); + if (needAlpha) + CGContextRestoreGState(cg); + if (ce == CE_MenuEmptyArea) + break; + contentRect = qt_qrectForHIRect(cr); + } + int xpos = contentRect.x() + 18; + int checkcol = maxpmw; + if (!enabled) + p->setPen(mi->palette.text().color()); + else if (active) + p->setPen(mi->palette.highlightedText().color()); + else + p->setPen(mi->palette.buttonText().color()); + + if (mi->checked) { + // Use the HIThemeTextInfo foo to draw the check mark correctly, if we do it, + // we somehow need to use a special encoding as it doesn't look right with our + // drawText(). + p->save(); + CGContextSetShouldAntialias(cg, true); + CGContextSetShouldSmoothFonts(cg, true); + QColor textColor = p->pen().color(); + CGFloat colorComp[] = { textColor.redF(), textColor.greenF(), + textColor.blueF(), textColor.alphaF() }; + CGContextSetFillColorSpace(cg, QCoreGraphicsPaintEngine::macGenericColorSpace()); + CGContextSetFillColor(cg, colorComp); + HIThemeTextInfo tti; + tti.version = qt_mac_hitheme_version; + tti.state = tds; + if (active && enabled) + tti.state = kThemeStatePressed; + switch (widgetSize) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + tti.fontID = kThemeMenuItemMarkFont; + break; + case QAquaSizeSmall: + tti.fontID = kThemeSmallSystemFont; + break; + case QAquaSizeMini: + tti.fontID = kThemeMiniSystemFont; + break; + } + tti.horizontalFlushness = kHIThemeTextHorizontalFlushLeft; + tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; + tti.options = kHIThemeTextBoxOptionNone; + tti.truncationPosition = kHIThemeTextTruncationNone; + tti.truncationMaxLines = 1; + QCFString checkmark; +#if 0 + if (mi->checkType == QStyleOptionMenuItem::Exclusive) + checkmark = QString(QChar(kDiamondUnicode)); + else +#endif + checkmark = QString(QChar(kCheckUnicode)); + int mw = checkcol + macItemFrame; + int mh = contentRect.height() - 2 * macItemFrame; + int xp = contentRect.x(); + xp += macItemFrame; + CGFloat outWidth, outHeight, outBaseline; + HIThemeGetTextDimensions(checkmark, 0, &tti, &outWidth, &outHeight, + &outBaseline); + if (widgetSize == QAquaSizeMini) + outBaseline += 1; + QRect r(xp, contentRect.y(), mw, mh); + r.translate(0, p->fontMetrics().ascent() - int(outBaseline) + 1); + HIRect bounds = qt_hirectForQRect(r); + HIThemeDrawTextBox(checkmark, &bounds, &tti, + cg, kHIThemeOrientationNormal); + p->restore(); + } + if (!mi->icon.isNull()) { + QIcon::Mode mode = (mi->state & State_Enabled) ? QIcon::Normal + : QIcon::Disabled; + // Always be normal or disabled to follow the Mac style. + int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize); + QSize iconSize(smallIconSize, smallIconSize); + if (const QComboBox *comboBox = qobject_cast(w)) { + iconSize = comboBox->iconSize(); + } + QPixmap pixmap = mi->icon.pixmap(iconSize, mode); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + QRect cr(xpos, contentRect.y(), checkcol, contentRect.height()); + QRect pmr(0, 0, pixw, pixh); + pmr.moveCenter(cr.center()); + p->drawPixmap(pmr.topLeft(), pixmap); + xpos += pixw + 6; + } + + QString s = mi->text; + if (!s.isEmpty()) { + int t = s.indexOf(QLatin1Char('\t')); + int text_flags = Qt::AlignRight | Qt::AlignVCenter | Qt::TextHideMnemonic + | Qt::TextSingleLine | Qt::AlignAbsolute; + int yPos = contentRect.y(); + if (widgetSize == QAquaSizeMini) + yPos += 1; + p->save(); + if (t >= 0) { + p->setFont(qt_app_fonts_hash()->value("QMenuItem", p->font())); + int xp = contentRect.right() - tabwidth - macRightBorder + - macItemHMargin - macItemFrame + 1; + p->drawText(xp, yPos, tabwidth, contentRect.height(), text_flags, + s.mid(t + 1)); + s = s.left(t); + } + + const int xm = macItemFrame + maxpmw + macItemHMargin; + QFont myFont = mi->font; + // myFont may not have any "hard" flags set. We override + // the point size so that when it is resolved against the device, this font will win. + // This is mainly to handle cases where someone sets the font on the window + // and then the combo inherits it and passes it onward. At that point the resolve mask + // is very, very weak. This makes it stonger. + myFont.setPointSizeF(QFontInfo(mi->font).pointSizeF()); + p->setFont(myFont); + p->drawText(xpos, yPos, contentRect.width() - xm - tabwidth + 1, + contentRect.height(), text_flags ^ Qt::AlignRight, s); + p->restore(); + } + } + break; + case CE_MenuHMargin: + case CE_MenuVMargin: + case CE_MenuTearoff: + case CE_MenuScroller: + if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { + p->fillRect(mi->rect, opt->palette.background()); + + HIRect menuRect = qt_hirectForQRect(mi->menuRect); + HIRect itemRect = qt_hirectForQRect(mi->rect); + HIThemeMenuItemDrawInfo mdi; + mdi.version = qt_mac_hitheme_version; + if (!(opt->state & State_Enabled)) + mdi.state = kThemeMenuDisabled; + else if (opt->state & State_Selected) + mdi.state = kThemeMenuSelected; + else + mdi.state = kThemeMenuActive; + if (ce == CE_MenuScroller) { + if (opt->state & State_DownArrow) + mdi.itemType = kThemeMenuItemScrollDownArrow; + else + mdi.itemType = kThemeMenuItemScrollUpArrow; + } else { + mdi.itemType = kThemeMenuItemPlain; + } + HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, + cg, + kHIThemeOrientationNormal, 0); + if (ce == CE_MenuTearoff) { + p->setPen(QPen(mi->palette.dark().color(), 1, Qt::DashLine)); + p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2 - 1, + mi->rect.x() + mi->rect.width() - 4, + mi->rect.y() + mi->rect.height() / 2 - 1); + p->setPen(QPen(mi->palette.light().color(), 1, Qt::DashLine)); + p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2, + mi->rect.x() + mi->rect.width() - 4, + mi->rect.y() + mi->rect.height() / 2); + } + } + break; + case CE_MenuBarItem: + if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { + HIRect menuRect = qt_hirectForQRect(mi->menuRect); + HIRect itemRect = qt_hirectForQRect(mi->rect); + + if ((opt->state & State_Selected) && (opt->state & State_Enabled) && (opt->state & State_Sunken)){ + // Draw a selected menu item background: + HIThemeMenuItemDrawInfo mdi; + mdi.version = qt_mac_hitheme_version; + mdi.state = kThemeMenuSelected; + mdi.itemType = kThemeMenuItemPlain; + HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, cg, kHIThemeOrientationNormal, 0); + } else { + // Draw the toolbar background: + HIThemeMenuBarDrawInfo bdi; + bdi.version = qt_mac_hitheme_version; + bdi.state = kThemeMenuBarNormal; + bdi.attributes = 0; + HIThemeDrawMenuBarBackground(&menuRect, &bdi, cg, kHIThemeOrientationNormal); + } + + if (!mi->icon.isNull()) { + drawItemPixmap(p, mi->rect, + Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip + | Qt::TextSingleLine, + mi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), + (mi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled)); + } else { + drawItemText(p, mi->rect, + Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip + | Qt::TextSingleLine, + mi->palette, mi->state & State_Enabled, + mi->text, QPalette::ButtonText); + } + } + break; + case CE_MenuBarEmptyArea: + if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { + HIThemeMenuBarDrawInfo bdi; + bdi.version = qt_mac_hitheme_version; + bdi.state = kThemeMenuBarNormal; + bdi.attributes = 0; + HIRect hirect = qt_hirectForQRect(mi->rect); + HIThemeDrawMenuBarBackground(&hirect, &bdi, cg, + kHIThemeOrientationNormal); + break; + } + case CE_ProgressBarContents: + if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { + HIThemeTrackDrawInfo tdi; + tdi.version = qt_mac_hitheme_version; + tdi.reserved = 0; + bool isIndeterminate = (pb->minimum == 0 && pb->maximum == 0); + bool vertical = false; + bool inverted = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt)) { + vertical = (pb2->orientation == Qt::Vertical); + inverted = pb2->invertedAppearance; + } + bool reverse = (!vertical && (pb->direction == Qt::RightToLeft)); + if (inverted) + reverse = !reverse; + switch (d->aquaSizeConstrain(opt, w)) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + tdi.kind = !isIndeterminate ? kThemeLargeProgressBar + : kThemeLargeIndeterminateBar; + break; + case QAquaSizeMini: + case QAquaSizeSmall: + tdi.kind = !isIndeterminate ? kThemeProgressBar : kThemeIndeterminateBar; + break; + } + tdi.bounds = qt_hirectForQRect(pb->rect); + tdi.max = pb->maximum; + tdi.min = pb->minimum; + tdi.value = pb->progress; + tdi.attributes = vertical ? 0 : kThemeTrackHorizontal; + tdi.trackInfo.progress.phase = d->progressFrame; + if (!(pb->state & State_Active)) + tdi.enableState = kThemeTrackInactive; + else if (!(pb->state & State_Enabled)) + tdi.enableState = kThemeTrackDisabled; + else + tdi.enableState = kThemeTrackActive; + HIThemeOrientation drawOrientation = kHIThemeOrientationNormal; + if (reverse) { + if (vertical) { + drawOrientation = kHIThemeOrientationInverted; + } else { + CGContextSaveGState(cg); + CGContextTranslateCTM(cg, pb->rect.width(), 0); + CGContextScaleCTM(cg, -1, 1); + } + } + HIThemeDrawTrack(&tdi, 0, cg, drawOrientation); + if (reverse && !vertical) + CGContextRestoreGState(cg); + } + break; + case CE_ProgressBarLabel: + case CE_ProgressBarGroove: + break; + case CE_SizeGrip: { + if (w && w->testAttribute(Qt::WA_MacOpaqueSizeGrip)) { + HIThemeGrowBoxDrawInfo gdi; + gdi.version = qt_mac_hitheme_version; + gdi.state = tds; + gdi.kind = kHIThemeGrowBoxKindNormal; + gdi.direction = kThemeGrowRight | kThemeGrowDown; + gdi.size = kHIThemeGrowBoxSizeNormal; + HIPoint pt = CGPointMake(opt->rect.x(), opt->rect.y()); + HIThemeDrawGrowBox(&pt, &gdi, cg, kHIThemeOrientationNormal); + } else { + // It isn't possible to draw a transparent size grip with the + // native API, so we do it ourselves here. + const bool metal = qt_mac_is_metal(w); + QPen lineColor = metal ? QColor(236, 236, 236) : QColor(82, 82, 82, 192); + QPen metalHighlight = QColor(5, 5, 5, 192); + lineColor.setWidth(1); + p->save(); + p->setRenderHint(QPainter::Antialiasing); + p->setPen(lineColor); + const Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : qApp->layoutDirection(); + const int NumLines = metal ? 4 : 3; + for (int l = 0; l < NumLines; ++l) { + const int offset = (l * 4 + (metal ? 2 : 3)); + QPoint start, end; + if (layoutDirection == Qt::LeftToRight) { + start = QPoint(opt->rect.width() - offset, opt->rect.height() - 1); + end = QPoint(opt->rect.width() - 1, opt->rect.height() - offset); + } else { + start = QPoint(offset, opt->rect.height() - 1); + end = QPoint(1, opt->rect.height() - offset); + } + p->drawLine(start, end); + if (metal) { + p->setPen(metalHighlight); + p->setRenderHint(QPainter::Antialiasing, false); + p->drawLine(start + QPoint(0, -1), end + QPoint(0, -1)); + p->setRenderHint(QPainter::Antialiasing, true); + p->setPen(lineColor); + } + } + p->restore(); + } + break; + } + case CE_Splitter: { + HIThemeSplitterDrawInfo sdi; + sdi.version = qt_mac_hitheme_version; + sdi.state = tds; + sdi.adornment = qt_mac_is_metal(w) ? kHIThemeSplitterAdornmentMetal + : kHIThemeSplitterAdornmentNone; + HIRect hirect = qt_hirectForQRect(opt->rect); + HIThemeDrawPaneSplitter(&hirect, &sdi, cg, kHIThemeOrientationNormal); + break; } + case CE_RubberBand: + if (const QStyleOptionRubberBand *rubber = qstyleoption_cast(opt)) { + QColor fillColor(opt->palette.color(QPalette::Disabled, QPalette::Highlight)); + if (!rubber->opaque) { + QColor strokeColor; + // I retrieved these colors from the Carbon-Dev mailing list + strokeColor.setHsvF(0, 0, 0.86, 1.0); + fillColor.setHsvF(0, 0, 0.53, 0.25); + if (opt->rect.width() * opt->rect.height() <= 3) { + p->fillRect(opt->rect, strokeColor); + } else { + QPen oldPen = p->pen(); + QBrush oldBrush = p->brush(); + QPen pen(strokeColor); + p->setPen(pen); + p->setBrush(fillColor); + p->drawRect(opt->rect.adjusted(0, 0, -1, -1)); + p->setPen(oldPen); + p->setBrush(oldBrush); + } + } else { + p->fillRect(opt->rect, fillColor); + } + } + break; + case CE_ToolBar: { + // For unified tool bars, draw nothing. + if (w) { + if (QMainWindow * mainWindow = qobject_cast(w->window())) { + if (mainWindow->unifiedTitleAndToolBarOnMac()) + break; + } + } + + // draw background gradient + QLinearGradient linearGrad; + if (opt->state & State_Horizontal) + linearGrad = QLinearGradient(0, opt->rect.top(), 0, opt->rect.bottom()); + else + linearGrad = QLinearGradient(opt->rect.left(), 0, opt->rect.right(), 0); + + linearGrad.setColorAt(0, mainWindowGradientBegin); + linearGrad.setColorAt(1, mainWindowGradientEnd); + p->fillRect(opt->rect, linearGrad); + + p->save(); + if (opt->state & State_Horizontal) { + p->setPen(mainWindowGradientBegin.lighter(114)); + p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); + p->setPen(mainWindowGradientEnd.darker(114)); + p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight()); + + } else { + p->setPen(mainWindowGradientBegin.lighter(114)); + p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); + p->setPen(mainWindowGradientEnd.darker(114)); + p->drawLine(opt->rect.topRight(), opt->rect.bottomRight()); + } + p->restore(); + + + } break; + default: + QWindowsStyle::drawControl(ce, opt, p, w); + break; + } +} + +static void setLayoutItemMargins(int left, int top, int right, int bottom, QRect *rect, Qt::LayoutDirection dir) +{ + if (dir == Qt::RightToLeft) { + rect->adjust(-right, top, -left, bottom); + } else { + rect->adjust(left, top, right, bottom); + } +} + +QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, + const QWidget *widget) const +{ + QRect rect; + int controlSize = getControlSize(opt, widget); + + switch (sr) { + case SE_ItemViewItemText: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(opt)) { + int fw = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, widget); + // We add the focusframeargin between icon and text in commonstyle + rect = QCommonStyle::subElementRect(sr, opt, widget); + if (vopt->features & QStyleOptionViewItemV2::HasDecoration) + rect.adjust(-fw, 0, 0, 0); + } + break; + case SE_ToolBoxTabContents: + rect = QCommonStyle::subElementRect(sr, opt, widget); + break; + case SE_PushButtonContents: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + // Unlike Carbon, we want the button to always be drawn inside its bounds. + // Therefore, the button is a bit smaller, so that even if it got focus, + // the focus 'shadow' will be inside. Adjust the content rect likewise. + HIThemeButtonDrawInfo bdi; + d->initHIThemePushButton(btn, widget, d->getDrawState(opt->state), &bdi); + HIRect contentRect = d->pushButtonContentBounds(btn, &bdi); + rect = qt_qrectForHIRect(contentRect); + } + break; + case SE_HeaderLabel: + if (qstyleoption_cast(opt)) { + rect = QWindowsStyle::subElementRect(sr, opt, widget); + if (widget && widget->height() <= 22){ + // We need to allow the text a bit more space when the header is + // small, otherwise it gets clipped: + rect.setY(0); + rect.setHeight(widget->height()); + } + } + break; + case SE_ProgressBarGroove: + case SE_ProgressBarLabel: + break; + case SE_ProgressBarContents: + rect = opt->rect; + break; + case SE_TreeViewDisclosureItem: { + HIRect inRect = CGRectMake(opt->rect.x(), opt->rect.y(), + opt->rect.width(), opt->rect.height()); + HIThemeButtonDrawInfo bdi; + bdi.version = qt_mac_hitheme_version; + bdi.state = kThemeStateActive; + bdi.kind = kThemeDisclosureButton; + bdi.value = kThemeDisclosureRight; + bdi.adornment = kThemeAdornmentNone; + HIRect contentRect; + HIThemeGetButtonContentBounds(&inRect, &bdi, &contentRect); + QCFType shape; + HIRect outRect; + HIThemeGetButtonShape(&inRect, &bdi, &shape); + ptrHIShapeGetBounds(shape, &outRect); + rect = QRect(int(outRect.origin.x + DisclosureOffset), int(outRect.origin.y), + int(contentRect.origin.x - outRect.origin.x + DisclosureOffset), + int(outRect.size.height)); + break; + } + case SE_TabWidgetLeftCorner: + if (const QStyleOptionTabWidgetFrame *twf + = qstyleoption_cast(opt)) { + switch (twf->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + rect = QRect(QPoint(0, 0), twf->leftCornerWidgetSize); + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + rect = QRect(QPoint(0, twf->rect.height() - twf->leftCornerWidgetSize.height()), + twf->leftCornerWidgetSize); + break; + default: + break; + } + rect = visualRect(twf->direction, twf->rect, rect); + } + break; + case SE_TabWidgetRightCorner: + if (const QStyleOptionTabWidgetFrame *twf + = qstyleoption_cast(opt)) { + switch (twf->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(), 0), + twf->rightCornerWidgetSize); + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(), + twf->rect.height() - twf->rightCornerWidgetSize.height()), + twf->rightCornerWidgetSize); + break; + default: + break; + } + rect = visualRect(twf->direction, twf->rect, rect); + } + break; + case SE_TabWidgetTabContents: + rect = QWindowsStyle::subElementRect(sr, opt, widget); + if (const QStyleOptionTabWidgetFrame *twf + = qstyleoption_cast(opt)) { + if (twf->lineWidth != 0) { + switch (getTabDirection(twf->shape)) { + case kThemeTabNorth: + rect.adjust(+1, +14, -1, -1); + break; + case kThemeTabSouth: + rect.adjust(+1, +1, -1, -14); + break; + case kThemeTabWest: + rect.adjust(+14, +1, -1, -1); + break; + case kThemeTabEast: + rect.adjust(+1, +1, -14, -1); + } + } + } + break; + case SE_LineEditContents: + rect = QWindowsStyle::subElementRect(sr, opt, widget); + if(widget->parentWidget() && qobject_cast(widget->parentWidget())) + rect.adjust(-1, -2, 0, 0); + else + rect.adjust(-1, 0, 0, +1); + break; + case SE_CheckBoxLayoutItem: + rect = opt->rect; + if (controlSize == QAquaSizeLarge) { + setLayoutItemMargins(+2, +3, -9, -4, &rect, opt->direction); + } else if (controlSize == QAquaSizeSmall) { + setLayoutItemMargins(+1, +5, 0 /* fix */, -6, &rect, opt->direction); + } else { + setLayoutItemMargins(0, +7, 0 /* fix */, -6, &rect, opt->direction); + } + break; + case SE_ComboBoxLayoutItem: + if (widget && qobject_cast(widget->parentWidget())) { + // Do nothing, because QToolbar needs the entire widget rect. + // Otherwise it will be clipped. Equivalent to + // widget->setAttribute(Qt::WA_LayoutUsesWidgetRect), but without + // all the hassle. + } else { + rect = opt->rect; + if (controlSize == QAquaSizeLarge) { + rect.adjust(+3, +2, -3, -4); + } else if (controlSize == QAquaSizeSmall) { + setLayoutItemMargins(+2, +1, -3, -4, &rect, opt->direction); + } else { + setLayoutItemMargins(+1, 0, -2, 0, &rect, opt->direction); + } + } + break; + case SE_LabelLayoutItem: + rect = opt->rect; + setLayoutItemMargins(+1, 0 /* SHOULD be -1, done for alignment */, 0, 0 /* SHOULD be -1, done for alignment */, &rect, opt->direction); + break; + case SE_ProgressBarLayoutItem: { + rect = opt->rect; + int bottom = SIZE(3, 8, 8); + if (opt->state & State_Horizontal) { + rect.adjust(0, +1, 0, -bottom); + } else { + setLayoutItemMargins(+1, 0, -bottom, 0, &rect, opt->direction); + } + break; + } + case SE_PushButtonLayoutItem: + if (const QStyleOptionButton *buttonOpt + = qstyleoption_cast(opt)) { + if ((buttonOpt->features & QStyleOptionButton::Flat)) + break; // leave rect alone + } + rect = opt->rect; + if (controlSize == QAquaSizeLarge) { + rect.adjust(+6, +4, -6, -8); + } else if (controlSize == QAquaSizeSmall) { + rect.adjust(+5, +4, -5, -6); + } else { + rect.adjust(+1, 0, -1, -2); + } + break; + case SE_RadioButtonLayoutItem: + rect = opt->rect; + if (controlSize == QAquaSizeLarge) { + setLayoutItemMargins(+2, +2 /* SHOULD BE +3, done for alignment */, + 0, -4 /* SHOULD BE -3, done for alignment */, &rect, opt->direction); + } else if (controlSize == QAquaSizeSmall) { + rect.adjust(0, +6, 0 /* fix */, -5); + } else { + rect.adjust(0, +6, 0 /* fix */, -7); + } + break; + case SE_SliderLayoutItem: + if (const QStyleOptionSlider *sliderOpt + = qstyleoption_cast(opt)) { + rect = opt->rect; + if (sliderOpt->tickPosition == QSlider::NoTicks) { + int above = SIZE(3, 0, 2); + int below = SIZE(4, 3, 0); + if (sliderOpt->orientation == Qt::Horizontal) { + rect.adjust(0, +above, 0, -below); + } else { + rect.adjust(+above, 0, -below, 0); //### Seems that QSlider flip the position of the ticks in reverse mode. + } + } else if (sliderOpt->tickPosition == QSlider::TicksAbove) { + int below = SIZE(3, 2, 0); + if (sliderOpt->orientation == Qt::Horizontal) { + rect.setHeight(rect.height() - below); + } else { + rect.setWidth(rect.width() - below); + } + } else if (sliderOpt->tickPosition == QSlider::TicksBelow) { + int above = SIZE(3, 2, 0); + if (sliderOpt->orientation == Qt::Horizontal) { + rect.setTop(rect.top() + above); + } else { + rect.setLeft(rect.left() + above); + } + } + } + break; + case SE_FrameLayoutItem: + // hack because QStyleOptionFrameV2 doesn't have a frameStyle member + if (const QFrame *frame = qobject_cast(widget)) { + rect = opt->rect; + switch (frame->frameStyle() & QFrame::Shape_Mask) { + case QFrame::HLine: + rect.adjust(0, +1, 0, -1); + break; + case QFrame::VLine: + rect.adjust(+1, 0, -1, 0); + break; + default: + ; + } + } + break; + case SE_GroupBoxLayoutItem: + rect = opt->rect; + if (const QStyleOptionGroupBox *groupBoxOpt = + qstyleoption_cast(opt)) { + /* + AHIG is very inconsistent when it comes to group boxes. + Basically, we make sure that (non-checkable) group boxes + and tab widgets look good when laid out side by side. + */ + if (groupBoxOpt->subControls & (QStyle::SC_GroupBoxCheckBox + | QStyle::SC_GroupBoxLabel)) { + int delta; + if (groupBoxOpt->subControls & QStyle::SC_GroupBoxCheckBox) { + delta = SIZE(8, 4, 4); // guess + } else { + delta = SIZE(15, 12, 12); // guess + } + rect.setTop(rect.top() + delta); + } + } + rect.setBottom(rect.bottom() - 1); + break; + case SE_TabWidgetLayoutItem: + if (const QStyleOptionTabWidgetFrame *tabWidgetOpt = + qstyleoption_cast(opt)) { + /* + AHIG specifies "12 or 14" as the distance from the window + edge. We choose 14 and since the default top margin is 20, + the overlap is 6. + */ + rect = tabWidgetOpt->rect; + if (tabWidgetOpt->shape == QTabBar::RoundedNorth) + rect.setTop(rect.top() + SIZE(6 /* AHIG */, 3 /* guess */, 2 /* AHIG */)); + } + break; + default: + rect = QWindowsStyle::subElementRect(sr, opt, widget); + break; + } + return rect; +} + +static inline void drawToolbarButtonArrow(const QRect &toolButtonRect, ThemeDrawState tds, CGContextRef cg) +{ + QRect arrowRect = QRect(toolButtonRect.right() - 9, toolButtonRect.bottom() - 9, 7, 5); + HIThemePopupArrowDrawInfo padi; + padi.version = qt_mac_hitheme_version; + padi.state = tds; + padi.orientation = kThemeArrowDown; + padi.size = kThemeArrow7pt; + HIRect hirect = qt_hirectForQRect(arrowRect); + HIThemeDrawPopupArrow(&hirect, &padi, cg, kHIThemeOrientationNormal); +} + +void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, + const QWidget *widget) const +{ + ThemeDrawState tds = d->getDrawState(opt->state); + QMacCGContext cg(p); + switch (cc) { + case CC_Slider: + case CC_ScrollBar: + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + HIThemeTrackDrawInfo tdi; + d->getSliderInfo(cc, slider, &tdi, widget); + if (slider->state & State_Sunken) { + if (cc == CC_Slider) { + if (slider->activeSubControls == SC_SliderHandle) + tdi.trackInfo.slider.pressState = kThemeThumbPressed; + else if (slider->activeSubControls == SC_SliderGroove) + tdi.trackInfo.slider.pressState = kThemeLeftTrackPressed; + } else { + if (slider->activeSubControls == SC_ScrollBarSubLine + || slider->activeSubControls == SC_ScrollBarAddLine) { + // This test looks complex but it basically boils down + // to the following: The "RTL look" on the mac also + // changed the directions of the controls, that's not + // what people expect (an arrow is an arrow), so we + // kind of fake and say the opposite button is hit. + // This works great, up until 10.4 which broke the + // scroll bars, so I also have actually do something + // similar when I have an upside down scroll bar + // because on Tiger I only "fake" the reverse stuff. + bool reverseHorizontal = (slider->direction == Qt::RightToLeft + && slider->orientation == Qt::Horizontal); + if ((reverseHorizontal + && slider->activeSubControls == SC_ScrollBarAddLine) + || (!reverseHorizontal + && slider->activeSubControls == SC_ScrollBarSubLine)) { + tdi.trackInfo.scrollbar.pressState = kThemeRightInsideArrowPressed + | kThemeLeftOutsideArrowPressed; + } else { + tdi.trackInfo.scrollbar.pressState = kThemeLeftInsideArrowPressed + | kThemeRightOutsideArrowPressed; + } + } else if (slider->activeSubControls == SC_ScrollBarAddPage) { + tdi.trackInfo.scrollbar.pressState = kThemeRightTrackPressed; + } else if (slider->activeSubControls == SC_ScrollBarSubPage) { + tdi.trackInfo.scrollbar.pressState = kThemeLeftTrackPressed; + } else if (slider->activeSubControls == SC_ScrollBarSlider) { + tdi.trackInfo.scrollbar.pressState = kThemeThumbPressed; + } + } + } + HIRect macRect; + bool tracking = slider->sliderPosition == slider->sliderValue; + if (!tracking) { + // Small optimization, the same as q->subControlRect + QCFType shape; + HIThemeGetTrackThumbShape(&tdi, &shape); + ptrHIShapeGetBounds(shape, &macRect); + tdi.value = slider->sliderValue; + } + + // Remove controls from the scroll bar if it is to short to draw them correctly. + // This is done in two stages: first the thumb indicator is removed when it is + // no longer possible to move it, second the up/down buttons are removed when + // there is not enough space for them. + if (cc == CC_ScrollBar) { + const int scrollBarLength = (slider->orientation == Qt::Horizontal) + ? slider->rect.width() : slider->rect.height(); + const QMacStyle::WidgetSizePolicy sizePolicy = widgetSizePolicy(widget); + if (scrollBarLength < scrollButtonsCutoffSize(thumbIndicatorCutoff, sizePolicy)) + tdi.attributes &= ~kThemeTrackShowThumb; + if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, sizePolicy)) + tdi.enableState = kThemeTrackNothingToScroll; + } else { + if (!(slider->subControls & SC_SliderHandle)) + tdi.attributes &= ~kThemeTrackShowThumb; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + if (!(slider->subControls & SC_SliderGroove)) + tdi.attributes |= kThemeTrackHideTrack; +#endif + } + + HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg, + kHIThemeOrientationNormal); + if (cc == CC_Slider && slider->subControls & SC_SliderTickmarks) { + if (qt_mac_is_metal(widget)) { + if (tdi.enableState == kThemeTrackInactive) + tdi.enableState = kThemeTrackActive; // Looks more Cocoa-like + } + int interval = slider->tickInterval; + if (interval == 0) { + interval = slider->pageStep; + if (interval == 0) + interval = slider->singleStep; + if (interval == 0) + interval = 1; + } + int numMarks = 1 + ((slider->maximum - slider->minimum) / interval); + + if (tdi.trackInfo.slider.thumbDir == kThemeThumbPlain) { + // They asked for both, so we'll give it to them. + tdi.trackInfo.slider.thumbDir = kThemeThumbDownward; + HIThemeDrawTrackTickMarks(&tdi, numMarks, + cg, + kHIThemeOrientationNormal); + tdi.trackInfo.slider.thumbDir = kThemeThumbUpward; + HIThemeDrawTrackTickMarks(&tdi, numMarks, + cg, + kHIThemeOrientationNormal); + } else { + HIThemeDrawTrackTickMarks(&tdi, numMarks, + cg, + kHIThemeOrientationNormal); + + } + } + } + break; + case CC_Q3ListView: + if (const QStyleOptionQ3ListView *lv = qstyleoption_cast(opt)) { + if (lv->subControls & SC_Q3ListView) + QWindowsStyle::drawComplexControl(cc, lv, p, widget); + if (lv->subControls & (SC_Q3ListViewBranch | SC_Q3ListViewExpand)) { + int y = lv->rect.y(); + int h = lv->rect.height(); + int x = lv->rect.right() - 10; + for (int i = 1; i < lv->items.size() && y < h; ++i) { + QStyleOptionQ3ListViewItem item = lv->items.at(i); + if (y + item.height > 0 && (item.childCount > 0 + || (item.features & (QStyleOptionQ3ListViewItem::Expandable + | QStyleOptionQ3ListViewItem::Visible)) + == (QStyleOptionQ3ListViewItem::Expandable + | QStyleOptionQ3ListViewItem::Visible))) { + QStyleOption treeOpt(0); + treeOpt.rect.setRect(x, y + item.height / 2 - 4, 9, 9); + treeOpt.palette = lv->palette; + treeOpt.state = lv->state; + treeOpt.state |= State_Children; + if (item.state & State_Open) + treeOpt.state |= State_Open; + proxy()->drawPrimitive(PE_IndicatorBranch, &treeOpt, p, widget); + } + y += item.totalHeight; + } + } + } + break; + case CC_SpinBox: + if (const QStyleOptionSpinBox *sb = qstyleoption_cast(opt)) { + QStyleOptionSpinBox newSB = *sb; + if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) { + SInt32 frame_size; + GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size); + + QRect lineeditRect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget); + lineeditRect.adjust(-frame_size, -frame_size, +frame_size, +frame_size); + + HIThemeFrameDrawInfo fdi; + fdi.version = qt_mac_hitheme_version; + fdi.state = kThemeStateInactive; + fdi.kind = kHIThemeFrameTextFieldSquare; + fdi.isFocused = false; + HIRect hirect = qt_hirectForQRect(lineeditRect); + HIThemeDrawFrame(&hirect, &fdi, cg, kHIThemeOrientationNormal); + } + if (sb->subControls & (SC_SpinBoxUp | SC_SpinBoxDown)) { + HIThemeButtonDrawInfo bdi; + bdi.version = qt_mac_hitheme_version; + QAquaWidgetSize aquaSize = d->aquaSizeConstrain(opt, widget); + switch (aquaSize) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + bdi.kind = kThemeIncDecButton; + break; + case QAquaSizeMini: + bdi.kind = kThemeIncDecButtonMini; + break; + case QAquaSizeSmall: + bdi.kind = kThemeIncDecButtonSmall; + break; + } + if (!(sb->stepEnabled & (QAbstractSpinBox::StepUpEnabled + | QAbstractSpinBox::StepDownEnabled))) + tds = kThemeStateUnavailable; + if (sb->activeSubControls == SC_SpinBoxDown + && (sb->state & State_Sunken)) + tds = kThemeStatePressedDown; + else if (sb->activeSubControls == SC_SpinBoxUp + && (sb->state & State_Sunken)) + tds = kThemeStatePressedUp; + bdi.state = tds; + if (!(sb->state & State_Active) + && sb->palette.currentColorGroup() == QPalette::Active + && tds == kThemeStateInactive) + bdi.state = kThemeStateActive; + bdi.value = kThemeButtonOff; + bdi.adornment = kThemeAdornmentNone; + + QRect updown = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget); + + updown |= proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget); + HIRect newRect = qt_hirectForQRect(updown); + QRect off_rct; + HIRect outRect; + HIThemeGetButtonBackgroundBounds(&newRect, &bdi, &outRect); + off_rct.setRect(int(newRect.origin.x - outRect.origin.x), + int(newRect.origin.y - outRect.origin.y), + int(outRect.size.width - newRect.size.width), + int(outRect.size.height - newRect.size.height)); + + newRect = qt_hirectForQRect(updown, off_rct); + HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); + } + } + break; + case CC_ComboBox: + if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)){ + HIThemeButtonDrawInfo bdi; + d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state)); + bool drawColorless = combo->palette.currentColorGroup() == QPalette::Active && tds == kThemeStateInactive; + if (!drawColorless) + QMacStylePrivate::drawCombobox(qt_hirectForQRect(combo->rect), bdi, p); + else + d->drawColorlessButton(qt_hirectForQRect(combo->rect), &bdi, p, opt); + } + break; + case CC_TitleBar: + if (const QStyleOptionTitleBar *titlebar + = qstyleoption_cast(opt)) { + if (titlebar->state & State_Active) { + if (titlebar->titleBarState & State_Active) + tds = kThemeStateActive; + else + tds = kThemeStateInactive; + } else { + tds = kThemeStateInactive; + } + + HIThemeWindowDrawInfo wdi; + wdi.version = qt_mac_hitheme_version; + wdi.state = tds; + wdi.windowType = QtWinType; + wdi.titleHeight = titlebar->rect.height(); + wdi.titleWidth = titlebar->rect.width(); + wdi.attributes = kThemeWindowHasTitleText; + // It seems HIThemeDrawTitleBarWidget is not able to draw a dirty + // close button, so use HIThemeDrawWindowFrame instead. + if (widget && widget->isWindowModified() && titlebar->subControls & SC_TitleBarCloseButton) + wdi.attributes |= kThemeWindowHasCloseBox | kThemeWindowHasDirty; + + HIRect titleBarRect; + HIRect tmpRect = qt_hirectForQRect(titlebar->rect); + { + QCFType titleRegion; + QRect newr = titlebar->rect.adjusted(0, 0, 2, 0); + HIThemeGetWindowShape(&tmpRect, &wdi, kWindowTitleBarRgn, &titleRegion); + ptrHIShapeGetBounds(titleRegion, &tmpRect); + newr.translate(newr.x() - int(tmpRect.origin.x), newr.y() - int(tmpRect.origin.y)); + titleBarRect = qt_hirectForQRect(newr); + } + HIThemeDrawWindowFrame(&titleBarRect, &wdi, cg, kHIThemeOrientationNormal, 0); + if (titlebar->subControls & (SC_TitleBarCloseButton + | SC_TitleBarMaxButton + | SC_TitleBarMinButton + | SC_TitleBarNormalButton)) { + HIThemeWindowWidgetDrawInfo wwdi; + wwdi.version = qt_mac_hitheme_version; + wwdi.widgetState = tds; + if (titlebar->state & State_MouseOver) + wwdi.widgetState = kThemeStateRollover; + wwdi.windowType = QtWinType; + wwdi.attributes = wdi.attributes | kThemeWindowHasFullZoom | kThemeWindowHasCloseBox | kThemeWindowHasCollapseBox; + wwdi.windowState = wdi.state; + wwdi.titleHeight = wdi.titleHeight; + wwdi.titleWidth = wdi.titleWidth; + ThemeDrawState savedControlState = wwdi.widgetState; + uint sc = SC_TitleBarMinButton; + ThemeTitleBarWidget tbw = kThemeWidgetCollapseBox; + bool active = titlebar->state & State_Active; + if (qMacVersion() < QSysInfo::MV_10_6) { + int border = 2; + titleBarRect.origin.x += border; + titleBarRect.origin.y -= border; + } + + while (sc <= SC_TitleBarCloseButton) { + if (sc & titlebar->subControls) { + uint tmp = sc; + wwdi.widgetState = savedControlState; + wwdi.widgetType = tbw; + if (sc == SC_TitleBarMinButton) + tmp |= SC_TitleBarNormalButton; + if (active && (titlebar->activeSubControls & tmp) + && (titlebar->state & State_Sunken)) + wwdi.widgetState = kThemeStatePressed; + // Draw all sub controllers except the dirty close button + // (it is already handled by HIThemeDrawWindowFrame). + if (!(widget && widget->isWindowModified() && tbw == kThemeWidgetCloseBox)) { + HIThemeDrawTitleBarWidget(&titleBarRect, &wwdi, cg, kHIThemeOrientationNormal); + p->paintEngine()->syncState(); + } + } + sc = sc << 1; + tbw = tbw >> 1; + } + } + p->paintEngine()->syncState(); + if (titlebar->subControls & SC_TitleBarLabel) { + int iw = 0; + if (!titlebar->icon.isNull()) { + QCFType titleRegion2; + HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleProxyIconRgn, + &titleRegion2); + ptrHIShapeGetBounds(titleRegion2, &tmpRect); + if (tmpRect.size.width != 1) { + int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); + iw = titlebar->icon.actualSize(QSize(iconExtent, iconExtent)).width(); + } + } + if (!titlebar->text.isEmpty()) { + p->save(); + QCFType titleRegion3; + HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleTextRgn, &titleRegion3); + ptrHIShapeGetBounds(titleRegion3, &tmpRect); + p->setClipRect(qt_qrectForHIRect(tmpRect)); + QRect br = p->clipRegion().boundingRect(); + int x = br.x(), + y = br.y() + (titlebar->rect.height() / 2 - p->fontMetrics().height() / 2); + if (br.width() <= (p->fontMetrics().width(titlebar->text) + iw * 2)) + x += iw; + else + x += br.width() / 2 - p->fontMetrics().width(titlebar->text) / 2; + if (iw) + p->drawPixmap(x - iw, y, + titlebar->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), QIcon::Normal)); + drawItemText(p, br, Qt::AlignCenter, opt->palette, tds == kThemeStateActive, + titlebar->text, QPalette::Text); + p->restore(); + } + } + } + break; + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox + = qstyleoption_cast(opt)) { + + QStyleOptionGroupBox groupBoxCopy(*groupBox); + if ((widget && !widget->testAttribute(Qt::WA_SetFont)) + && QApplication::desktopSettingsAware()) + groupBoxCopy.subControls = groupBoxCopy.subControls & ~SC_GroupBoxLabel; + QWindowsStyle::drawComplexControl(cc, &groupBoxCopy, p, widget); + if (groupBoxCopy.subControls != groupBox->subControls) { + bool checkable = groupBox->subControls & SC_GroupBoxCheckBox; + p->save(); + CGContextSetShouldAntialias(cg, true); + CGContextSetShouldSmoothFonts(cg, true); + HIThemeTextInfo tti; + tti.version = qt_mac_hitheme_version; + tti.state = tds; + QColor textColor = groupBox->palette.windowText().color(); + CGFloat colorComp[] = { textColor.redF(), textColor.greenF(), + textColor.blueF(), textColor.alphaF() }; + CGContextSetFillColorSpace(cg, QCoreGraphicsPaintEngine::macGenericColorSpace()); + CGContextSetFillColor(cg, colorComp); + tti.fontID = checkable ? kThemeSystemFont : kThemeSmallSystemFont; + tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; + tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; + tti.options = kHIThemeTextBoxOptionNone; + tti.truncationPosition = kHIThemeTextTruncationNone; + tti.truncationMaxLines = 1 + groupBox->text.count(QLatin1Char('\n')); + QCFString groupText = qt_mac_removeMnemonics(groupBox->text); + QRect r = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget); + HIRect bounds = qt_hirectForQRect(r); + HIThemeDrawTextBox(groupText, &bounds, &tti, cg, kHIThemeOrientationNormal); + p->restore(); + } + } + break; + case CC_ToolButton: + if (const QStyleOptionToolButton *tb + = qstyleoption_cast(opt)) { + if (widget && qobject_cast(widget->parentWidget())) { + if (tb->subControls & SC_ToolButtonMenu) { + QStyleOption arrowOpt(0); + arrowOpt.rect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); + arrowOpt.rect.setY(arrowOpt.rect.y() + arrowOpt.rect.height() / 2); + arrowOpt.rect.setHeight(arrowOpt.rect.height() / 2); + arrowOpt.state = tb->state; + arrowOpt.palette = tb->palette; + proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); + } else if ((tb->features & QStyleOptionToolButton::HasMenu) + && (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) { + drawToolbarButtonArrow(tb->rect, tds, cg); + } + if (tb->state & State_On) { + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { + static QPixmap pm(QLatin1String(":/trolltech/mac/style/images/leopard-unified-toolbar-on.png")); + p->setRenderHint(QPainter::SmoothPixmapTransform); + QStyleHelper::drawBorderPixmap(pm, p, tb->rect, 2, 2, 2, 2); + } else { + QPen oldPen = p->pen(); + p->setPen(QColor(0, 0, 0, 0x3a)); + p->fillRect(tb->rect.adjusted(1, 1, -1, -1), QColor(0, 0, 0, 0x12)); + p->drawLine(tb->rect.left() + 1, tb->rect.top(), + tb->rect.right() - 1, tb->rect.top()); + p->drawLine(tb->rect.left() + 1, tb->rect.bottom(), + tb->rect.right() - 1, tb->rect.bottom()); + p->drawLine(tb->rect.topLeft(), tb->rect.bottomLeft()); + p->drawLine(tb->rect.topRight(), tb->rect.bottomRight()); + p->setPen(oldPen); + } + } + proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget); + } else { + ThemeButtonKind bkind = kThemeBevelButton; + switch (d->aquaSizeConstrain(opt, widget)) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + bkind = kThemeBevelButton; + break; + case QAquaSizeMini: + case QAquaSizeSmall: + bkind = kThemeSmallBevelButton; + break; + } + + QRect button, menuarea; + button = proxy()->subControlRect(cc, tb, SC_ToolButton, widget); + menuarea = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); + State bflags = tb->state, + mflags = tb->state; + if (tb->subControls & SC_ToolButton) + bflags |= State_Sunken; + if (tb->subControls & SC_ToolButtonMenu) + mflags |= State_Sunken; + + if (tb->subControls & SC_ToolButton) { + if (bflags & (State_Sunken | State_On | State_Raised)) { + HIThemeButtonDrawInfo bdi; + bdi.version = qt_mac_hitheme_version; + bdi.state = tds; + bdi.adornment = kThemeAdornmentNone; + bdi.kind = bkind; + bdi.value = kThemeButtonOff; + if (tb->state & State_HasFocus) + bdi.adornment = kThemeAdornmentFocus; + if (tb->state & State_Sunken) + bdi.state = kThemeStatePressed; + if (tb->state & State_On) + bdi.value = kThemeButtonOn; + + QRect off_rct(0, 0, 0, 0); + HIRect myRect, macRect; + myRect = CGRectMake(tb->rect.x(), tb->rect.y(), + tb->rect.width(), tb->rect.height()); + HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect); + off_rct.setRect(int(myRect.origin.x - macRect.origin.x), + int(myRect.origin.y - macRect.origin.y), + int(macRect.size.width - myRect.size.width), + int(macRect.size.height - myRect.size.height)); + + myRect = qt_hirectForQRect(button, off_rct); + HIThemeDrawButton(&myRect, &bdi, cg, kHIThemeOrientationNormal, 0); + } + } + + if (tb->subControls & SC_ToolButtonMenu) { + HIThemeButtonDrawInfo bdi; + bdi.version = qt_mac_hitheme_version; + bdi.state = tds; + bdi.value = kThemeButtonOff; + bdi.adornment = kThemeAdornmentNone; + bdi.kind = bkind; + if (tb->state & State_HasFocus) + bdi.adornment = kThemeAdornmentFocus; + if (tb->state & (State_On | State_Sunken) + || (tb->activeSubControls & SC_ToolButtonMenu)) + bdi.state = kThemeStatePressed; + HIRect hirect = qt_hirectForQRect(menuarea); + HIThemeDrawButton(&hirect, &bdi, cg, kHIThemeOrientationNormal, 0); + QRect r(menuarea.x() + ((menuarea.width() / 2) - 3), menuarea.height() - 8, 8, 8); + HIThemePopupArrowDrawInfo padi; + padi.version = qt_mac_hitheme_version; + padi.state = tds; + padi.orientation = kThemeArrowDown; + padi.size = kThemeArrow7pt; + hirect = qt_hirectForQRect(r); + HIThemeDrawPopupArrow(&hirect, &padi, cg, kHIThemeOrientationNormal); + } else if (tb->features & QStyleOptionToolButton::HasMenu) { + drawToolbarButtonArrow(tb->rect, tds, cg); + } + QRect buttonRect = proxy()->subControlRect(CC_ToolButton, tb, SC_ToolButton, widget); + int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); + QStyleOptionToolButton label = *tb; + label.rect = buttonRect.adjusted(fw, fw, -fw, -fw); + proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); + } + } + break; + case CC_Dial: + if (const QStyleOptionSlider *dial = qstyleoption_cast(opt)) + QStyleHelper::drawDial(dial, p); + break; + default: + QWindowsStyle::drawComplexControl(cc, opt, p, widget); + break; + } +} + +QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, + const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *widget) const +{ + SubControl sc = QStyle::SC_None; + switch (cc) { + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(opt)) { + sc = QWindowsStyle::hitTestComplexControl(cc, cmb, pt, widget); + if (!cmb->editable && sc != QStyle::SC_None) + sc = SC_ComboBoxArrow; // A bit of a lie, but what we want + } + break; + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + HIThemeTrackDrawInfo tdi; + d->getSliderInfo(cc, slider, &tdi, widget); + ControlPartCode part; + HIPoint pos = CGPointMake(pt.x(), pt.y()); + if (HIThemeHitTestTrack(&tdi, &pos, &part)) { + if (part == kControlPageUpPart || part == kControlPageDownPart) + sc = SC_SliderGroove; + else + sc = SC_SliderHandle; + } + } + break; + case CC_ScrollBar: + if (const QStyleOptionSlider *sb = qstyleoption_cast(opt)) { + HIScrollBarTrackInfo sbi; + sbi.version = qt_mac_hitheme_version; + if (!(sb->state & State_Active)) + sbi.enableState = kThemeTrackInactive; + else if (sb->state & State_Enabled) + sbi.enableState = kThemeTrackActive; + else + sbi.enableState = kThemeTrackDisabled; + + // The arrow buttons are not drawn if the scroll bar is to short, + // exclude them from the hit test. + const int scrollBarLength = (sb->orientation == Qt::Horizontal) + ? sb->rect.width() : sb->rect.height(); + if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, widgetSizePolicy(widget))) + sbi.enableState = kThemeTrackNothingToScroll; + + sbi.viewsize = sb->pageStep; + HIPoint pos = CGPointMake(pt.x(), pt.y()); + + HIRect macSBRect = qt_hirectForQRect(sb->rect); + ControlPartCode part; + bool reverseHorizontal = (sb->direction == Qt::RightToLeft + && sb->orientation == Qt::Horizontal + && (!sb->upsideDown || + (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 + && sb->upsideDown))); + if (HIThemeHitTestScrollBarArrows(&macSBRect, &sbi, sb->orientation == Qt::Horizontal, + &pos, 0, &part)) { + if (part == kControlUpButtonPart) + sc = reverseHorizontal ? SC_ScrollBarAddLine : SC_ScrollBarSubLine; + else if (part == kControlDownButtonPart) + sc = reverseHorizontal ? SC_ScrollBarSubLine : SC_ScrollBarAddLine; + } else { + HIThemeTrackDrawInfo tdi; + d->getSliderInfo(cc, sb, &tdi, widget); + if(tdi.enableState == kThemeTrackInactive) + tdi.enableState = kThemeTrackActive; + if (HIThemeHitTestTrack(&tdi, &pos, &part)) { + if (part == kControlPageUpPart) + sc = reverseHorizontal ? SC_ScrollBarAddPage + : SC_ScrollBarSubPage; + else if (part == kControlPageDownPart) + sc = reverseHorizontal ? SC_ScrollBarSubPage + : SC_ScrollBarAddPage; + else + sc = SC_ScrollBarSlider; + } + } + } + break; +/* + I don't know why, but we only get kWindowContentRgn here, which isn't what we want at all. + It would be very nice if this would work. + case QStyle::CC_TitleBar: + if (const QStyleOptionTitleBar *tbar = qstyleoption_cast(opt)) { + HIThemeWindowDrawInfo wdi; + memset(&wdi, 0, sizeof(wdi)); + wdi.version = qt_mac_hitheme_version; + wdi.state = kThemeStateActive; + wdi.windowType = QtWinType; + wdi.titleWidth = tbar->rect.width(); + wdi.titleHeight = tbar->rect.height(); + if (tbar->titleBarState) + wdi.attributes |= kThemeWindowHasFullZoom | kThemeWindowHasCloseBox + | kThemeWindowHasCollapseBox; + else if (tbar->titleBarFlags & Qt::WindowSystemMenuHint) + wdi.attributes |= kThemeWindowHasCloseBox; + QRect tmpRect = tbar->rect; + tmpRect.setHeight(tmpRect.height() + 100); + HIRect hirect = qt_hirectForQRect(tmpRect); + WindowRegionCode hit; + HIPoint hipt = CGPointMake(pt.x(), pt.y()); + if (HIThemeGetWindowRegionHit(&hirect, &wdi, &hipt, &hit)) { + switch (hit) { + case kWindowCloseBoxRgn: + sc = QStyle::SC_TitleBarCloseButton; + break; + case kWindowCollapseBoxRgn: + sc = QStyle::SC_TitleBarMinButton; + break; + case kWindowZoomBoxRgn: + sc = QStyle::SC_TitleBarMaxButton; + break; + case kWindowTitleTextRgn: + sc = QStyle::SC_TitleBarLabel; + break; + default: + qDebug("got something else %d", hit); + break; + } + } + } + break; +*/ + default: + sc = QWindowsStyle::hitTestComplexControl(cc, opt, pt, widget); + break; + } + return sc; +} + +QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, + const QWidget *widget) const +{ + QRect ret; + switch (cc) { + case CC_Slider: + case CC_ScrollBar: + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + HIThemeTrackDrawInfo tdi; + d->getSliderInfo(cc, slider, &tdi, widget); + HIRect macRect; + QCFType shape; + bool scrollBar = cc == CC_ScrollBar; + if ((scrollBar && sc == SC_ScrollBarSlider) + || (!scrollBar && sc == SC_SliderHandle)) { + HIThemeGetTrackThumbShape(&tdi, &shape); + ptrHIShapeGetBounds(shape, &macRect); + } else if (!scrollBar && sc == SC_SliderGroove) { + HIThemeGetTrackBounds(&tdi, &macRect); + } else if (sc == SC_ScrollBarGroove) { // Only scroll bar parts available... + HIThemeGetTrackDragRect(&tdi, &macRect); + } else { + ControlPartCode cpc; + if (sc == SC_ScrollBarSubPage || sc == SC_ScrollBarAddPage) { + cpc = sc == SC_ScrollBarSubPage ? kControlPageDownPart + : kControlPageUpPart; + } else { + cpc = sc == SC_ScrollBarSubLine ? kControlUpButtonPart + : kControlDownButtonPart; + if (slider->direction == Qt::RightToLeft + && slider->orientation == Qt::Horizontal) { + if (cpc == kControlDownButtonPart) + cpc = kControlUpButtonPart; + else if (cpc == kControlUpButtonPart) + cpc = kControlDownButtonPart; + } + } + HIThemeGetTrackPartBounds(&tdi, cpc, &macRect); + } + ret = qt_qrectForHIRect(macRect); + + // Tweak: the dark line between the sub/add line buttons belong to only one of the buttons + // when doing hit-testing, but both of them have to repaint it. Extend the rect to cover + // the line in the cases where HIThemeGetTrackPartBounds returns a rect that doesn't. + if (slider->orientation == Qt::Horizontal) { + if (slider->direction == Qt::LeftToRight && sc == SC_ScrollBarSubLine) + ret.adjust(0, 0, 1, 0); + else if (slider->direction == Qt::RightToLeft && sc == SC_ScrollBarAddLine) + ret.adjust(-1, 0, 1, 0); + } else if (sc == SC_ScrollBarAddLine) { + ret.adjust(0, -1, 0, 1); + } + } + break; + case CC_TitleBar: + if (const QStyleOptionTitleBar *titlebar + = qstyleoption_cast(opt)) { + HIThemeWindowDrawInfo wdi; + memset(&wdi, 0, sizeof(wdi)); + wdi.version = qt_mac_hitheme_version; + wdi.state = kThemeStateActive; + wdi.windowType = QtWinType; + wdi.titleHeight = titlebar->rect.height(); + wdi.titleWidth = titlebar->rect.width(); + wdi.attributes = kThemeWindowHasTitleText; + if (titlebar->subControls & SC_TitleBarCloseButton) + wdi.attributes |= kThemeWindowHasCloseBox; + if (titlebar->subControls & SC_TitleBarMaxButton + | SC_TitleBarNormalButton) + wdi.attributes |= kThemeWindowHasFullZoom; + if (titlebar->subControls & SC_TitleBarMinButton) + wdi.attributes |= kThemeWindowHasCollapseBox; + WindowRegionCode wrc = kWindowGlobalPortRgn; + + if (sc == SC_TitleBarCloseButton) + wrc = kWindowCloseBoxRgn; + else if (sc == SC_TitleBarMinButton) + wrc = kWindowCollapseBoxRgn; + else if (sc == SC_TitleBarMaxButton) + wrc = kWindowZoomBoxRgn; + else if (sc == SC_TitleBarLabel) + wrc = kWindowTitleTextRgn; + else if (sc == SC_TitleBarSysMenu) + ret.setRect(-1024, -1024, 10, proxy()->pixelMetric(PM_TitleBarHeight, + titlebar, widget)); + if (wrc != kWindowGlobalPortRgn) { + QCFType region; + QRect tmpRect = titlebar->rect; + HIRect titleRect = qt_hirectForQRect(tmpRect); + HIThemeGetWindowShape(&titleRect, &wdi, kWindowTitleBarRgn, ®ion); + ptrHIShapeGetBounds(region, &titleRect); + CFRelease(region); + tmpRect.translate(tmpRect.x() - int(titleRect.origin.x), + tmpRect.y() - int(titleRect.origin.y)); + titleRect = qt_hirectForQRect(tmpRect); + HIThemeGetWindowShape(&titleRect, &wdi, wrc, ®ion); + ptrHIShapeGetBounds(region, &titleRect); + ret = qt_qrectForHIRect(titleRect); + } + } + break; + case CC_ComboBox: + if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)) { + HIThemeButtonDrawInfo bdi; + d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state)); + + switch (sc) { + case SC_ComboBoxEditField:{ + ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); + // hack to posistion the edit feld correctly for QDateTimeEdits + // in calendarPopup mode. + if (qobject_cast(widget)) { + ret.moveTop(ret.top() - 2); + ret.setHeight(ret.height() +1); + } + break; } + case SC_ComboBoxArrow:{ + ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); + ret.setX(ret.x() + ret.width()); + ret.setWidth(combo->rect.right() - ret.right()); + break; } + case SC_ComboBoxListBoxPopup:{ + if (combo->editable) { + HIRect inner = QMacStylePrivate::comboboxInnerBounds(qt_hirectForQRect(combo->rect), bdi.kind); + QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); + const int comboTop = combo->rect.top(); + ret = QRect(qRound(inner.origin.x), + comboTop, + qRound(inner.origin.x - combo->rect.left() + inner.size.width), + editRect.bottom() - comboTop + 2); + } else { + QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); + ret = QRect(combo->rect.x() + 4 - 11, + combo->rect.y() + 1, + editRect.width() + 10 + 11, + 1); + } + break; } + default: + break; + } + } + break; + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(opt)) { + bool checkable = groupBox->subControls & SC_GroupBoxCheckBox; + bool flat = (groupBox->features & QStyleOptionFrameV2::Flat); + bool hasNoText = !checkable && groupBox->text.isEmpty(); + switch (sc) { + case SC_GroupBoxLabel: + case SC_GroupBoxCheckBox: { + // Cheat and use the smaller font if we need to + bool checkable = groupBox->subControls & SC_GroupBoxCheckBox; + bool fontIsSet = (widget && widget->testAttribute(Qt::WA_SetFont)) + || !QApplication::desktopSettingsAware(); + int tw; + int h; + int margin = flat || hasNoText ? 0 : 12; + ret = groupBox->rect.adjusted(margin, 0, -margin, 0); + + if (!fontIsSet) { + HIThemeTextInfo tti; + tti.version = qt_mac_hitheme_version; + tti.state = kThemeStateActive; + tti.fontID = checkable ? kThemeSystemFont : kThemeSmallSystemFont; + tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; + tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; + tti.options = kHIThemeTextBoxOptionNone; + tti.truncationPosition = kHIThemeTextTruncationNone; + tti.truncationMaxLines = 1 + groupBox->text.count(QLatin1Char('\n')); + CGFloat width; + CGFloat height; + QCFString groupText = qt_mac_removeMnemonics(groupBox->text); + HIThemeGetTextDimensions(groupText, 0, &tti, &width, &height, 0); + tw = qRound(width); + h = qCeil(height); + } else { + QFontMetricsF fm = QFontMetricsF(groupBox->fontMetrics); + h = qCeil(fm.height()); + tw = qCeil(fm.size(Qt::TextShowMnemonic, groupBox->text).width()); + } + ret.setHeight(h); + + QRect labelRect = alignedRect(groupBox->direction, groupBox->textAlignment, + QSize(tw, h), ret); + int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget); + bool rtl = groupBox->direction == Qt::RightToLeft; + if (sc == SC_GroupBoxLabel) { + if (checkable) { + int newSum = indicatorWidth + 1; + int newLeft = labelRect.left() + (rtl ? -newSum : newSum); + labelRect.moveLeft(newLeft); + } else if (flat) { + int newLeft = labelRect.left() - (rtl ? 3 : -3); + labelRect.moveLeft(newLeft); + labelRect.moveTop(labelRect.top() + 3); + } else { + int newLeft = labelRect.left() - (rtl ? 3 : 2); + labelRect.moveLeft(newLeft); + labelRect.moveTop(labelRect.top() + 5); + } + ret = labelRect; + } + + if (sc == SC_GroupBoxCheckBox) { + int left = rtl ? labelRect.right() - indicatorWidth : labelRect.left(); + ret.setRect(left, ret.top(), + indicatorWidth, proxy()->pixelMetric(PM_IndicatorHeight, opt, widget)); + } + break; + } + case SC_GroupBoxContents: + case SC_GroupBoxFrame: { + if (flat) { + ret = QWindowsStyle::subControlRect(cc, groupBox, sc, widget); + break; + } + QFontMetrics fm = groupBox->fontMetrics; + bool checkable = groupBox->subControls & SC_GroupBoxCheckBox; + int yOffset = 3; + if (!checkable) { + if (widget && !widget->testAttribute(Qt::WA_SetFont) + && QApplication::desktopSettingsAware()) + fm = QFontMetrics(qt_app_fonts_hash()->value("QSmallFont", QFont())); + yOffset = 5; + if (hasNoText) + yOffset = -qCeil(QFontMetricsF(fm).height()); + } + + ret = opt->rect.adjusted(0, qCeil(QFontMetricsF(fm).height()) + yOffset, 0, 0); + if (sc == SC_GroupBoxContents) + ret.adjust(3, 3, -3, -4); // guess + } + break; + default: + ret = QWindowsStyle::subControlRect(cc, groupBox, sc, widget); + break; + } + } + break; + case CC_SpinBox: + if (const QStyleOptionSpinBox *spin = qstyleoption_cast(opt)) { + QAquaWidgetSize aquaSize = d->aquaSizeConstrain(spin, widget); + int spinner_w; + int spinBoxSep; + int fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, spin, widget); + switch (aquaSize) { + default: + case QAquaSizeUnknown: + case QAquaSizeLarge: + spinner_w = 14; + spinBoxSep = 2; + break; + case QAquaSizeSmall: + spinner_w = 12; + spinBoxSep = 2; + break; + case QAquaSizeMini: + spinner_w = 10; + spinBoxSep = 1; + break; + } + + switch (sc) { + case SC_SpinBoxUp: + case SC_SpinBoxDown: { + if (spin->buttonSymbols == QAbstractSpinBox::NoButtons) + break; + + const int y = fw; + const int x = spin->rect.width() - spinner_w; + ret.setRect(x + spin->rect.x(), y + spin->rect.y(), spinner_w, spin->rect.height() - y * 2); + HIThemeButtonDrawInfo bdi; + bdi.version = qt_mac_hitheme_version; + bdi.kind = kThemeIncDecButton; + int hackTranslateX; + switch (aquaSize) { + default: + case QAquaSizeUnknown: + case QAquaSizeLarge: + bdi.kind = kThemeIncDecButton; + hackTranslateX = 0; + break; + case QAquaSizeSmall: + bdi.kind = kThemeIncDecButtonSmall; + hackTranslateX = -2; + break; + case QAquaSizeMini: + bdi.kind = kThemeIncDecButtonMini; + hackTranslateX = -1; + break; + } + bdi.state = kThemeStateActive; + bdi.value = kThemeButtonOff; + bdi.adornment = kThemeAdornmentNone; + HIRect hirect = qt_hirectForQRect(ret); + + HIRect outRect; + HIThemeGetButtonBackgroundBounds(&hirect, &bdi, &outRect); + ret = qt_qrectForHIRect(outRect); + switch (sc) { + case SC_SpinBoxUp: + ret.setHeight(ret.height() / 2); + break; + case SC_SpinBoxDown: + ret.setY(ret.y() + ret.height() / 2); + break; + default: + Q_ASSERT(0); + break; + } + ret.translate(hackTranslateX, 0); // hack: position the buttons correctly (weird that we need this) + ret = visualRect(spin->direction, spin->rect, ret); + break; + } + case SC_SpinBoxEditField: + if (spin->buttonSymbols == QAbstractSpinBox::NoButtons) { + ret.setRect(fw, fw, + spin->rect.width() - fw * 2, + spin->rect.height() - fw * 2); + } else { + ret.setRect(fw, fw, + spin->rect.width() - fw * 2 - spinBoxSep - spinner_w, + spin->rect.height() - fw * 2); + } + ret = visualRect(spin->direction, spin->rect, ret); + break; + default: + ret = QWindowsStyle::subControlRect(cc, spin, sc, widget); + break; + } + } + break; + case CC_ToolButton: + ret = QWindowsStyle::subControlRect(cc, opt, sc, widget); + if (sc == SC_ToolButtonMenu && widget && !qobject_cast(widget->parentWidget())) { + ret.adjust(-1, 0, 0, 0); + } + break; + default: + ret = QWindowsStyle::subControlRect(cc, opt, sc, widget); + break; + } + return ret; +} + +QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, + const QSize &csz, const QWidget *widget) const +{ + QSize sz(csz); + bool useAquaGuideline = true; + + switch (ct) { + case QStyle::CT_SpinBox: + // hack to work around horrible sizeHint() code in QAbstractSpinBox + sz.setHeight(sz.height() - 3); + break; + case QStyle::CT_TabWidget: + // the size between the pane and the "contentsRect" (+4,+4) + // (the "contentsRect" is on the inside of the pane) + sz = QWindowsStyle::sizeFromContents(ct, opt, csz, widget); + /** + This is supposed to show the relationship between the tabBar and + the stack widget of a QTabWidget. + Unfortunately ascii is not a good way of representing graphics..... + PS: The '=' line is the painted frame. + + top ---+ + | + | + | + | vvv just outside the painted frame is the "pane" + - -|- - - - - - - - - - <-+ + TAB BAR +=====^============ | +2 pixels + - - -|- - -|- - - - - - - <-+ + | | ^ ^^^ just inside the painted frame is the "contentsRect" + | | | + | overlap | + | | | + bottom ------+ <-+ +14 pixels + | + v + ------------------------------ <- top of stack widget + + + To summarize: + * 2 is the distance between the pane and the contentsRect + * The 14 and the 1's are the distance from the contentsRect to the stack widget. + (same value as used in SE_TabWidgetTabContents) + * overlap is how much the pane should overlap the tab bar + */ + // then add the size between the stackwidget and the "contentsRect" + + if (const QStyleOptionTabWidgetFrame *twf + = qstyleoption_cast(opt)) { + QSize extra(0,0); + const int overlap = pixelMetric(PM_TabBarBaseOverlap, opt, widget); + const int gapBetweenTabbarAndStackWidget = 2 + 14 - overlap; + + if (getTabDirection(twf->shape) == kThemeTabNorth || getTabDirection(twf->shape) == kThemeTabSouth) { + extra = QSize(2, gapBetweenTabbarAndStackWidget + 1); + } else { + extra = QSize(gapBetweenTabbarAndStackWidget + 1, 2); + } + sz+= extra; + } + + break; + case QStyle::CT_TabBarTab: + if (const QStyleOptionTabV3 *tab = qstyleoption_cast(opt)) { + const QAquaWidgetSize AquaSize = d->aquaSizeConstrain(opt, widget); + const bool differentFont = (widget && widget->testAttribute(Qt::WA_SetFont)) + || !QApplication::desktopSettingsAware(); + ThemeTabDirection ttd = getTabDirection(tab->shape); + bool vertTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; + if (vertTabs) + sz.transpose(); + int defaultTabHeight; + int defaultExtraSpace = proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget); // Remove spurious gcc warning (AFAIK) + QFontMetrics fm = opt->fontMetrics; + switch (AquaSize) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + if (tab->documentMode) + defaultTabHeight = 23; + else + defaultTabHeight = 21; + break; + case QAquaSizeSmall: + defaultTabHeight = 18; + break; + case QAquaSizeMini: + defaultTabHeight = 16; + break; + } + bool setWidth = false; + if (differentFont || !tab->icon.isNull()) { + sz.rheight() = qMax(defaultTabHeight, sz.height()); + } else { + QSize textSize = fm.size(Qt::TextShowMnemonic, tab->text); + sz.rheight() = qMax(defaultTabHeight, textSize.height()); + sz.rwidth() = textSize.width() + defaultExtraSpace; + setWidth = true; + } + + if (vertTabs) + sz.transpose(); + + int maxWidgetHeight = qMax(tab->leftButtonSize.height(), tab->rightButtonSize.height()); + int maxWidgetWidth = qMax(tab->leftButtonSize.width(), tab->rightButtonSize.width()); + + int widgetWidth = 0; + int widgetHeight = 0; + int padding = 0; + if (tab->leftButtonSize.isValid()) { + padding += 8; + widgetWidth += tab->leftButtonSize.width(); + widgetHeight += tab->leftButtonSize.height(); + } + if (tab->rightButtonSize.isValid()) { + padding += 8; + widgetWidth += tab->rightButtonSize.width(); + widgetHeight += tab->rightButtonSize.height(); + } + + if (vertTabs) { + sz.setHeight(sz.height() + widgetHeight + padding); + sz.setWidth(qMax(sz.width(), maxWidgetWidth)); + } else { + if (setWidth) + sz.setWidth(sz.width() + widgetWidth + padding); + sz.setHeight(qMax(sz.height(), maxWidgetHeight)); + } + } + break; + case QStyle::CT_PushButton: + // By default, we fit the contents inside a normal rounded push button. + // Do this by add enough space around the contents so that rounded + // borders (including highlighting when active) will show. + sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12; + sz.rheight() += QMacStylePrivate::PushButtonTopOffset + QMacStylePrivate::PushButtonBottomOffset; + break; + case QStyle::CT_MenuItem: + if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { + int maxpmw = mi->maxIconWidth; + const QComboBox *comboBox = qobject_cast(widget); + int w = sz.width(), + h = sz.height(); + if (mi->menuItemType == QStyleOptionMenuItem::Separator) { + w = 10; + SInt16 ash; + GetThemeMenuSeparatorHeight(&ash); + h = ash; + } else { + h = mi->fontMetrics.height() + 2; + if (!mi->icon.isNull()) { + if (comboBox) { + const QSize &iconSize = comboBox->iconSize(); + h = qMax(h, iconSize.height() + 4); + maxpmw = qMax(maxpmw, iconSize.width()); + } else { + int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); + h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4); + } + } + } + if (mi->text.contains(QLatin1Char('\t'))) + w += 12; + if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) + w += 20; + if (maxpmw) + w += maxpmw + 6; + // add space for a check. All items have place for a check too. + w += 20; + if (comboBox && comboBox->isVisible()) { + QStyleOptionComboBox cmb; + cmb.initFrom(comboBox); + cmb.editable = false; + cmb.subControls = QStyle::SC_ComboBoxEditField; + cmb.activeSubControls = QStyle::SC_None; + w = qMax(w, subControlRect(QStyle::CC_ComboBox, &cmb, + QStyle::SC_ComboBoxEditField, + comboBox).width()); + } else { + w += 12; + } + sz = QSize(w, h); + } + break; + case CT_ToolButton: + if (widget && qobject_cast(widget->parentWidget())) { + if (QMainWindow * mainWindow = qobject_cast(widget->parent())) { + if (mainWindow->unifiedTitleAndToolBarOnMac()) { + sz.rwidth() += 4; + if (sz.height() <= 32) { + // Workaround strange HIToolBar bug when getting constraints. + sz.rheight() += 1; + } + return sz; + } + } + } + sz.rwidth() += 10; + sz.rheight() += 10; + return sz; + case CT_ComboBox: + sz.rwidth() += 50; + break; + case CT_Menu: { + QStyleHintReturnMask menuMask; + QStyleOption myOption = *opt; + myOption.rect.setSize(sz); + if (proxy()->styleHint(SH_Menu_Mask, &myOption, widget, &menuMask)) { + sz = menuMask.region.boundingRect().size(); + } + break; } + case CT_HeaderSection:{ + const QStyleOptionHeader *header = qstyleoption_cast(opt); + sz = QWindowsStyle::sizeFromContents(ct, opt, csz, widget); + if (header->text.contains(QLatin1Char('\n'))) + useAquaGuideline = false; + break; } + case CT_ScrollBar : + // Make sure that the scroll bar is large enough to display the thumb indicator. + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + const int minimumSize = scrollButtonsCutoffSize(thumbIndicatorCutoff, widgetSizePolicy(widget)); + if (slider->orientation == Qt::Horizontal) + sz = sz.expandedTo(QSize(minimumSize, sz.height())); + else + sz = sz.expandedTo(QSize(sz.width(), minimumSize)); + } + break; + case CT_ItemViewItem: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(opt)) { + sz = QCommonStyle::sizeFromContents(ct, vopt, csz, widget); + sz.setHeight(sz.height() + 2); + } + break; + + default: + sz = QWindowsStyle::sizeFromContents(ct, opt, csz, widget); + } + + if (useAquaGuideline){ + QSize macsz; + if (d->aquaSizeConstrain(opt, widget, ct, sz, &macsz) != QAquaSizeUnknown) { + if (macsz.width() != -1) + sz.setWidth(macsz.width()); + if (macsz.height() != -1) + sz.setHeight(macsz.height()); + } + } + + // The sizes that Carbon and the guidelines gives us excludes the focus frame. + // We compensate for this by adding some extra space here to make room for the frame when drawing: + if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)){ + QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, widget); + int bkind = 0; + switch (widgetSize) { + default: + case QAquaSizeLarge: + bkind = combo->editable ? kThemeComboBox : kThemePopupButton; + break; + case QAquaSizeSmall: + bkind = combo->editable ? int(kThemeComboBoxSmall) : int(kThemePopupButtonSmall); + break; + case QAquaSizeMini: + bkind = combo->editable ? kThemeComboBoxMini : kThemePopupButtonMini; + break; + } + HIRect tmpRect = {{0, 0}, {0, 0}}; + HIRect diffRect = QMacStylePrivate::comboboxInnerBounds(tmpRect, bkind); + sz.rwidth() -= qRound(diffRect.size.width); + sz.rheight() -= qRound(diffRect.size.height); + } else if (ct == CT_PushButton || ct == CT_ToolButton){ + ThemeButtonKind bkind; + QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, widget); + switch (ct) { + default: + case CT_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + if (btn->features & QStyleOptionButton::CommandLinkButton) { + return QWindowsStyle::sizeFromContents(ct, opt, sz, widget); + } + } + + switch (widgetSize) { + default: + case QAquaSizeLarge: + bkind = kThemePushButton; + break; + case QAquaSizeSmall: + bkind = kThemePushButtonSmall; + break; + case QAquaSizeMini: + bkind = kThemePushButtonMini; + break; + } + break; + case CT_ToolButton: + switch (widgetSize) { + default: + case QAquaSizeLarge: + bkind = kThemeLargeBevelButton; + break; + case QAquaSizeMini: + case QAquaSizeSmall: + bkind = kThemeSmallBevelButton; + } + break; + } + + HIThemeButtonDrawInfo bdi; + bdi.version = qt_mac_hitheme_version; + bdi.state = kThemeStateActive; + bdi.kind = bkind; + bdi.value = kThemeButtonOff; + bdi.adornment = kThemeAdornmentNone; + HIRect macRect, myRect; + myRect = CGRectMake(0, 0, sz.width(), sz.height()); + HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect); + // Mini buttons only return their actual size in HIThemeGetButtonBackgroundBounds, so help them out a bit (guess), + if (bkind == kThemePushButtonMini) + macRect.size.height += 8.; + else if (bkind == kThemePushButtonSmall) + macRect.size.height -= 10; + sz.setWidth(sz.width() + int(macRect.size.width - myRect.size.width)); + sz.setHeight(sz.height() + int(macRect.size.height - myRect.size.height)); + } + return sz; +} + +void QMacStyle::drawItemText(QPainter *p, const QRect &r, int flags, const QPalette &pal, + bool enabled, const QString &text, QPalette::ColorRole textRole) const +{ + if(flags & Qt::TextShowMnemonic) + flags |= Qt::TextHideMnemonic; + QWindowsStyle::drawItemText(p, r, flags, pal, enabled, text, textRole); +} + +bool QMacStyle::event(QEvent *e) +{ + if(e->type() == QEvent::FocusIn) { + QWidget *f = 0; + QWidget *focusWidget = QApplication::focusWidget(); +#ifndef QT_NO_GRAPHICSVIEW + if (QGraphicsView *graphicsView = qobject_cast(focusWidget)) { + QGraphicsItem *focusItem = graphicsView->scene() ? graphicsView->scene()->focusItem() : 0; + if (focusItem && focusItem->type() == QGraphicsProxyWidget::Type) { + QGraphicsProxyWidget *proxy = static_cast(focusItem); + if (proxy->widget()) + focusWidget = proxy->widget()->focusWidget(); + } + } +#endif + if (focusWidget && focusWidget->testAttribute(Qt::WA_MacShowFocusRect)) { + f = focusWidget; + QWidget *top = f->parentWidget(); + while (top && !top->isWindow() && !(top->windowType() == Qt::SubWindow)) + top = top->parentWidget(); +#ifndef QT_NO_MAINWINDOW + if (qobject_cast(top)) { + QWidget *central = static_cast(top)->centralWidget(); + for (const QWidget *par = f; par; par = par->parentWidget()) { + if (par == central) { + top = central; + break; + } + if (par->isWindow()) + break; + } + } +#endif + } + if (f) { + if(!d->focusWidget) + d->focusWidget = new QFocusFrame(f); + d->focusWidget->setWidget(f); + } else if(d->focusWidget) { + d->focusWidget->setWidget(0); + } + } else if(e->type() == QEvent::FocusOut) { + if(d->focusWidget) + d->focusWidget->setWidget(0); + } + return false; +} + +QIcon QMacStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt, + const QWidget *widget) const +{ + switch (standardIcon) { + default: + return QWindowsStyle::standardIconImplementation(standardIcon, opt, widget); + case SP_ToolBarHorizontalExtensionButton: + case SP_ToolBarVerticalExtensionButton: { + QPixmap pixmap(qt_mac_toolbar_ext); + if (standardIcon == SP_ToolBarVerticalExtensionButton) { + QPixmap pix2(pixmap.height(), pixmap.width()); + pix2.fill(Qt::transparent); + QPainter p(&pix2); + p.translate(pix2.width(), 0); + p.rotate(90); + p.drawPixmap(0, 0, pixmap); + return pix2; + } + return pixmap; + } + } +} + +int QMacStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1, + QSizePolicy::ControlType control2, + Qt::Orientation orientation, + const QStyleOption *option, + const QWidget *widget) const +{ + const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton; + bool isMetal = (widget && widget->testAttribute(Qt::WA_MacBrushedMetal)); + int controlSize = getControlSize(option, widget); + + if (control2 == QSizePolicy::ButtonBox) { + /* + AHIG seems to prefer a 12-pixel margin between group + boxes and the row of buttons. The 20 pixel comes from + Builder. + */ + if (isMetal // (AHIG, guess, guess) + || (control1 & (QSizePolicy::Frame // guess + | QSizePolicy::GroupBox // (AHIG, guess, guess) + | QSizePolicy::TabWidget // guess + | ButtonMask))) { // AHIG + return_SIZE(14, 8, 8); + } else if (control1 == QSizePolicy::LineEdit) { + return_SIZE(8, 8, 8); // Interface Builder + } else { + return_SIZE(20, 7, 7); // Interface Builder + } + } + + if ((control1 | control2) & ButtonMask) { + if (control1 == QSizePolicy::LineEdit) + return_SIZE(8, 8, 8); // Interface Builder + else if (control2 == QSizePolicy::LineEdit) { + if (orientation == Qt::Vertical) + return_SIZE(20, 7, 7); // Interface Builder + else + return_SIZE(20, 8, 8); + } + return_SIZE(14, 8, 8); // Interface Builder + } + + switch (CT2(control1, control2)) { + case CT1(QSizePolicy::Label): // guess + case CT2(QSizePolicy::Label, QSizePolicy::DefaultType): // guess + case CT2(QSizePolicy::Label, QSizePolicy::CheckBox): // AHIG + case CT2(QSizePolicy::Label, QSizePolicy::ComboBox): // AHIG + case CT2(QSizePolicy::Label, QSizePolicy::LineEdit): // guess + case CT2(QSizePolicy::Label, QSizePolicy::RadioButton): // AHIG + case CT2(QSizePolicy::Label, QSizePolicy::Slider): // guess + case CT2(QSizePolicy::Label, QSizePolicy::SpinBox): // guess + case CT2(QSizePolicy::Label, QSizePolicy::ToolButton): // guess + return_SIZE(8, 6, 5); + case CT1(QSizePolicy::ToolButton): + return 8; // AHIG + case CT1(QSizePolicy::CheckBox): + case CT2(QSizePolicy::CheckBox, QSizePolicy::RadioButton): + case CT2(QSizePolicy::RadioButton, QSizePolicy::CheckBox): + if (orientation == Qt::Vertical) + return_SIZE(8, 8, 7); // AHIG and Builder + break; + case CT1(QSizePolicy::RadioButton): + if (orientation == Qt::Vertical) + return 5; // (Builder, guess, AHIG) + } + + if (orientation == Qt::Horizontal + && (control2 & (QSizePolicy::CheckBox | QSizePolicy::RadioButton))) + return_SIZE(12, 10, 8); // guess + + if ((control1 | control2) & (QSizePolicy::Frame + | QSizePolicy::GroupBox + | QSizePolicy::TabWidget)) { + /* + These values were chosen so that nested container widgets + look good side by side. Builder uses 8, which looks way + too small, and AHIG doesn't say anything. + */ + return_SIZE(16, 10, 10); // guess + } + + if ((control1 | control2) & (QSizePolicy::Line | QSizePolicy::Slider)) + return_SIZE(12, 10, 8); // AHIG + + if ((control1 | control2) & QSizePolicy::LineEdit) + return_SIZE(10, 8, 8); // AHIG + + /* + AHIG and Builder differ by up to 4 pixels for stacked editable + comboboxes. We use some values that work fairly well in all + cases. + */ + if ((control1 | control2) & QSizePolicy::ComboBox) + return_SIZE(10, 8, 7); // guess + + /* + Builder defaults to 8, 6, 5 in lots of cases, but most of the time the + result looks too cramped. + */ + return_SIZE(10, 8, 6); // guess +} + +QT_END_NAMESPACE diff --git a/src/widgets/styles/qmacstyle_mac_p.h b/src/widgets/styles/qmacstyle_mac_p.h new file mode 100644 index 0000000000..fbd6d57e09 --- /dev/null +++ b/src/widgets/styles/qmacstyle_mac_p.h @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QMACSTYLE_MAC_P_H +#define QMACSTYLE_MAC_P_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5) +enum { + kThemePushButtonTextured = 31, + kThemePushButtonTexturedSmall = 32, + kThemePushButtonTexturedMini = 33 +}; + +/* Search fields */ +enum { + kHIThemeFrameTextFieldRound = 1000, + kHIThemeFrameTextFieldRoundSmall = 1001, + kHIThemeFrameTextFieldRoundMini = 1002 +}; +#endif + +/* + AHIG: + Apple Human Interface Guidelines + http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/ + + Builder: + Apple Interface Builder v. 3.1.1 +*/ + +// this works as long as we have at most 16 different control types +#define CT1(c) CT2(c, c) +#define CT2(c1, c2) ((uint(c1) << 16) | uint(c2)) + +enum QAquaWidgetSize { QAquaSizeLarge = 0, QAquaSizeSmall = 1, QAquaSizeMini = 2, + QAquaSizeUnknown = -1 }; + +#define SIZE(large, small, mini) \ + (controlSize == QAquaSizeLarge ? (large) : controlSize == QAquaSizeSmall ? (small) : (mini)) + +// same as return SIZE(...) but optimized +#define return_SIZE(large, small, mini) \ + do { \ + static const int sizes[] = { (large), (small), (mini) }; \ + return sizes[controlSize]; \ + } while (0) + +bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option); + +class QMacStylePrivate : public QObject +{ + Q_OBJECT + +public: + QMacStylePrivate(QMacStyle *style); + + // Ideally these wouldn't exist, but since they already exist we need some accessors. + static const int PushButtonLeftOffset; + static const int PushButtonTopOffset; + static const int PushButtonRightOffset; + static const int PushButtonBottomOffset; + static const int MiniButtonH; + static const int SmallButtonH; + static const int BevelButtonW; + static const int BevelButtonH; + static const int PushButtonContentPadding; + + + // Stuff from QAquaAnimate: + bool addWidget(QWidget *); + void removeWidget(QWidget *); + + enum Animates { AquaPushButton, AquaProgressBar, AquaListViewItemOpen }; + bool animatable(Animates, const QWidget *) const; + void stopAnimate(Animates, QWidget *); + void startAnimate(Animates, QWidget *); + static ThemeDrawState getDrawState(QStyle::State flags); + QAquaWidgetSize aquaSizeConstrain(const QStyleOption *option, const QWidget *widg, + QStyle::ContentsType ct = QStyle::CT_CustomBase, + QSize szHint=QSize(-1, -1), QSize *insz = 0) const; + void getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider, + HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe); + bool doAnimate(Animates); + inline int animateSpeed(Animates) const { return 33; } + + // Utility functions + void drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi, + QPainter *p, const QStyleOption *opt) const; + + QSize pushButtonSizeFromContents(const QStyleOptionButton *btn) const; + + HIRect pushButtonContentBounds(const QStyleOptionButton *btn, + const HIThemeButtonDrawInfo *bdi) const; + + void initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi, + const QWidget *widget, const ThemeDrawState &tds); + + static HIRect comboboxInnerBounds(const HIRect &outerBounds, int buttonKind); + + static QRect comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi); + + static void drawCombobox(const HIRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p); + static void drawTableHeader(const HIRect &outerBounds, bool drawTopBorder, bool drawLeftBorder, + const HIThemeButtonDrawInfo &bdi, QPainter *p); + bool contentFitsInPushButton(const QStyleOptionButton *btn, HIThemeButtonDrawInfo *bdi, + ThemeButtonKind buttonKindToCheck) const; + void initHIThemePushButton(const QStyleOptionButton *btn, const QWidget *widget, + const ThemeDrawState tds, + HIThemeButtonDrawInfo *bdi) const; + QPixmap generateBackgroundPattern() const; +protected: + bool eventFilter(QObject *, QEvent *); + void timerEvent(QTimerEvent *); + +private slots: + void startAnimationTimer(); + +public: + QPointer defaultButton; //default push buttons + int timerID; + QList > progressBars; //existing progress bars that need animation + + struct ButtonState { + int frame; + enum { ButtonDark, ButtonLight } dir; + } buttonState; + UInt8 progressFrame; + QPointer focusWidget; + CFAbsoluteTime defaultButtonStart; + QMacStyle *q; + bool mouseDown; +}; + +QT_END_NAMESPACE + +#endif // QMACSTYLE_MAC_P_H diff --git a/src/widgets/styles/qmacstylepixmaps_mac_p.h b/src/widgets/styles/qmacstylepixmaps_mac_p.h new file mode 100644 index 0000000000..41794387ea --- /dev/null +++ b/src/widgets/styles/qmacstylepixmaps_mac_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMACSTYLEPIXMAPS_MAC_P_H +#define QMACSTYLEPIXMAPS_MAC_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +static const char * const qt_mac_toolbar_ext[]={ + "14 9 4 1", + "# c #858585", + "b c #d9d9d9", + ". c #dbdbdb", + "a c None", + ".###..###.aaaa", + "a.###..###.aaa", + "aab###bb###baa", + "aaab###bb###ba", + "aaaa.###..###.", + "aaa.###..###.a", + "aab###bb###baa", + "ab###bb###baaa", + ".###..###.aaaa"}; + +#endif // QMACSTYLEPIXMAPS_MAC_P_H diff --git a/src/widgets/styles/qmotifstyle.cpp b/src/widgets/styles/qmotifstyle.cpp new file mode 100644 index 0000000000..3bf8996650 --- /dev/null +++ b/src/widgets/styles/qmotifstyle.cpp @@ -0,0 +1,2721 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmotifstyle.h" +#include "qcdestyle.h" + +#if !defined(QT_NO_STYLE_MOTIF) || defined(QT_PLUGIN) + +#include "qmenu.h" +#include "qapplication.h" +#include "qpainter.h" +#include "qdrawutil.h" +#include "qpixmap.h" +#include "qpalette.h" +#include "qwidget.h" +#include "qpushbutton.h" +#include "qscrollbar.h" +#include "qtabbar.h" +#include "qtabwidget.h" +#include "qlistview.h" +#include "qsplitter.h" +#include "qslider.h" +#include "qcombobox.h" +#include "qlineedit.h" +#include "qprogressbar.h" +#include "qimage.h" +#include "qfocusframe.h" +#include "qdebug.h" +#include "qpainterpath.h" +#include "qmotifstyle_p.h" +#include "qdialogbuttonbox.h" +#include "qformlayout.h" +#include +#include +#include + +#ifdef Q_WS_X11 +#include "qx11info_x11.h" +#endif + +QT_BEGIN_NAMESPACE + +// old constants that might still be useful... +static const int motifItemFrame = 2; // menu item frame width +static const int motifSepHeight = 2; // separator item height +static const int motifItemHMargin = 3; // menu item hor text margin +static const int motifItemVMargin = 2; // menu item ver text margin +static const int motifArrowHMargin = 6; // arrow horizontal margin +static const int motifTabSpacing = 12; // space between text and tab +static const int motifCheckMarkHMargin = 2; // horiz. margins of check mark +static const int motifCheckMarkSpace = 16; + + +/*! + \class QMotifStyle + \brief The QMotifStyle class provides Motif look and feel. + + \ingroup appearance + + This class implements the Motif look and feel. It closely + resembles the original Motif look as defined by the Open Group, + but with some minor improvements. The Motif style is Qt's default + GUI style on Unix platforms. + + \img qmotifstyle.png + \sa QWindowsXPStyle, QMacStyle, QWindowsStyle, QPlastiqueStyle, QCDEStyle +*/ + +/*! + \variable QMotifStyle::focus + \internal +*/ + +/*! + Constructs a QMotifStyle. + + If \a useHighlightCols is false (the default), the style will + polish the application's color palette to emulate the Motif way of + highlighting, which is a simple inversion between the base and the + text color. +*/ +QMotifStyle::QMotifStyle(bool useHighlightCols) + : QCommonStyle(*new QMotifStylePrivate) +{ + focus = 0; + highlightCols = useHighlightCols; +} + + +/*! + \internal +*/ +QMotifStyle::QMotifStyle(QMotifStylePrivate &dd, bool useHighlightColors) + : QCommonStyle(dd) +{ + focus = 0; + highlightCols = useHighlightColors; +} + + +/*! + \overload + + Destroys the style. +*/ +QMotifStyle::~QMotifStyle() +{ + delete focus; +} + +/*! + \internal + Animate indeterminate progress bars only when visible +*/ +bool QMotifStyle::eventFilter(QObject *o, QEvent *e) +{ +#ifndef QT_NO_PROGRESSBAR + Q_D(QMotifStyle); + switch(e->type()) { + case QEvent::StyleChange: + case QEvent::Show: + if (QProgressBar *bar = qobject_cast(o)) { + d->bars << bar; + if (d->bars.size() == 1) { + Q_ASSERT(d->animationFps> 0); + d->animateTimer = startTimer(1000 / d->animationFps); + } + } + break; + case QEvent::Destroy: + case QEvent::Hide: + // reinterpret_cast because there is no type info when getting + // the destroy event. We know that it is a QProgressBar. + if (QProgressBar *bar = reinterpret_cast(o)) { + d->bars.removeAll(bar); + if (d->bars.isEmpty() && d->animateTimer) { + killTimer(d->animateTimer); + d->animateTimer = 0; + } + } + default: + break; + } +#endif // QT_NO_PROGRESSBAR + return QStyle::eventFilter(o, e); +} + +/*! + \internal +*/ +QIcon QMotifStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt, + const QWidget *widget) const +{ + return QCommonStyle::standardIconImplementation(standardIcon, opt, widget); +} + +/*! + \reimp +*/ +void QMotifStyle::timerEvent(QTimerEvent *event) +{ +#ifndef QT_NO_PROGRESSBAR + Q_D(QMotifStyle); + if (event->timerId() == d->animateTimer) { + Q_ASSERT(d->animationFps > 0); + d->animateStep = d->startTime.elapsed() / (1000 / d->animationFps); + foreach (QProgressBar *bar, d->bars) { + if ((bar->minimum() == 0 && bar->maximum() == 0)) + bar->update(); + } + } +#endif // QT_NO_PROGRESSBAR + event->ignore(); +} + + +QMotifStylePrivate::QMotifStylePrivate() +#ifndef QT_NO_PROGRESSBAR + : animationFps(25), animateTimer(0), animateStep(0) +#endif +{ +} + +/*! + If \a arg is false, the style will polish the application's color + palette to emulate the Motif way of highlighting, which is a + simple inversion between the base and the text color. + + The effect will show up the next time an application palette is + set via QApplication::setPalette(). The current color palette of + the application remains unchanged. + + \sa QStyle::polish() +*/ +void QMotifStyle::setUseHighlightColors(bool arg) +{ + highlightCols = arg; +} + +/*! + Returns true if the style treats the highlight colors of the + palette in a Motif-like manner, which is a simple inversion + between the base and the text color; otherwise returns false. The + default is false. +*/ +bool QMotifStyle::useHighlightColors() const +{ + return highlightCols; +} + +/*! \reimp */ + +void QMotifStyle::polish(QPalette& pal) +{ + if (pal.brush(QPalette::Active, QPalette::Light) == pal.brush(QPalette::Active, QPalette::Base)) { + QColor nlight = pal.color(QPalette::Active, QPalette::Light).darker(108); + pal.setColor(QPalette::Active, QPalette::Light, nlight) ; + pal.setColor(QPalette::Disabled, QPalette::Light, nlight) ; + pal.setColor(QPalette::Inactive, QPalette::Light, nlight) ; + } + + if (highlightCols) + return; + + // force the ugly motif way of highlighting *sigh* + pal.setColor(QPalette::Active, QPalette::Highlight, + pal.color(QPalette::Active, QPalette::Text)); + pal.setColor(QPalette::Active, QPalette::HighlightedText, + pal.color(QPalette::Active, QPalette::Base)); + pal.setColor(QPalette::Disabled, QPalette::Highlight, + pal.color(QPalette::Disabled, QPalette::Text)); + pal.setColor(QPalette::Disabled, QPalette::HighlightedText, + pal.color(QPalette::Disabled, QPalette::Base)); + pal.setColor(QPalette::Inactive, QPalette::Highlight, + pal.color(QPalette::Active, QPalette::Text)); + pal.setColor(QPalette::Inactive, QPalette::HighlightedText, + pal.color(QPalette::Active, QPalette::Base)); +} + +/*! + \reimp + \internal + Keep QStyle::polish() visible. +*/ +void QMotifStyle::polish(QWidget* widget) +{ + QStyle::polish(widget); +#ifndef QT_NO_PROGRESSBAR + if (qobject_cast(widget)) + widget->installEventFilter(this); +#endif +} + +/*! + \reimp + \internal + Keep QStyle::polish() visible. +*/ +void QMotifStyle::unpolish(QWidget* widget) +{ + QCommonStyle::unpolish(widget); +#ifndef QT_NO_PROGRESSBAR + if (qobject_cast(widget)) { + Q_D(QMotifStyle); + widget->removeEventFilter(this); + d->bars.removeAll(static_cast(widget)); + } +#endif +} + + +/*! + \reimp + \internal + Keep QStyle::polish() visible. +*/ +void QMotifStyle::polish(QApplication* a) +{ + QCommonStyle::polish(a); +} + + +/*! + \reimp + \internal + Keep QStyle::polish() visible. +*/ +void QMotifStyle::unpolish(QApplication* a) +{ + QCommonStyle::unpolish(a); +} + +static void rot(QPolygon& a, int n) +{ + QPolygon r(a.size()); + for (int i = 0; i < (int)a.size(); i++) { + switch (n) { + case 1: r.setPoint(i,-a[i].y(),a[i].x()); break; + case 2: r.setPoint(i,-a[i].x(),-a[i].y()); break; + case 3: r.setPoint(i,a[i].y(),-a[i].x()); break; + } + } + a = r; +} + + +/*! + \reimp +*/ +void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *w) const +{ + switch(pe) { + case PE_Q3CheckListExclusiveIndicator: + if (const QStyleOptionQ3ListView *lv = qstyleoption_cast(opt)) { + if (lv->items.isEmpty()) + return; + + if (lv->state & State_Enabled) + p->setPen(QPen(opt->palette.text().color())); + else + p->setPen(QPen(lv->palette.color(QPalette::Disabled, QPalette::Text))); + QPolygon a; + + int cx = opt->rect.width()/2 - 1; + int cy = opt->rect.height()/2; + int e = opt->rect.width()/2 - 1; + for (int i = 0; i < 3; i++) { //penWidth 2 doesn't quite work + a.setPoints(4, cx-e, cy, cx, cy-e, cx+e, cy, cx, cy+e); + p->drawPolygon(a); + e--; + } + if (opt->state & State_On) { + if (lv->state & State_Enabled) + p->setPen(QPen(opt->palette.text().color())); + else + p->setPen(QPen(lv->palette.color(QPalette::Disabled, + QPalette::Text))); + QBrush saveBrush = p->brush(); + p->setBrush(opt->palette.text()); + e = e - 2; + a.setPoints(4, cx-e, cy, cx, cy-e, cx+e, cy, cx, cy+e); + p->drawPolygon(a); + p->setBrush(saveBrush); + } + } + break; + + case PE_FrameTabWidget: + case PE_FrameWindow: + qDrawShadePanel(p, opt->rect, opt->palette, QStyle::State_None, proxy()->pixelMetric(PM_DefaultFrameWidth)); + break; + case PE_FrameFocusRect: + if (const QStyleOptionFocusRect *fropt = qstyleoption_cast(opt)) { + if ((fropt->state & State_HasFocus) && focus && focus->isVisible() + && !(fropt->state & QStyle::State_Item)) + break; + QCommonStyle::drawPrimitive(pe, opt, p, w); + } + break; + + case PE_IndicatorToolBarHandle: { + p->save(); + p->translate(opt->rect.x(), opt->rect.y()); + + QColor dark(opt->palette.dark().color()); + QColor light(opt->palette.light().color()); + int i; + if (opt->state & State_Horizontal) { + int h = opt->rect.height(); + if (h > 6) { + if (opt->state & State_On) + p->fillRect(1, 1, 8, h - 2, opt->palette.highlight()); + QPolygon a(2 * ((h-6)/3)); + int y = 3 + (h%3)/2; + p->setPen(dark); + p->drawLine(8, 1, 8, h-2); + for (i=0; 2*i < a.size(); ++i) { + a.setPoint(2*i, 5, y+1+3*i); + a.setPoint(2*i+1, 2, y+2+3*i); + } + p->drawPoints(a); + p->setPen(light); + p->drawLine(9, 1, 9, h-2); + for (i=0; 2*i < a.size(); i++) { + a.setPoint(2*i, 4, y+3*i); + a.setPoint(2*i+1, 1, y+1+3*i); + } + p->drawPoints(a); + // if (drawBorder) { + // p->setPen(QPen(Qt::darkGray)); + // p->drawLine(0, opt->rect.height() - 1, + // tbExtent, opt->rect.height() - 1); + // } + } + } else { + int w = opt->rect.width(); + if (w > 6) { + if (opt->state & State_On) + p->fillRect(1, 1, w - 2, 9, opt->palette.highlight()); + QPolygon a(2 * ((w-6)/3)); + + int x = 3 + (w%3)/2; + p->setPen(dark); + p->drawLine(1, 8, w-2, 8); + for (i=0; 2*i < a.size(); ++i) { + a.setPoint(2*i, x+1+3*i, 6); + a.setPoint(2*i+1, x+2+3*i, 3); + } + p->drawPoints(a); + p->setPen(light); + p->drawLine(1, 9, w-2, 9); + for (i=0; 2*i < a.size(); ++i) { + a.setPoint(2*i, x+3*i, 5); + a.setPoint(2*i+1, x+1+3*i, 2); + } + p->drawPoints(a); + // if (drawBorder) { + // p->setPen(QPen(Qt::darkGray)); + // p->drawLine(opt->rect.width() - 1, 0, + // opt->rect.width() - 1, tbExtent); + // } + } + } + p->restore(); + break; } + + case PE_PanelButtonCommand: + case PE_PanelButtonBevel: + case PE_PanelButtonTool: { + QBrush fill; + if (opt->state & State_Sunken) + fill = opt->palette.brush(QPalette::Mid); + else if ((opt->state & State_On) && (opt->state & State_Enabled)) + fill = QBrush(opt->palette.mid().color(), Qt::Dense4Pattern); + else + fill = opt->palette.brush(QPalette::Button); + if ((opt->state & State_Enabled || opt->state & State_On) || !(opt->state & State_AutoRaise)) + qDrawShadePanel(p, opt->rect, opt->palette, bool(opt->state & (State_Sunken | State_On)), + proxy()->pixelMetric(PM_DefaultFrameWidth), &fill); + break; } + + case PE_IndicatorCheckBox: { + bool on = opt->state & State_On; + bool down = opt->state & State_Sunken; + bool showUp = !(down ^ on); + QBrush fill = opt->palette.brush((showUp || opt->state & State_NoChange) ?QPalette::Button : QPalette::Mid); + if (opt->state & State_NoChange) { + qDrawPlainRect(p, opt->rect, opt->palette.text().color(), + 1, &fill); + p->drawLine(opt->rect.x() + opt->rect.width() - 1, opt->rect.y(), + opt->rect.x(), opt->rect.y() + opt->rect.height() - 1); + } else { + qDrawShadePanel(p, opt->rect, opt->palette, !showUp, + proxy()->pixelMetric(PM_DefaultFrameWidth), &fill); + } + if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) + p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern)); + break; } + + case PE_IndicatorRadioButton: { +#define INTARRLEN(x) sizeof(x)/(sizeof(int)*2) + int inner_pts[] = { // used for filling diamond + 2,opt->rect.height()/2, + opt->rect.width()/2,2, + opt->rect.width()-3,opt->rect.height()/2, + opt->rect.width()/2,opt->rect.height()-3 + }; + int top_pts[] = { // top (^) of diamond + 0,opt->rect.height()/2, + opt->rect.width()/2,0, + opt->rect.width()-2,opt->rect.height()/2-1, + opt->rect.width()-3,opt->rect.height()/2-1, + opt->rect.width()/2,1, + 1,opt->rect.height()/2, + 2,opt->rect.height()/2, + opt->rect.width()/2,2, + opt->rect.width()-4,opt->rect.height()/2-1 + }; + int bottom_pts[] = { // bottom (v) of diamond + 1,opt->rect.height()/2+1, + opt->rect.width()/2,opt->rect.height()-1, + opt->rect.width()-1,opt->rect.height()/2, + opt->rect.width()-2,opt->rect.height()/2, + opt->rect.width()/2,opt->rect.height()-2, + 2,opt->rect.height()/2+1, + 3,opt->rect.height()/2+1, + opt->rect.width()/2,opt->rect.height()-3, + opt->rect.width()-3,opt->rect.height()/2 + }; + bool on = opt->state & State_On; + bool down = opt->state & State_Sunken; + bool showUp = !(down ^ on); + QPen oldPen = p->pen(); + QBrush oldBrush = p->brush(); + QPolygon a(INTARRLEN(inner_pts), inner_pts); + p->setPen(Qt::NoPen); + p->setBrush(opt->palette.brush(showUp ? QPalette::Button : QPalette::Mid)); + a.translate(opt->rect.x(), opt->rect.y()); + p->drawPolygon(a); + p->setPen(showUp ? opt->palette.light().color() : opt->palette.dark().color()); + p->setBrush(Qt::NoBrush); + a.setPoints(INTARRLEN(top_pts), top_pts); + a.translate(opt->rect.x(), opt->rect.y()); + p->drawPolyline(a); + p->setPen(showUp ? opt->palette.dark().color() : opt->palette.light().color()); + a.setPoints(INTARRLEN(bottom_pts), bottom_pts); + a.translate(opt->rect.x(), opt->rect.y()); + p->drawPolyline(a); + if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) + p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern)); + p->setPen(oldPen); + p->setBrush(oldBrush); + break; } + + case PE_IndicatorSpinUp: + case PE_IndicatorSpinPlus: + case PE_IndicatorSpinDown: + case PE_IndicatorSpinMinus: + case PE_IndicatorArrowUp: + case PE_IndicatorArrowDown: + case PE_IndicatorArrowRight: + case PE_IndicatorArrowLeft: { + QRect rect = opt->rect; + QPolygon bFill; + QPolygon bTop; + QPolygon bBot; + QPolygon bLeft; + if (pe == PE_IndicatorSpinPlus || pe == PE_IndicatorSpinUp) + pe = PE_IndicatorArrowUp; + else if (pe == PE_IndicatorSpinMinus || pe == PE_IndicatorSpinDown) + pe = PE_IndicatorArrowDown; + bool vertical = pe == PE_IndicatorArrowUp || pe == PE_IndicatorArrowDown; + bool horizontal = !vertical; + int dim = rect.width() < rect.height() ? rect.width() : rect.height(); + int colspec = 0x0000; + + if (!(opt->state & State_Enabled)) + dim -= 2; + if(dim < 2) + break; + + // adjust size and center (to fix rotation below) + if (rect.width() > dim) { + rect.setX(rect.x() + ((rect.width() - dim) / 2)); + rect.setWidth(dim); + } + if (rect.height() > dim) { + rect.setY(rect.y() + ((rect.height() - dim) / 2)); + rect.setHeight(dim); + } + + if (dim > 3) { + if (pixelMetric(PM_DefaultFrameWidth) < 2) { // thin style + bFill.resize( dim & 1 ? 3 : 4 ); + bTop.resize( 2 ); + bBot.resize( 2 ); + bLeft.resize( 2 ); + bLeft.putPoints( 0, 2, 0, 0, 0, dim-1 ); + bTop.putPoints( 0, 2, 1, 0, dim-1, dim/2 ); + bBot.putPoints( 0, 2, 1, dim-1, dim-1, dim/2 ); + + if ( dim > 6 ) { // dim>6: must fill interior + bFill.putPoints( 0, 2, 0, dim-1, 0, 0 ); + if ( dim & 1 ) // if size is an odd number + bFill.setPoint( 2, dim - 1, dim / 2 ); + else + bFill.putPoints( 2, 2, dim-1, dim/2-1, dim-1, dim/2 ); + } + } else { + if (dim > 6) + bFill.resize(dim & 1 ? 3 : 4); + bTop.resize((dim/2)*2); + bBot.resize(dim & 1 ? dim + 1 : dim); + bLeft.resize(dim > 4 ? 4 : 2); + bLeft.putPoints(0, 2, 0,0, 0,dim-1); + if (dim > 4) + bLeft.putPoints(2, 2, 1,2, 1,dim-3); + bTop.putPoints(0, 4, 1,0, 1,1, 2,1, 3,1); + bBot.putPoints(0, 4, 1,dim-1, 1,dim-2, 2,dim-2, 3,dim-2); + + for(int i=0; i 6) { // dim>6: must fill interior + bFill.putPoints(0, 2, 1,dim-3, 1,2); + if (dim & 1) // if size is an odd number + bFill.setPoint(2, dim - 3, dim / 2); + else + bFill.putPoints(2, 2, dim-4,dim/2-1, dim-4,dim/2); + } + } + } else { + if (dim == 3) { // 3x3 arrow pattern + bLeft.setPoints(4, 0,0, 0,2, 1,1, 1,1); + bTop .setPoints(2, 1,0, 1,0); + bBot .setPoints(2, 1,2, 2,1); + } + else { // 2x2 arrow pattern + bLeft.setPoints(2, 0,0, 0,1); + bTop .setPoints(2, 1,0, 1,0); + bBot .setPoints(2, 1,1, 1,1); + } + } + + // We use rot() and translate() as it is more efficient that + // matrix transformations on the painter, and because it still + // works with QT_NO_TRANSFORMATIONS defined. + + if (pe == PE_IndicatorArrowUp || pe == PE_IndicatorArrowLeft) { + if (vertical) { + rot(bFill,3); + rot(bLeft,3); + rot(bTop,3); + rot(bBot,3); + bFill.translate(0, rect.height() - 1); + bLeft.translate(0, rect.height() - 1); + bTop.translate(0, rect.height() - 1); + bBot.translate(0, rect.height() - 1); + } else { + rot(bFill,2); + rot(bLeft,2); + rot(bTop,2); + rot(bBot,2); + bFill.translate(rect.width() - 1, rect.height() - 1); + bLeft.translate(rect.width() - 1, rect.height() - 1); + bTop.translate(rect.width() - 1, rect.height() - 1); + bBot.translate(rect.width() - 1, rect.height() - 1); + } + if (opt->state & State_Sunken) + colspec = horizontal ? 0x2334 : 0x2343; + else + colspec = horizontal ? 0x1443 : 0x1434; + } else { + if (vertical) { + rot(bFill,1); + rot(bLeft,1); + rot(bTop,1); + rot(bBot,1); + bFill.translate(rect.width() - 1, 0); + bLeft.translate(rect.width() - 1, 0); + bTop.translate(rect.width() - 1, 0); + bBot.translate(rect.width() - 1, 0); + } + if (opt->state & State_Sunken) + colspec = horizontal ? 0x2443 : 0x2434; + else + colspec = horizontal ? 0x1334 : 0x1343; + } + bFill.translate(rect.x(), rect.y()); + bLeft.translate(rect.x(), rect.y()); + bTop.translate(rect.x(), rect.y()); + bBot.translate(rect.x(), rect.y()); + + const QColor *cols[5]; + if (opt->state & State_Enabled) { + cols[0] = 0; + cols[1] = &opt->palette.button().color(); + cols[2] = &opt->palette.mid().color(); + cols[3] = &opt->palette.light().color(); + cols[4] = &opt->palette.dark().color(); + } else { + cols[0] = 0; + cols[1] = &opt->palette.mid().color(); + cols[2] = &opt->palette.mid().color(); + cols[3] = &opt->palette.mid().color(); + cols[4] = &opt->palette.mid().color(); + } + +#define CMID *cols[(colspec>>12) & 0xf] +#define CLEFT *cols[(colspec>>8) & 0xf] +#define CTOP *cols[(colspec>>4) & 0xf] +#define CBOT *cols[colspec & 0xf] + + QPen savePen = p->pen(); + QBrush saveBrush = p->brush(); + QPen pen(Qt::NoPen); + QBrush brush = opt->palette.brush((opt->state & State_Enabled) ? + QPalette::Button : QPalette::Mid); + p->setPen(pen); + p->setBrush(brush); + p->drawPolygon(bFill); + p->setBrush(Qt::NoBrush); + + p->setPen(CLEFT); + p->drawPolyline(bLeft); + p->setPen(CTOP); + p->drawPolyline(bTop); + p->setPen(CBOT); + p->drawPolyline(bBot); + + p->setBrush(saveBrush); + p->setPen(savePen); +#undef CMID +#undef CLEFT +#undef CTOP +#undef CBOT + if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) + p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern)); + break; } + + case PE_IndicatorDockWidgetResizeHandle: { + const int motifOffset = 10; + int sw = proxy()->pixelMetric(PM_SplitterWidth); + if (opt->state & State_Horizontal) { + int yPos = opt->rect.y() + opt->rect.height() / 2; + int kPos = opt->rect.right() - motifOffset - sw; + int kSize = sw - 2; + + qDrawShadeLine(p, opt->rect.left(), yPos, kPos, yPos, opt->palette); + qDrawShadePanel(p, kPos, yPos - sw / 2 + 1, kSize, kSize, + opt->palette, false, 1, &opt->palette.brush(QPalette::Button)); + qDrawShadeLine(p, kPos + kSize - 1, yPos, opt->rect.right(), yPos, opt->palette); + } else { + int xPos = opt->rect.x() + opt->rect.width() / 2; + int kPos = motifOffset; + int kSize = sw - 2; + + qDrawShadeLine(p, xPos, opt->rect.top() + kPos + kSize - 1, xPos, opt->rect.bottom(), opt->palette); + qDrawShadePanel(p, xPos - sw / 2 + 1, opt->rect.top() + kPos, kSize, kSize, opt->palette, + false, 1, &opt->palette.brush(QPalette::Button)); + qDrawShadeLine(p, xPos, opt->rect.top(), xPos, opt->rect.top() + kPos, opt->palette); + } + break; } + + case PE_IndicatorMenuCheckMark: { + const int markW = 6; + const int markH = 6; + int posX = opt->rect.x() + (opt->rect.width() - markW) / 2 - 1; + int posY = opt->rect.y() + (opt->rect.height() - markH) / 2; + int dfw = proxy()->pixelMetric(PM_DefaultFrameWidth); + + if (dfw < 2) { + // Could do with some optimizing/caching... + QPolygon a(7*2); + int i, xx, yy; + xx = posX; + yy = 3 + posY; + for (i=0; i<3; i++) { + a.setPoint(2*i, xx, yy); + a.setPoint(2*i+1, xx, yy+2); + xx++; yy++; + } + yy -= 2; + for (i=3; i<7; i++) { + a.setPoint(2*i, xx, yy); + a.setPoint(2*i+1, xx, yy+2); + xx++; yy--; + } + if (! (opt->state & State_Enabled) && ! (opt->state & State_On)) { + int pnt; + p->setPen(opt->palette.highlightedText().color()); + QPoint offset(1,1); + for (pnt = 0; pnt < (int)a.size(); pnt++) + a[pnt] += offset; + p->drawPolyline(a); + for (pnt = 0; pnt < (int)a.size(); pnt++) + a[pnt] -= offset; + } + p->setPen(opt->palette.text().color()); + p->drawPolyline(a); + + qDrawShadePanel(p, posX-2, posY-2, markW+4, markH+6, opt->palette, true, dfw); + } else + qDrawShadePanel(p, posX, posY, markW, markH, opt->palette, true, dfw, + &opt->palette.brush(QPalette::Mid)); + + break; } + + case PE_IndicatorProgressChunk: + { + bool vertical = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt)) + vertical = (pb2->orientation == Qt::Vertical); + if (!vertical) { + p->fillRect(opt->rect.x(), opt->rect.y(), opt->rect.width(), + opt->rect.height(), opt->palette.brush(QPalette::Highlight)); + } else { + p->fillRect(opt->rect.x(), opt->rect.y(), opt->rect.width(), opt->rect.height(), + opt->palette.brush(QPalette::Highlight)); + } + } + break; + + default: + QCommonStyle::drawPrimitive(pe, opt, p, w); + break; + } +} + + +/*! + \reimp +*/ +void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, + const QWidget *widget) const +{ + switch(element) { + case CE_Splitter: { + QStyleOption handleOpt = *opt; + if (handleOpt.state & State_Horizontal) + handleOpt.state &= ~State_Horizontal; + else + handleOpt.state |= State_Horizontal; + proxy()->drawPrimitive(PE_IndicatorDockWidgetResizeHandle, &handleOpt, p, widget); + break; } + + case CE_ScrollBarSubLine: + case CE_ScrollBarAddLine:{ + PrimitiveElement pe; + if (element == CE_ScrollBarAddLine) + pe = (opt->state & State_Horizontal) ? (opt->direction == Qt::LeftToRight ? PE_IndicatorArrowRight : PE_IndicatorArrowLeft) : PE_IndicatorArrowDown; + else + pe = (opt->state & State_Horizontal) ? (opt->direction == Qt::LeftToRight ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight) : PE_IndicatorArrowUp; + QStyleOption arrowOpt = *opt; + arrowOpt.state |= State_Enabled; + proxy()->drawPrimitive(pe, &arrowOpt, p, widget); + if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) { + int fw = proxy()->pixelMetric(PM_DefaultFrameWidth); + p->fillRect(opt->rect.adjusted(fw, fw, -fw, -fw), QBrush(p->background().color(), Qt::Dense5Pattern)); + } + }break; + + case CE_ScrollBarSubPage: + case CE_ScrollBarAddPage: + p->fillRect(opt->rect, opt->palette.brush((opt->state & State_Enabled) ? QPalette::Mid : QPalette::Window)); + break; + + case CE_ScrollBarSlider: { + QStyleOption bevelOpt = *opt; + bevelOpt.state |= State_Raised; + bevelOpt.state &= ~(State_Sunken | State_On); + p->save(); + p->setBrushOrigin(bevelOpt.rect.topLeft()); + proxy()->drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget); + p->restore(); + if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) + p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern)); + break; } + + case CE_RadioButton: + case CE_CheckBox: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + bool isRadio = (element == CE_RadioButton); + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator + : SE_CheckBoxIndicator, btn, widget); + proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox, + &subopt, p, widget); + subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents + : SE_CheckBoxContents, btn, widget); + proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, widget); + if ((btn->state & State_HasFocus) && (!focus || !focus->isVisible())) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*btn); + fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect + : SE_CheckBoxFocusRect, btn, widget); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + break; + case CE_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + proxy()->drawControl(CE_PushButtonBevel, btn, p, widget); + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); + proxy()->drawControl(CE_PushButtonLabel, &subopt, p, widget); + if ((btn->state & State_HasFocus) && (!focus || !focus->isVisible())) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*btn); + fropt.rect = subElementRect(SE_PushButtonFocusRect, btn, widget); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + break; + case CE_PushButtonBevel: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + int diw, x1, y1, x2, y2; + p->setPen(opt->palette.foreground().color()); + p->setBrush(QBrush(opt->palette.button().color(), Qt::NoBrush)); + diw = proxy()->pixelMetric(PM_ButtonDefaultIndicator); + opt->rect.getCoords(&x1, &y1, &x2, &y2); + if (btn->features & (QStyleOptionButton::AutoDefaultButton|QStyleOptionButton::DefaultButton)) { + x1 += diw; + y1 += diw; + x2 -= diw; + y2 -= diw; + } + if (btn->features & QStyleOptionButton::DefaultButton) { + if (diw == 0) { + QPolygon a; + a.setPoints(9, + x1, y1, x2, y1, x2, y2, x1, y2, x1, y1+1, + x2-1, y1+1, x2-1, y2-1, x1+1, y2-1, x1+1, y1+1); + p->setPen(opt->palette.shadow().color()); + p->drawPolygon(a); + x1 += 2; + y1 += 2; + x2 -= 2; + y2 -= 2; + } else { + qDrawShadePanel(p, opt->rect.adjusted(1, 1, -1, -1), opt->palette, true); + } + } + if (!(btn->features & QStyleOptionButton::Flat) || + (btn->state & (State_Sunken | State_On))) { + QStyleOptionButton newOpt = *btn; + newOpt.rect = QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); + p->setBrushOrigin(p->brushOrigin()); + proxy()->drawPrimitive(PE_PanelButtonCommand, &newOpt, p, widget); + } + if (btn->features & QStyleOptionButton::HasMenu) { + int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget); + QRect ir = btn->rect; + QStyleOptionButton newBtn = *btn; + newBtn.rect = QRect(ir.right() - mbi - 3, ir.y() + 4, mbi, ir.height() - 8); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); + } + break; + } + +#ifndef QT_NO_TABBAR + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + const int default_frame = proxy()->pixelMetric(PM_DefaultFrameWidth, tab, widget); + const int frame_offset = (default_frame > 1) ? 1 : 0; + + if (tab->shape == QTabBar::RoundedNorth || tab->shape == QTabBar::RoundedEast || + tab->shape == QTabBar::RoundedSouth || tab->shape == QTabBar::RoundedWest) { + p->save(); + QRect tabRect = opt->rect; + QColor tabLight = opt->palette.light().color(); + QColor tabDark = opt->palette.dark().color(); + + p->fillRect(opt->rect.adjusted(default_frame, default_frame, + -default_frame, -default_frame), + tab->palette.background()); + + if(tab->shape == QTabBar::RoundedWest) { + tabDark = opt->palette.light().color(); + tabLight = opt->palette.dark().color(); + tabRect = QRect(0, 0, tabRect.height(), tabRect.width()); + p->translate(opt->rect.left(), opt->rect.bottom()); + p->rotate(-90); + } else if(tab->shape == QTabBar::RoundedSouth) { + tabDark = opt->palette.light().color(); + tabLight = opt->palette.dark().color(); + tabRect = QRect(0, 0, tabRect.width(), tabRect.height()); + p->translate(opt->rect.right(), opt->rect.bottom()); + p->rotate(180); + } else if(tab->shape == QTabBar::RoundedEast) { + tabRect = QRect(0, 0, tabRect.height(), tabRect.width()); + p->translate(opt->rect.right(), opt->rect.top()); + p->rotate(90); + } + + if (default_frame > 1) { + p->setPen(tabLight); + p->drawLine(tabRect.left(), tabRect.bottom(), + tabRect.right(), tabRect.bottom()); + p->setPen(tabLight); + p->drawLine(tabRect.left(), tabRect.bottom()-1, + tabRect.right(), tabRect.bottom()-1); + if (tabRect.left() == 0) + p->drawPoint(tabRect.bottomLeft()); + } else { + p->setPen(tabLight); + p->drawLine(tabRect.left(), tabRect.bottom(), + tabRect.right(), tabRect.bottom()); + } + + if (opt->state & State_Selected) { + p->fillRect(QRect(tabRect.left()+1, tabRect.bottom()-frame_offset, + tabRect.width()-3, 2), + tab->palette.brush(QPalette::Active, QPalette::Background)); + p->setPen(tab->palette.background().color()); + p->drawLine(tabRect.left()+1, tabRect.bottom(), + tabRect.left()+1, tabRect.top()+2); + p->setPen(tabLight); + } else { + p->setPen(tabLight); + } + p->drawLine(tabRect.left(), tabRect.bottom()-1, + tabRect.left(), tabRect.top() + 2); + p->drawPoint(tabRect.left()+1, tabRect.top() + 1); + p->drawLine(tabRect.left()+2, tabRect.top(), + tabRect.right() - 2, tabRect.top()); + p->drawPoint(tabRect.left(), tabRect.bottom()); + + if (default_frame > 1) { + p->drawLine(tabRect.left()+1, tabRect.bottom(), + tabRect.left()+1, tabRect.top() + 2); + p->drawLine(tabRect.left()+2, tabRect.top()+1, + tabRect.right() - 2, tabRect.top()+1); + } + + p->setPen(tabDark); + p->drawLine(tabRect.right() - 1, tabRect.top() + 2, + tabRect.right() - 1, tabRect.bottom() - 1 + + ((opt->state & State_Selected) ? frame_offset : -frame_offset)); + if (default_frame > 1) { + p->drawPoint(tabRect.right() - 1, tabRect.top() + 1); + p->drawLine(tabRect.right(), tabRect.top() + 2, tabRect.right(), + tabRect.bottom() - + ((opt->state & State_Selected) ? + ((tab->position == QStyleOptionTab::End) ? 0:1):1+frame_offset)); + p->drawPoint(tabRect.right() - 1, tabRect.top() + 1); + } + p->restore(); + } else { + QCommonStyle::drawControl(element, opt, p, widget); + } + break; } +#endif // QT_NO_TABBAR + case CE_ProgressBarGroove: + qDrawShadePanel(p, opt->rect, opt->palette, true, 2); + break; + + case CE_ProgressBarLabel: + if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { + QTransform oldMatrix = p->transform(); + QRect rect = pb->rect; + bool vertical = false; + bool invert = false; + bool bottomToTop = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt)) { + vertical = (pb2->orientation == Qt::Vertical); + invert = pb2->invertedAppearance; + bottomToTop = pb2->bottomToTop; + } + if (vertical) { + QTransform m; + rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height + if (bottomToTop) { + m.translate(0.0, rect.width()); + m.rotate(-90); + } else { + m.translate(rect.height(), 0.0); + m.rotate(90); + } + p->setTransform(m, true); + } + const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, opt, widget); + int u = rect.width() / unit_width; + int p_v = pb->progress - pb->minimum; + int t_s = qMax(0, pb->maximum - pb->minimum); + if (u > 0 && pb->progress >= INT_MAX / u && t_s >= u) { + // scale down to something usable. + p_v /= u; + t_s /= u; + } + if (pb->textVisible && t_s) { + int nu = (u * p_v + t_s/2) / t_s; + int x = unit_width * nu; + QRect left(rect.x(), rect.y(), x, rect.height()); + QRect right(rect.x() + x, rect.y(), rect.width() - x, rect.height()); + Qt::LayoutDirection dir; + dir = vertical ? (bottomToTop ? Qt::LeftToRight : Qt::RightToLeft) : pb->direction; + if (invert) + dir = (dir == Qt::LeftToRight) ? Qt::RightToLeft : Qt::LeftToRight; + const QRect highlighted = visualRect(dir, rect, left); + const QRect background = visualRect(dir, rect, right); + p->setPen(opt->palette.highlightedText().color()); + p->setClipRect(highlighted); + p->drawText(rect, Qt::AlignCenter | Qt::TextSingleLine, pb->text); + + if (pb->progress != pb->maximum) { + p->setClipRect(background); + p->setPen(opt->palette.highlight().color()); + p->drawText(rect, Qt::AlignCenter | Qt::TextSingleLine, pb->text); + } + } + p->setTransform(oldMatrix, false); + break; + } + + case CE_MenuTearoff: { + if(opt->state & State_Selected) { + if(pixelMetric(PM_MenuPanelWidth, opt, widget) > 1) + qDrawShadePanel(p, opt->rect.x(), opt->rect.y(), opt->rect.width(), + opt->rect.height(), opt->palette, false, motifItemFrame, + &opt->palette.brush(QPalette::Button)); + else + qDrawShadePanel(p, opt->rect.x()+1, opt->rect.y()+1, opt->rect.width()-2, + opt->rect.height()-2, opt->palette, true, 1, &opt->palette.brush(QPalette::Button)); + } else { + p->fillRect(opt->rect, opt->palette.brush(QPalette::Button)); + } + p->setPen(QPen(opt->palette.dark().color(), 1, Qt::DashLine)); + p->drawLine(opt->rect.x()+2, opt->rect.y()+opt->rect.height()/2-1, opt->rect.x()+opt->rect.width()-4, + opt->rect.y()+opt->rect.height()/2-1); + p->setPen(QPen(opt->palette.light().color(), 1, Qt::DashLine)); + p->drawLine(opt->rect.x()+2, opt->rect.y()+opt->rect.height()/2, opt->rect.x()+opt->rect.width()-4, + opt->rect.y()+opt->rect.height()/2); + break; } + + case CE_MenuItem: + if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(opt)) { + int maxpmw = menuitem->maxIconWidth; + if(menuitem->menuHasCheckableItems) + maxpmw = qMax(maxpmw, motifCheckMarkSpace); + + int x, y, w, h; + opt->rect.getRect(&x, &y, &w, &h); + + if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) { // draw separator + int textWidth = 0; + if (!menuitem->text.isEmpty()) { + QFont oldFont = p->font(); + p->setFont(menuitem->font); + p->fillRect(x, y, w, h, opt->palette.brush(QPalette::Button)); + proxy()->drawItemText(p, menuitem->rect.adjusted(10, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter, + menuitem->palette, menuitem->state & State_Enabled, menuitem->text, + QPalette::Text); + textWidth = menuitem->fontMetrics.width(menuitem->text) + 10; + y += menuitem->fontMetrics.height() / 2; + p->setFont(oldFont); + } + p->setPen(opt->palette.dark().color()); + p->drawLine(x, y, x + 5, y); + p->drawLine(x + 5 + textWidth, y, x+w, y); + p->setPen(opt->palette.light().color()); + p->drawLine(x, y + 1, x + 5, y + 1); + p->drawLine(x + 5 + textWidth, y + 1, x+w, y + 1); + return; + } + + int pw = motifItemFrame; + if((opt->state & State_Selected) && (opt->state & State_Enabled)) { // active item frame + if(pixelMetric(PM_MenuPanelWidth, opt) > 1) + qDrawShadePanel(p, x, y, w, h, opt->palette, false, pw, + &opt->palette.brush(QPalette::Button)); + else + qDrawShadePanel(p, x+1, y+1, w-2, h-2, opt->palette, true, 1, + &opt->palette.brush(QPalette::Button)); + } else { // incognito frame + p->fillRect(x, y, w, h, opt->palette.brush(QPalette::Button)); + } + + QRect vrect = visualRect(opt->direction, opt->rect, + QRect(x+motifItemFrame, y+motifItemFrame, maxpmw, + h-2*motifItemFrame)); + int xvis = vrect.x(); + if (menuitem->checked) { + if(!menuitem->icon.isNull()) + qDrawShadePanel(p, xvis, y+motifItemFrame, maxpmw, h-2*motifItemFrame, + opt->palette, true, 1, &opt->palette.brush(QPalette::Midlight)); + } else if (!(opt->state & State_Selected)) { + p->fillRect(xvis, y+motifItemFrame, maxpmw, h-2*motifItemFrame, + opt->palette.brush(QPalette::Button)); + } + + if(!menuitem->icon.isNull()) { // draw icon + QIcon::Mode mode = QIcon::Normal; // no disabled icons in Motif + if ((opt->state & State_Selected) && !!(opt->state & State_Enabled)) + mode = QIcon::Active; + QPixmap pixmap; + if (menuitem->checkType != QStyleOptionMenuItem::NotCheckable && menuitem->checked) + pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, opt, widget), mode, QIcon::On); + else + pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, opt, widget), mode); + + int pixw = pixmap.width(); + int pixh = pixmap.height(); + QRect pmr(0, 0, pixw, pixh); + pmr.moveCenter(vrect.center()); + p->setPen(opt->palette.text().color()); + p->drawPixmap(pmr.topLeft(), pixmap); + + } else if (menuitem->checkType != QStyleOptionMenuItem::NotCheckable) { // just "checking"... + int mh = h - 2*motifItemFrame; + + QStyleOptionButton newMenuItem; + newMenuItem.state = menuitem->checked ? State_On : State_None; + if (opt->state & State_Enabled) { + newMenuItem.state |= State_Enabled; + if (menuitem->state & State_Sunken) + newMenuItem.state |= State_Sunken; + } + if (menuitem->checkType & QStyleOptionMenuItem::Exclusive) { + newMenuItem.rect.setRect(xvis + 2, y + motifItemFrame + mh / 4, 11, 11); + proxy()->drawPrimitive(PE_IndicatorRadioButton, &newMenuItem, p, widget); + } else { + newMenuItem.rect.setRect(xvis + 5, y + motifItemFrame + mh / 4, 9, 9); + proxy()->drawPrimitive(PE_IndicatorCheckBox, &newMenuItem, p, widget); + } + } + + p->setPen(opt->palette.buttonText().color()); + + QColor discol; + if (!(opt->state & State_Enabled)) { + discol = opt->palette.text().color(); + p->setPen(discol); + } + + int xm = motifItemFrame + maxpmw + motifItemHMargin; + + vrect = visualRect(opt->direction, opt->rect, + QRect(x+xm, y+motifItemVMargin, w-xm-menuitem->tabWidth, + h-2*motifItemVMargin)); + xvis = vrect.x(); + + QString s = menuitem->text; + if (!s.isNull()) { // draw text + int t = s.indexOf(QLatin1Char('\t')); + int m = motifItemVMargin; + int text_flags = Qt::AlignVCenter|Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + text_flags |= Qt::AlignLeft; + QFont oldFont = p->font(); + p->setFont(menuitem->font); + if (t >= 0) { // draw tab text + QRect vr = visualRect(opt->direction, opt->rect, + QRect(x+w-menuitem->tabWidth-motifItemHMargin-motifItemFrame, + y+motifItemVMargin, menuitem->tabWidth, + h-2*motifItemVMargin)); + int xv = vr.x(); + QRect tr(xv, y+m, menuitem->tabWidth, h-2*m); + p->drawText(tr, text_flags, s.mid(t+1)); + if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) + p->fillRect(tr, QBrush(p->background().color(), Qt::Dense5Pattern)); + s = s.left(t); + } + QRect tr(xvis, y+m, w - xm - menuitem->tabWidth + 1, h-2*m); + p->drawText(tr, text_flags, s.left(t)); + p->setFont(oldFont); + if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) + p->fillRect(tr, QBrush(p->background().color(), Qt::Dense5Pattern)); + } + if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) { // draw sub menu arrow + int dim = (h-2*motifItemFrame) / 2; + QStyle::PrimitiveElement arrow = (opt->direction == Qt::RightToLeft ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight); + QStyleOption arrowOpt = *opt; + arrowOpt.rect = visualRect(opt->direction, opt->rect, + QRect(x+w - motifArrowHMargin - motifItemFrame - dim, + y+h/2-dim/2, dim, dim)); + if ((opt->state & State_Selected)) + arrowOpt.state = (State_Sunken | ((opt->state & State_Enabled) ? State_Enabled : State_None)); + else + arrowOpt.state = ((opt->state & State_Enabled) ? State_Enabled : State_None); + proxy()->drawPrimitive(arrow, &arrowOpt, p, widget); + } + break; } + + case CE_MenuBarItem: + if (opt->state & State_Selected) // active item + qDrawShadePanel(p, opt->rect, opt->palette, false, motifItemFrame, + &opt->palette.brush(QPalette::Button)); + else // other item + p->fillRect(opt->rect, opt->palette.brush(QPalette::Button)); + QCommonStyle::drawControl(element, opt, p, widget); + break; + + case CE_HeaderSection: + p->save(); + p->setBrushOrigin(opt->rect.topLeft()); + qDrawShadePanel(p, opt->rect, opt->palette, bool(opt->state & (State_Sunken|State_On)), + proxy()->pixelMetric(PM_DefaultFrameWidth), + &opt->palette.brush((opt->state & State_Sunken) ? QPalette::Mid : QPalette::Button)); + p->restore(); + break; + case CE_RubberBand: { + QPixmap tiledPixmap(16, 16); + QPainter pixmapPainter(&tiledPixmap); + pixmapPainter.setPen(Qt::NoPen); + pixmapPainter.setBrush(Qt::Dense4Pattern); + pixmapPainter.setBackground(QBrush(opt->palette.base())); + pixmapPainter.setBackgroundMode(Qt::OpaqueMode); + pixmapPainter.drawRect(0, 0, tiledPixmap.width(), tiledPixmap.height()); + pixmapPainter.end(); + // ### workaround for borked XRENDER + tiledPixmap = QPixmap::fromImage(tiledPixmap.toImage()); + + p->save(); + QRect r = opt->rect; + QStyleHintReturnMask mask; + if (styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask)) + p->setClipRegion(mask.region); + p->drawTiledPixmap(r.x(), r.y(), r.width(), r.height(), tiledPixmap); + p->restore(); + } + break; +#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBarContents: + if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { + QRect rect = pb->rect; + bool vertical = false; + bool inverted = false; + + // Get extra style options if version 2 + const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt); + if (pb2) { + vertical = (pb2->orientation == Qt::Vertical); + inverted = pb2->invertedAppearance; + } + + QTransform m; + if (vertical) { + rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height + m.rotate(90); + m.translate(0, -(rect.height() + rect.y()*2)); + } + + QPalette pal2 = pb->palette; + // Correct the highlight color if it is the same as the background + if (pal2.highlight() == pal2.background()) + pal2.setColor(QPalette::Highlight, pb->palette.color(QPalette::Active, + QPalette::Highlight)); + bool reverse = ((!vertical && (pb->direction == Qt::RightToLeft)) || vertical); + if (inverted) + reverse = !reverse; + int w = rect.width(); + if (pb->minimum == 0 && pb->maximum == 0) { + QRect progressBar; + Q_D(const QMotifStyle); + // draw busy indicator + int x = (d->animateStep*8)% (w * 2); + if (x > w) + x = 2 * w - x; + x = reverse ? rect.right() - x : x + rect.x(); + p->setTransform(m, true); + p->setPen(QPen(pal2.highlight().color(), 4)); + p->drawLine(x, rect.y(), x, rect.height()); + + } else + QCommonStyle::drawControl(element, opt, p, widget); + } + break; +#endif // QT_NO_PROGRESSBAR + default: + QCommonStyle::drawControl(element, opt, p, widget); + break; } +} + +static int get_combo_extra_width(int h, int w, int *return_awh=0) +{ + int awh, + tmp; + if (h < 8) { + awh = 6; + } else if (h < 14) { + awh = h - 2; + } else { + awh = h/2; + } + tmp = (awh * 3) / 2; + if (tmp > w / 2) { + awh = w / 2 - 3; + tmp = w / 2 + 3; + } + + if (return_awh) + *return_awh = awh; + + return tmp; +} + +static void get_combo_parameters(const QRect &r, + int &ew, int &awh, int &ax, + int &ay, int &sh, int &dh, + int &sy) +{ + ew = get_combo_extra_width(r.height(), r.width(), &awh); + + sh = (awh+3)/4; + if (sh < 3) + sh = 3; + dh = sh/2 + 1; + + ay = r.y() + (r.height()-awh-sh-dh)/2; + if (ay < 0) { + //panic mode + ay = 0; + sy = r.height(); + } else { + sy = ay+awh+dh; + } + ax = r.x() + r.width() - ew; + ax += (ew-awh)/2; +} + +/*! + \reimp +*/ +void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, + const QWidget *widget) const +{ + switch (cc) { + case CC_ToolButton: + if (const QStyleOptionToolButton *toolbutton + = qstyleoption_cast(opt)) { + QRect button, menuarea; + button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget); + menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget); + + State bflags = toolbutton->state & ~State_Sunken; + if (bflags & State_AutoRaise) { + if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) { + bflags &= ~State_Raised; + } + } + State mflags = bflags; + if (toolbutton->state & State_Sunken) { + if (toolbutton->activeSubControls & SC_ToolButton) + bflags |= State_Sunken; + mflags |= State_Sunken; + } + + QStyleOption tool(0); + tool.palette = toolbutton->palette; + if (toolbutton->subControls & SC_ToolButton) { + if (bflags & (State_Sunken | State_On | State_Raised)) { + tool.rect = button; + tool.state = bflags; + proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + } + } + + if ((toolbutton->state & State_HasFocus) && (!focus || !focus->isVisible())) { + QStyleOptionFocusRect fr; + fr.QStyleOption::operator=(*toolbutton); + fr.rect = toolbutton->rect.adjusted(3, 3, -3, -3); + proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget); + } + QStyleOptionToolButton label = *toolbutton; + label.state = bflags; + int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); + label.rect = button.adjusted(fw, fw, -fw, -fw); + proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); + + if (toolbutton->subControls & SC_ToolButtonMenu) { + tool.rect = menuarea; + tool.state = mflags; + if (mflags & (State_Sunken | State_On | State_Raised)) + proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget); + } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { + int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget); + QRect ir = toolbutton->rect; + QStyleOptionToolButton newBtn = *toolbutton; + newBtn.rect = QRect(ir.right() + 5 - mbi, ir.height() - mbi + 4, mbi - 6, mbi - 6); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); + } + } + break; +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(opt)) { + QStyleOptionSpinBox copy = *spinbox; + PrimitiveElement pe; + + if (spinbox->frame && (spinbox->subControls & SC_SpinBoxFrame)) { + QRect r = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxFrame, widget); + qDrawShadePanel(p, r, opt->palette, false, proxy()->pixelMetric(PM_SpinBoxFrameWidth)); + + int fw = proxy()->pixelMetric(QStyle::PM_DefaultFrameWidth); + r = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxEditField, widget).adjusted(-fw,-fw,fw,fw); + QStyleOptionFrame lineOpt; + lineOpt.QStyleOption::operator=(*opt); + lineOpt.rect = r; + lineOpt.lineWidth = fw; + lineOpt.midLineWidth = 0; + lineOpt.state |= QStyle::State_Sunken; + proxy()->drawPrimitive(QStyle::PE_FrameLineEdit, &lineOpt, p, widget); + } + + if (spinbox->subControls & SC_SpinBoxUp) { + copy.subControls = SC_SpinBoxUp; + QPalette pal2 = spinbox->palette; + if (!(spinbox->stepEnabled & QAbstractSpinBox::StepUpEnabled)) { + pal2.setCurrentColorGroup(QPalette::Disabled); + copy.state &= ~State_Enabled; + } + + copy.palette = pal2; + + if (spinbox->activeSubControls == SC_SpinBoxUp && (spinbox->state & State_Sunken)) { + copy.state |= State_On; + copy.state |= State_Sunken; + } else { + copy.state |= State_Raised; + copy.state &= ~State_Sunken; + } + pe = (spinbox->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus + : PE_IndicatorSpinUp); + + copy.rect = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxUp, widget); + proxy()->drawPrimitive(pe, ©, p, widget); + } + + if (spinbox->subControls & SC_SpinBoxDown) { + copy.subControls = SC_SpinBoxDown; + copy.state = spinbox->state; + QPalette pal2 = spinbox->palette; + if (!(spinbox->stepEnabled & QAbstractSpinBox::StepDownEnabled)) { + pal2.setCurrentColorGroup(QPalette::Disabled); + copy.state &= ~State_Enabled; + } + copy.palette = pal2; + + if (spinbox->activeSubControls == SC_SpinBoxDown && (spinbox->state & State_Sunken)) { + copy.state |= State_On; + copy.state |= State_Sunken; + } else { + copy.state |= State_Raised; + copy.state &= ~State_Sunken; + } + pe = (spinbox->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus + : PE_IndicatorSpinDown); + + copy.rect = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxDown, widget); + proxy()->drawPrimitive(pe, ©, p, widget); + } + } + break; +#endif // QT_NO_SPINBOX +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + QRect groove = proxy()->subControlRect(CC_Slider, opt, SC_SliderGroove, widget), + handle = proxy()->subControlRect(CC_Slider, opt, SC_SliderHandle, widget); + + if ((opt->subControls & SC_SliderGroove) && groove.isValid()) { + qDrawShadePanel(p, groove, opt->palette, true, proxy()->pixelMetric(PM_DefaultFrameWidth), + &opt->palette.brush((opt->state & State_Enabled) ? QPalette::Mid : QPalette::Window)); + if ((opt->state & State_HasFocus) && (!focus || !focus->isVisible())) { + QStyleOption focusOpt = *opt; + focusOpt.rect = subElementRect(SE_SliderFocusRect, opt, widget); + proxy()->drawPrimitive(PE_FrameFocusRect, &focusOpt, p, widget); + } + } + + if ((opt->subControls & SC_SliderHandle) && handle.isValid()) { + QStyleOption bevelOpt = *opt; + bevelOpt.state = (opt->state | State_Raised) & ~State_Sunken; + bevelOpt.rect = handle; + p->save(); + p->setBrushOrigin(bevelOpt.rect.topLeft()); + proxy()->drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget); + p->restore(); + + if (slider->orientation == Qt::Horizontal) { + int mid = handle.x() + handle.width() / 2; + qDrawShadeLine(p, mid, handle.y(), mid, handle.y() + handle.height() - 2, + opt->palette, true, 1); + } else { + int mid = handle.y() + handle.height() / 2; + qDrawShadeLine(p, handle.x(), mid, handle.x() + handle.width() - 2, mid, opt->palette, + true, 1); + } + if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) + p->fillRect(handle, QBrush(p->background().color(), Qt::Dense5Pattern)); + } + + if (slider->subControls & SC_SliderTickmarks) { + QStyleOptionSlider tmpSlider = *slider; + tmpSlider.subControls = SC_SliderTickmarks; + int frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth); + tmpSlider.rect.translate(frameWidth - 1, 0); + QCommonStyle::drawComplexControl(cc, &tmpSlider, p, widget); + } + } + break; +#endif // QT_NO_SLIDER + case CC_ComboBox: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { + if (opt->subControls & SC_ComboBoxArrow) { + int awh, ax, ay, sh, sy, dh, ew; + int fw = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0; + + if (cb->frame) { + QStyleOptionButton btn; + btn.QStyleOption::operator=(*cb); + btn.state |= QStyle::State_Raised; + proxy()->drawPrimitive(PE_PanelButtonCommand, &btn, p, widget); + } else { + p->fillRect(opt->rect, opt->palette.brush(QPalette::Button)); + } + + QRect tr = opt->rect; + tr.adjust(fw, fw, -fw, -fw); + get_combo_parameters(tr, ew, awh, ax, ay, sh, dh, sy); + + QRect ar = QStyle::visualRect(opt->direction, opt->rect, QRect(ax,ay,awh,awh)); + + QStyleOption arrowOpt = *opt; + arrowOpt.rect = ar; + arrowOpt.state |= State_Enabled; + proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); + + + // draws the shaded line under the arrow + p->setPen(opt->palette.light().color()); + p->drawLine(ar.x(), sy, ar.x()+awh-1, sy); + p->drawLine(ar.x(), sy, ar.x(), sy+sh-1); + p->setPen(opt->palette.dark().color()); + p->drawLine(ar.x()+1, sy+sh-1, ar.x()+awh-1, sy+sh-1); + p->drawLine(ar.x()+awh-1, sy+1, ar.x()+awh-1, sy+sh-1); + + if ((cb->state & State_HasFocus) && (!focus || !focus->isVisible())) { + QStyleOptionFocusRect focus; + focus.QStyleOption::operator=(*opt); + focus.rect = subElementRect(SE_ComboBoxFocusRect, opt, widget); + focus.backgroundColor = opt->palette.button().color(); + proxy()->drawPrimitive(PE_FrameFocusRect, &focus, p, widget); + } + } + + if (opt->subControls & SC_ComboBoxEditField) { + if (cb->editable) { + QRect er = proxy()->subControlRect(CC_ComboBox, opt, SC_ComboBoxEditField, widget); + er.adjust(-1, -1, 1, 1); + qDrawShadePanel(p, er, opt->palette, true, 1, + &opt->palette.brush(QPalette::Base)); + } + } + p->setPen(opt->palette.buttonText().color()); + } + break; + +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: { + if (opt->subControls & SC_ScrollBarGroove) + qDrawShadePanel(p, opt->rect, opt->palette, true, + proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget), + &opt->palette.brush((opt->state & State_Enabled) ? QPalette::Mid : QPalette::Window)); + + if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(opt)) { + QStyleOptionSlider newScrollbar = *scrollbar; + if (scrollbar->minimum == scrollbar->maximum) + newScrollbar.state |= State_Enabled; // make sure that the slider is drawn. + QCommonStyle::drawComplexControl(cc, &newScrollbar, p, widget); + } + break; } +#endif + + case CC_Q3ListView: + if (opt->subControls & (SC_Q3ListViewBranch | SC_Q3ListViewExpand)) { + int i; + if (opt->subControls & SC_Q3ListView) + QCommonStyle::drawComplexControl(cc, opt, p, widget); + if (const QStyleOptionQ3ListView *lv = qstyleoption_cast(opt)) { + QStyleOptionQ3ListViewItem item = lv->items.at(0); + int y = opt->rect.y(); + int c; + QPolygon dotlines; + if ((opt->activeSubControls & SC_All) && (opt->subControls & SC_Q3ListViewExpand)) { + c = 2; + dotlines.resize(2); + dotlines[0] = QPoint(opt->rect.right(), opt->rect.top()); + dotlines[1] = QPoint(opt->rect.right(), opt->rect.bottom()); + } else { + int linetop = 0, linebot = 0; + // each branch needs at most two lines, ie. four end points + dotlines.resize(item.childCount * 4); + c = 0; + + // skip the stuff above the exposed rectangle + for (i = 1; i < lv->items.size(); ++i) { + QStyleOptionQ3ListViewItem child = lv->items.at(i); + if (child.height + y > 0) + break; + y += child.totalHeight; + } + + int bx = opt->rect.width() / 2; + + // paint stuff in the magical area + while (i < lv->items.size() && y < lv->rect.height()) { + QStyleOptionQ3ListViewItem child = lv->items.at(i); + if (child.features & QStyleOptionQ3ListViewItem::Visible) { + int lh; + if (!(item.features & QStyleOptionQ3ListViewItem::MultiLine)) + lh = child.height; + else + lh = p->fontMetrics().height() + 2 * lv->itemMargin; + lh = qMax(lh, QApplication::globalStrut().height()); + if (lh % 2 > 0) + lh++; + linebot = y + lh/2; + if ((child.features & QStyleOptionQ3ListViewItem::Expandable || child.childCount > 0) && + child.height > 0) { + // needs a box + p->setPen(opt->palette.text().color()); + p->drawRect(bx-4, linebot-4, 9, 9); + QPolygon a; + if ((child.state & State_Open)) + a.setPoints(3, bx-2, linebot-2, + bx, linebot+2, + bx+2, linebot-2); //Qt::RightArrow + else + a.setPoints(3, bx-2, linebot-2, + bx+2, linebot, + bx-2, linebot+2); //Qt::DownArrow + p->setBrush(opt->palette.text()); + p->drawPolygon(a); + p->setBrush(Qt::NoBrush); + // dotlinery + dotlines[c++] = QPoint(bx, linetop); + dotlines[c++] = QPoint(bx, linebot - 5); + dotlines[c++] = QPoint(bx + 5, linebot); + dotlines[c++] = QPoint(opt->rect.width(), linebot); + linetop = linebot + 5; + } else { + // just dotlinery + dotlines[c++] = QPoint(bx+1, linebot); + dotlines[c++] = QPoint(opt->rect.width(), linebot); + } + y += child.totalHeight; + } + ++i; + } + + // Expand line height to edge of rectangle if there's any + // visible child below + while (i < lv->items.size() && lv->items.at(i).height <= 0) + ++i; + if (i < lv->items.size()) + linebot = opt->rect.height(); + + if (linetop < linebot) { + dotlines[c++] = QPoint(bx, linetop); + dotlines[c++] = QPoint(bx, linebot); + } + } + + int line; // index into dotlines + p->setPen(opt->palette.text().color()); + if (opt->subControls & SC_Q3ListViewBranch) for(line = 0; line < c; line += 2) { + p->drawLine(dotlines[line].x(), dotlines[line].y(), + dotlines[line+1].x(), dotlines[line+1].y()); + } + } + break; } + + default: + QCommonStyle::drawComplexControl(cc, opt, p, widget); + break; + } +} + + +/*! \reimp */ +int QMotifStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, + const QWidget *widget) const +{ + int ret = 0; + + switch(pm) { + case PM_ButtonDefaultIndicator: + ret = 5; + break; + + case PM_CheckBoxLabelSpacing: + case PM_RadioButtonLabelSpacing: + ret = 10; + break; + + case PM_ToolBarFrameWidth: + ret = proxy()->pixelMetric(PM_DefaultFrameWidth); + break; + + case PM_ToolBarItemMargin: + ret = 1; + break; + + case PM_ButtonShiftHorizontal: + case PM_ButtonShiftVertical: + ret = 0; + break; + + case PM_SplitterWidth: + ret = qMax(10, QApplication::globalStrut().width()); + break; + + case PM_SliderLength: + ret = 30; + break; + + case PM_SliderThickness: + ret = 16 + 4 * proxy()->pixelMetric(PM_DefaultFrameWidth); + break; +#ifndef QT_NO_SLIDER + case PM_SliderControlThickness: + if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { + int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height() : sl->rect.width(); + int ticks = sl->tickPosition; + int n = 0; + if (ticks & QSlider::TicksAbove) + n++; + if (ticks & QSlider::TicksBelow) + n++; + if (!n) { + ret = space; + break; + } + + int thick = 6; // Magic constant to get 5 + 16 + 5 + + space -= thick; + //### the two sides may be unequal in size + if (space > 0) + thick += (space * 2) / (n + 2); + ret = thick; + } + break; + + case PM_SliderSpaceAvailable: + if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { + if (sl->orientation == Qt::Horizontal) + ret = sl->rect.width() - proxy()->pixelMetric(PM_SliderLength, opt, widget) - 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); + else + ret = sl->rect.height() - proxy()->pixelMetric(PM_SliderLength, opt, widget) - 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); + } + break; +#endif // QT_NO_SLIDER + case PM_DockWidgetFrameWidth: + ret = 2; + break; + + case PM_DockWidgetHandleExtent: + ret = 9; + break; + + case PM_ProgressBarChunkWidth: + ret = 1; + break; + + case PM_ExclusiveIndicatorWidth: + case PM_ExclusiveIndicatorHeight: + ret = 13; + break; + + case PM_MenuBarHMargin: + ret = 2; // really ugly, but Motif + break; + + case PM_MenuButtonIndicator: + if (!opt) + ret = 12; + else + ret = qMax(12, (opt->rect.height() - 4) / 3); + break; + default: + ret = QCommonStyle::pixelMetric(pm, opt, widget); + break; + } + return ret; +} + + +/*! + \reimp +*/ +QRect +QMotifStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, + SubControl sc, const QWidget *widget) const +{ + switch (cc) { +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(opt)) { + int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0; + QSize bs; + bs.setHeight(opt->rect.height()/2 - fw); + bs.setWidth(qMin(bs.height() * 8 / 5, opt->rect.width() / 4)); // 1.6 -approximate golden mean + bs = bs.expandedTo(QApplication::globalStrut()); + int y = fw + spinbox->rect.y(); + int x, lx, rx; + x = spinbox->rect.x() + opt->rect.width() - fw - bs.width(); + lx = fw; + rx = x - fw * 2; + const int margin = spinbox->frame ? 4 : 0; + switch (sc) { + case SC_SpinBoxUp: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + return visualRect(spinbox->direction, spinbox->rect, + QRect(x, y, bs.width(), bs.height() - 1)); + case SC_SpinBoxDown: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + return visualRect(spinbox->direction, spinbox->rect, + QRect(x, y + bs.height() + 1, bs.width(), bs.height() - 1)); + case SC_SpinBoxEditField: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return visualRect(spinbox->direction, spinbox->rect, + QRect(lx + margin, y + margin, + spinbox->rect.width() - 2*fw - 2*margin, + spinbox->rect.height() - 2*fw - 2*margin)); + + return visualRect(spinbox->direction, spinbox->rect, + QRect(lx + margin, y + margin, rx - margin, + spinbox->rect.height() - 2*fw - 2 * margin)); + case SC_SpinBoxFrame: + return visualRect(spinbox->direction, spinbox->rect, spinbox->rect); + default: + break; + } + break; } +#endif // QT_NO_SPINBOX +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + if (sc == SC_SliderHandle) { + int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, opt, widget); + int thickness = proxy()->pixelMetric(PM_SliderControlThickness, opt, widget); + bool horizontal = slider->orientation == Qt::Horizontal; + int len = proxy()->pixelMetric(PM_SliderLength, opt, widget); + int motifBorder = proxy()->pixelMetric(PM_DefaultFrameWidth); + int sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum, slider->sliderPosition, + horizontal ? slider->rect.width() - len - 2 * motifBorder + : slider->rect.height() - len - 2 * motifBorder, + slider->upsideDown); + if (horizontal) + return visualRect(slider->direction, slider->rect, + QRect(sliderPos + motifBorder, tickOffset + motifBorder, len, + thickness - 2 * motifBorder)); + return visualRect(slider->direction, slider->rect, + QRect(tickOffset + motifBorder, sliderPos + motifBorder, + thickness - 2 * motifBorder, len)); + } + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(opt)) { + int dfw = proxy()->pixelMetric(PM_DefaultFrameWidth); + QRect rect = visualRect(scrollbar->direction, scrollbar->rect, + QCommonStyle::subControlRect(cc, scrollbar, sc, widget)); + if (sc == SC_ScrollBarSlider) { + if (scrollbar->orientation == Qt::Horizontal) + rect.adjust(-dfw, dfw, dfw, -dfw); + else + rect.adjust(dfw, -dfw, -dfw, dfw); + } else if (sc != SC_ScrollBarGroove) { + if (scrollbar->orientation == Qt::Horizontal) + rect.adjust(0, dfw, 0, -dfw); + else + rect.adjust(dfw, 0, -dfw, 0); + } + return visualRect(scrollbar->direction, scrollbar->rect, rect); + } + break; +#endif // QT_NO_SCROLLBAR +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { + switch (sc) { + case SC_ComboBoxArrow: { + int ew, awh, sh, dh, ax, ay, sy; + int fw = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0; + QRect cr = opt->rect; + cr.adjust(fw, fw, -fw, -fw); + get_combo_parameters(cr, ew, awh, ax, ay, sh, dh, sy); + return visualRect(cb->direction, cb->rect, QRect(QPoint(ax, ay), cr.bottomRight())); + } + + case SC_ComboBoxEditField: { + int fw = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0; + QRect rect = opt->rect; + rect.adjust(fw, fw, -fw, -fw); + int ew = get_combo_extra_width(rect.height(), rect.width()); + rect.adjust(1, 1, -1-ew, -1); + return visualRect(cb->direction, cb->rect, rect); + } + + default: + break; + } + } + break; +#endif // QT_NO_SCROLLBAR + default: + break; + } + return QCommonStyle::subControlRect(cc, opt, sc, widget); +} + +/*! + \reimp +*/ +QSize +QMotifStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, + const QSize &contentsSize, const QWidget *widget) const +{ + QSize sz(contentsSize); + + switch(ct) { + case CT_RadioButton: + case CT_CheckBox: + sz = QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget); + sz.rwidth() += motifItemFrame; + break; + + case CT_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + sz = QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget); + if (!btn->text.isEmpty() && (btn->features & (QStyleOptionButton::AutoDefaultButton|QStyleOptionButton::DefaultButton))) + sz.setWidth(qMax(75, sz.width())); + sz += QSize(0, 1); // magical extra pixel + } + break; + + case CT_MenuBarItem: { + if(!sz.isEmpty()) + sz += QSize(5*motifItemHMargin+1, 2*motifItemVMargin + motifItemFrame); + break; } + + case CT_MenuItem: + if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { + sz = QCommonStyle::sizeFromContents(ct, opt, sz, widget); + int w = sz.width(), h = sz.height(); + + if (mi->menuItemType == QStyleOptionMenuItem::Separator) { + w = 10; + h = (mi->text.isEmpty()) ? motifSepHeight : mi->fontMetrics.height(); + } + + // a little bit of border can never harm + w += 2*motifItemHMargin + 2*motifItemFrame; + + if (!mi->text.isNull() && mi->text.indexOf(QLatin1Char('\t')) >= 0) + // string contains tab + w += motifTabSpacing; + else if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) + // submenu indicator needs some room if we don't have a tab column + w += motifArrowHMargin + 4*motifItemFrame; + + int checkColumn = mi->maxIconWidth; + if (mi->menuHasCheckableItems) + checkColumn = qMax(checkColumn, motifCheckMarkSpace); + if (checkColumn > 0) + w += checkColumn + motifCheckMarkHMargin; + + sz = QSize(w, h); + } + break; + + + default: + sz = QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget); + break; + } + + return sz; +} + +/*! + \reimp +*/ +QRect +QMotifStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *widget) const +{ + QRect rect; + + switch (sr) { + case SE_SliderFocusRect: + rect = QCommonStyle::subElementRect(sr, opt, widget); + rect.adjust(2, 2, -2, -2); + break; + + case SE_CheckBoxIndicator: + case SE_RadioButtonIndicator: + { + rect = visualRect(opt->direction, opt->rect, + QCommonStyle::subElementRect(sr, opt, widget)); + rect.adjust(motifItemFrame,0, motifItemFrame,0); + rect = visualRect(opt->direction, opt->rect, rect); + } + break; + + case SE_ComboBoxFocusRect: + { + int awh, ax, ay, sh, sy, dh, ew; + int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); + QRect tr = opt->rect; + + tr.adjust(fw, fw, -fw, -fw); + get_combo_parameters(tr, ew, awh, ax, ay, sh, dh, sy); + rect.setRect(ax-2, ay-2, awh+4, awh+sh+dh+4); + break; + } + + case SE_Q3DockWindowHandleRect: + if (const QStyleOptionQ3DockWindow *dw = qstyleoption_cast(opt)) { + if (!dw->docked || !dw->closeEnabled) + rect.setRect(0, 0, opt->rect.width(), opt->rect.height()); + else { + if (dw->state == State_Horizontal) + rect.setRect(2, 15, opt->rect.width()-2, opt->rect.height() - 15); + else + rect.setRect(0, 2, opt->rect.width() - 15, opt->rect.height() - 2); + } + rect = visualRect(dw->direction, dw->rect, rect); + } + break; + + case SE_ProgressBarLabel: + case SE_ProgressBarGroove: + case SE_ProgressBarContents: + if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { + int textw = 0; + if (pb->textVisible) + textw = pb->fontMetrics.width(QLatin1String("100%")) + 6; + + if (pb->textAlignment == Qt::AlignLeft || pb->textAlignment == Qt::AlignCenter) { + rect = opt->rect; + } else { + if(sr == SE_ProgressBarLabel) + rect.setCoords(opt->rect.right() - textw, opt->rect.top(), + opt->rect.right(), opt->rect.bottom()); + else + rect.setCoords(opt->rect.left(), opt->rect.top(), + opt->rect.right() - textw, opt->rect.bottom()); + } + if (sr == SE_ProgressBarContents) + rect.adjust(2, 2, -2, -2); + rect = visualRect(pb->direction, pb->rect, rect); + } + break; + case SE_CheckBoxClickRect: + case SE_RadioButtonClickRect: + rect = visualRect(opt->direction, opt->rect, opt->rect); + break; + + default: + rect = QCommonStyle::subElementRect(sr, opt, widget); + } + return rect; +} + +#ifndef QT_NO_IMAGEFORMAT_XPM +static const char * const qt_menu_xpm[] = { +"16 16 11 1", +" c #000000", +", c #336600", +". c #99CC00", +"X c #666600", +"o c #999933", +"+ c #333300", +"@ c #669900", +"# c #999900", +"$ c #336633", +"% c #666633", +"& c #99CC33", +"................", +"................", +".....#,++X#.....", +"....X X....", +"...X Xo#% X&..", +"..# o..&@o o..", +".., X..#+ @X X..", +"..+ o.o+ +o# +..", +"..+ #o+ +## +..", +".., %@ ++ +, X..", +"..# o@oo+ #..", +"...X X##$ o..", +"....X X..", +"....&oX++X#oX...", +"................", +"................"}; + + +static const char * const qt_close_xpm[] = { + "12 12 2 1", + " s None c None", + ". c black", + " ", + " ", + " . . ", + " ... ... ", + " ...... ", + " .... ", + " .... ", + " ...... ", + " ... ... ", + " . . ", + " ", + " "}; + +static const char * const qt_maximize_xpm[] = { + "12 12 2 1", + " s None c None", + ". c black", + " ", + " ", + " ", + " . ", + " ... ", + " ..... ", + " ....... ", + " ......... ", + " ", + " ", + " ", + " "}; + +static const char * const qt_minimize_xpm[] = { + "12 12 2 1", + " s None c None", + ". c black", + " ", + " ", + " ", + " ", + " ......... ", + " ....... ", + " ..... ", + " ... ", + " . ", + " ", + " ", + " "}; + +#if 0 // ### not used??? +static const char * const qt_normalize_xpm[] = { + "12 12 2 1", + " s None c None", + ". c black", + " ", + " ", + " . ", + " .. ", + " ... ", + " .... ", + " ..... ", + " ...... ", + " ....... ", + " ", + " ", + " "}; +#endif + +static const char * const qt_normalizeup_xpm[] = { + "12 12 2 1", + " s None c None", + ". c black", + " ", + " ", + " ", + " ....... ", + " ...... ", + " ..... ", + " .... ", + " ... ", + " .. ", + " . ", + " ", + " "}; + +static const char * const qt_shade_xpm[] = { + "12 12 2 1", "# c #000000", + ". c None", + "............", + "............", + ".#########..", + ".#########..", + "............", + "............", + "............", + "............", + "............", + "............", + "............", + "............"}; + + +static const char * const qt_unshade_xpm[] = { + "12 12 2 1", + "# c #000000", + ". c None", + "............", + "............", + ".#########..", + ".#########..", + ".#.......#..", + ".#.......#..", + ".#.......#..", + ".#.......#..", + ".#.......#..", + ".#########..", + "............", + "............"}; + + +static const char * dock_window_close_xpm[] = { + "8 8 2 1", + "# c #000000", + ". c None", + "##....##", + ".##..##.", + "..####..", + "...##...", + "..####..", + ".##..##.", + "##....##", + "........"}; + +// Message box icons, from page 210 of the Windows style guide. + +// Hand-drawn to resemble Microsoft's icons, but in the Mac/Netscape palette. +// Thanks to TrueColor displays, it is slightly more efficient to have +// them duplicated. +/* XPM */ +static const char * const information_xpm[]={ + "32 32 5 1", + ". c None", + "c c #000000", + "* c #999999", + "a c #ffffff", + "b c #0000ff", + "...........********.............", + "........***aaaaaaaa***..........", + "......**aaaaaaaaaaaaaa**........", + ".....*aaaaaaaaaaaaaaaaaa*.......", + "....*aaaaaaaabbbbaaaaaaaac......", + "...*aaaaaaaabbbbbbaaaaaaaac.....", + "..*aaaaaaaaabbbbbbaaaaaaaaac....", + ".*aaaaaaaaaaabbbbaaaaaaaaaaac...", + ".*aaaaaaaaaaaaaaaaaaaaaaaaaac*..", + "*aaaaaaaaaaaaaaaaaaaaaaaaaaaac*.", + "*aaaaaaaaaabbbbbbbaaaaaaaaaaac*.", + "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", + "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", + "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", + "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", + "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", + ".*aaaaaaaaaaabbbbbaaaaaaaaaac***", + ".*aaaaaaaaaaabbbbbaaaaaaaaaac***", + "..*aaaaaaaaaabbbbbaaaaaaaaac***.", + "...caaaaaaabbbbbbbbbaaaaaac****.", + "....caaaaaaaaaaaaaaaaaaaac****..", + ".....caaaaaaaaaaaaaaaaaac****...", + "......ccaaaaaaaaaaaaaacc****....", + ".......*cccaaaaaaaaccc*****.....", + "........***cccaaaac*******......", + "..........****caaac*****........", + ".............*caaac**...........", + "...............caac**...........", + "................cac**...........", + ".................cc**...........", + "..................***...........", + "...................**..........."}; +/* XPM */ +static const char* const warning_xpm[]={ + "32 32 4 1", + ". c None", + "a c #ffff00", + "* c #000000", + "b c #999999", + ".............***................", + "............*aaa*...............", + "...........*aaaaa*b.............", + "...........*aaaaa*bb............", + "..........*aaaaaaa*bb...........", + "..........*aaaaaaa*bb...........", + ".........*aaaaaaaaa*bb..........", + ".........*aaaaaaaaa*bb..........", + "........*aaaaaaaaaaa*bb.........", + "........*aaaa***aaaa*bb.........", + ".......*aaaa*****aaaa*bb........", + ".......*aaaa*****aaaa*bb........", + "......*aaaaa*****aaaaa*bb.......", + "......*aaaaa*****aaaaa*bb.......", + ".....*aaaaaa*****aaaaaa*bb......", + ".....*aaaaaa*****aaaaaa*bb......", + "....*aaaaaaaa***aaaaaaaa*bb.....", + "....*aaaaaaaa***aaaaaaaa*bb.....", + "...*aaaaaaaaa***aaaaaaaaa*bb....", + "...*aaaaaaaaaa*aaaaaaaaaa*bb....", + "..*aaaaaaaaaaa*aaaaaaaaaaa*bb...", + "..*aaaaaaaaaaaaaaaaaaaaaaa*bb...", + ".*aaaaaaaaaaaa**aaaaaaaaaaa*bb..", + ".*aaaaaaaaaaa****aaaaaaaaaa*bb..", + "*aaaaaaaaaaaa****aaaaaaaaaaa*bb.", + "*aaaaaaaaaaaaa**aaaaaaaaaaaa*bb.", + "*aaaaaaaaaaaaaaaaaaaaaaaaaaa*bbb", + "*aaaaaaaaaaaaaaaaaaaaaaaaaaa*bbb", + ".*aaaaaaaaaaaaaaaaaaaaaaaaa*bbbb", + "..*************************bbbbb", + "....bbbbbbbbbbbbbbbbbbbbbbbbbbb.", + ".....bbbbbbbbbbbbbbbbbbbbbbbbb.."}; +/* XPM */ +static const char* const critical_xpm[]={ + "32 32 4 1", + ". c None", + "a c #999999", + "* c #ff0000", + "b c #ffffff", + "...........********.............", + ".........************...........", + ".......****************.........", + "......******************........", + ".....********************a......", + "....**********************a.....", + "...************************a....", + "..*******b**********b*******a...", + "..******bbb********bbb******a...", + ".******bbbbb******bbbbb******a..", + ".*******bbbbb****bbbbb*******a..", + "*********bbbbb**bbbbb*********a.", + "**********bbbbbbbbbb**********a.", + "***********bbbbbbbb***********aa", + "************bbbbbb************aa", + "************bbbbbb************aa", + "***********bbbbbbbb***********aa", + "**********bbbbbbbbbb**********aa", + "*********bbbbb**bbbbb*********aa", + ".*******bbbbb****bbbbb*******aa.", + ".******bbbbb******bbbbb******aa.", + "..******bbb********bbb******aaa.", + "..*******b**********b*******aa..", + "...************************aaa..", + "....**********************aaa...", + "....a********************aaa....", + ".....a******************aaa.....", + "......a****************aaa......", + ".......aa************aaaa.......", + ".........aa********aaaaa........", + "...........aaaaaaaaaaa..........", + ".............aaaaaaa............"}; +/* XPM */ +static const char *const question_xpm[] = { + "32 32 5 1", + ". c None", + "c c #000000", + "* c #999999", + "a c #ffffff", + "b c #0000ff", + "...........********.............", + "........***aaaaaaaa***..........", + "......**aaaaaaaaaaaaaa**........", + ".....*aaaaaaaaaaaaaaaaaa*.......", + "....*aaaaaaaaaaaaaaaaaaaac......", + "...*aaaaaaaabbbbbbaaaaaaaac.....", + "..*aaaaaaaabaaabbbbaaaaaaaac....", + ".*aaaaaaaabbaaaabbbbaaaaaaaac...", + ".*aaaaaaaabbbbaabbbbaaaaaaaac*..", + "*aaaaaaaaabbbbaabbbbaaaaaaaaac*.", + "*aaaaaaaaaabbaabbbbaaaaaaaaaac*.", + "*aaaaaaaaaaaaabbbbaaaaaaaaaaac**", + "*aaaaaaaaaaaaabbbaaaaaaaaaaaac**", + "*aaaaaaaaaaaaabbaaaaaaaaaaaaac**", + "*aaaaaaaaaaaaabbaaaaaaaaaaaaac**", + "*aaaaaaaaaaaaaaaaaaaaaaaaaaaac**", + ".*aaaaaaaaaaaabbaaaaaaaaaaaac***", + ".*aaaaaaaaaaabbbbaaaaaaaaaaac***", + "..*aaaaaaaaaabbbbaaaaaaaaaac***.", + "...caaaaaaaaaabbaaaaaaaaaac****.", + "....caaaaaaaaaaaaaaaaaaaac****..", + ".....caaaaaaaaaaaaaaaaaac****...", + "......ccaaaaaaaaaaaaaacc****....", + ".......*cccaaaaaaaaccc*****.....", + "........***cccaaaac*******......", + "..........****caaac*****........", + ".............*caaac**...........", + "...............caac**...........", + "................cac**...........", + ".................cc**...........", + "..................***...........", + "...................**...........", +}; +#endif + +/*! + \reimp +*/ +QPixmap +QMotifStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget) const +{ +#ifndef QT_NO_IMAGEFORMAT_XPM + switch (standardPixmap) { + case SP_TitleBarMenuButton: + return QPixmap(qt_menu_xpm); + case SP_TitleBarShadeButton: + return QPixmap(qt_shade_xpm); + case SP_TitleBarUnshadeButton: + return QPixmap(qt_unshade_xpm); + case SP_TitleBarNormalButton: + return QPixmap(qt_normalizeup_xpm); + case SP_TitleBarMinButton: + return QPixmap(qt_minimize_xpm); + case SP_TitleBarMaxButton: + return QPixmap(qt_maximize_xpm); + case SP_TitleBarCloseButton: + return QPixmap(qt_close_xpm); + case SP_DockWidgetCloseButton: + return QPixmap(dock_window_close_xpm); + + case SP_MessageBoxInformation: + case SP_MessageBoxWarning: + case SP_MessageBoxCritical: + case SP_MessageBoxQuestion: + { + const char * const * xpm_data; + switch (standardPixmap) { + case SP_MessageBoxInformation: + xpm_data = information_xpm; + break; + case SP_MessageBoxWarning: + xpm_data = warning_xpm; + break; + case SP_MessageBoxCritical: + xpm_data = critical_xpm; + break; + case SP_MessageBoxQuestion: + xpm_data = question_xpm; + break; + default: + xpm_data = 0; + break; + } + QPixmap pm; + if (xpm_data) { + QImage image((const char **) xpm_data); + // All that color looks ugly in Motif + const QPalette &pal = QApplication::palette(); + switch (standardPixmap) { + case SP_MessageBoxInformation: + case SP_MessageBoxQuestion: + image.setColor(2, 0xff000000 | + pal.color(QPalette::Active, QPalette::Dark).rgb()); + image.setColor(3, 0xff000000 | + pal.color(QPalette::Active, QPalette::Base).rgb()); + image.setColor(4, 0xff000000 | + pal.color(QPalette::Active, QPalette::Text).rgb()); + break; + case SP_MessageBoxWarning: + image.setColor(1, 0xff000000 | + pal.color(QPalette::Active, QPalette::Base).rgb()); + image.setColor(2, 0xff000000 | + pal.color(QPalette::Active, QPalette::Text).rgb()); + image.setColor(3, 0xff000000 | + pal.color(QPalette::Active, QPalette::Dark).rgb()); + break; + case SP_MessageBoxCritical: + image.setColor(1, 0xff000000 | + pal.color(QPalette::Active, QPalette::Dark).rgb()); + image.setColor(2, 0xff000000 | + pal.color(QPalette::Active, QPalette::Text).rgb()); + image.setColor(3, 0xff000000 | + pal.color(QPalette::Active, QPalette::Base).rgb()); + break; + default: + break; + } + pm = QPixmap::fromImage(image); + } + return pm; + } + + default: + break; + } +#endif + + return QCommonStyle::standardPixmap(standardPixmap, opt, widget); +} + +/*! \reimp */ +bool QMotifStyle::event(QEvent *e) +{ + if(e->type() == QEvent::FocusIn) { + if (QWidget *focusWidget = QApplication::focusWidget()) { +#ifndef QT_NO_GRAPHICSVIEW + if (QGraphicsView *graphicsView = qobject_cast(focusWidget)) { + QGraphicsItem *focusItem = graphicsView->scene() ? graphicsView->scene()->focusItem() : 0; + if (focusItem && focusItem->type() == QGraphicsProxyWidget::Type) { + QGraphicsProxyWidget *proxy = static_cast(focusItem); + if (proxy->widget()) + focusWidget = proxy->widget()->focusWidget(); + } + } +#endif + if(!focus) + focus = new QFocusFrame(focusWidget); + focus->setWidget(focusWidget); + } else { + if(focus) + focus->setWidget(0); + } + } else if(e->type() == QEvent::FocusOut) { + if(focus) + focus->setWidget(0); + } + return QCommonStyle::event(e); +} + + +/*! \reimp */ +int +QMotifStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWidget *widget, + QStyleHintReturn *returnData) const +{ + int ret; + + switch (hint) { +#ifdef QT3_SUPPORT + case SH_GUIStyle: + ret = Qt::MotifStyle; + break; +#endif + case SH_DrawMenuBarSeparator: + ret = true; + break; + + case SH_ScrollBar_MiddleClickAbsolutePosition: + case SH_Slider_SloppyKeyEvents: + case SH_ProgressDialog_CenterCancelButton: + case SH_Menu_SpaceActivatesItem: + case SH_ScrollView_FrameOnlyAroundContents: + case SH_DitherDisabledText: + ret = 1; + break; + + case SH_Menu_SubMenuPopupDelay: + ret = 96; + break; + + case SH_ProgressDialog_TextLabelAlignment: + ret = Qt::AlignLeft | Qt::AlignVCenter; + break; + + case SH_ItemView_ChangeHighlightOnFocus: + ret = 0; + break; + + case SH_MessageBox_UseBorderForButtonSpacing: + ret = 1; + break; + + case SH_Dial_BackgroundRole: + ret = QPalette::Mid; + break; + + case SH_DialogButtonLayout: + ret = QDialogButtonBox::KdeLayout; + break; + case SH_LineEdit_PasswordCharacter: + ret = '*'; + break; + case SH_DialogButtonBox_ButtonsHaveIcons: + ret = 0; + break; + default: + ret = QCommonStyle::styleHint(hint, opt, widget, returnData); + break; + } + + return ret; +} + +/*! \reimp */ +QPalette QMotifStyle::standardPalette() const +{ +#ifdef Q_WS_X11 + QColor background(0xcf, 0xcf, 0xcf); + if (QX11Info::appDepth() <= 8) + background = QColor(0xc0, 0xc0, 0xc0); +#else + QColor background = QColor(0xcf, 0xcf, 0xcf); +#endif + + QColor light = background.lighter(); + QColor mid = QColor(0xa6, 0xa6, 0xa6); + QColor dark = QColor(0x79, 0x7d, 0x79); + QPalette palette(Qt::black, background, light, dark, mid, Qt::black, Qt::white); + palette.setBrush(QPalette::Disabled, QPalette::WindowText, dark); + palette.setBrush(QPalette::Disabled, QPalette::Text, dark); + palette.setBrush(QPalette::Disabled, QPalette::ButtonText, dark); + palette.setBrush(QPalette::Disabled, QPalette::Base, background); + return palette; +} + +QT_END_NAMESPACE + +#endif // !defined(QT_NO_STYLE_MOTIF) || defined(QT_PLUGIN) diff --git a/src/widgets/styles/qmotifstyle.h b/src/widgets/styles/qmotifstyle.h new file mode 100644 index 0000000000..5ca0795216 --- /dev/null +++ b/src/widgets/styles/qmotifstyle.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMOTIFSTYLE_H +#define QMOTIFSTYLE_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_STYLE_MOTIF) + +class QPalette; +class QFocusFrame; + +class QMotifStylePrivate; +class Q_GUI_EXPORT QMotifStyle : public QCommonStyle +{ + Q_OBJECT +public: + explicit QMotifStyle(bool useHighlightCols=false); + virtual ~QMotifStyle(); + + void setUseHighlightColors(bool); + bool useHighlightColors() const; + + void polish(QPalette&); + void polish(QWidget*); + void unpolish(QWidget*); + void polish(QApplication*); + void unpolish(QApplication*); + + void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const; + + void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const; + + void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, + const QWidget *w = 0) const; + + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, + SubControl sc, const QWidget *widget = 0) const; + + int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, + const QWidget *widget = 0) const; + + QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, + const QSize &contentsSize, const QWidget *widget = 0) const; + + QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const; + + QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget = 0) const; + + int styleHint(StyleHint hint, const QStyleOption *opt = 0, const QWidget *widget = 0, + QStyleHintReturn *returnData = 0) const; + + bool event(QEvent *); + QPalette standardPalette() const; + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt = 0, + const QWidget *widget = 0) const; + +protected: + QPointer focus; + QMotifStyle(QMotifStylePrivate &dd, bool useHighlightCols = false); + void timerEvent(QTimerEvent *event); + bool eventFilter(QObject *o, QEvent *e); + +private: + Q_DECLARE_PRIVATE(QMotifStyle) + Q_DISABLE_COPY(QMotifStyle) + + bool highlightCols; +}; + +#endif // QT_NO_STYLE_MOTIF + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMOTIFSTYLE_H diff --git a/src/widgets/styles/qmotifstyle_p.h b/src/widgets/styles/qmotifstyle_p.h new file mode 100644 index 0000000000..47043b582b --- /dev/null +++ b/src/widgets/styles/qmotifstyle_p.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMOTIFSTYLE_P_H +#define QMOTIFSTYLE_P_H +#include +#include +#include +#include "qmotifstyle.h" +#include "qcommonstyle_p.h" + +QT_BEGIN_NAMESPACE + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +// Private class +class QMotifStylePrivate : public QCommonStylePrivate +{ + Q_DECLARE_PUBLIC(QMotifStyle) +public: + QMotifStylePrivate(); + +public: +#ifndef QT_NO_PROGRESSBAR + QList bars; + int animationFps; + int animateTimer; + QTime startTime; + int animateStep; +#endif // QT_NO_PROGRESSBAR +}; + +QT_END_NAMESPACE + +#endif //QMOTIFSTYLE_P_H diff --git a/src/widgets/styles/qplastiquestyle.cpp b/src/widgets/styles/qplastiquestyle.cpp new file mode 100644 index 0000000000..02ce60efab --- /dev/null +++ b/src/widgets/styles/qplastiquestyle.cpp @@ -0,0 +1,6011 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplastiquestyle.h" + +#if !defined(QT_NO_STYLE_PLASTIQUE) || defined(QT_PLUGIN) + +static const bool AnimateBusyProgressBar = true; +static const bool AnimateProgressBar = false; +// #define QPlastique_MaskButtons +static const int ProgressBarFps = 25; +static const int blueFrameWidth = 2; // with of line edit focus frame + +#include "qwindowsstyle_p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// from windows style +static const int windowsItemFrame = 2; // menu item frame width +static const int windowsSepHeight = 2; // separator item height +static const int windowsItemHMargin = 3; // menu item hor text margin +static const int windowsItemVMargin = 2; // menu item ver text margin +static const int windowsArrowHMargin = 6; // arrow horizontal margin +static const int windowsTabSpacing = 12; // space between text and tab +static const int windowsRightBorder = 15; // right border on windows +static const int windowsCheckMarkWidth = 12; // checkmarks width on windows + +static const char * const qt_plastique_slider_verticalhandle[] = { + "15 11 6 1", + " c None", + "+ c #979797", + "@ c #C9C9C9", + "$ c #C1C1C1", + "b c None", + "d c None", + " $++++++++$ ", + "$+bbbbbbbb+$ ", + "+b $$ +$ ", + "+b $@ +$ ", + "+b +$", + "+b d+", + "+b d+$", + "+b $$ d+$ ", + "+b $@ d+$ ", + "$+dddddddd+$ ", + " $++++++++$ "}; + +static const char * const qt_plastique_slider_verticalhandle_left[] = { + "15 11 6 1", + " c None", + "+ c #979797", + "@ c #C9C9C9", + "$ c #C1C1C1", + "b c None", + "d c None", + " $++++++++$ ", + " $+bbbbbbbb+$", + " $+b $$ d+", + " $+b $@ d+", + "$+b d+", + "+b d+", + "$+ d+", + " $+ $$ d+", + " $+ $@ d+", + " $+dddddddd+$", + " $++++++++$ "}; + +static const char * const qt_plastique_slider_horizontalhandle[] = { + "11 15 6 1", + " c None", + "+ c #979797", + "@ c #C9C9C9", + "$ c #C1C1C1", + "b c None", + "d c None", + " $+++++++$ ", + "$+bbbbbbb+$", + "+b d+", + "+b$$ $$d+", + "+b$@ $@d+", + "+b d+", + "+b d+", + "+b d+", + "+b d+", + "+b d+", + "$+ d+$", + " $+ d+$ ", + " $+ d+$ ", + " $+d+$ ", + " $+$ "}; + +static const char * const qt_plastique_slider_horizontalhandle_up[] = { + "11 15 6 1", + " c None", + "+ c #979797", + "@ c #C9C9C9", + "$ c #C1C1C1", + "b c None", + "d c None", + " $+$ ", + " $+b+$ ", + " $+b +$ ", + " $+b +$ ", + "$+b +$", + "+b d+", + "+b d+", + "+b d+", + "+b d+", + "+b d+", + "+b$$ $$d+", + "+b$@ $@d+", + "+b d+", + "$+ddddddd+$", + " $+++++++$ "}; + +static const char * const qt_scrollbar_button_arrow_left[] = { + "4 7 2 1", + " c None", + "* c #BFBFBF", + " *", + " **", + " ***", + "****", + " ***", + " **", + " *"}; + +static const char * const qt_scrollbar_button_arrow_right[] = { + "4 7 2 1", + " c None", + "* c #BFBFBF", + "* ", + "** ", + "*** ", + "****", + "*** ", + "** ", + "* "}; + +static const char * const qt_scrollbar_button_arrow_up[] = { + "7 4 2 1", + " c None", + "* c #BFBFBF", + " * ", + " *** ", + " ***** ", + "*******"}; + +static const char * const qt_scrollbar_button_arrow_down[] = { + "7 4 2 1", + " c None", + "* c #BFBFBF", + "*******", + " ***** ", + " *** ", + " * "}; + +static const char * const qt_scrollbar_button_left[] = { + "16 16 6 1", + " c None", + ". c #BFBFBF", + "+ c #979797", + "# c #FAFAFA", + "< c #FAFAFA", + "* c #FAFAFA", + " .+++++++++++++.", + ".+#############+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + ".+<<<<<<<<<<<<<+", + " .+++++++++++++."}; + +static const char * const qt_scrollbar_button_right[] = { + "16 16 6 1", + " c None", + ". c #BFBFBF", + "+ c #979797", + "# c #FAFAFA", + "< c #FAFAFA", + "* c #FAFAFA", + ".+++++++++++++. ", + "+#############+.", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+<<<<<<<<<<<<<+.", + ".+++++++++++++. "}; + +static const char * const qt_scrollbar_button_up[] = { + "16 16 6 1", + " c None", + ". c #BFBFBF", + "+ c #979797", + "# c #FAFAFA", + "< c #FAFAFA", + "* c #FAFAFA", + " .++++++++++++. ", + ".+############+.", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+<<<<<<<<<<<<<<+", + ".++++++++++++++."}; + +static const char * const qt_scrollbar_button_down[] = { + "16 16 6 1", + " c None", + ". c #BFBFBF", + "+ c #979797", + "# c #FAFAFA", + "< c #FAFAFA", + "* c #FAFAFA", + "++++++++++++++++", + "+##############+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + "+# <+", + ".+<<<<<<<<<<<<+.", + " .++++++++++++. "}; + +static const char * const qt_scrollbar_slider_pattern_vertical[] = { + "10 18 3 1", + " c None", + ". c #BFBFBF", + "+ c #979797", + ".. .. ..", + ".+ .+ .+", + " ", + " ", + ".. .. ..", + ".+ .+ .+", + " ", + " ", + ".. .. ..", + ".+ .+ .+", + " ", + " ", + ".. .. ..", + ".+ .+ .+", + " ", + " ", + ".. .. ..", + ".+ .+ .+"}; + +static const char * const qt_scrollbar_slider_pattern_horizontal[] = { + "18 10 3 1", + " c None", + ". c #BFBFBF", + "+ c #979797", + ".. .. .. .. ..", + ".+ .+ .+ .+ .+", + " ", + " ", + ".. .. .. .. ..", + ".+ .+ .+ .+ .+", + " ", + " ", + ".. .. .. .. ..", + ".+ .+ .+ .+ .+"}; + +static const char * const qt_toolbarhandle[] = { + "6 6 4 1", + " c None", + ". c #C5C5C5", + "+ c #EEEEEE", + "@ c #FAFAFA", + ".. ", + ".+@ ", + " @@ ", + " .. ", + " .+@", + " @@"}; + +static const char * const qt_simple_toolbarhandle[] = { + "3 3 4 1", + " c None", + ". c #C5C5C5", + "+ c #EEEEEE", + "@ c #FAFAFA", + ".. ", + ".+@", + " @@"}; + +static const char * const qt_titlebar_context_help[] = { +"27 27 5 1", +" c None", +". c #0A0C12", +"+ c #1B202D", +"@ c #293144", +"# c #3C435D", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" +@##@+ ", +" .@@@.+@@.. ", +" .##+ +@@+. ", +" .##@ @#@+. ", +" .... +@+.. ", +" .@+@@.. ", +" +#@@+ ", +" .##. ", +" .++. ", +" .++. ", +" +##+ ", +" .@@. ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; + +static QLinearGradient qMapGradientToRect(const QLinearGradient &gradient, const QRectF &rect) +{ + QLinearGradient tmpGrad(rect.center().x(), rect.top(), + rect.center().x(), rect.bottom()); + tmpGrad.setStops(gradient.stops()); + return tmpGrad; +} + +static QBrush qMapBrushToRect(const QBrush &brush, const QRectF &rect) +{ + if (!brush.gradient()) + return brush; + + // ### Ugly assumption that it's a linear gradient + QBrush tmp(qMapGradientToRect(*static_cast(brush.gradient()), rect)); + return tmp; +} + +static void qBrushSetAlphaF(QBrush *brush, qreal alpha) +{ + if (const QGradient *gradient = brush->gradient()) { + // Use the gradient. Call QColor::setAlphaF() on all color stops. + QGradientStops stops = gradient->stops(); + QMutableVectorIterator it(stops); + QColor tmpColor; + while (it.hasNext()) { + it.next(); + tmpColor = it.value().second; + tmpColor.setAlphaF(alpha * tmpColor.alphaF()); + it.setValue(QPair(it.value().first, tmpColor)); + } + + switch (gradient->type()) { + case QGradient::RadialGradient: { + QRadialGradient grad = *static_cast(gradient); + grad.setStops(stops); + *brush = QBrush(grad); + break; + } + case QGradient::ConicalGradient: { + QConicalGradient grad = *static_cast(gradient); + grad.setStops(stops); + *brush = QBrush(grad); + break; + } + default: + qWarning("QPlastiqueStyle::qBrushLight() - unknown gradient type" + " - falling back to QLinearGradient"); + case QGradient::LinearGradient: { + QLinearGradient grad = *static_cast(gradient); + grad.setStops(stops); + *brush = QBrush(grad); + break; + } + } + } else if (!brush->texture().isNull()) { + // Modify the texture - ridiculously expensive. + QPixmap texture = brush->texture(); + QPixmap pixmap; + QString name = QLatin1Literal("qbrushtexture-alpha") + % HexString(alpha) + % HexString(texture.cacheKey()); + if (!QPixmapCache::find(name, pixmap)) { + QImage image = texture.toImage(); + QRgb *rgb = reinterpret_cast(image.bits()); + int pixels = image.width() * image.height(); + QColor tmpColor; + while (pixels--) { + tmpColor.setRgb(*rgb); + tmpColor.setAlphaF(alpha * tmpColor.alphaF()); + *rgb++ = tmpColor.rgba(); + } + pixmap = QPixmap::fromImage(image); + QPixmapCache::insert(name, pixmap); + } + brush->setTexture(pixmap); + } else { + // Use the color + QColor tmpColor = brush->color(); + tmpColor.setAlphaF(alpha * tmpColor.alphaF()); + brush->setColor(tmpColor); + } +} + +static QBrush qBrushLight(QBrush brush, int light) +{ + if (const QGradient *gradient = brush.gradient()) { + // Use the gradient. Call QColor::lighter() on all color stops. + QGradientStops stops = gradient->stops(); + QMutableVectorIterator it(stops); + while (it.hasNext()) { + it.next(); + it.setValue(QPair(it.value().first, it.value().second.lighter(light))); + } + + switch (gradient->type()) { + case QGradient::RadialGradient: { + QRadialGradient grad = *static_cast(gradient); + grad.setStops(stops); + brush = QBrush(grad); + break; + } + case QGradient::ConicalGradient: { + QConicalGradient grad = *static_cast(gradient); + grad.setStops(stops); + brush = QBrush(grad); + break; + } + default: + qWarning("QPlastiqueStyle::qBrushLight() - unknown gradient type" + " - falling back to QLinearGradient"); + case QGradient::LinearGradient: { + QLinearGradient grad = *static_cast(gradient); + grad.setStops(stops); + brush = QBrush(grad); + break; + } + } + } else if (!brush.texture().isNull()) { + // Modify the texture - ridiculously expensive. + QPixmap texture = brush.texture(); + QPixmap pixmap; + QString name = QLatin1Literal("qbrushtexture-light") + % HexString(light) + % HexString(texture.cacheKey()); + + if (!QPixmapCache::find(name, pixmap)) { + QImage image = texture.toImage(); + QRgb *rgb = reinterpret_cast(image.bits()); + int pixels = image.width() * image.height(); + QColor tmpColor; + while (pixels--) { + tmpColor.setRgb(*rgb); + *rgb++ = tmpColor.lighter(light).rgba(); + } + pixmap = QPixmap::fromImage(image); + QPixmapCache::insert(name, pixmap); + } + brush.setTexture(pixmap); + } else { + // Use the color + brush.setColor(brush.color().lighter(light)); + } + return brush; +} + +static QBrush qBrushDark(QBrush brush, int dark) +{ + if (const QGradient *gradient = brush.gradient()) { + // Use the gradient. Call QColor::darker() on all color stops. + QGradientStops stops = gradient->stops(); + QMutableVectorIterator it(stops); + while (it.hasNext()) { + it.next(); + it.setValue(QPair(it.value().first, it.value().second.darker(dark))); + } + + switch (gradient->type()) { + case QGradient::RadialGradient: { + QRadialGradient grad = *static_cast(gradient); + grad.setStops(stops); + brush = QBrush(grad); + break; + } + case QGradient::ConicalGradient: { + QConicalGradient grad = *static_cast(gradient); + grad.setStops(stops); + brush = QBrush(grad); + break; + } + default: + qWarning("QPlastiqueStyle::qBrushDark() - unknown gradient type" + " - falling back to QLinearGradient"); + case QGradient::LinearGradient: { + QLinearGradient grad = *static_cast(gradient); + grad.setStops(stops); + brush = QBrush(grad); + break; + } + } + } else if (!brush.texture().isNull()) { + // Modify the texture - ridiculously expensive. + QPixmap texture = brush.texture(); + QPixmap pixmap; + QString name = QLatin1Literal("qbrushtexture-dark") + % HexString(dark) + % HexString(texture.cacheKey()); + + if (!QPixmapCache::find(name, pixmap)) { + QImage image = texture.toImage(); + QRgb *rgb = reinterpret_cast(image.bits()); + int pixels = image.width() * image.height(); + QColor tmpColor; + while (pixels--) { + tmpColor.setRgb(*rgb); + *rgb++ = tmpColor.darker(dark).rgba(); + } + pixmap = QPixmap::fromImage(image); + QPixmapCache::insert(name, pixmap); + } + brush.setTexture(pixmap); + } else { + // Use the color + brush.setColor(brush.color().darker(dark)); + } + return brush; +} + +/* + Draws a rounded frame using the provided brush for 1, and adds 0.5 alpha + for 0. + + 0111111110 + 01 10 + 1 1 + 1 1 + 1 1 + 01 10 + 0111111110 +*/ +static void qt_plastique_draw_frame(QPainter *painter, const QRect &rect, const QStyleOption *option, + QFrame::Shadow shadow = QFrame::Plain) +{ + QPen oldPen = painter->pen(); + QBrush border; + QBrush corner; + QBrush innerTopLeft; + QBrush innerBottomRight; + + if (shadow != QFrame::Plain && (option->state & QStyle::State_HasFocus)) { + border = option->palette.highlight(); + qBrushSetAlphaF(&border, qreal(0.8)); + corner = option->palette.highlight(); + qBrushSetAlphaF(&corner, 0.5); + innerTopLeft = qBrushDark(option->palette.highlight(), 125); + innerBottomRight = option->palette.highlight(); + qBrushSetAlphaF(&innerBottomRight, qreal(0.65)); + } else { + border = option->palette.shadow(); + qBrushSetAlphaF(&border, qreal(0.4)); + corner = option->palette.shadow(); + qBrushSetAlphaF(&corner, 0.25); + innerTopLeft = option->palette.shadow(); + innerBottomRight = option->palette.shadow(); + if (shadow == QFrame::Sunken) { + qBrushSetAlphaF(&innerTopLeft, qreal(0.23)); + qBrushSetAlphaF(&innerBottomRight, qreal(0.075)); + } else { + qBrushSetAlphaF(&innerTopLeft, qreal(0.075)); + qBrushSetAlphaF(&innerBottomRight, qreal(0.23)); + } + } + + QLine lines[4]; + QPoint points[8]; + + // Opaque corner lines + painter->setPen(QPen(border, 0)); + lines[0] = QLine(rect.left() + 2, rect.top(), rect.right() - 2, rect.top()); + lines[1] = QLine(rect.left() + 2, rect.bottom(), rect.right() - 2, rect.bottom()); + lines[2] = QLine(rect.left(), rect.top() + 2, rect.left(), rect.bottom() - 2); + lines[3] = QLine(rect.right(), rect.top() + 2, rect.right(), rect.bottom() - 2); + painter->drawLines(lines, 4); + + // Opaque corner dots + points[0] = QPoint(rect.left() + 1, rect.top() + 1); + points[1] = QPoint(rect.left() + 1, rect.bottom() - 1); + points[2] = QPoint(rect.right() - 1, rect.top() + 1); + points[3] = QPoint(rect.right() - 1, rect.bottom() - 1); + painter->drawPoints(points, 4); + + // Shaded corner dots + painter->setPen(QPen(corner, 0)); + points[0] = QPoint(rect.left(), rect.top() + 1); + points[1] = QPoint(rect.left(), rect.bottom() - 1); + points[2] = QPoint(rect.left() + 1, rect.top()); + points[3] = QPoint(rect.left() + 1, rect.bottom()); + points[4] = QPoint(rect.right(), rect.top() + 1); + points[5] = QPoint(rect.right(), rect.bottom() - 1); + points[6] = QPoint(rect.right() - 1, rect.top()); + points[7] = QPoint(rect.right() - 1, rect.bottom()); + painter->drawPoints(points, 8); + + // Shadows + if (shadow != QFrame::Plain) { + painter->setPen(QPen(innerTopLeft, 0)); + lines[0] = QLine(rect.left() + 2, rect.top() + 1, rect.right() - 2, rect.top() + 1); + lines[1] = QLine(rect.left() + 1, rect.top() + 2, rect.left() + 1, rect.bottom() - 2); + painter->drawLines(lines, 2); + painter->setPen(QPen(innerBottomRight, 0)); + lines[0] = QLine(rect.left() + 2, rect.bottom() - 1, rect.right() - 2, rect.bottom() - 1); + lines[1] = QLine(rect.right() - 1, rect.top() + 2, rect.right() - 1, rect.bottom() - 2); + painter->drawLines(lines, 2); + } + + painter->setPen(oldPen); +} + +static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50) +{ + const int maxFactor = 100; + QColor tmp = colorA; + tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor); + tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor); + tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor); + return tmp; +} + +static void qt_plastique_draw_gradient(QPainter *painter, const QRect &rect, const QColor &gradientStart, + const QColor &gradientStop) +{ + QString gradientName = QLatin1Literal("qplastique-g") + % HexString(rect.width()) + % HexString(rect.height()) + % HexString(gradientStart.rgba()) + % HexString(gradientStop.rgba()); + + QPixmap cache; + QPainter *p = painter; + QRect r = rect; + + bool doPixmapCache = painter->deviceTransform().isIdentity() + && painter->worldMatrix().isIdentity(); + if (doPixmapCache && QPixmapCache::find(gradientName, cache)) { + painter->drawPixmap(rect, cache); + } else { + if (doPixmapCache) { + cache = QPixmap(rect.size()); + cache.fill(Qt::transparent); + p = new QPainter(&cache); + r = QRect(0, 0, rect.width(), rect.height()); + } + + int x = r.center().x(); + QLinearGradient gradient(x, r.top(), x, r.bottom()); + gradient.setColorAt(0, gradientStart); + gradient.setColorAt(1, gradientStop); + p->fillRect(r, gradient); + + if (doPixmapCache) { + p->end(); + delete p; + painter->drawPixmap(rect, cache); + QPixmapCache::insert(gradientName, cache); + } + } +} + +static void qt_plastique_drawFrame(QPainter *painter, const QStyleOption *option, const QWidget *widget) +{ + QRect rect = option->rect; + QPen oldPen = painter->pen(); + + QColor borderColor = option->palette.background().color().darker(178); + QColor gradientStartColor = option->palette.button().color().lighter(104); + QColor gradientStopColor = option->palette.button().color().darker(105); + QColor alphaCornerColor; + if (widget) { + // ### backgroundrole/foregroundrole should be part of the style option + alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), borderColor); + } else { + alphaCornerColor = mergedColors(option->palette.background().color(), borderColor); + } + + QLine lines[4]; + QPoint points[8]; + + // outline / border + painter->setPen(borderColor); + lines[0] = QLine(rect.left() + 2, rect.top(), rect.right() - 2, rect.top()); + lines[1] = QLine(rect.left() + 2, rect.bottom(), rect.right() - 2, rect.bottom()); + lines[2] = QLine(rect.left(), rect.top() + 2, rect.left(), rect.bottom() - 2); + lines[3] = QLine(rect.right(), rect.top() + 2, rect.right(), rect.bottom() - 2); + painter->drawLines(lines, 4); + + points[0] = QPoint(rect.left() + 1, rect.top() + 1); + points[1] = QPoint(rect.right() - 1, rect.top() + 1); + points[2] = QPoint(rect.left() + 1, rect.bottom() - 1); + points[3] = QPoint(rect.right() - 1, rect.bottom() - 1); + painter->drawPoints(points, 4); + + painter->setPen(alphaCornerColor); + + points[0] = QPoint(rect.left() + 1, rect.top()); + points[1] = QPoint(rect.right() - 1, rect.top()); + points[2] = QPoint(rect.left() + 1, rect.bottom()); + points[3] = QPoint(rect.right() - 1, rect.bottom()); + points[4] = QPoint(rect.left(), rect.top() + 1); + points[5] = QPoint(rect.right(), rect.top() + 1); + points[6] = QPoint(rect.left(), rect.bottom() - 1); + points[7] = QPoint(rect.right(), rect.bottom() - 1); + painter->drawPoints(points, 8); + + // inner border + if ((option->state & QStyle::State_Sunken) || (option->state & QStyle::State_On)) + painter->setPen(option->palette.button().color().darker(118)); + else + painter->setPen(gradientStartColor); + + lines[0] = QLine(rect.left() + 2, rect.top() + 1, rect.right() - 2, option->rect.top() + 1); + lines[1] = QLine(rect.left() + 1, rect.top() + 2, rect.left() + 1, option->rect.bottom() - 2); + painter->drawLines(lines, 2); + + if ((option->state & QStyle::State_Sunken) || (option->state & QStyle::State_On)) + painter->setPen(option->palette.button().color().darker(110)); + else + painter->setPen(gradientStopColor.darker(102)); + + lines[0] = QLine(rect.left() + 2, rect.bottom() - 1, rect.right() - 2, rect.bottom() - 1); + lines[1] = QLine(rect.right() - 1, rect.top() + 2, rect.right() - 1, rect.bottom() - 2); + painter->drawLines(lines, 2); + + painter->setPen(oldPen); +} + +static void qt_plastique_drawShadedPanel(QPainter *painter, const QStyleOption *option, bool base, + const QWidget *widget) +{ + QRect rect = option->rect; + QPen oldPen = painter->pen(); + + QColor gradientStartColor = option->palette.button().color().lighter(104); + QColor gradientStopColor = option->palette.button().color().darker(105); + + // gradient fill + if ((option->state & QStyle::State_Enabled) || !(option->state & QStyle::State_AutoRaise)) { + if ((option->state & QStyle::State_Sunken) || (option->state & QStyle::State_On)) { + qt_plastique_draw_gradient(painter, rect.adjusted(1, 1, -1, -1), + option->palette.button().color().darker(114), + option->palette.button().color().darker(106)); + } else { + qt_plastique_draw_gradient(painter, rect.adjusted(1, 1, -1, -1), + base ? option->palette.background().color().lighter(105) : gradientStartColor, + base ? option->palette.background().color().darker(102) : gradientStopColor); + } + } + + qt_plastique_drawFrame(painter, option, widget); + + painter->setPen(oldPen); +} + +static void qt_plastique_draw_mdibutton(QPainter *painter, const QStyleOptionTitleBar *option, const QRect &tmp, bool hover, bool sunken) +{ + if (tmp.isNull()) + return; + bool active = (option->titleBarState & QStyle::State_Active); + + // ### use palette colors instead + QColor mdiButtonGradientStartColor; + QColor mdiButtonGradientStopColor; + if (active) { + mdiButtonGradientStartColor = QColor((hover || sunken) ? 0x7d8bb1 : 0x55689a); + mdiButtonGradientStopColor = QColor((hover || sunken) ? 0x939ebe : 0x7381ab); + } else { + mdiButtonGradientStartColor = QColor((hover || sunken) ? 0x9e9e9e : 0x818181); + mdiButtonGradientStopColor = QColor((hover || sunken) ? 0xababab : 0x929292); + } + + qt_plastique_draw_gradient(painter, tmp.adjusted(1, 1, -1, -1), + mdiButtonGradientStartColor, mdiButtonGradientStopColor); + + QColor mdiButtonBorderColor; + if (active) { + mdiButtonBorderColor = (hover || sunken) ? QColor(0x627097) : QColor(0x324577); + } else { + mdiButtonBorderColor = (hover || sunken) ? QColor(0x838383) : QColor(0x5e5e5e); + } + painter->setPen(QPen(mdiButtonBorderColor, 1)); + + const QLine lines[4] = { + QLine(tmp.left() + 2, tmp.top(), tmp.right() - 2, tmp.top()), + QLine(tmp.left() + 2, tmp.bottom(), tmp.right() - 2, tmp.bottom()), + QLine(tmp.left(), tmp.top() + 2, tmp.left(), tmp.bottom() - 2), + QLine(tmp.right(), tmp.top() + 2, tmp.right(), tmp.bottom() - 2) }; + painter->drawLines(lines, 4); + + const QPoint points[4] = { + QPoint(tmp.left() + 1, tmp.top() + 1), + QPoint(tmp.right() - 1, tmp.top() + 1), + QPoint(tmp.left() + 1, tmp.bottom() - 1), + QPoint(tmp.right() - 1, tmp.bottom() - 1) }; + painter->drawPoints(points, 4); +} + +#ifndef QT_NO_DOCKWIDGET +static QString elliditide(const QString &text, const QFontMetrics &fontMetrics, const QRect &rect, int *textWidth = 0) +{ + // Chop and insert ellide into title if text is too wide + QString title = text; + int width = textWidth ? *textWidth : fontMetrics.width(text); + QString ellipsis = QLatin1String("..."); + if (width > rect.width()) { + QString leftHalf = title.left(title.size() / 2); + QString rightHalf = title.mid(leftHalf.size() + 1); + while (!leftHalf.isEmpty() && !rightHalf.isEmpty()) { + leftHalf.chop(1); + int width = fontMetrics.width(leftHalf + ellipsis + rightHalf); + if (width < rect.width()) { + title = leftHalf + ellipsis + rightHalf; + width = width; + break; + } + rightHalf.remove(0, 1); + width = fontMetrics.width(leftHalf + ellipsis + rightHalf); + if (width < rect.width()) { + title = leftHalf + ellipsis + rightHalf; + width = width; + break; + } + } + } + if (textWidth) + *textWidth = width; + return title; +} +#endif + +#if !defined(QT_NO_DOCKWIDGET) || !defined(QT_NO_SPLITTER) +static void qt_plastique_draw_handle(QPainter *painter, const QStyleOption *option, + const QRect &rect, Qt::Orientation orientation, + const QWidget *widget) +{ + QColor borderColor = option->palette.background().color().darker(178); + QColor alphaCornerColor; + if (widget) { + // ### backgroundrole/foregroundrole should be part of the style option + alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), borderColor); + } else { + alphaCornerColor = mergedColors(option->palette.background().color(), borderColor); + } + QImage handle(qt_simple_toolbarhandle); + alphaCornerColor.setAlpha(170); + handle.setColor(1, alphaCornerColor.rgba()); + handle.setColor(2, mergedColors(alphaCornerColor, option->palette.light().color()).rgba()); + handle.setColor(3, option->palette.light().color().rgba()); + + const int spacing = 2; + + if (orientation == Qt::Vertical) { + int nchunks = rect.width() / (handle.width() + spacing); + for (int i = 0; i < nchunks; ++i) + painter->drawImage(QPoint(rect.left() + i * (handle.width() + spacing), rect.top()), handle); + } else { + int nchunks = rect.height() / (handle.height() + spacing); + for (int i = 0; i < nchunks; ++i) + painter->drawImage(QPoint(rect.left(), rect.top() + i * (handle.height() + spacing)), handle); + } +} +#endif + +class QPlastiqueStylePrivate : public QWindowsStylePrivate +{ + Q_DECLARE_PUBLIC(QPlastiqueStyle) +public: + QPlastiqueStylePrivate(); + virtual ~QPlastiqueStylePrivate(); + void drawPartialFrame(QPainter *painter, const QStyleOptionComplex *option, + const QRect &rect, const QWidget *widget) const; + +#ifndef QT_NO_PROGRESSBAR + QList bars; + int progressBarAnimateTimer; + QElapsedTimer timer; +#endif +}; + +/*! + \internal + */ +QPlastiqueStylePrivate::QPlastiqueStylePrivate() : + QWindowsStylePrivate() +#ifndef QT_NO_PROGRESSBAR + , progressBarAnimateTimer(0) +#endif +{ +} + +/*! + \internal + */ +QPlastiqueStylePrivate::~QPlastiqueStylePrivate() +{ +} + +/*! + \class QPlastiqueStyle + \brief The QPlastiqueStyle class provides a widget style similar to the + Plastik style available in KDE. + + The Plastique style provides a default look and feel for widgets on X11 + that closely resembles the Plastik style, introduced by Sandro Giessl in + KDE 3.2. + + \img qplastiquestyle.png + \sa QWindowsXPStyle, QMacStyle, QWindowsStyle, QCDEStyle, QMotifStyle +*/ + +/*! + Constructs a QPlastiqueStyle object. +*/ +QPlastiqueStyle::QPlastiqueStyle() + : QWindowsStyle(*new QPlastiqueStylePrivate) +{ + setObjectName(QLatin1String("Plastique")); +} + +/*! + Destructs the QPlastiqueStyle object. +*/ +QPlastiqueStyle::~QPlastiqueStyle() +{ +} + +/* + Used by spin- and combo box. + Draws a rounded frame around rect but omits the right hand edge +*/ +void QPlastiqueStylePrivate::drawPartialFrame(QPainter *painter, const QStyleOptionComplex *option, + const QRect &rect, const QWidget *widget) const +{ + Q_Q(const QPlastiqueStyle); + bool reverse = option->direction == Qt::RightToLeft; + QStyleOptionFrame frameOpt; +#ifndef QT_NO_LINEEDIT + if (QLineEdit *lineedit = widget->findChild()) + frameOpt.initFrom(lineedit); +#else + Q_UNUSED(widget) +#endif // QT_NO_LINEEDIT + + frameOpt.rect = rect; + painter->save(); + frameOpt.rect.adjust(-blueFrameWidth + (reverse ? 1 : 0), -blueFrameWidth, + blueFrameWidth + (reverse ? 0 : -1), blueFrameWidth); + painter->setClipRect(frameOpt.rect); + frameOpt.rect.adjust(reverse ? -2 : 0, 0, reverse ? 0 : 2, 0); + frameOpt.lineWidth = q->pixelMetric(QStyle::PM_DefaultFrameWidth); + frameOpt.midLineWidth = 0; + frameOpt.state = option->state | QStyle::State_Sunken; + frameOpt.palette = option->palette; + q->drawPrimitive(QStyle::PE_PanelLineEdit, &frameOpt, painter, widget); + painter->restore(); + + // Draw a two pixel highlight on the flat edge + if (option->state & QStyle::State_HasFocus) { + painter->setPen(QPen(option->palette.highlight(), 0)); + QBrush focusBorder = option->palette.highlight(); + qBrushSetAlphaF(&focusBorder, qreal(0.65)); + if (!reverse) { + painter->drawLine(rect.topRight() + QPoint(1, -1), + rect.bottomRight() + QPoint(1, 1)); + painter->setPen(QPen(focusBorder, 0)); + painter->drawLine(rect.topRight(), + rect.bottomRight()); + } + else { + painter->drawLine(rect.topLeft() + QPoint(-1, -1), + rect.bottomLeft() + QPoint(-1, 1)); + painter->setPen(QPen(focusBorder, 0)); + painter->drawLine(rect.topLeft(), + rect.bottomLeft()); + } + } +} + +/*! + \reimp +*/ +void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const +{ + Q_ASSERT(option); + + QColor borderColor = option->palette.background().color().darker(178); + QColor alphaCornerColor; + if (widget) { + // ### backgroundrole/foregroundrole should be part of the style option + alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), borderColor); + } else { + alphaCornerColor = mergedColors(option->palette.background().color(), borderColor); + } + QColor alphaTextColor = mergedColors(option->palette.background().color(), option->palette.text().color()); + + switch (element) { + case PE_IndicatorButtonDropDown: + proxy()->drawPrimitive(PE_PanelButtonTool, option, painter, widget); + break; + case PE_FrameDefaultButton: { + if (!(option->state & QStyle::State_Enabled)) + break; + painter->setPen(QPen(QColor(0, 0, 0, 127), 0)); + const QLine lines[4] = { + QLine(option->rect.left() + 2, option->rect.top(), + option->rect.right() - 2, option->rect.top()), + QLine(option->rect.left() + 2, option->rect.bottom(), + option->rect.right() - 2, option->rect.bottom()), + QLine(option->rect.left(), option->rect.top() + 2, + option->rect.left(), option->rect.bottom() - 2), + QLine(option->rect.right(), option->rect.top() + 2, + option->rect.right(), option->rect.bottom() - 2) }; + painter->drawLines(lines, 4); + + QPoint points[8]; + points[0] = QPoint(option->rect.left() + 1, option->rect.top() + 1); + points[1] = QPoint(option->rect.right() - 1, option->rect.top() + 1); + points[2] = QPoint(option->rect.left() + 1, option->rect.bottom() - 1); + points[3] = QPoint(option->rect.right() - 1, option->rect.bottom() - 1); + painter->drawPoints(points, 4); + + painter->setPen(QPen(QColor(0, 0, 0, 63), 0)); + points[0] = QPoint(option->rect.left() + 1, option->rect.top()); + points[1] = QPoint(option->rect.right() - 1, option->rect.top()); + points[2] = QPoint(option->rect.left(), option->rect.top() + 1); + points[3] = QPoint(option->rect.right(), option->rect.top() + 1); + points[4] = QPoint(option->rect.left() + 1, option->rect.bottom()); + points[5] = QPoint(option->rect.right() - 1, option->rect.bottom()); + points[6] = QPoint(option->rect.left(), option->rect.bottom() - 1); + points[7] = QPoint(option->rect.right(), option->rect.bottom() - 1); + painter->drawPoints(points, 8); + + break; + } +#ifndef QT_NO_TABWIDGET + case PE_FrameTabWidget: + if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast(option)) { + if (twf->shape != QTabBar::RoundedNorth && twf->shape != QTabBar::RoundedWest && + twf->shape != QTabBar::RoundedSouth && twf->shape != QTabBar::RoundedEast) { + QWindowsStyle::drawPrimitive(element, option, painter, widget); + break; + } + + int borderThickness = proxy()->pixelMetric(PM_TabBarBaseOverlap, twf, widget); + bool reverse = (twf->direction == Qt::RightToLeft); + + painter->save(); + + // Start by filling the contents of the tab widget frame (which is + // actually a panel). + painter->fillRect(option->rect.adjusted(1, 1, -1, -1), option->palette.window()); + + QRect tabBarRect; + switch (twf->shape) { + case QTabBar::RoundedNorth: + if (reverse) + tabBarRect = QRect(twf->rect.right() - twf->leftCornerWidgetSize.width() - twf->tabBarSize.width() + 1, twf->rect.top(), twf->tabBarSize.width(), borderThickness); + else + tabBarRect = QRect(twf->rect.left() + twf->leftCornerWidgetSize.width(), twf->rect.top(), twf->tabBarSize.width(), borderThickness); + break ; + case QTabBar::RoundedWest: + tabBarRect = QRect(twf->rect.left(), twf->rect.top() + twf->leftCornerWidgetSize.height(), borderThickness, twf->tabBarSize.height()); + break ; + case QTabBar::RoundedEast: + tabBarRect = QRect(twf->rect.right() - borderThickness + 1, twf->rect.top() + twf->leftCornerWidgetSize.height(), + borderThickness, twf->tabBarSize.height()); + break ; + case QTabBar::RoundedSouth: + if (reverse) + tabBarRect = QRect(twf->rect.right() - twf->leftCornerWidgetSize.width() - twf->tabBarSize.width() + 1, + twf->rect.bottom() - borderThickness + 1, twf->tabBarSize.width(), borderThickness); + else + tabBarRect = QRect(twf->rect.left() + twf->leftCornerWidgetSize.width(), + twf->rect.bottom() - borderThickness + 1, twf->tabBarSize.width(), borderThickness); + break ; + default: + break; + } + + QRegion region(twf->rect); + region -= tabBarRect; + painter->setClipRegion(region); + + // Outer border + QLine leftLine = QLine(twf->rect.topLeft() + QPoint(0, 2), twf->rect.bottomLeft() - QPoint(0, 2)); + QLine rightLine = QLine(twf->rect.topRight() + QPoint(0, 2), twf->rect.bottomRight() - QPoint(0, 2)); + QLine bottomLine = QLine(twf->rect.bottomLeft() + QPoint(2, 0), twf->rect.bottomRight() - QPoint(2, 0)); + QLine topLine = QLine(twf->rect.topLeft() + QPoint(2, 0), twf->rect.topRight() - QPoint(2, 0)); + + QBrush border = option->palette.shadow(); + qBrushSetAlphaF(&border, qreal(0.4)); + painter->setPen(QPen(border, 0)); + + QVarLengthArray lines; + QVarLengthArray points; + + lines.append(topLine); + + // Inner border + QLine innerLeftLine = QLine(leftLine.p1() + QPoint(1, 0), leftLine.p2() + QPoint(1, 0)); + QLine innerRightLine = QLine(rightLine.p1() - QPoint(1, 0), rightLine.p2() - QPoint(1, 0)); + QLine innerBottomLine = QLine(bottomLine.p1() - QPoint(0, 1), bottomLine.p2() - QPoint(0, 1)); + QLine innerTopLine = QLine(topLine.p1() + QPoint(0, 1), topLine.p2() + QPoint(0, 1)); + + // Rounded Corner + QPoint leftBottomOuterCorner = QPoint(innerLeftLine.p2() + QPoint(0, 1)); + QPoint leftBottomInnerCorner1 = QPoint(leftLine.p2() + QPoint(0, 1)); + QPoint leftBottomInnerCorner2 = QPoint(bottomLine.p1() - QPoint(1, 0)); + QPoint rightBottomOuterCorner = QPoint(innerRightLine.p2() + QPoint(0, 1)); + QPoint rightBottomInnerCorner1 = QPoint(rightLine.p2() + QPoint(0, 1)); + QPoint rightBottomInnerCorner2 = QPoint(bottomLine.p2() + QPoint(1, 0)); + QPoint rightTopOuterCorner = QPoint(innerRightLine.p1() - QPoint(0, 1)); + QPoint rightTopInnerCorner1 = QPoint(rightLine.p1() - QPoint(0, 1)); + QPoint rightTopInnerCorner2 = QPoint(topLine.p2() + QPoint(1, 0)); + QPoint leftTopOuterCorner = QPoint(innerLeftLine.p1() - QPoint(0, 1)); + QPoint leftTopInnerCorner1 = QPoint(leftLine.p1() - QPoint(0, 1)); + QPoint leftTopInnerCorner2 = QPoint(topLine.p1() - QPoint(1, 0)); + + lines.append(leftLine); + lines.append(rightLine); + lines.append(bottomLine); + + painter->drawLines(lines.constData(), lines.size()); + lines.clear(); + + points.append(leftBottomOuterCorner); + points.append(rightBottomOuterCorner); + points.append(rightTopOuterCorner); + points.append(leftTopOuterCorner); + + painter->drawPoints(points.constData(), points.size()); + points.clear(); + + QBrush innerTopLeft = option->palette.shadow(); + qBrushSetAlphaF(&innerTopLeft, qreal(0.075)); + painter->setPen(QPen(innerTopLeft, 0)); + + lines.append(innerLeftLine); + lines.append(innerTopLine); + painter->drawLines(lines.constData(), lines.size()); + lines.clear(); + + QBrush innerBottomRight = option->palette.shadow(); + qBrushSetAlphaF(&innerBottomRight, qreal(0.23)); + painter->setPen(QPen(innerBottomRight, 0)); + lines.append(innerRightLine); + lines.append(innerBottomLine); + painter->drawLines(lines.constData(), lines.size()); + lines.clear(); + + QBrush corner = option->palette.shadow(); + qBrushSetAlphaF(&corner, 0.25); + painter->setPen(QPen(corner, 0)); + points.append(leftBottomInnerCorner1); + points.append(leftBottomInnerCorner2); + points.append(rightBottomInnerCorner1); + points.append(rightBottomInnerCorner2); + points.append(rightTopInnerCorner1); + points.append(rightTopInnerCorner2); + points.append(leftTopInnerCorner1); + points.append(leftTopInnerCorner2); + painter->drawPoints(points.constData(), points.size()); + points.clear(); + + painter->restore(); + } + break ; +#endif // QT_NO_TABWIDGET +#ifndef QT_NO_TABBAR + case PE_FrameTabBarBase: + if (const QStyleOptionTabBarBase *tbb = qstyleoption_cast(option)) { + if (tbb->shape != QTabBar::RoundedNorth && tbb->shape != QTabBar::RoundedWest && + tbb->shape != QTabBar::RoundedSouth && tbb->shape != QTabBar::RoundedEast) { + QWindowsStyle::drawPrimitive(element, option, painter, widget); + break; + } + + painter->save(); + + QRegion region(tbb->rect); + region -= tbb->tabBarRect; + painter->setClipRegion(region); + + QLine topLine = QLine(tbb->rect.bottomLeft() - QPoint(0, 1), tbb->rect.bottomRight() - QPoint(0, 1)); + QLine bottomLine = QLine(tbb->rect.bottomLeft(), tbb->rect.bottomRight()); + + QBrush border = option->palette.shadow(); + qBrushSetAlphaF(&border, qreal(0.4)); + QBrush innerTopLeft = option->palette.shadow(); + qBrushSetAlphaF(&innerTopLeft, qreal(0.075)); + QBrush innerBottomRight = option->palette.shadow(); + qBrushSetAlphaF(&innerBottomRight, qreal(0.23)); + QBrush corner = option->palette.shadow(); + qBrushSetAlphaF(&corner, 0.25); + + if (tbb->shape == QTabBar::RoundedSouth) + painter->setPen(QPen(corner, 0)); + else + painter->setPen(QPen(border, 0)); + painter->drawLine(topLine); + + if (tbb->shape != QTabBar::RoundedSouth) + painter->setPen(QPen(innerTopLeft, 0)); + else + painter->setPen(QPen(border, 0)); + painter->drawLine(bottomLine); + + painter->restore(); + } + break ; +#endif // QT_NO_TABBAR +#ifndef QT_NO_GROUPBOX + case PE_FrameGroupBox: + if (const QStyleOptionFrame *frame = qstyleoption_cast(option)) { + QStyleOptionFrameV2 frameV2(*frame); + if (frameV2.features & QStyleOptionFrameV2::Flat) { + QPen oldPen = painter->pen(); + painter->setPen(borderColor); + painter->drawLine(frameV2.rect.topLeft(), frameV2.rect.topRight()); + painter->setPen(oldPen); + } else { + frameV2.state &= ~(State_Sunken | State_HasFocus); + proxy()->drawPrimitive(PE_Frame, &frameV2, painter, widget); + } + } + break; +#endif // QT_NO_GROUPBOX + case PE_Frame: { + QFrame::Shadow shadow = QFrame::Plain; + if (option->state & State_Sunken) + shadow = QFrame::Sunken; + else if (option->state & State_Raised) + shadow = QFrame::Raised; + qt_plastique_draw_frame(painter, option->rect, option, shadow); + break; + } +#ifndef QT_NO_LINEEDIT + case PE_FrameLineEdit: + qt_plastique_draw_frame(painter, option->rect, option, QFrame::Sunken); + break; + case PE_PanelLineEdit: + if (const QStyleOptionFrame *lineEdit = qstyleoption_cast(option)) { + // Panel of a line edit inside combo box or spin box is drawn in CC_ComboBox and CC_SpinBox + if (widget) { +#ifndef QT_NO_SPINBOX + // Spinbox doesn't need a separate palette for the lineedit + if (qobject_cast(widget->parentWidget())) + break; +#endif + } + + painter->save(); + + // Fill the line edit insides + QRect filledRect = lineEdit->rect.adjusted(1, 1, -1, -1); + QBrush baseBrush = qMapBrushToRect(lineEdit->palette.base(), filledRect); + painter->setBrushOrigin(filledRect.topLeft()); + painter->fillRect(filledRect.adjusted(1, 1, -1, -1), baseBrush); + + painter->setPen(QPen(baseBrush, 0)); + const QLine lines[4] = { + QLine(filledRect.left(), filledRect.top() + 1, + filledRect.left(), filledRect.bottom() - 1), + QLine(filledRect.right(), filledRect.top() + 1, + filledRect.right(), filledRect.bottom() - 1), + QLine(filledRect.left() + 1, filledRect.top(), + filledRect.right() - 1, filledRect.top()), + QLine(filledRect.left() + 1, filledRect.bottom(), + filledRect.right() - 1, filledRect.bottom()) }; + painter->drawLines(lines, 4); + + if (lineEdit->lineWidth != 0) + qt_plastique_draw_frame(painter, option->rect, option, QFrame::Sunken); + + painter->restore(); + break; + } +#endif // QT_NO_LINEEDIT + case PE_FrameDockWidget: + case PE_FrameMenu: + case PE_FrameStatusBarItem: { + // Draws the frame around a popup menu. + QPen oldPen = painter->pen(); + painter->setPen(borderColor); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + painter->setPen(alphaCornerColor); + const QPoint points[4] = { + QPoint(option->rect.topLeft()), + QPoint(option->rect.topRight()), + QPoint(option->rect.bottomLeft()), + QPoint(option->rect.bottomRight()) }; + painter->drawPoints(points, 4); + painter->setPen(oldPen); + break; + } +#ifdef QT3_SUPPORT + case PE_Q3DockWindowSeparator: { + QPen oldPen = painter->pen(); + painter->setPen(alphaCornerColor); + QRect rect = option->rect; + if (option->state & State_Horizontal) { + painter->drawLine(rect.right(), rect.top() + 2, rect.right(), rect.bottom() - 1); + } else { + painter->drawLine(rect.left() + 2, rect.bottom(), rect.right() - 1, rect.bottom()); + } + painter->setPen(oldPen); + break; + } + case PE_Q3Separator: { + QPen oldPen = painter->pen(); + painter->setPen(alphaCornerColor); + if ((option->state & State_Horizontal) == 0) + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + else + painter->drawLine(option->rect.topRight(), option->rect.bottomRight()); + painter->setPen(option->palette.background().color().lighter(104)); + if ((option->state & State_Horizontal) == 0) + painter->drawLine(option->rect.topLeft(), option->rect.topRight()); + else + painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft()); + painter->setPen(oldPen); + break; + } +#endif // QT3_SUPPORT +#ifndef QT_NO_MAINWINDOW + case PE_PanelMenuBar: + if ((widget && qobject_cast(widget->parentWidget())) +#ifdef QT3_SUPPORT + || (widget && widget->parentWidget() && widget->parentWidget()->inherits("Q3MainWindow")) +#endif + ) { + // Draws the light line above and the dark line below menu bars and + // tool bars. + QPen oldPen = painter->pen(); + if (element == PE_PanelMenuBar || (option->state & State_Horizontal)) { + painter->setPen(alphaCornerColor); + painter->drawLine(option->rect.left(), option->rect.bottom(), + option->rect.right(), option->rect.bottom()); + painter->setPen(option->palette.background().color().lighter(104)); + painter->drawLine(option->rect.left(), option->rect.top(), + option->rect.right(), option->rect.top()); + } else { + painter->setPen(option->palette.background().color().lighter(104)); + painter->drawLine(option->rect.left(), option->rect.top(), + option->rect.left(), option->rect.bottom()); + painter->setPen(alphaCornerColor); + painter->drawLine(option->rect.right(), option->rect.top(), + option->rect.right(), option->rect.bottom()); + } + painter->setPen(oldPen); + } + break; +#endif // QT_NO_MAINWINDOW + case PE_IndicatorHeaderArrow: { + bool usedAntialiasing = painter->renderHints() & QPainter::Antialiasing; + if (!usedAntialiasing) + painter->setRenderHint(QPainter::Antialiasing); + QWindowsStyle::drawPrimitive(element, option, painter, widget); + if (!usedAntialiasing) + painter->setRenderHint(QPainter::Antialiasing, false); + break; + } + case PE_PanelButtonTool: + // Draws a tool button (f.ex., in QToolBar and QTabBar) + if ((option->state & State_Enabled || option->state & State_On) || !(option->state & State_AutoRaise)) + qt_plastique_drawShadedPanel(painter, option, true, widget); + break; +#ifndef QT_NO_TOOLBAR + case PE_IndicatorToolBarHandle: { + QPixmap cache; + QRect rect = option->rect; +#ifdef QT3_SUPPORT + if (widget && widget->inherits("Q3DockWindowHandle") && widget->parentWidget()->inherits("Q3DockWindow")) { + if (!(option->state & State_Horizontal)) + rect.adjust(2, 0, -2, 0); + } +#endif + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("toolbarhandle"), option, rect.size()); + if (!QPixmapCache::find(pixmapName, cache)) { + cache = QPixmap(rect.size()); + cache.fill(Qt::transparent); + QPainter cachePainter(&cache); + QRect cacheRect(QPoint(0, 0), rect.size()); + if (widget) + cachePainter.fillRect(cacheRect, option->palette.brush(widget->backgroundRole())); + else + cachePainter.fillRect(cacheRect, option->palette.background()); + + QImage handle(qt_toolbarhandle); + alphaCornerColor.setAlpha(170); + handle.setColor(1, alphaCornerColor.rgba()); + handle.setColor(2, mergedColors(alphaCornerColor, option->palette.light().color()).rgba()); + handle.setColor(3, option->palette.light().color().rgba()); + + if (option->state & State_Horizontal) { + int nchunks = cacheRect.height() / handle.height(); + int indent = (cacheRect.height() - (nchunks * handle.height())) / 2; + for (int i = 0; i < nchunks; ++i) + cachePainter.drawImage(QPoint(cacheRect.left() + 3, cacheRect.top() + indent + i * handle.height()), + handle); + } else { + int nchunks = cacheRect.width() / handle.width(); + int indent = (cacheRect.width() - (nchunks * handle.width())) / 2; + for (int i = 0; i < nchunks; ++i) + cachePainter.drawImage(QPoint(cacheRect.left() + indent + i * handle.width(), cacheRect.top() + 3), + handle); + } + cachePainter.end(); + QPixmapCache::insert(pixmapName, cache); + } + painter->drawPixmap(rect.topLeft(), cache); + break; + } + case PE_IndicatorToolBarSeparator: { + QPen oldPen = painter->pen(); + painter->setPen(alphaCornerColor); + if (option->state & State_Horizontal) { + painter->drawLine(option->rect.left(), option->rect.top() + 1, option->rect.left(), option->rect.bottom() - 2); + painter->setPen(option->palette.base().color()); + painter->drawLine(option->rect.right(), option->rect.top() + 1, option->rect.right(), option->rect.bottom() - 2); + } else { + painter->drawLine(option->rect.left() + 1, option->rect.top(), option->rect.right() - 2, option->rect.top()); + painter->setPen(option->palette.base().color()); + painter->drawLine(option->rect.left() + 1, option->rect.bottom(), option->rect.right() - 2, option->rect.bottom()); + } + painter->setPen(oldPen); + break; + } +#endif // QT_NO_TOOLBAR + case PE_PanelButtonCommand: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + bool sunken = (button->state & State_Sunken) || (button->state & State_On); + if ((button->features & QStyleOptionButton::Flat) && !sunken) + break; + + bool defaultButton = (button->features & (QStyleOptionButton::DefaultButton + | QStyleOptionButton::AutoDefaultButton)); + + BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("pushbutton-%1").arg(defaultButton)) + + QPen oldPen = p->pen(); + bool hover = (button->state & State_Enabled) && (button->state & State_MouseOver); + + // Give the painter a different brush origin for sunken buttons + if (sunken) { + // ### No such function + // p->setPenOrigin(rect.left() + 1, rect.top() + 1); + p->setBrushOrigin(rect.left() + 1, rect.top() + 1); + } + + // Draw border + qt_plastique_draw_frame(p, rect, option); + + // Fill the panel + QRectF fillRect = rect.adjusted(2, 2, -2, -2); + + // Button colors + QBrush alphaCornerBrush = qMapBrushToRect(qBrushDark(option->palette.button(), 165), rect); + qBrushSetAlphaF(&alphaCornerBrush, 0.5); + QBrush buttonGradientBrush; + QBrush leftLineGradientBrush; + QBrush rightLineGradientBrush; + QBrush sunkenButtonGradientBrush; + QBrush sunkenLeftLineGradientBrush; + QBrush sunkenRightLineGradientBrush; + QBrush buttonBrush = qMapBrushToRect(option->palette.button(), rect); + if (buttonBrush.gradient() || !buttonBrush.texture().isNull()) { + buttonGradientBrush = buttonBrush; + sunkenButtonGradientBrush = qBrushDark(buttonBrush, 108); + leftLineGradientBrush = qBrushLight(buttonBrush, 105); + rightLineGradientBrush = qBrushDark(buttonBrush, 105); + sunkenLeftLineGradientBrush = qBrushDark(buttonBrush, 110); + sunkenRightLineGradientBrush = qBrushDark(buttonBrush, 106); + } else { + // Generate gradients + QLinearGradient buttonGradient(rect.topLeft(), rect.bottomLeft()); + if (hover) { + buttonGradient.setColorAt(0.0, mergedColors(option->palette.highlight().color(), + buttonBrush.color().lighter(104), 6)); + buttonGradient.setColorAt(1.0, mergedColors(option->palette.highlight().color(), + buttonBrush.color().darker(110), 6)); + } else { + buttonGradient.setColorAt(0.0, buttonBrush.color().lighter(104)); + buttonGradient.setColorAt(1.0, buttonBrush.color().darker(110)); + } + buttonGradientBrush = QBrush(buttonGradient); + + QLinearGradient buttonGradient2(rect.topLeft(), rect.bottomLeft()); + buttonGradient2.setColorAt(0.0, buttonBrush.color().darker(113)); + buttonGradient2.setColorAt(1.0, buttonBrush.color().darker(103)); + sunkenButtonGradientBrush = QBrush(buttonGradient2); + + QLinearGradient buttonGradient3(rect.topLeft(), rect.bottomLeft()); + buttonGradient3.setColorAt(0.0, buttonBrush.color().lighter(105)); + buttonGradient3.setColorAt(1.0, buttonBrush.color()); + leftLineGradientBrush = QBrush(buttonGradient3); + + QLinearGradient buttonGradient4(rect.topLeft(), rect.bottomLeft()); + buttonGradient4.setColorAt(0.0, buttonBrush.color()); + buttonGradient4.setColorAt(1.0, buttonBrush.color().darker(110)); + rightLineGradientBrush = QBrush(buttonGradient4); + + QLinearGradient buttonGradient5(rect.topLeft(), rect.bottomLeft()); + buttonGradient5.setColorAt(0.0, buttonBrush.color().darker(113)); + buttonGradient5.setColorAt(1.0, buttonBrush.color().darker(107)); + sunkenLeftLineGradientBrush = QBrush(buttonGradient5); + + QLinearGradient buttonGradient6(rect.topLeft(), rect.bottomLeft()); + buttonGradient6.setColorAt(0.0, buttonBrush.color().darker(108)); + buttonGradient6.setColorAt(1.0, buttonBrush.color().darker(103)); + sunkenRightLineGradientBrush = QBrush(buttonGradient6); + } + + // Main fill + p->fillRect(fillRect, + qMapBrushToRect(sunken ? sunkenButtonGradientBrush + : buttonGradientBrush, rect)); + + // Top line + p->setPen(QPen(qBrushLight(qMapBrushToRect(sunken ? sunkenButtonGradientBrush + : buttonGradientBrush, rect), 105), 0)); + p->drawLine(QPointF(rect.left() + 2, rect.top() + 1), + QPointF(rect.right() - 2, rect.top() + 1)); + + // Bottom line + p->setPen(QPen(qBrushDark(qMapBrushToRect(sunken ? sunkenButtonGradientBrush + : buttonGradientBrush, rect), 105), 0)); + p->drawLine(QPointF(rect.left() + 2, rect.bottom() - 1), + QPointF(rect.right() - 2, rect.bottom() - 1)); + + // Left line + p->setPen(QPen(qMapBrushToRect(sunken ? sunkenLeftLineGradientBrush + : leftLineGradientBrush, rect), 1)); + p->drawLine(QPointF(rect.left() + 1, rect.top() + 2), + QPointF(rect.left() + 1, rect.bottom() - 2)); + + // Right line + p->setPen(QPen(qMapBrushToRect(sunken ? sunkenRightLineGradientBrush + : rightLineGradientBrush, rect), 1)); + p->drawLine(QPointF(rect.right() - 1, rect.top() + 2), + QPointF(rect.right() - 1, rect.bottom() - 2)); + + // Hovering + if (hover && !sunken) { + QBrush hover = qMapBrushToRect(option->palette.highlight(), rect); + QBrush hoverOuter = hover; + qBrushSetAlphaF(&hoverOuter, qreal(0.7)); + + QLine lines[2]; + + p->setPen(QPen(hoverOuter, 0)); + lines[0] = QLine(rect.left() + 1, rect.top() + 1, rect.right() - 1, rect.top() + 1); + lines[1] = QLine(rect.left() + 1, rect.bottom() - 1, rect.right() - 1, rect.bottom() - 1); + p->drawLines(lines, 2); + + QBrush hoverInner = hover; + qBrushSetAlphaF(&hoverInner, qreal(0.45)); + p->setPen(QPen(hoverInner, 0)); + lines[0] = QLine(rect.left() + 1, rect.top() + 2, rect.right() - 1, rect.top() + 2); + lines[1] = QLine(rect.left() + 1, rect.bottom() - 2, rect.right() - 1, rect.bottom() - 2); + p->drawLines(lines, 2); + + QBrush hoverSide = hover; + qBrushSetAlphaF(&hoverSide, qreal(0.075)); + p->setPen(QPen(hoverSide, 0)); + lines[0] = QLine(rect.left() + 1, rect.top() + 2, rect.left() + 1, rect.bottom() - 2); + lines[1] = QLine(rect.right() - 1, rect.top() + 2, rect.right() - 1, rect.bottom() - 2); + p->drawLines(lines, 2); + } + + p->setPen(oldPen); + + END_STYLE_PIXMAPCACHE + } + break; + case PE_IndicatorCheckBox: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + BEGIN_STYLE_PIXMAPCACHE(QLatin1String("checkbox")) + + p->save(); + + // Outline + QBrush border = option->palette.shadow(); + qBrushSetAlphaF(&border, qreal(0.4)); + p->setPen(QPen(border, 0)); + const QLine lines[4] = { + QLine(rect.left() + 1, rect.top(), rect.right() - 1, rect.top()), + QLine(rect.left() + 1, rect.bottom(), rect.right() - 1, rect.bottom()), + QLine(rect.left(), rect.top() + 1, rect.left(), rect.bottom() - 1), + QLine(rect.right(), rect.top() + 1, rect.right(), rect.bottom() - 1) }; + p->drawLines(lines, 4); + + QBrush corner = option->palette.shadow(); + qBrushSetAlphaF(&corner, qreal(0.2)); + p->setPen(QPen(corner, 0)); + const QPoint points[4] = { + rect.topLeft(), rect.topRight(), + rect.bottomLeft(), rect.bottomRight() }; + p->drawPoints(points, 4); + + // Fill + QBrush baseBrush = qMapBrushToRect(button->palette.base(), rect); + if (!baseBrush.gradient() && baseBrush.texture().isNull()) { + QLinearGradient gradient(rect.center().x(), rect.top(), rect.center().x(), rect.bottom()); + gradient.setColorAt(0, baseBrush.color()); + gradient.setColorAt(1, baseBrush.color().darker(105)); + baseBrush = gradient; + } + p->fillRect(rect.adjusted(1, 1, -1, -1), baseBrush); + + // Hover + if ((button->state & State_Enabled) && (button->state & State_MouseOver)) { + QBrush pen = qMapBrushToRect(button->palette.highlight(), rect); + qBrushSetAlphaF(&pen, qreal(0.8)); + p->setPen(QPen(pen, 0)); + p->drawRect(rect.adjusted(1, 1, -2, -2)); + qBrushSetAlphaF(&pen, 0.5); + p->setPen(QPen(pen, 0)); + p->drawRect(rect.adjusted(2, 2, -3, -3)); + + qBrushSetAlphaF(&pen, qreal(0.2)); + p->setBrush(pen); + p->drawRect(rect.adjusted(2, 2, -3, -3)); + } + + // Indicator + bool on = button->state & State_On; + bool sunken = button->state & State_Sunken; + bool unchanged = button->state & State_NoChange; + bool enabled = button->state & State_Enabled; + if (on || (enabled && sunken) || unchanged) { + p->setRenderHint(QPainter::Antialiasing); + QBrush pointBrush = qMapBrushToRect(button->palette.text(), rect); + if (sunken) + qBrushSetAlphaF(&pointBrush, qreal(0.5)); + else if (unchanged) + qBrushSetAlphaF(&pointBrush, qreal(0.3)); + p->setPen(QPen(pointBrush, 3)); + const QLine lines[2] = { + QLine(rect.left() + 4, rect.top() + 4, rect.right() - 3, rect.bottom() - 3), + QLine(rect.right() - 3, rect.top() + 4, rect.left() + 4, rect.bottom() - 3) }; + p->drawLines(lines, 2); + } + + p->restore(); + END_STYLE_PIXMAPCACHE + } + break; + case PE_IndicatorRadioButton: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + BEGIN_STYLE_PIXMAPCACHE(QLatin1String("radiobutton")) + + p->save(); + p->setRenderHint(QPainter::Antialiasing); + + // The the filled ellipse + QBrush border = qMapBrushToRect(option->palette.shadow(), rect); + qBrushSetAlphaF(&border, qreal(0.51)); + p->setPen(QPen(border, 0)); + + QBrush baseBrush = qMapBrushToRect(button->palette.base(), rect); + if (!baseBrush.gradient() && baseBrush.texture().isNull()) { + QLinearGradient gradient(rect.center().x(), rect.top(), rect.center().x(), rect.bottom()); + gradient.setColorAt(0, baseBrush.color()); + gradient.setColorAt(1, baseBrush.color().darker(105)); + baseBrush = gradient; + } + p->setBrush(baseBrush); + p->drawEllipse(QRectF(rect).adjusted(1, 1, -1, -1)); + + // Hover + if ((button->state & State_Enabled) && (button->state & State_MouseOver)) { + QBrush pen = qMapBrushToRect(button->palette.highlight(), rect); + qBrushSetAlphaF(&pen, qreal(0.8)); + p->setPen(QPen(pen, 0)); + qBrushSetAlphaF(&pen, qreal(0.2)); + p->setBrush(pen); + p->drawEllipse(QRectF(rect).adjusted(2, 2, -2, -2)); + } + + // Indicator + bool on = button->state & State_On; + bool sunken = button->state & State_Sunken; + bool enabled = button->state & State_Enabled; + if (on || (enabled && sunken)) { + p->setPen(Qt::NoPen); + QBrush pointBrush = qMapBrushToRect(button->palette.text(), rect); + if (sunken) + qBrushSetAlphaF(&pointBrush, 0.5); + p->setBrush(pointBrush); + p->drawEllipse(QRectF(rect).adjusted(3, 3, -3, -3)); + } + + p->restore(); + END_STYLE_PIXMAPCACHE + } + break; +#ifndef QT_NO_DOCKWIDGET + case PE_IndicatorDockWidgetResizeHandle: + if ((option->state & State_Enabled) && (option->state & State_MouseOver)) + painter->fillRect(option->rect, QColor(255, 255, 255, 128)); + if (option->state & State_Horizontal) { + int width = option->rect.width() / 3; + QRect rect(option->rect.center().x() - width / 2, + option->rect.top() + (option->rect.height() / 2) - 1, width, 3); + qt_plastique_draw_handle(painter, option, rect, Qt::Vertical, widget); + } else { + int height = option->rect.height() / 3; + QRect rect(option->rect.left() + (option->rect.width() / 2 - 1), + option->rect.center().y() - height / 2, 3, height); + qt_plastique_draw_handle(painter, option, rect, Qt::Horizontal, widget); + } + break; +#endif // QT_NO_DOCKWIDGET + case PE_IndicatorViewItemCheck: { + QStyleOptionButton button; + button.QStyleOption::operator=(*option); + button.state &= ~State_MouseOver; + proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget); + break; + } + case PE_FrameWindow: { + painter->save(); + bool active = (option->state & State_Active); + int titleBarStop = option->rect.top() + proxy()->pixelMetric(PM_TitleBarHeight, option, widget); + + QPalette palette = option->palette; + if (!active) + palette.setCurrentColorGroup(QPalette::Disabled); + + // Frame and rounded corners + painter->setPen(mergedColors(palette.highlight().color(), Qt::black, 50)); + + QLine lines[3]; + QPoint points[4]; + + // bottom border line + lines[0] = QLine(option->rect.left() + 1, option->rect.bottom(), option->rect.right() - 1, option->rect.bottom()); + + // bottom left and right side border lines + lines[1] = QLine(option->rect.left(), titleBarStop, option->rect.left(), option->rect.bottom() - 1); + lines[2] = QLine(option->rect.right(), titleBarStop, option->rect.right(), option->rect.bottom() - 1); + painter->drawLines(lines, 3); + points[0] = QPoint(option->rect.left() + 1, option->rect.bottom() - 1); + points[1] = QPoint(option->rect.right() - 1, option->rect.bottom() - 1); + painter->drawPoints(points, 2); + +#ifdef QT3_SUPPORT + if (widget && widget->inherits("Q3DockWindow")) { + // also draw the frame on the title bar + lines[0] = QLine(option->rect.left() + 1, option->rect.top(), + option->rect.right() - 1, option->rect.top()); + lines[1] = QLine(option->rect.left(), option->rect.top() + 1, + option->rect.left(), titleBarStop); + lines[2] = QLine(option->rect.right(), option->rect.top() + 1, + option->rect.right(), titleBarStop); + painter->drawLines(lines, 3); + } +#endif + + // alpha corners + painter->setPen(mergedColors(palette.highlight().color(), palette.background().color(), 55)); + points[0] = QPoint(option->rect.left() + 2, option->rect.bottom() - 1); + points[1] = QPoint(option->rect.left() + 1, option->rect.bottom() - 2); + points[2] = QPoint(option->rect.right() - 2, option->rect.bottom() - 1); + points[3] = QPoint(option->rect.right() - 1, option->rect.bottom() - 2); + painter->drawPoints(points, 4); + +#ifdef QT3_SUPPORT + if (widget && widget->inherits("Q3DockWindow")) { + // also draw the frame on the title bar + points[0] = option->rect.topLeft(); + points[1] = option->rect.topRight(); + painter->drawPoints(points, 2); + } +#endif + + // upper and lower left inner + painter->setPen(active ? mergedColors(palette.highlight().color(), palette.background().color()) : palette.background().color().darker(120)); + painter->drawLine(option->rect.left() + 1, titleBarStop, option->rect.left() + 1, option->rect.bottom() - 2); + +#ifdef QT3_SUPPORT + if (widget && widget->inherits("Q3DockWindow")) { + // also draw the frame on the title bar + lines[0] = QLine(option->rect.left() + 1, option->rect.top() + 1, + option->rect.left() + 1, titleBarStop); + lines[1] = QLine(option->rect.right() - 1, option->rect.top() + 1, + option->rect.right() - 1, titleBarStop); + lines[2] = QLine(option->rect.left() + 1, option->rect.top() + 1, + option->rect.right() - 1, option->rect.top() + 1); + painter->drawLines(lines, 3); + } +#endif + + painter->setPen(active ? mergedColors(palette.highlight().color(), palette.background().color(), 57) : palette.background().color().darker(130)); + lines[0] = QLine(option->rect.right() - 1, titleBarStop, option->rect.right() - 1, option->rect.bottom() - 2); + lines[1] = QLine(option->rect.left() + 1, option->rect.bottom() - 1, option->rect.right() - 1, option->rect.bottom() - 1); + painter->drawLines(lines, 2); + + painter->restore(); + } + break; + case PE_IndicatorBranch: { + int mid_h = option->rect.x() + option->rect.width() / 2; + int mid_v = option->rect.y() + option->rect.height() / 2; + int bef_h = mid_h; + int bef_v = mid_v; + int aft_h = mid_h; + int aft_v = mid_v; + QBrush brush(option->palette.dark().color(), Qt::Dense4Pattern); + if (option->state & State_Item) { + if (option->direction == Qt::RightToLeft) + painter->fillRect(option->rect.left(), mid_v, bef_h - option->rect.left(), 1, brush); + else + painter->fillRect(aft_h, mid_v, option->rect.right() - aft_h + 1, 1, brush); + } + if (option->state & State_Sibling) + painter->fillRect(mid_h, aft_v, 1, option->rect.bottom() - aft_v + 1, brush); + if (option->state & (State_Open | State_Children | State_Item | State_Sibling)) + painter->fillRect(mid_h, option->rect.y(), 1, bef_v - option->rect.y(), brush); + + if (option->state & State_Children) { + painter->save(); + QPoint center = option->rect.center(); + // border + QRect fullRect(center.x() - 4, center.y() - 4, 9, 9); + painter->setPen(borderColor); + + const QLine lines[4] = { + QLine(fullRect.left() + 1, fullRect.top(), + fullRect.right() - 1, fullRect.top()), + QLine(fullRect.left() + 1, fullRect.bottom(), + fullRect.right() - 1, fullRect.bottom()), + QLine(fullRect.left(), fullRect.top() + 1, + fullRect.left(), fullRect.bottom() - 1), + QLine(fullRect.right(), fullRect.top() + 1, + fullRect.right(), fullRect.bottom() - 1) }; + painter->drawLines(lines, 4); + + // "antialiased" corners + painter->setPen(alphaCornerColor); + const QPoint points[4] = { + fullRect.topLeft(), + fullRect.topRight(), + fullRect.bottomLeft(), + fullRect.bottomRight() }; + painter->drawPoints(points, 4); + + // fill + QRect adjustedRect = fullRect; + QRect gradientRect(adjustedRect.left() + 1, adjustedRect.top() + 1, + adjustedRect.right() - adjustedRect.left() - 1, + adjustedRect.bottom() - adjustedRect.top() - 1); + if (option->palette.base().style() == Qt::SolidPattern) { + QColor baseGradientStartColor = option->palette.base().color().darker(101); + QColor baseGradientStopColor = option->palette.base().color().darker(106); + qt_plastique_draw_gradient(painter, gradientRect, baseGradientStartColor, baseGradientStopColor); + } else { + painter->fillRect(gradientRect, option->palette.base()); + } + // draw "+" or "-" + painter->setPen(alphaTextColor); + painter->drawLine(center.x() - 2, center.y(), center.x() + 2, center.y()); + if (!(option->state & State_Open)) + painter->drawLine(center.x(), center.y() - 2, center.x(), center.y() + 2); + painter->restore(); + } + } + break; + default: + QWindowsStyle::drawPrimitive(element, option, painter, widget); + break; + } +} + +/*! + \reimp +*/ +void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const +{ + QColor borderColor = option->palette.background().color().darker(178); + QColor alphaCornerColor; + if (widget) { + // ### backgroundrole/foregroundrole should be part of the style option + alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), borderColor); + } else { + alphaCornerColor = mergedColors(option->palette.background().color(), borderColor); + } + QColor alphaTextColor = mergedColors(option->palette.background().color(), option->palette.text().color()); + + QColor gradientStartColor = option->palette.button().color().lighter(104); + QColor gradientStopColor = option->palette.button().color().darker(105); + + QColor shadowGradientStartColor = option->palette.button().color().darker(115); + QColor shadowGradientStopColor = option->palette.button().color().darker(120); + + QColor highlightedGradientStartColor = option->palette.button().color().lighter(101); + QColor highlightedGradientStopColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 85); + + QColor lightShadowGradientStartColor = highlightedGradientStartColor.lighter(105); + QColor lightShadowGradientStopColor = highlightedGradientStopColor.lighter(105); + + QColor highlightedDarkInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 35); + QColor highlightedLightInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 58); + + QColor alphaInnerColor = mergedColors(highlightedDarkInnerBorderColor, option->palette.base().color()); + QColor lightShadow = lightShadowGradientStartColor; + QColor shadow = shadowGradientStartColor; + + switch (element) { +#ifndef QT_NO_TABBAR + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { + + if (tab->shape != QTabBar::RoundedNorth && tab->shape != QTabBar::RoundedWest && + tab->shape != QTabBar::RoundedSouth && tab->shape != QTabBar::RoundedEast) { + QWindowsStyle::drawControl(element, option, painter, widget); + break; + } + + painter->save(); + + // Set up some convenience variables + bool disabled = !(tab->state & State_Enabled); + bool onlyTab = tab->position == QStyleOptionTab::OnlyOneTab; + bool selected = tab->state & State_Selected; + bool mouseOver = (tab->state & State_MouseOver) && !selected && !disabled; + bool previousSelected = tab->selectedPosition == QStyleOptionTab::PreviousIsSelected; + bool nextSelected = tab->selectedPosition == QStyleOptionTab::NextIsSelected; + bool leftCornerWidget = (tab->cornerWidgets & QStyleOptionTab::LeftCornerWidget); + bool reverse = (tab->direction == Qt::RightToLeft); + + int lowerTop = selected ? 0 : 3; // to make the selected tab bigger than the rest + bool atEnd = (tab->position == QStyleOptionTab::End) || onlyTab; + bool atBeginning = ((tab->position == QStyleOptionTab::Beginning) || onlyTab) + && !leftCornerWidget; + bool reverseShadow = false; + + int borderThickness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget); + int marginLeft = 0; + if ((atBeginning && !selected) || (selected && leftCornerWidget && ((tab->position == QStyleOptionTab::Beginning) || onlyTab))) { + marginLeft = 1; + } + + // I've set the names based on the natural coordinate system. Vectors are used to rotate everything + // if the orientation of the tab bare is different than north. + { + // Coordinates of corners of rectangle for transformation + QPoint topLeft; + QPoint topRight; + QPoint bottomLeft; + QPoint bottomRight; + + // Fill with normalized vectors in the direction of the coordinate system + // (down and right should be complement of up and left, or it will look odd) + QPoint vectorUp; + QPoint vectorDown; + QPoint vectorLeft; + QPoint vectorRight; + + QBrush border = option->palette.shadow(); + qBrushSetAlphaF(&border, qreal(0.4)); + QBrush innerTopLeft = option->palette.shadow(); + qBrushSetAlphaF(&innerTopLeft, qreal(0.075)); + QBrush innerBottomRight = option->palette.shadow(); + qBrushSetAlphaF(&innerBottomRight, qreal(0.23)); + QBrush corner = option->palette.shadow(); + qBrushSetAlphaF(&corner, qreal(0.25)); + + QBrush baseColor1; + QBrush baseColor2; + + switch (tab->shape) { + case QTabBar::RoundedNorth: + vectorUp = QPoint(0, -1); + vectorDown = QPoint(0, 1); + + if (reverse) { + vectorLeft = QPoint(1, 0); + vectorRight = QPoint(-1, 0); + reverseShadow = true; + } else { + vectorLeft = QPoint(-1, 0); + vectorRight = QPoint(1, 0); + } + + if (reverse) { + topLeft = tab->rect.topRight(); + topRight = tab->rect.topLeft(); + bottomLeft = tab->rect.bottomRight(); + bottomRight = tab->rect.bottomLeft(); + } else { + topLeft = tab->rect.topLeft(); + topRight = tab->rect.topRight(); + bottomLeft = tab->rect.bottomLeft(); + bottomRight = tab->rect.bottomRight(); + } + + + baseColor1 = border; + baseColor2 = innerTopLeft; + break ; + case QTabBar::RoundedWest: + vectorUp = QPoint(-1, 0); + vectorDown = QPoint(1, 0); + vectorLeft = QPoint(0, -1); + vectorRight = QPoint(0, 1); + + topLeft = tab->rect.topLeft(); + topRight = tab->rect.bottomLeft(); + bottomLeft = tab->rect.topRight(); + bottomRight = tab->rect.bottomRight(); + + baseColor1 = border; + baseColor2 = innerTopLeft; + break ; + case QTabBar::RoundedEast: + vectorUp = QPoint(1, 0); + vectorDown = QPoint(-1, 0); + vectorLeft = QPoint(0, -1); + vectorRight = QPoint(0, 1); + + topLeft = tab->rect.topRight(); + topRight = tab->rect.bottomRight(); + bottomLeft = tab->rect.topLeft(); + bottomRight = tab->rect.bottomLeft(); + + baseColor1 = border; + baseColor2 = innerBottomRight; + break ; + case QTabBar::RoundedSouth: + vectorUp = QPoint(0, 1); + vectorDown = QPoint(0, -1); + + if (reverse) { + vectorLeft = QPoint(1, 0); + vectorRight = QPoint(-1, 0); + reverseShadow = true; + + topLeft = tab->rect.bottomRight(); + topRight = tab->rect.bottomLeft(); + bottomLeft = tab->rect.topRight(); + bottomRight = tab->rect.topLeft(); + } else { + vectorLeft = QPoint(-1, 0); + vectorRight = QPoint(1, 0); + + topLeft = tab->rect.bottomLeft(); + topRight = tab->rect.bottomRight(); + bottomLeft = tab->rect.topLeft(); + bottomRight = tab->rect.topRight(); + } + + baseColor1 = border; + baseColor2 = innerBottomRight; + break ; + default: + break; + } + + // Make the tab smaller when it's at the end, so that we are able to draw the corner + if (atEnd) { + topRight += vectorLeft; + bottomRight += vectorLeft; + } + + { + // Outer border + QLine topLine; + { + QPoint adjustTopLineLeft = (vectorRight * (marginLeft + (previousSelected ? 0 : 1))) + + (vectorDown * lowerTop); + QPoint adjustTopLineRight = (vectorDown * lowerTop); + if (atBeginning || selected) + adjustTopLineLeft += vectorRight; + if (atEnd || selected) + adjustTopLineRight += 2 * vectorLeft; + + topLine = QLine(topLeft + adjustTopLineLeft, topRight + adjustTopLineRight); + } + + QLine leftLine; + { + QPoint adjustLeftLineTop = (vectorRight * marginLeft) + (vectorDown * (lowerTop + 1)); + QPoint adjustLeftLineBottom = (vectorRight * marginLeft) + (vectorUp * borderThickness); + if (atBeginning || selected) + adjustLeftLineTop += vectorDown; // Make place for rounded corner + if (atBeginning && selected) + adjustLeftLineBottom += borderThickness * vectorDown; + else if (selected) + adjustLeftLineBottom += vectorUp; + + leftLine = QLine(topLeft + adjustLeftLineTop, bottomLeft + adjustLeftLineBottom); + } + + QLine rightLine; + { + QPoint adjustRightLineTop = vectorDown * (2 + lowerTop); + QPoint adjustRightLineBottom = vectorUp * borderThickness; + if (selected) + adjustRightLineBottom += vectorUp; + + rightLine = QLine(topRight + adjustRightLineTop, bottomRight + adjustRightLineBottom); + } + + // Background + QPoint startPoint = topLine.p1() + vectorDown + vectorLeft; + if (mouseOver) + startPoint += vectorDown; + QPoint endPoint = rightLine.p2(); + + if (tab->state & State_Enabled) { + QRect fillRect = QRect(startPoint, endPoint).normalized(); + if (fillRect.isValid()) { + if (selected) { + fillRect = QRect(startPoint, endPoint + vectorLeft + vectorDown * 3).normalized(); + painter->fillRect(fillRect, option->palette.window()); + + // Connect to the base + painter->setPen(QPen(option->palette.window(), 0)); + QVarLengthArray points; + points.append(rightLine.p2() + vectorDown); + points.append(rightLine.p2() + vectorDown + vectorDown); + points.append(rightLine.p2() + vectorDown + vectorDown + vectorRight); + if (tab->position != QStyleOptionTab::Beginning) { + points.append(leftLine.p2() + vectorDown); + points.append(leftLine.p2() + vectorDown + vectorDown); + points.append(leftLine.p2() + vectorDown + vectorDown + vectorLeft); + } + painter->drawPoints(points.constData(), points.size()); + } else { + QBrush buttonGradientBrush; + QBrush buttonBrush = qMapBrushToRect(option->palette.button(), fillRect); + if (buttonBrush.gradient() || !buttonBrush.texture().isNull()) { + buttonGradientBrush = buttonBrush; + } else { + // Generate gradients + QLinearGradient buttonGradient(fillRect.topLeft(), fillRect.bottomLeft()); + buttonGradient.setColorAt(0.0, buttonBrush.color().lighter(104)); + buttonGradient.setColorAt(1.0, buttonBrush.color().darker(110)); + buttonGradientBrush = QBrush(buttonGradient); + } + + painter->fillRect(fillRect, buttonGradientBrush); + } + } + } + + QPoint rightCornerDot = topRight + vectorLeft + (lowerTop + 1)*vectorDown; + QPoint leftCornerDot = topLeft + (marginLeft + 1)*vectorRight + (lowerTop + 1)*vectorDown; + QPoint bottomRightConnectToBase = rightLine.p2() + vectorRight + vectorDown; + QPoint bottomLeftConnectToBase = leftLine.p2() + vectorLeft + vectorDown; + + painter->setPen(QPen(border, 0)); + + QVarLengthArray lines; + QVarLengthArray points; + + lines.append(topLine); + + if (mouseOver) { + painter->drawLines(lines.constData(), lines.count()); + lines.clear(); + + QLine secondHoverLine = QLine(topLine.p1() + vectorDown * 2 + vectorLeft, topLine.p2() + vectorDown * 2 + vectorRight); + painter->setPen(highlightedLightInnerBorderColor); + painter->drawLine(secondHoverLine); + } + + if (mouseOver) + painter->setPen(QPen(border, 0)); + + if (!previousSelected) + lines.append(leftLine); + if (atEnd || selected) { + lines.append(rightLine); + points.append(rightCornerDot); + } + if (atBeginning || selected) + points.append(leftCornerDot); + if (selected) { + points.append(bottomRightConnectToBase); + points.append(bottomLeftConnectToBase); + } + if (lines.size() > 0) { + painter->drawLines(lines.constData(), lines.size()); + lines.clear(); + } + if (points.size() > 0) { + painter->drawPoints(points.constData(), points.size()); + points.clear(); + } + + // Antialiasing + painter->setPen(QPen(corner, 0)); + if (atBeginning || selected) + points.append(topLine.p1() + vectorLeft); + if (!previousSelected) + points.append(leftLine.p1() + vectorUp); + if (atEnd || selected) { + points.append(topLine.p2() + vectorRight); + points.append(rightLine.p1() + vectorUp); + } + + if (selected) { + points.append(bottomRightConnectToBase + vectorLeft); + if (!atBeginning) { + points.append(bottomLeftConnectToBase + vectorRight); + + if (((tab->position == QStyleOptionTab::Beginning) || onlyTab) && leftCornerWidget) { + // A special case: When the first tab is selected and + // has a left corner widget, it needs to do more work + // to connect to the base + QPoint p1 = bottomLeftConnectToBase + vectorDown; + + points.append(p1); + } + } + } + if (points.size() > 0) { + painter->drawPoints(points.constData(), points.size()); + points.clear(); + } + + // Inner border + QLine innerTopLine = QLine(topLine.p1() + vectorDown, topLine.p2() + vectorDown); + if (!selected) { + QLinearGradient topLineGradient(innerTopLine.p1(),innerTopLine.p2()); + topLineGradient.setColorAt(0, lightShadowGradientStartColor); + topLineGradient.setColorAt(1, lightShadowGradientStopColor); + painter->setPen(QPen(mouseOver ? QBrush(highlightedDarkInnerBorderColor) : QBrush(topLineGradient), 1)); + } else { + painter->setPen(QPen(innerTopLeft, 0)); + } + painter->drawLine(innerTopLine); + + QLine innerLeftLine = QLine(leftLine.p1() + vectorRight + vectorDown, leftLine.p2() + vectorRight); + QLine innerRightLine = QLine(rightLine.p1() + vectorLeft + vectorDown, rightLine.p2() + vectorLeft); + + if (selected) { + innerRightLine = QLine(innerRightLine.p1() + vectorUp, innerRightLine.p2()); + innerLeftLine = QLine(innerLeftLine.p1() + vectorUp, innerLeftLine.p2()); + } + + if (selected || atBeginning) { + QBrush leftLineGradientBrush; + QRect rect = QRect(innerLeftLine.p1(), innerLeftLine.p2()).normalized(); + QBrush buttonBrush = qMapBrushToRect(option->palette.button(), rect); + if (buttonBrush.gradient() || !buttonBrush.texture().isNull()) { + leftLineGradientBrush = qBrushLight(buttonBrush, 105); + } else { + QLinearGradient buttonGradient3(rect.topLeft(), rect.bottomLeft()); + buttonGradient3.setColorAt(0.0, buttonBrush.color().lighter(105)); + buttonGradient3.setColorAt(1.0, buttonBrush.color()); + leftLineGradientBrush = QBrush(buttonGradient3); + } + + if (!selected) + painter->setPen(QPen(leftLineGradientBrush, 0)); + + // Assume the sun is on the same side in Right-To-Left layouts and draw the + // light shadow on the left side always (the right line is on the left side in + // reverse layouts for north and south) + if (reverseShadow) + painter->drawLine(innerRightLine); + else + painter->drawLine(innerLeftLine); + } + + if (atEnd || selected) { + if (!selected) { + QBrush rightLineGradientBrush; + QRect rect = QRect(innerRightLine.p1(), innerRightLine.p2()).normalized(); + QBrush buttonBrush = qMapBrushToRect(option->palette.button(), rect); + if (buttonBrush.gradient() || !buttonBrush.texture().isNull()) { + rightLineGradientBrush = qBrushDark(buttonBrush, 105); + } else { + QLinearGradient buttonGradient4(rect.topLeft(), rect.bottomLeft()); + buttonGradient4.setColorAt(0.0, buttonBrush.color()); + buttonGradient4.setColorAt(1.0, buttonBrush.color().darker(110)); + rightLineGradientBrush = QBrush(buttonGradient4); + } + + painter->setPen(QPen(rightLineGradientBrush, 0)); + } else { + painter->setPen(QPen(innerBottomRight, 0)); + } + + if (reverseShadow) + painter->drawLine(innerLeftLine); + else + painter->drawLine(innerRightLine); + } + + + // Base + QLine baseLine = QLine(bottomLeft + marginLeft * 2 * vectorRight, bottomRight); + { + + QPoint adjustedLeft; + QPoint adjustedRight; + + if (atEnd && !selected) { + baseLine = QLine(baseLine.p1(), baseLine.p2() + vectorRight); + } + + if (nextSelected) { + adjustedRight += vectorLeft; + baseLine = QLine(baseLine.p1(), baseLine.p2() + vectorLeft); + } + if (previousSelected) { + adjustedLeft += vectorRight; + baseLine = QLine(baseLine.p1() + vectorRight, baseLine.p2()); + } + if (atBeginning) + adjustedLeft += vectorRight; + + painter->setPen(QPen(baseColor2, 0)); + if (!selected) + painter->drawLine(baseLine); + + if (atEnd && !selected) + painter->drawPoint(baseLine.p2() + vectorRight); + + if (atBeginning && !selected) + adjustedLeft = vectorRight; + else + adjustedLeft = QPoint(0, 0); + painter->setPen(QPen(baseColor1, 0)); + if (!selected) + painter->drawLine(bottomLeft + vectorUp + adjustedLeft, baseLine.p2() + vectorUp); + + QPoint endPoint = bottomRight + vectorUp; + if (atEnd && !selected) + painter->drawPoint(endPoint); + + // For drawing a lower left "fake" corner on the base when the first tab is unselected + if (atBeginning && !selected) { + painter->drawPoint(baseLine.p1() + vectorLeft); + } + + painter->setPen(QPen(corner, 0)); + if (nextSelected) + painter->drawPoint(endPoint); + else if (selected) + painter->drawPoint(endPoint + vectorRight); + + // For drawing a lower left "fake" corner on the base when the first tab is unselected + if (atBeginning && !selected) { + painter->drawPoint(baseLine.p1() + 2 * vectorLeft); + } + } + } + } + + // Yay we're done + + painter->restore(); + } + break; +#endif // QT_NO_TABBAR +#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBarGroove: + if (const QStyleOptionProgressBar *bar = qstyleoption_cast(option)) { + QRect rect = bar->rect; + QPen oldPen = painter->pen(); + + QLine lines[4]; + + // outline + painter->setPen(borderColor); + lines[0] = QLine(rect.left() + 2, rect.top(), rect.right() - 2, rect.top()); + lines[1] = QLine(rect.left() + 2, rect.bottom(), rect.right() - 2, rect.bottom()); + lines[2] = QLine(rect.left(), rect.top() + 2, rect.left(), rect.bottom() - 2); + lines[3] = QLine(rect.right(), rect.top() + 2, rect.right(), rect.bottom() - 2); + painter->drawLines(lines, 4); + + QPoint points[8]; + points[0] = QPoint(rect.left() + 1, rect.top() + 1); + points[1] = QPoint(rect.right() - 1, rect.top() + 1); + points[2] = QPoint(rect.left() + 1, rect.bottom() - 1); + points[3] = QPoint(rect.right() - 1, rect.bottom() - 1); + painter->drawPoints(points, 4); + + // alpha corners + painter->setPen(alphaCornerColor); + points[0] = QPoint(rect.left(), rect.top() + 1); + points[1] = QPoint(rect.left() + 1, rect.top()); + points[2] = QPoint(rect.right(), rect.top() + 1); + points[3] = QPoint(rect.right() - 1, rect.top()); + points[4] = QPoint(rect.left(), rect.bottom() - 1); + points[5] = QPoint(rect.left() + 1, rect.bottom()); + points[6] = QPoint(rect.right(), rect.bottom() - 1); + points[7] = QPoint(rect.right() - 1, rect.bottom()); + painter->drawPoints(points, 8); + + // inner outline, north-west + painter->setPen(gradientStartColor.darker(105)); + lines[0] = QLine(rect.left() + 2, rect.top() + 1, rect.right() - 2, rect.top() + 1); + lines[1] = QLine(rect.left() + 1, rect.top() + 2, rect.left() + 1, rect.bottom() - 2); + painter->drawLines(lines, 2); + + // base of the groove + painter->setPen(QPen()); + painter->fillRect(rect.adjusted(2, 2, -2, -1), QBrush(bar->palette.base().color())); + painter->setPen(bar->palette.base().color()); + painter->drawLine(rect.right() - 1, rect.top() + 2, rect.right() - 1, rect.bottom() - 2); + + painter->setPen(oldPen); + } + break; + case CE_ProgressBarLabel: + if (const QStyleOptionProgressBar *bar = qstyleoption_cast(option)) { + // The busy indicator doesn't draw a label + if (bar->minimum == 0 && bar->maximum == 0) + return; + + painter->save(); + + QRect rect = bar->rect; + QRect leftRect; + + QFont font; + font.setBold(true); + painter->setFont(font); + painter->setPen(bar->palette.text().color()); + + bool vertical = false; + bool inverted = false; + bool bottomToTop = false; + // Get extra style options if version 2 + if (const QStyleOptionProgressBarV2 *bar2 = qstyleoption_cast(option)) { + vertical = (bar2->orientation == Qt::Vertical); + inverted = bar2->invertedAppearance; + bottomToTop = bar2->bottomToTop; + } + + if (vertical) { + rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height + QTransform m; + if (bottomToTop) { + m.translate(0.0, rect.width()); + m.rotate(-90); + } else { + m.translate(rect.height(), 0.0); + m.rotate(90); + } + painter->setTransform(m, true); + } + + int progressIndicatorPos = (bar->progress - qreal(bar->minimum)) / qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum) * rect.width(); + + bool flip = (!vertical && (((bar->direction == Qt::RightToLeft) && !inverted) + || ((bar->direction == Qt::LeftToRight) && inverted))) || (vertical && ((!inverted && !bottomToTop) || (inverted && bottomToTop))); + if (flip) { + int indicatorPos = rect.width() - progressIndicatorPos; + if (indicatorPos >= 0 && indicatorPos <= rect.width()) { + painter->setPen(bar->palette.base().color()); + leftRect = QRect(rect.left(), rect.top(), indicatorPos, rect.height()); + } else if (indicatorPos > rect.width()) { + painter->setPen(bar->palette.text().color()); + } else { + painter->setPen(bar->palette.base().color()); + } + } else { + if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width()) { + leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height()); + } else if (progressIndicatorPos > rect.width()) { + painter->setPen(bar->palette.base().color()); + } else { + painter->setPen(bar->palette.text().color()); + } + } + + QRegion rightRect = rect; + rightRect = rightRect.subtracted(leftRect); + painter->setClipRegion(rightRect); + painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); + if (!leftRect.isNull()) { + painter->setPen(flip ? bar->palette.text().color() : bar->palette.base().color()); + painter->setClipRect(leftRect); + painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); + } + + painter->restore(); + } + break; + case CE_ProgressBarContents: + if (const QStyleOptionProgressBar *bar = qstyleoption_cast(option)) { + Q_D(const QPlastiqueStyle); + QRect rect = bar->rect; + bool vertical = false; + bool inverted = false; + bool indeterminate = (bar->minimum == 0 && bar->maximum == 0); + if (!indeterminate && bar->progress == -1) + break; + + painter->save(); + + // Get extra style options if version 2 + if (const QStyleOptionProgressBarV2 *bar2 = qstyleoption_cast(option)) { + vertical = (bar2->orientation == Qt::Vertical); + inverted = bar2->invertedAppearance; + } + + // If the orientation is vertical, we use a transform to rotate + // the progress bar 90 degrees clockwise. This way we can use the + // same rendering code for both orientations. + if (vertical) { + rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height + QTransform m = QTransform::fromTranslate(rect.height()-1, 0); + m.rotate(90.0); + painter->setTransform(m, true); + } + + int maxWidth = rect.width() - 4; + int minWidth = 4; + qint64 progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar + double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxWidth); + int width = indeterminate ? maxWidth : qMax(int(vc6_workaround), minWidth); + bool reverse = (!vertical && (bar->direction == Qt::RightToLeft)) || vertical; + if (inverted) + reverse = !reverse; + + QRect progressBar; + if (!indeterminate) { + if (!reverse) { + progressBar.setRect(rect.left() + 2, rect.top() + 2, width, rect.height() - 4); + } else { + progressBar.setRect(rect.right() - 1 - width, rect.top() + 2, width, rect.height() - 4); + } + } else { + int slideWidth = ((rect.width() - 4) * 2) / 3; + int step = ((d->animateStep * slideWidth) / ProgressBarFps) % slideWidth; + if ((((d->animateStep * slideWidth) / ProgressBarFps) % (2 * slideWidth)) >= slideWidth) + step = slideWidth - step; + progressBar.setRect(rect.left() + 2 + step, rect.top() + 2, + slideWidth / 2, rect.height() - 4); + } + + // outline + painter->setPen(highlightedDarkInnerBorderColor); + + QVarLengthArray lines; + QVarLengthArray points; + if (!reverse) { + if (width == minWidth) { + points.append(QPoint(progressBar.left() + 1, progressBar.top())); + points.append(QPoint(progressBar.left() + 1, progressBar.bottom())); + } else { + if (indeterminate) { + lines.append(QLine(progressBar.left() + 2, progressBar.top(), + progressBar.right() - 2, progressBar.top())); + lines.append(QLine(progressBar.left() + 2, progressBar.bottom(), + progressBar.right() - 2, progressBar.bottom())); + } else { + lines.append(QLine(progressBar.left() + 1, progressBar.top(), + progressBar.right() - 2, progressBar.top())); + lines.append(QLine(progressBar.left() + 1, progressBar.bottom(), + progressBar.right() - 2, progressBar.bottom())); + } + } + + if (indeterminate) { + lines.append(QLine(progressBar.left(), progressBar.top() + 2, + progressBar.left(), progressBar.bottom() - 2)); + } else { + lines.append(QLine(progressBar.left(), progressBar.top() + 1, + progressBar.left(), progressBar.bottom() - 1)); + } + lines.append(QLine(progressBar.right(), progressBar.top() + 2, + progressBar.right(), progressBar.bottom() - 2)); + } else { + if (width == minWidth) { + points.append(QPoint(progressBar.right() - 1, progressBar.top())); + points.append(QPoint(progressBar.right() - 1, progressBar.bottom())); + } else { + if (indeterminate) { + lines.append(QLine(progressBar.right() - 2, progressBar.top(), + progressBar.left() + 2, progressBar.top())); + lines.append(QLine(progressBar.right() - 2, progressBar.bottom(), + progressBar.left() + 2, progressBar.bottom())); + } else { + lines.append(QLine(progressBar.right() - 1, progressBar.top(), + progressBar.left() + 2, progressBar.top())); + lines.append(QLine(progressBar.right() - 1, progressBar.bottom(), + progressBar.left() + 2, progressBar.bottom())); + } + } + if (indeterminate) { + lines.append(QLine(progressBar.right(), progressBar.top() + 2, + progressBar.right(), progressBar.bottom() - 2)); + } else { + lines.append(QLine(progressBar.right(), progressBar.top() + 1, + progressBar.right(), progressBar.bottom() - 1)); + } + lines.append(QLine(progressBar.left(), progressBar.top() + 2, + progressBar.left(), progressBar.bottom() - 2)); + } + + if (points.size() > 0) { + painter->drawPoints(points.constData(), points.size()); + points.clear(); + } + painter->drawLines(lines.constData(), lines.size()); + lines.clear(); + + // alpha corners + painter->setPen(alphaInnerColor); + if (!reverse) { + if (indeterminate) { + points.append(QPoint(progressBar.left() + 1, progressBar.top())); + points.append(QPoint(progressBar.left(), progressBar.top() + 1)); + points.append(QPoint(progressBar.left() + 1, progressBar.bottom())); + points.append(QPoint(progressBar.left(), progressBar.bottom() - 1)); + } else { + points.append(QPoint(progressBar.left(), progressBar.top())); + points.append(QPoint(progressBar.left(), progressBar.bottom())); + } + points.append(QPoint(progressBar.right() - 1, progressBar.top())); + points.append(QPoint(progressBar.right(), progressBar.top() + 1)); + points.append(QPoint(progressBar.right() - 1, progressBar.bottom())); + points.append(QPoint(progressBar.right(), progressBar.bottom() - 1)); + } else { + if (indeterminate) { + points.append(QPoint(progressBar.right() - 1, progressBar.top())); + points.append(QPoint(progressBar.right(), progressBar.top() + 1)); + points.append(QPoint(progressBar.right() - 1, progressBar.bottom())); + points.append(QPoint(progressBar.right(), progressBar.bottom() - 1)); + } else { + points.append(QPoint(progressBar.right(), progressBar.top())); + points.append(QPoint(progressBar.right(), progressBar.bottom())); + } + points.append(QPoint(progressBar.left() + 1, progressBar.top())); + points.append(QPoint(progressBar.left(), progressBar.top() + 1)); + points.append(QPoint(progressBar.left() + 1, progressBar.bottom())); + points.append(QPoint(progressBar.left(), progressBar.bottom() - 1)); + } + + painter->drawPoints(points.constData(), points.size()); + points.clear(); + + // contents + painter->setPen(QPen()); + + QString progressBarName = QStyleHelper::uniqueName(QLatin1String("progressBarContents"), + option, rect.size()); + QPixmap cache; + if (!QPixmapCache::find(progressBarName, cache) && rect.height() > 7) { + QSize size = rect.size(); + cache = QPixmap(QSize(size.width() - 6 + 30, size.height() - 6)); + cache.fill(Qt::white); + QPainter cachePainter(&cache); + QRect pixmapRect(0, 0, cache.width(), cache.height()); + + int leftEdge = 0; + bool flip = false; + while (leftEdge < cache.width() + 1) { + QColor rectColor = option->palette.highlight().color(); + QColor lineColor = option->palette.highlight().color(); + if (flip) { + flip = false; + rectColor = rectColor.lighter(105); + lineColor = lineColor.lighter(105); + } else { + flip = true; + } + + cachePainter.setPen(lineColor); + const QLine cacheLines[2] = { + QLine(pixmapRect.left() + leftEdge - 1, pixmapRect.top(), + pixmapRect.left() + leftEdge + 9, pixmapRect.top()), + QLine(pixmapRect.left() + leftEdge - 1, pixmapRect.bottom(), + pixmapRect.left() + leftEdge + 9, pixmapRect.bottom()) }; + cachePainter.drawLines(cacheLines, 2); + cachePainter.fillRect(QRect(pixmapRect.left() + leftEdge, pixmapRect.top(), + 10, pixmapRect.height()), rectColor); + + leftEdge += 10; + } + + QPixmapCache::insert(progressBarName, cache); + } + painter->setClipRect(progressBar.adjusted(1, 0, -1, -1)); + + if (!vertical) + progressBar.adjust(0, 1, 0, 1); + if (!indeterminate) { + int step = (AnimateProgressBar || (indeterminate && AnimateBusyProgressBar)) ? (d->animateStep % 20) : 0; + if (reverse) + painter->drawPixmap(progressBar.left() - 25 + step, progressBar.top(), cache); + else + painter->drawPixmap(progressBar.left() - 25 - step + width % 20, progressBar.top(), cache); + } else { + painter->drawPixmap(progressBar.left(), progressBar.top(), cache); + } + + painter->restore(); + } + break; +#endif // QT_NO_PROGRESSBAR + case CE_HeaderSection: + // Draws the header in tables. + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + QPixmap cache; + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("headersection"), option, option->rect.size()); + pixmapName += QString::number(- int(header->position)); + pixmapName += QString::number(- int(header->orientation)); + + if (!QPixmapCache::find(pixmapName, cache)) { + cache = QPixmap(option->rect.size()); + cache.fill(Qt::white); + QRect pixmapRect(0, 0, option->rect.width(), option->rect.height()); + QPainter cachePainter(&cache); + + bool sunken = (header->state & State_Enabled) && (header->state & State_Sunken); + + QColor headerGradientStart = sunken ? option->palette.background().color().darker(114) : gradientStartColor; + QColor headerGradientStop = sunken ? option->palette.background().color().darker(106) : gradientStopColor; + + QColor lightLine = sunken ? option->palette.background().color().darker(118) : gradientStartColor; + QColor darkLine = sunken ? option->palette.background().color().darker(110) : gradientStopColor.darker(105); + + qt_plastique_draw_gradient(&cachePainter, pixmapRect, + headerGradientStart, headerGradientStop); + + cachePainter.setPen(borderColor); + cachePainter.drawRect(pixmapRect.adjusted(0, 0, -1, -1)); + cachePainter.setPen(alphaCornerColor); + + const QPoint points[4] = { + pixmapRect.topLeft(), pixmapRect.topRight(), + pixmapRect.bottomLeft(), pixmapRect.bottomRight() }; + cachePainter.drawPoints(points, 4); + + QLine lines[2]; + + // inner lines + cachePainter.setPen(lightLine); + lines[0] = QLine(pixmapRect.left() + 2, pixmapRect.top() + 1, + pixmapRect.right() - 2, pixmapRect.top() + 1); + lines[1] = QLine(pixmapRect.left() + 1, pixmapRect.top() + 2, + pixmapRect.left() + 1, pixmapRect.bottom() - 2); + cachePainter.drawLines(lines, 2); + + cachePainter.setPen(darkLine); + lines[0] = QLine(pixmapRect.left() + 2, pixmapRect.bottom() - 1, + pixmapRect.right() - 2, pixmapRect.bottom() - 1); + lines[1] = QLine(pixmapRect.right() - 1, pixmapRect.bottom() - 2, + pixmapRect.right() - 1, pixmapRect.top() + 2); + cachePainter.drawLines(lines, 2); + + cachePainter.end(); + QPixmapCache::insert(pixmapName, cache); + } + painter->drawPixmap(option->rect.topLeft(), cache); + + } + break; +#ifndef QT_NO_MENU + case CE_MenuItem: + // Draws one item in a popup menu. + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast(option)) { + painter->save(); + QBrush textBrush; + if (option->palette.resolve() & (1 << QPalette::ButtonText)) + textBrush = option->palette.buttonText(); + else + textBrush = option->palette.windowText(); // KDE uses windowText rather than buttonText for menus + + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + painter->fillRect(menuItem->rect, option->palette.background().color().lighter(103)); + + int w = 0; + if (!menuItem->text.isEmpty()) { + painter->setFont(menuItem->font); + proxy()->drawItemText(painter, menuItem->rect.adjusted(5, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter, + menuItem->palette, menuItem->state & State_Enabled, menuItem->text, + QPalette::Text); + w = menuItem->fontMetrics.width(menuItem->text) + 5; + } + + painter->setPen(alphaCornerColor); + bool reverse = menuItem->direction == Qt::RightToLeft; + painter->drawLine(menuItem->rect.left() + 5 + (reverse ? 0 : w), menuItem->rect.center().y(), + menuItem->rect.right() - 5 - (reverse ? w : 0), menuItem->rect.center().y()); + + painter->restore(); + break; + } + + bool selected = menuItem->state & State_Selected; + bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable; + bool checked = menuItem->checked; + + if (selected) { + qt_plastique_draw_gradient(painter, menuItem->rect, + option->palette.highlight().color().lighter(105), + option->palette.highlight().color().darker(110)); + + painter->setPen(option->palette.highlight().color().lighter(110)); + painter->drawLine(option->rect.topLeft(), option->rect.topRight()); + painter->setPen(option->palette.highlight().color().darker(115)); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + } else { + painter->fillRect(option->rect, option->palette.background().color().lighter(103)); + } + + // Check + QRect checkRect(option->rect.left() + 7, option->rect.center().y() - 6, 13, 13); + checkRect = visualRect(menuItem->direction, menuItem->rect, checkRect); + if (checkable) { + if ((menuItem->checkType & QStyleOptionMenuItem::Exclusive) && menuItem->icon.isNull()) { + QStyleOptionButton button; + button.rect = checkRect; + button.state = menuItem->state; + if (checked) + button.state |= State_On; + button.palette = menuItem->palette; + proxy()->drawPrimitive(PE_IndicatorRadioButton, &button, painter, widget); + } else { + if (menuItem->icon.isNull()) { + QStyleOptionButton button; + button.rect = checkRect; + button.state = menuItem->state; + if (checked) + button.state |= State_On; + button.palette = menuItem->palette; + proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget); + } else if (checked) { + int iconSize = qMax(menuItem->maxIconWidth, 20); + QRect sunkenRect(option->rect.left() + 1, + option->rect.top() + (option->rect.height() - iconSize) / 2 + 1, + iconSize, iconSize); + sunkenRect = visualRect(menuItem->direction, menuItem->rect, sunkenRect); + + QStyleOption opt = *option; + opt.state |= State_Sunken; + opt.rect = sunkenRect; + qt_plastique_drawShadedPanel(painter, &opt, false, widget); + } + } + } + + // Text and icon, ripped from windows style + bool dis = !(menuItem->state & State_Enabled); + bool act = menuItem->state & State_Selected; + const QStyleOption *opt = option; + const QStyleOptionMenuItem *menuitem = menuItem; + int checkcol = qMax(menuitem->maxIconWidth, 20); + QPainter *p = painter; + QRect vCheckRect = visualRect(opt->direction, menuitem->rect, + QRect(menuitem->rect.x(), menuitem->rect.y(), + checkcol, menuitem->rect.height())); + if (!menuItem->icon.isNull()) { + QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; + if (act && !dis) + mode = QIcon::Active; + QPixmap pixmap; + if (checked) + pixmap = menuItem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On); + else + pixmap = menuItem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + + QRect pmr(0, 0, pixw, pixh); + pmr.moveCenter(vCheckRect.center()); + painter->setPen(textBrush.color()); + if (checkable && checked) + painter->drawPixmap(QPoint(pmr.left() + 1, pmr.top() + 1), pixmap); + else + painter->drawPixmap(pmr.topLeft(), pixmap); + } + + if (selected) { + painter->setPen(menuItem->palette.highlightedText().color()); + } else { + painter->setPen(textBrush.color()); + } + int x, y, w, h; + menuitem->rect.getRect(&x, &y, &w, &h); + int tab = menuitem->tabWidth; + QColor discol; + if (dis) { + discol = textBrush.color(); + p->setPen(discol); + } + int xm = windowsItemFrame + checkcol + windowsItemHMargin; + int xpos = menuitem->rect.x() + xm; + QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); + QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect); + QString s = menuitem->text; + if (!s.isEmpty()) { // draw text + p->save(); + int t = s.indexOf(QLatin1Char('\t')); + int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!styleHint(SH_UnderlineShortcut, menuitem, widget)) + text_flags |= Qt::TextHideMnemonic; + text_flags |= Qt::AlignLeft; + if (t >= 0) { + QRect vShortcutRect = visualRect(opt->direction, menuitem->rect, + QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom()))); + if (dis && !act && styleHint(SH_EtchDisabledText, option, widget)) { + p->setPen(menuitem->palette.light().color()); + p->drawText(vShortcutRect.adjusted(1,1,1,1), text_flags, s.mid(t + 1)); + p->setPen(discol); + } + p->drawText(vShortcutRect, text_flags, s.mid(t + 1)); + s = s.left(t); + } + QFont font = menuitem->font; + if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) + font.setBold(true); + p->setFont(font); + if (dis && !act && styleHint(SH_EtchDisabledText, option, widget)) { + p->setPen(menuitem->palette.light().color()); + p->drawText(vTextRect.adjusted(1,1,1,1), text_flags, s.left(t)); + p->setPen(discol); + } + p->drawText(vTextRect, text_flags, s.left(t)); + p->restore(); + } + + // Arrow + if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow + int dim = (menuItem->rect.height() - 4) / 2; + PrimitiveElement arrow; + arrow = (opt->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; + int xpos = menuItem->rect.left() + menuItem->rect.width() - 6 - 2 - dim; + QRect vSubMenuRect = visualRect(option->direction, menuItem->rect, + QRect(xpos, menuItem->rect.top() + menuItem->rect.height() / 2 - dim / 2, dim, dim)); + QStyleOptionMenuItem newMI = *menuItem; + newMI.rect = vSubMenuRect; + newMI.state = option->state & State_Enabled; + if (selected) + newMI.palette.setColor(QPalette::ButtonText, + newMI.palette.highlightedText().color()); + else + newMI.palette.setColor(QPalette::ButtonText, textBrush.color()); + proxy()->drawPrimitive(arrow, &newMI, painter, widget); + } + + painter->restore(); + } + break; +#endif // QT_NO_MENU +#ifndef QT_NO_MENUBAR + case CE_MenuBarItem: + // Draws a menu bar item; File, Edit, Help etc.. + if ((option->state & State_Selected)) { + QPixmap cache; + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("menubaritem"), option, option->rect.size()); + if (!QPixmapCache::find(pixmapName, cache)) { + cache = QPixmap(option->rect.size()); + cache.fill(Qt::white); + QRect pixmapRect(0, 0, option->rect.width(), option->rect.height()); + QPainter cachePainter(&cache); + + QRect rect = pixmapRect; + + // gradient fill + if ((option->state & QStyle::State_Sunken) || (option->state & QStyle::State_On)) { + qt_plastique_draw_gradient(&cachePainter, rect.adjusted(1, 1, -1, -1), + option->palette.button().color().darker(114), + option->palette.button().color().darker(106)); + } else { + qt_plastique_draw_gradient(&cachePainter, rect.adjusted(1, 1, -1, -1), + option->palette.background().color().lighter(105), + option->palette.background().color().darker(102)); + } + + // outer border and corners + cachePainter.setPen(borderColor); + cachePainter.drawRect(rect.adjusted(0, 0, -1, -1)); + cachePainter.setPen(alphaCornerColor); + + const QPoint points[4] = { + rect.topLeft(), + rect.topRight(), + rect.bottomLeft(), + rect.bottomRight() }; + cachePainter.drawPoints(points, 4); + + // inner border + if ((option->state & QStyle::State_Sunken) || (option->state & QStyle::State_On)) + cachePainter.setPen(option->palette.button().color().darker(118)); + else + cachePainter.setPen(gradientStartColor); + + QLine lines[2]; + lines[0] = QLine(rect.left() + 1, rect.top() + 1, rect.right() - 1, rect.top() + 1); + lines[1] = QLine(rect.left() + 1, rect.top() + 2, rect.left() + 1, rect.bottom() - 2); + cachePainter.drawLines(lines, 2); + + if ((option->state & QStyle::State_Sunken) || (option->state & QStyle::State_On)) + cachePainter.setPen(option->palette.button().color().darker(114)); + else + cachePainter.setPen(gradientStopColor.darker(102)); + lines[0] = QLine(rect.left() + 1, rect.bottom() - 1, rect.right() - 1, rect.bottom() - 1); + lines[1] = QLine(rect.right() - 1, rect.top() + 1, rect.right() - 1, rect.bottom() - 2); + cachePainter.drawLines(lines, 2); + cachePainter.end(); + QPixmapCache::insert(pixmapName, cache); + } + painter->drawPixmap(option->rect.topLeft(), cache); + } else { + painter->fillRect(option->rect, option->palette.background()); + } + + if (const QStyleOptionMenuItem *mbi = qstyleoption_cast(option)) { + QStyleOptionMenuItem newMI = *mbi; + if (!(option->palette.resolve() & (1 << QPalette::ButtonText))) //KDE uses windowText rather than buttonText for menus + newMI.palette.setColor(QPalette::ButtonText, newMI.palette.windowText().color()); + QCommonStyle::drawControl(element, &newMI, painter, widget); + } + break; + +#ifndef QT_NO_MAINWINDOW + case CE_MenuBarEmptyArea: + if (widget && qobject_cast(widget->parentWidget())) { + painter->fillRect(option->rect, option->palette.window()); + QPen oldPen = painter->pen(); + painter->setPen(QPen(option->palette.dark().color())); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + painter->setPen(oldPen); + } + break; +#endif // QT_NO_MAINWINDOW + +#endif // QT_NO_MENUBAR + +#ifndef QT_NO_TOOLBOX + case CE_ToolBoxTabShape: + if (const QStyleOptionToolBox *toolBox = qstyleoption_cast(option)) { + painter->save(); + + int width = toolBox->rect.width(); + int diag = toolBox->rect.height() - 2; + + // The essential points + QPoint rightMost; + QPoint rightEdge; + QPoint leftEdge; + QPoint leftMost; + QPoint leftOne; + QPoint rightOne; + QPoint upOne(0, -1); + QPoint downOne(0, 1); + + if (toolBox->direction != Qt::RightToLeft) { + rightMost = QPoint(toolBox->rect.right(), toolBox->rect.bottom() - 2); + rightEdge = QPoint(toolBox->rect.right() - width / 10, toolBox->rect.bottom() - 2); + leftEdge = QPoint(toolBox->rect.right() - width / 10 - diag, toolBox->rect.top()); + leftMost = QPoint(toolBox->rect.left(), toolBox->rect.top()); + leftOne = QPoint(-1, 0); + rightOne = QPoint(1, 0); + } else { + rightMost = QPoint(toolBox->rect.left(), toolBox->rect.bottom() - 2); + rightEdge = QPoint(toolBox->rect.left() + width / 10, toolBox->rect.bottom() - 2); + leftEdge = QPoint(toolBox->rect.left() + width / 10 + diag, toolBox->rect.top()); + leftMost = QPoint(toolBox->rect.right(), toolBox->rect.top()); + leftOne = QPoint(1, 0); + rightOne = QPoint(-1, 0); + } + + QLine lines[3]; + + // Draw the outline + painter->setPen(borderColor); + lines[0] = QLine(rightMost, rightEdge); + lines[1] = QLine(rightEdge + leftOne, leftEdge); + lines[2] = QLine(leftEdge + leftOne, leftMost); + painter->drawLines(lines, 3); + painter->setPen(toolBox->palette.base().color()); + lines[0] = QLine(rightMost + downOne, rightEdge + downOne); + lines[1] = QLine(rightEdge + leftOne + downOne, leftEdge + downOne); + lines[2] = QLine(leftEdge + leftOne + downOne, leftMost + downOne); + painter->drawLines(lines, 3); + + painter->restore(); + } + break; +#endif // QT_NO_TOOLBOX +#ifndef QT_NO_SPLITTER + case CE_Splitter: + if ((option->state & State_Enabled) && (option->state & State_MouseOver)) + painter->fillRect(option->rect, QColor(255, 255, 255, 128)); + if (option->state & State_Horizontal) { + int height = option->rect.height() / 3; + QRect rect(option->rect.left() + (option->rect.width() / 2 - 1), + option->rect.center().y() - height / 2, 3, height); + qt_plastique_draw_handle(painter, option, rect, Qt::Horizontal, widget); + } else { + int width = option->rect.width() / 3; + QRect rect(option->rect.center().x() - width / 2, + option->rect.top() + (option->rect.height() / 2) - 1, width, 3); + qt_plastique_draw_handle(painter, option, rect, Qt::Vertical, widget); + } + break; +#endif // QT_NO_SPLITTER +#ifndef QT_NO_DOCKWIDGET + case CE_DockWidgetTitle: + if (const QStyleOptionDockWidget *dockWidget = qstyleoption_cast(option)) { + painter->save(); + + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(dockWidget); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + + // Find text width and title rect + int textWidth = option->fontMetrics.width(dockWidget->title); + int margin = 4; + QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, option, widget); + QRect rect = dockWidget->rect; + + if (verticalTitleBar) { + QRect r = rect; + QSize s = r.size(); + s.transpose(); + r.setSize(s); + + titleRect = QRect(r.left() + rect.bottom() + - titleRect.bottom(), + r.top() + titleRect.left() - rect.left(), + titleRect.height(), titleRect.width()); + + painter->translate(r.left(), r.top() + r.width()); + painter->rotate(-90); + painter->translate(-r.left(), -r.top()); + + rect = r; + } + + // Chop and insert ellide into title if text is too wide + QString title = elliditide(dockWidget->title, dockWidget->fontMetrics, titleRect, &textWidth); + + // Draw the toolbar handle pattern to the left and right of the text + QImage handle(qt_toolbarhandle); + alphaCornerColor.setAlpha(170); + handle.setColor(1, alphaCornerColor.rgba()); + handle.setColor(2, mergedColors(alphaCornerColor, option->palette.light().color()).rgba()); + handle.setColor(3, option->palette.light().color().rgba()); + + if (title.isEmpty()) { + // Joint handle if there's no title + QRect r; +#ifdef QT3_SUPPORT + // Q3DockWindow doesn't need space for buttons + if (widget && widget->inherits("Q3DockWindowTitleBar")) { + r = rect; + } else +#endif + r.setRect(titleRect.left(), titleRect.top(), titleRect.width(), titleRect.bottom()); + int nchunks = (r.width() / handle.width()) - 1; + int indent = (r.width() - (nchunks * handle.width())) / 2; + for (int i = 0; i < nchunks; ++i) { + painter->drawImage(QPoint(r.left() + indent + i * handle.width(), + r.center().y() - handle.height() / 2), + handle); + } + } else { + // Handle pattern to the left of the title + QRect leftSide(titleRect.left(), titleRect.top(), + titleRect.width() / 2 - textWidth / 2 - margin, titleRect.bottom()); + int nchunks = leftSide.width() / handle.width(); + int indent = (leftSide.width() - (nchunks * handle.width())) / 2; + for (int i = 0; i < nchunks; ++i) { + painter->drawImage(QPoint(leftSide.left() + indent + + i * handle.width(), + leftSide.center().y() + - handle.height() / 2), + handle); + } + + // Handle pattern to the right of the title + QRect rightSide = titleRect.adjusted(titleRect.width() / 2 + textWidth / 2 + margin, 0, 0, 0); + nchunks = rightSide.width() / handle.width(); + indent = (rightSide.width() - (nchunks * handle.width())) / 2; + for (int j = 0; j < nchunks; ++j) { + painter->drawImage(QPoint(rightSide.left() + indent + j * handle.width(), + rightSide.center().y() - handle.height() / 2), + handle); + } + } + + // Draw the text centered + QFont font = painter->font(); + font.setPointSize(QFontInfo(font).pointSize() - 1); + painter->setFont(font); + painter->setPen(dockWidget->palette.windowText().color()); + painter->drawText(titleRect, + int(Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextShowMnemonic), + title); + + painter->restore(); + } + + break; +#endif // QT_NO_DOCKWIDGET +#ifndef QT_NO_TOOLBAR + case CE_ToolBar: + if (const QStyleOptionToolBar *toolBar = qstyleoption_cast(option)) { + // Draws the light line above and the dark line below menu bars and + // tool bars. + QPen oldPen = painter->pen(); + if (toolBar->toolBarArea == Qt::TopToolBarArea) { + if (toolBar->positionOfLine == QStyleOptionToolBar::End + || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) { + // The end and onlyone top toolbar lines draw a double + // line at the bottom to blend with the central + // widget. + painter->setPen(option->palette.background().color().lighter(104)); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + painter->setPen(alphaCornerColor); + painter->drawLine(option->rect.left(), option->rect.bottom() - 1, + option->rect.right(), option->rect.bottom() - 1); + } else { + // All others draw a single dark line at the bottom. + painter->setPen(alphaCornerColor); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + } + // All top toolbar lines draw a light line at the top. + painter->setPen(option->palette.background().color().lighter(104)); + painter->drawLine(option->rect.topLeft(), option->rect.topRight()); + } else if (toolBar->toolBarArea == Qt::BottomToolBarArea) { + if (toolBar->positionOfLine == QStyleOptionToolBar::End + || toolBar->positionOfLine == QStyleOptionToolBar::Middle) { + // The end and middle bottom tool bar lines draw a dark + // line at the bottom. + painter->setPen(alphaCornerColor); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + } + if (toolBar->positionOfLine == QStyleOptionToolBar::Beginning + || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) { + // The beginning and only one tool bar lines draw a + // double line at the bottom to blend with the + // status bar. + // ### The styleoption could contain whether the + // main window has a menu bar and a status bar, and + // possibly dock widgets. + painter->setPen(alphaCornerColor); + painter->drawLine(option->rect.left(), option->rect.bottom() - 1, + option->rect.right(), option->rect.bottom() - 1); + painter->setPen(option->palette.background().color().lighter(104)); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + } + if (toolBar->positionOfLine == QStyleOptionToolBar::End) { + painter->setPen(alphaCornerColor); + painter->drawLine(option->rect.topLeft(), option->rect.topRight()); + painter->setPen(option->palette.background().color().lighter(104)); + painter->drawLine(option->rect.left(), option->rect.top() + 1, + option->rect.right(), option->rect.top() + 1); + + } else { + // All other bottom toolbars draw a light line at the top. + painter->setPen(option->palette.background().color().lighter(104)); + painter->drawLine(option->rect.topLeft(), option->rect.topRight()); + } + } + if (toolBar->toolBarArea == Qt::LeftToolBarArea) { + if (toolBar->positionOfLine == QStyleOptionToolBar::Middle + || toolBar->positionOfLine == QStyleOptionToolBar::End) { + // The middle and left end toolbar lines draw a light + // line to the left. + painter->setPen(option->palette.background().color().lighter(104)); + painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft()); + } + if (toolBar->positionOfLine == QStyleOptionToolBar::End) { + // All other left toolbar lines draw a dark line to the right + painter->setPen(alphaCornerColor); + painter->drawLine(option->rect.right() - 1, option->rect.top(), + option->rect.right() - 1, option->rect.bottom()); + painter->setPen(option->palette.background().color().lighter(104)); + painter->drawLine(option->rect.topRight(), option->rect.bottomRight()); + } else { + // All other left toolbar lines draw a dark line to the right + painter->setPen(alphaCornerColor); + painter->drawLine(option->rect.topRight(), option->rect.bottomRight()); + } + } else if (toolBar->toolBarArea == Qt::RightToolBarArea) { + if (toolBar->positionOfLine == QStyleOptionToolBar::Middle + || toolBar->positionOfLine == QStyleOptionToolBar::End) { + // Right middle and end toolbar lines draw the dark right line + painter->setPen(alphaCornerColor); + painter->drawLine(option->rect.topRight(), option->rect.bottomRight()); + } + if (toolBar->positionOfLine == QStyleOptionToolBar::End + || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) { + // The right end and single toolbar draws the dark + // line on its left edge + painter->setPen(alphaCornerColor); + painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft()); + // And a light line next to it + painter->setPen(option->palette.background().color().lighter(104)); + painter->drawLine(option->rect.left() + 1, option->rect.top(), + option->rect.left() + 1, option->rect.bottom()); + } else { + // Other right toolbars draw a light line on its left edge + painter->setPen(option->palette.background().color().lighter(104)); + painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft()); + } + } + painter->setPen(oldPen); + } + break; +#endif // QT_NO_TOOLBAR +#ifndef QT_NO_SCROLLBAR + case CE_ScrollBarAddLine: + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast(option)) { + + bool horizontal = scrollBar->orientation == Qt::Horizontal; + bool reverse = scrollBar->direction == Qt::RightToLeft; + bool sunken = scrollBar->state & State_Sunken; + + QString addLinePixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_addline"), option, option->rect.size()); + QPixmap cache; + if (!QPixmapCache::find(addLinePixmapName, cache)) { + cache = QPixmap(option->rect.size()); + cache.fill(Qt::white); + QRect pixmapRect(0, 0, cache.width(), cache.height()); + QPainter addLinePainter(&cache); + addLinePainter.fillRect(pixmapRect, option->palette.background()); + + if (option->state & State_Enabled) { + // Gradient + QLinearGradient gradient(pixmapRect.center().x(), pixmapRect.top() + 2, + pixmapRect.center().x(), pixmapRect.bottom() - 2); + if ((scrollBar->activeSubControls & SC_ScrollBarAddLine) && sunken) { + gradient.setColorAt(0, gradientStopColor); + gradient.setColorAt(1, gradientStopColor); + } else { + gradient.setColorAt(0, gradientStartColor.lighter(105)); + gradient.setColorAt(1, gradientStopColor); + } + addLinePainter.fillRect(pixmapRect.left() + 2, pixmapRect.top() + 2, + pixmapRect.right() - 3, pixmapRect.bottom() - 3, + gradient); + } + + // Details + QImage addButton; + if (horizontal) { + addButton = QImage(reverse ? qt_scrollbar_button_left : qt_scrollbar_button_right); + } else { + addButton = QImage(qt_scrollbar_button_down); + } + addButton.setColor(1, alphaCornerColor.rgba()); + addButton.setColor(2, borderColor.rgba()); + if ((scrollBar->activeSubControls & SC_ScrollBarAddLine) && sunken) { + addButton.setColor(3, gradientStopColor.rgba()); + addButton.setColor(4, gradientStopColor.rgba()); + } else { + addButton.setColor(3, gradientStartColor.lighter(105).rgba()); + addButton.setColor(4, gradientStopColor.rgba()); + } + addButton.setColor(5, scrollBar->palette.text().color().rgba()); + addLinePainter.drawImage(pixmapRect, addButton); + + // Arrow + if (horizontal) { + QImage arrow(reverse ? qt_scrollbar_button_arrow_left : qt_scrollbar_button_arrow_right); + arrow.setColor(1, scrollBar->palette.foreground().color().rgba()); + + if ((scrollBar->activeSubControls & SC_ScrollBarAddLine) && sunken) + addLinePainter.translate(1, 1); + addLinePainter.drawImage(QPoint(pixmapRect.center().x() - 2, pixmapRect.center().y() - 3), arrow); + } else { + QImage arrow(qt_scrollbar_button_arrow_down); + arrow.setColor(1, scrollBar->palette.foreground().color().rgba()); + + if ((scrollBar->activeSubControls & SC_ScrollBarAddLine) && sunken) + addLinePainter.translate(1, 1); + addLinePainter.drawImage(QPoint(pixmapRect.center().x() - 3, pixmapRect.center().y() - 2), arrow); + } + addLinePainter.end(); + QPixmapCache::insert(addLinePixmapName, cache); + } + painter->drawPixmap(option->rect.topLeft(), cache); + } + break; + case CE_ScrollBarSubPage: + case CE_ScrollBarAddPage: + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast(option)) { + bool sunken = scrollBar->state & State_Sunken; + bool horizontal = scrollBar->orientation == Qt::Horizontal; + + QString groovePixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_groove"), option, option->rect.size()); + if (sunken) + groovePixmapName += QLatin1String("-sunken"); + if (element == CE_ScrollBarAddPage) + groovePixmapName += QLatin1String("-addpage"); + + QPixmap cache; + if (!QPixmapCache::find(groovePixmapName, cache)) { + cache = QPixmap(option->rect.size()); + cache.fill(option->palette.background().color()); + QPainter groovePainter(&cache); + QRect pixmapRect = QRect(0, 0, option->rect.width(), option->rect.height()); + QColor color = scrollBar->palette.base().color().darker(sunken ? 125 : 100); + groovePainter.setBrushOrigin((element == CE_ScrollBarAddPage) ? pixmapRect.width() : 0, + (element == CE_ScrollBarAddPage) ? pixmapRect.height() : 0); + groovePainter.fillRect(pixmapRect, QBrush(color, Qt::Dense4Pattern)); + + QColor edgeColor = scrollBar->palette.base().color().darker(125); + if (horizontal) { + groovePainter.setBrushOrigin((element == CE_ScrollBarAddPage) ? pixmapRect.width() : 1, 0); + groovePainter.fillRect(QRect(pixmapRect.topLeft(), QSize(pixmapRect.width(), 1)), + QBrush(edgeColor, Qt::Dense4Pattern)); + groovePainter.fillRect(QRect(pixmapRect.bottomLeft(), QSize(pixmapRect.width(), 1)), + QBrush(edgeColor, Qt::Dense4Pattern)); + } else { + groovePainter.setBrushOrigin(0, (element == CE_ScrollBarAddPage) ? pixmapRect.height() : 1); + groovePainter.fillRect(QRect(pixmapRect.topLeft(), QSize(1, pixmapRect.height())), + QBrush(edgeColor, Qt::Dense4Pattern)); + groovePainter.fillRect(QRect(pixmapRect.topRight(), QSize(1, pixmapRect.height())), + QBrush(edgeColor, Qt::Dense4Pattern)); + } + + groovePainter.end(); + QPixmapCache::insert(groovePixmapName, cache); + } + painter->drawPixmap(option->rect.topLeft(), cache); + } + break; + case CE_ScrollBarSubLine: + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast(option)) { + QRect scrollBarSubLine = scrollBar->rect; + + bool horizontal = scrollBar->orientation == Qt::Horizontal; + bool isEnabled = scrollBar->state & State_Enabled; + bool reverse = scrollBar->direction == Qt::RightToLeft; + bool sunken = scrollBar->state & State_Sunken; + + // The SubLine (up/left) buttons + QRect button1; + QRect button2; + int scrollBarExtent = proxy()->pixelMetric(PM_ScrollBarExtent, option, widget); + if (horizontal) { + button1.setRect(scrollBarSubLine.left(), scrollBarSubLine.top(), scrollBarExtent, scrollBarSubLine.height()); + button2.setRect(scrollBarSubLine.right() - (scrollBarExtent - 1), scrollBarSubLine.top(), scrollBarExtent, scrollBarSubLine.height()); + } else { + button1.setRect(scrollBarSubLine.left(), scrollBarSubLine.top(), scrollBarSubLine.width(), scrollBarExtent); + button2.setRect(scrollBarSubLine.left(), scrollBarSubLine.bottom() - (scrollBarExtent - 1), scrollBarSubLine.width(), scrollBarExtent); + } + + QString subLinePixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_subline"), option, button1.size()); + QPixmap cache; + if (!QPixmapCache::find(subLinePixmapName, cache)) { + cache = QPixmap(button1.size()); + cache.fill(Qt::white); + QRect pixmapRect(0, 0, cache.width(), cache.height()); + QPainter subLinePainter(&cache); + subLinePainter.fillRect(pixmapRect, option->palette.background()); + + if (isEnabled) { + // Gradients + if ((scrollBar->activeSubControls & SC_ScrollBarSubLine) && sunken) { + qt_plastique_draw_gradient(&subLinePainter, + QRect(pixmapRect.left() + 2, pixmapRect.top() + 2, + pixmapRect.right() - 3, pixmapRect.bottom() - 3), + gradientStopColor, + gradientStopColor); + } else { + qt_plastique_draw_gradient(&subLinePainter, + QRect(pixmapRect.left() + 2, pixmapRect.top() + 2, + pixmapRect.right() - 3, pixmapRect.bottom() - 3), + gradientStartColor.lighter(105), + gradientStopColor); + } + } + + // Details + QImage subButton; + if (horizontal) { + subButton = QImage(reverse ? qt_scrollbar_button_right : qt_scrollbar_button_left); + } else { + subButton = QImage(qt_scrollbar_button_up); + } + subButton.setColor(1, alphaCornerColor.rgba()); + subButton.setColor(2, borderColor.rgba()); + if ((scrollBar->activeSubControls & SC_ScrollBarSubLine) && sunken) { + subButton.setColor(3, gradientStopColor.rgba()); + subButton.setColor(4, gradientStopColor.rgba()); + } else { + subButton.setColor(3, gradientStartColor.lighter(105).rgba()); + subButton.setColor(4, gradientStopColor.rgba()); + } + subButton.setColor(5, scrollBar->palette.text().color().rgba()); + subLinePainter.drawImage(pixmapRect, subButton); + + // Arrows + if (horizontal) { + QImage arrow(reverse ? qt_scrollbar_button_arrow_right : qt_scrollbar_button_arrow_left); + arrow.setColor(1, scrollBar->palette.foreground().color().rgba()); + + if ((scrollBar->activeSubControls & SC_ScrollBarSubLine) && sunken) + subLinePainter.translate(1, 1); + subLinePainter.drawImage(QPoint(pixmapRect.center().x() - 2, pixmapRect.center().y() - 3), arrow); + } else { + QImage arrow(qt_scrollbar_button_arrow_up); + arrow.setColor(1, scrollBar->palette.foreground().color().rgba()); + + if ((scrollBar->activeSubControls & SC_ScrollBarSubLine) && sunken) + subLinePainter.translate(1, 1); + subLinePainter.drawImage(QPoint(pixmapRect.center().x() - 3, pixmapRect.center().y() - 2), arrow); + } + subLinePainter.end(); + QPixmapCache::insert(subLinePixmapName, cache); + } + painter->drawPixmap(button1.topLeft(), cache); + painter->drawPixmap(button2.topLeft(), cache); + } + break; + case CE_ScrollBarSlider: + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast(option)) { + bool horizontal = scrollBar->orientation == Qt::Horizontal; + bool isEnabled = scrollBar->state & State_Enabled; + + // The slider + if (option->rect.isValid()) { + QString sliderPixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_slider"), option, option->rect.size()); + if (horizontal) + sliderPixmapName += QLatin1String("-horizontal"); + + QPixmap cache; + if (!QPixmapCache::find(sliderPixmapName, cache)) { + cache = QPixmap(option->rect.size()); + cache.fill(Qt::white); + QRect pixmapRect(0, 0, cache.width(), cache.height()); + QPainter sliderPainter(&cache); + bool sunken = (scrollBar->state & State_Sunken); + + if (isEnabled) { + QLinearGradient gradient(pixmapRect.left(), pixmapRect.center().y(), + pixmapRect.right(), pixmapRect.center().y()); + if (horizontal) + gradient = QLinearGradient(pixmapRect.center().x(), pixmapRect.top(), + pixmapRect.center().x(), pixmapRect.bottom()); + + if (sunken) { + gradient.setColorAt(0, gradientStartColor.lighter(110)); + gradient.setColorAt(1, gradientStopColor.lighter(105)); + } else { + gradient.setColorAt(0, gradientStartColor.lighter(105)); + gradient.setColorAt(1, gradientStopColor); + } + sliderPainter.fillRect(pixmapRect.adjusted(2, 2, -2, -2), gradient); + } else { + sliderPainter.fillRect(pixmapRect.adjusted(2, 2, -2, -2), option->palette.background()); + } + + sliderPainter.setPen(borderColor); + sliderPainter.drawRect(pixmapRect.adjusted(0, 0, -1, -1)); + sliderPainter.setPen(alphaCornerColor); + QPoint points[4] = { + QPoint(pixmapRect.left(), pixmapRect.top()), + QPoint(pixmapRect.left(), pixmapRect.bottom()), + QPoint(pixmapRect.right(), pixmapRect.top()), + QPoint(pixmapRect.right(), pixmapRect.bottom()) }; + sliderPainter.drawPoints(points, 4); + + QLine lines[2]; + sliderPainter.setPen(sunken ? gradientStartColor.lighter(110) : gradientStartColor.lighter(105)); + lines[0] = QLine(pixmapRect.left() + 1, pixmapRect.top() + 1, + pixmapRect.right() - 1, pixmapRect.top() + 1); + lines[1] = QLine(pixmapRect.left() + 1, pixmapRect.top() + 2, + pixmapRect.left() + 1, pixmapRect.bottom() - 2); + sliderPainter.drawLines(lines, 2); + + sliderPainter.setPen(sunken ? gradientStopColor.lighter(105) : gradientStopColor); + lines[0] = QLine(pixmapRect.left() + 1, pixmapRect.bottom() - 1, + pixmapRect.right() - 1, pixmapRect.bottom() - 1); + lines[1] = QLine(pixmapRect.right() - 1, pixmapRect.top() + 2, + pixmapRect.right() - 1, pixmapRect.bottom() - 1); + sliderPainter.drawLines(lines, 2); + + int sliderMinLength = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollBar, widget); + if ((horizontal && scrollBar->rect.width() > sliderMinLength) + || (!horizontal && scrollBar->rect.height() > sliderMinLength)) { + QImage pattern(horizontal ? qt_scrollbar_slider_pattern_horizontal + : qt_scrollbar_slider_pattern_vertical); + pattern.setColor(1, alphaCornerColor.rgba()); + pattern.setColor(2, (sunken ? gradientStartColor.lighter(110) : gradientStartColor.lighter(105)).rgba()); + + if (horizontal) { + sliderPainter.drawImage(pixmapRect.center().x() - pattern.width() / 2 + 1, + pixmapRect.center().y() - 4, + pattern); + } else { + sliderPainter.drawImage(pixmapRect.center().x() - 4, + pixmapRect.center().y() - pattern.height() / 2 + 1, + pattern); + } + } + sliderPainter.end(); + // insert the slider into the cache + QPixmapCache::insert(sliderPixmapName, cache); + } + painter->drawPixmap(option->rect.topLeft(), cache); + } + } + break; +#endif +#ifndef QT_NO_COMBOBOX + case CE_ComboBoxLabel: + if (const QStyleOptionComboBox *comboBox = qstyleoption_cast(option)) { + painter->save(); + if (!comboBox->editable) { + // Plastique's non-editable combo box is drawn as a button, so + // we need the label to be drawn using ButtonText where it + // would usually use Text. + painter->setPen(QPen(comboBox->palette.buttonText(), 0)); + QWindowsStyle::drawControl(element, option, painter, widget); + } else if (!comboBox->currentIcon.isNull()) { + { + QRect editRect = proxy()->subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget); + if (comboBox->direction == Qt::RightToLeft) + editRect.adjust(0, 2, -2, -2); + else + editRect.adjust(2, 2, 0, -2); + painter->save(); + painter->setClipRect(editRect); + if (!comboBox->currentIcon.isNull()) { + QIcon::Mode mode = comboBox->state & State_Enabled ? QIcon::Normal + : QIcon::Disabled; + QPixmap pixmap = comboBox->currentIcon.pixmap(comboBox->iconSize, mode); + QRect iconRect(editRect); + iconRect.setWidth(comboBox->iconSize.width() + 5); + iconRect = alignedRect(comboBox->direction, + Qt::AlignLeft | Qt::AlignVCenter, + iconRect.size(), editRect); + painter->fillRect(iconRect, option->palette.brush(QPalette::Base)); + proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); + } + painter->restore(); + } + } else { + QWindowsStyle::drawControl(element, option, painter, widget); + } + + painter->restore(); + } + break; +#endif + default: + QWindowsStyle::drawControl(element, option, painter, widget); + break; + } +} + +/*! + \reimp +*/ +void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const +{ + QColor borderColor = option->palette.background().color().darker(178); + QColor alphaCornerColor; + if (widget) { + // ### backgroundrole/foregroundrole should be part of the style option + alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), borderColor); + } else { + alphaCornerColor = mergedColors(option->palette.background().color(), borderColor); + } + QColor gradientStartColor = option->palette.button().color().lighter(104); + QColor gradientStopColor = option->palette.button().color().darker(105); + QColor highlightedGradientStartColor = option->palette.button().color().lighter(101); + QColor highlightedGradientStopColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 85); + QColor highlightedDarkInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 35); + QColor highlightedLightInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 58); + + switch (control) { +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + QRect grooveRegion = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget); + QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget); + QRect ticks = proxy()->subControlRect(CC_Slider, option, SC_SliderTickmarks, widget); + bool horizontal = slider->orientation == Qt::Horizontal; + bool ticksAbove = slider->tickPosition & QSlider::TicksAbove; + bool ticksBelow = slider->tickPosition & QSlider::TicksBelow; + + QRect groove; + //The clickable region is 5 px wider than the visible groove for improved usability + if (grooveRegion.isValid()) + groove = horizontal ? grooveRegion.adjusted(0, 5, 0, -5) : grooveRegion.adjusted(5, 0, -5, 0); + + + QPixmap cache; + + if ((option->subControls & SC_SliderGroove) && groove.isValid()) { + BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("slider_groove-%0-%1").arg(ticksAbove).arg(ticksBelow)) + p->fillRect(groove, option->palette.background()); + + // draw groove + if (horizontal) { + p->setPen(borderColor); + const QLine lines[4] = { + QLine(groove.left() + 1, groove.top(), + groove.right() - 1, groove.top()), + QLine(groove.left() + 1, groove.bottom(), + groove.right() - 1, groove.bottom()), + QLine(groove.left(), groove.top() + 1, + groove.left(), groove.bottom() - 1), + QLine(groove.right(), groove.top() + 1, + groove.right(), groove.bottom() - 1) }; + p->drawLines(lines, 4); + + p->setPen(alphaCornerColor); + const QPoint points[4] = { + QPoint(groove.left(), groove.top()), + QPoint(groove.left(), groove.bottom()), + QPoint(groove.right(), groove.top()), + QPoint(groove.right(), groove.bottom()) }; + p->drawPoints(points, 4); + } else { + p->setPen(borderColor); + const QLine lines[4] = { + QLine(groove.left() + 1, groove.top(), + groove.right() - 1, groove.top()), + QLine(groove.left() + 1, groove.bottom(), + groove.right() - 1, groove.bottom()), + QLine(groove.left(), groove.top() + 1, + groove.left(), groove.bottom() - 1), + QLine(groove.right(), groove.top() + 1, + groove.right(), groove.bottom() - 1) }; + p->drawLines(lines, 4); + + p->setPen(alphaCornerColor); + const QPoint points[4] = { + QPoint(groove.left(), groove.top()), + QPoint(groove.right(), groove.top()), + QPoint(groove.left(), groove.bottom()), + QPoint(groove.right(), groove.bottom()) }; + p->drawPoints(points, 4); + } + END_STYLE_PIXMAPCACHE + } + + if ((option->subControls & SC_SliderHandle) && handle.isValid()) { + QString handlePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_handle"), option, handle.size()); + if (ticksAbove && !ticksBelow) + handlePixmapName += QLatin1String("-flipped"); + if ((option->activeSubControls & SC_SliderHandle) && (option->state & State_Sunken)) + handlePixmapName += QLatin1String("-sunken"); + + if (!QPixmapCache::find(handlePixmapName, cache)) { + cache = QPixmap(handle.size()); + cache.fill(Qt::white); + QRect pixmapRect(0, 0, handle.width(), handle.height()); + QPainter handlePainter(&cache); + handlePainter.fillRect(pixmapRect, option->palette.background()); + + // draw handle + if (horizontal) { + QPainterPath path; + if (ticksAbove && !ticksBelow) { + path.moveTo(QPoint(pixmapRect.right(), pixmapRect.bottom())); + path.lineTo(QPoint(pixmapRect.right(), pixmapRect.bottom() - 10)); + path.lineTo(QPoint(pixmapRect.right() - 5, pixmapRect.bottom() - 14)); + path.lineTo(QPoint(pixmapRect.left() + 1, pixmapRect.bottom() - 10)); + path.lineTo(QPoint(pixmapRect.left() + 1, pixmapRect.bottom())); + path.lineTo(QPoint(pixmapRect.right(), pixmapRect.bottom())); + } else { + path.moveTo(QPoint(pixmapRect.right(), pixmapRect.top() + 1)); + path.lineTo(QPoint(pixmapRect.right(), pixmapRect.top() + 10)); + path.lineTo(QPoint(pixmapRect.right() - 5, pixmapRect.top() + 14)); + path.lineTo(QPoint(pixmapRect.left() + 1, pixmapRect.top() + 10)); + path.lineTo(QPoint(pixmapRect.left() + 1, pixmapRect.top() + 1)); + path.lineTo(QPoint(pixmapRect.right(), pixmapRect.top() + 1)); + } + if (slider->state & State_Enabled) { + QLinearGradient gradient(pixmapRect.center().x(), pixmapRect.top(), + pixmapRect.center().x(), pixmapRect.bottom()); + if ((option->activeSubControls & SC_SliderHandle) && (option->state & State_Sunken)) { + gradient.setColorAt(0, gradientStartColor.lighter(110)); + gradient.setColorAt(1, gradientStopColor.lighter(110)); + } else { + gradient.setColorAt(0, gradientStartColor); + gradient.setColorAt(1, gradientStopColor); + } + handlePainter.fillPath(path, gradient); + } else { + handlePainter.fillPath(path, slider->palette.background()); + } + } else { + QPainterPath path; + if (ticksAbove && !ticksBelow) { + path.moveTo(QPoint(pixmapRect.right(), pixmapRect.top() + 1)); + path.lineTo(QPoint(pixmapRect.right() - 10, pixmapRect.top() + 1)); + path.lineTo(QPoint(pixmapRect.right() - 14, pixmapRect.top() + 5)); + path.lineTo(QPoint(pixmapRect.right() - 10, pixmapRect.bottom())); + path.lineTo(QPoint(pixmapRect.right(), pixmapRect.bottom())); + path.lineTo(QPoint(pixmapRect.right(), pixmapRect.top() + 1)); + } else { + path.moveTo(QPoint(pixmapRect.left() + 1, pixmapRect.top() + 1)); + path.lineTo(QPoint(pixmapRect.left() + 10, pixmapRect.top() + 1)); + path.lineTo(QPoint(pixmapRect.left() + 14, pixmapRect.top() + 5)); + path.lineTo(QPoint(pixmapRect.left() + 10, pixmapRect.bottom())); + path.lineTo(QPoint(pixmapRect.left() + 1, pixmapRect.bottom())); + path.lineTo(QPoint(pixmapRect.left() + 1, pixmapRect.top() + 1)); + } + if (slider->state & State_Enabled) { + QLinearGradient gradient(pixmapRect.center().x(), pixmapRect.top(), + pixmapRect.center().x(), pixmapRect.bottom()); + gradient.setColorAt(0, gradientStartColor); + gradient.setColorAt(1, gradientStopColor); + handlePainter.fillPath(path, gradient); + } else { + handlePainter.fillPath(path, slider->palette.background()); + } + } + + QImage image; + if (horizontal) { + image = QImage((ticksAbove && !ticksBelow) ? qt_plastique_slider_horizontalhandle_up : qt_plastique_slider_horizontalhandle); + } else { + image = QImage((ticksAbove && !ticksBelow) ? qt_plastique_slider_verticalhandle_left : qt_plastique_slider_verticalhandle); + } + + image.setColor(1, borderColor.rgba()); + image.setColor(2, gradientStartColor.rgba()); + image.setColor(3, alphaCornerColor.rgba()); + if (option->state & State_Enabled) { + image.setColor(4, 0x80ffffff); + image.setColor(5, 0x25000000); + } + handlePainter.drawImage(pixmapRect, image); + handlePainter.end(); + QPixmapCache::insert(handlePixmapName, cache); + } + + painter->drawPixmap(handle.topLeft(), cache); + + if (slider->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*slider); + fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + } + + if (option->subControls & SC_SliderTickmarks) { + QPen oldPen = painter->pen(); + painter->setPen(borderColor); + int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget); + int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget); + int interval = slider->tickInterval; + if (interval <= 0) { + interval = slider->singleStep; + if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval, + available) + - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, + 0, available) < 3) + interval = slider->pageStep; + } + if (interval <= 0) + interval = 1; + + int v = slider->minimum; + int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); + QVarLengthArray lines; + while (v <= slider->maximum + 1) { + if (v == slider->maximum + 1 && interval == 1) + break; + const int v_ = qMin(v, slider->maximum); + int pos = sliderPositionFromValue(slider->minimum, slider->maximum, + v_, (horizontal + ? slider->rect.width() + : slider->rect.height()) - len, + slider->upsideDown) + len / 2; + + int extra = 2 - ((v_ == slider->minimum || v_ == slider->maximum) ? 1 : 0); + + if (horizontal) { + if (ticksAbove) { + lines.append(QLine(pos, slider->rect.top() + extra, + pos, slider->rect.top() + tickSize)); + } + if (ticksBelow) { + lines.append(QLine(pos, slider->rect.bottom() - extra, + pos, slider->rect.bottom() - tickSize)); + } + } else { + if (ticksAbove) { + lines.append(QLine(slider->rect.left() + extra, pos, + slider->rect.left() + tickSize, pos)); + } + if (ticksBelow) { + lines.append(QLine(slider->rect.right() - extra, pos, + slider->rect.right() - tickSize, pos)); + } + } + + // in the case where maximum is max int + int nextInterval = v + interval; + if (nextInterval < v) + break; + v = nextInterval; + } + painter->drawLines(lines.constData(), lines.size()); + painter->setPen(oldPen); + } + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { + painter->save(); + bool upSunken = (spinBox->activeSubControls & SC_SpinBoxUp) && (spinBox->state & (State_Sunken | State_On)); + bool downSunken = (spinBox->activeSubControls & SC_SpinBoxDown) && (spinBox->state & (State_Sunken | State_On)); + bool reverse = (spinBox->direction == Qt::RightToLeft); + + // Rects + QRect upRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget); + QRect downRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget); + QRect buttonRect = upRect | downRect; + + // Brushes + QBrush corner = qMapBrushToRect(option->palette.shadow(), buttonRect); + qBrushSetAlphaF(&corner, qreal(0.25)); + QBrush border = qMapBrushToRect(option->palette.shadow(), buttonRect); + qBrushSetAlphaF(&border, qreal(0.4)); + + QVarLengthArray points; + + Q_D(const QPlastiqueStyle); + if (spinBox->buttonSymbols == QAbstractSpinBox::NoButtons) { + QRect filledRect = option->rect.adjusted(1, 1, -1, -1); + QBrush baseBrush = qMapBrushToRect(option->palette.base(), filledRect); + painter->setBrushOrigin(filledRect.topLeft()); + painter->fillRect(filledRect.adjusted(1, 1, -1, -1), baseBrush); + qt_plastique_draw_frame(painter, option->rect, option, QFrame::Sunken); + } else { + d->drawPartialFrame(painter, + option, + proxy()->subControlRect(CC_SpinBox, spinBox, SC_SpinBoxEditField, widget), + widget); + } + // Paint buttons + if (spinBox->buttonSymbols == QAbstractSpinBox::NoButtons) { + painter->restore(); + break; + } + // Button outlines + painter->setPen(QPen(border, 0)); + if (!reverse) + painter->drawLine(buttonRect.topLeft() + QPoint(0, 1), buttonRect.bottomLeft() + QPoint(0, -1)); + else + painter->drawLine(buttonRect.topRight() + QPoint(0, -1), buttonRect.bottomRight() + QPoint(0, 1)); + + if (!reverse) { + const QLine lines[4] = { + QLine(upRect.left(), upRect.top(), upRect.right() - 2, upRect.top()), + QLine(upRect.left() + 1, upRect.bottom(), upRect.right() - 1, upRect.bottom()), + QLine(downRect.left(), downRect.bottom(), downRect.right() - 2, downRect.bottom()), + QLine(buttonRect.right(), buttonRect.top() + 2, buttonRect.right(), buttonRect.bottom() - 2) }; + painter->drawLines(lines, 4); + + points.append(QPoint(upRect.right() - 1, upRect.top() + 1)); + points.append(QPoint(downRect.right() - 1, downRect.bottom() - 1)); + painter->drawPoints(points.constData(), points.size()); + points.clear(); + painter->setPen(QPen(corner, 0)); + points.append(QPoint(upRect.right() - 1, upRect.top())); + points.append(QPoint(upRect.right(), upRect.top() + 1)); + points.append(QPoint(upRect.right(), downRect.bottom() - 1)); + points.append(QPoint(upRect.right() - 1, downRect.bottom())); + } else { + const QLine lines[4] = { + QLine(upRect.right(), upRect.top(), upRect.left() + 2, upRect.top()), + QLine(upRect.right() - 1, upRect.bottom(), upRect.left() + 1, upRect.bottom()), + QLine(downRect.right(), downRect.bottom(), downRect.left() + 2, downRect.bottom()), + QLine(buttonRect.left(), buttonRect.top() + 2, buttonRect.left(), buttonRect.bottom() - 2) }; + painter->drawLines(lines, 4); + + points.append(QPoint(upRect.left() + 1, upRect.top() + 1)); + points.append(QPoint(downRect.left() + 1, downRect.bottom() - 1)); + painter->drawPoints(points.constData(), points.size()); + points.clear(); + painter->setPen(QPen(corner, 0)); + points.append(QPoint(upRect.left() + 1, upRect.top())); + points.append(QPoint(upRect.left(), upRect.top() + 1)); + points.append(QPoint(upRect.left(), downRect.bottom() - 1)); + points.append(QPoint(upRect.left() + 1, downRect.bottom())); + } + painter->drawPoints(points.constData(), points.size()); + points.clear(); + + // Button colors + QBrush buttonGradientBrush; + QBrush leftLineGradientBrush; + QBrush rightLineGradientBrush; + QBrush sunkenButtonGradientBrush; + QBrush sunkenLeftLineGradientBrush; + QBrush sunkenRightLineGradientBrush; + QBrush buttonBrush = qMapBrushToRect(option->palette.button(), buttonRect); + if (buttonBrush.gradient() || !buttonBrush.texture().isNull()) { + buttonGradientBrush = buttonBrush; + sunkenButtonGradientBrush = qBrushDark(buttonBrush, 108); + leftLineGradientBrush = qBrushLight(buttonBrush, 105); + rightLineGradientBrush = qBrushDark(buttonBrush, 105); + sunkenLeftLineGradientBrush = qBrushDark(buttonBrush, 110); + sunkenRightLineGradientBrush = qBrushDark(buttonBrush, 106); + } else { + // Generate gradients + QLinearGradient buttonGradient(buttonRect.topLeft(), buttonRect.bottomLeft()); + buttonGradient.setColorAt(0.0, buttonBrush.color().lighter(104)); + buttonGradient.setColorAt(1.0, buttonBrush.color().darker(110)); + buttonGradientBrush = QBrush(buttonGradient); + + QLinearGradient buttonGradient2(buttonRect.topLeft(), buttonRect.bottomLeft()); + buttonGradient2.setColorAt(0.0, buttonBrush.color().darker(113)); + buttonGradient2.setColorAt(1.0, buttonBrush.color().darker(103)); + sunkenButtonGradientBrush = QBrush(buttonGradient2); + + QLinearGradient buttonGradient3(buttonRect.topLeft(), buttonRect.bottomLeft()); + buttonGradient3.setColorAt(0.0, buttonBrush.color().lighter(105)); + buttonGradient3.setColorAt(1.0, buttonBrush.color()); + leftLineGradientBrush = QBrush(buttonGradient3); + + QLinearGradient buttonGradient4(buttonRect.topLeft(), buttonRect.bottomLeft()); + buttonGradient4.setColorAt(0.0, buttonBrush.color()); + buttonGradient4.setColorAt(1.0, buttonBrush.color().darker(110)); + rightLineGradientBrush = QBrush(buttonGradient4); + + QLinearGradient buttonGradient5(buttonRect.topLeft(), buttonRect.bottomLeft()); + buttonGradient5.setColorAt(0.0, buttonBrush.color().darker(113)); + buttonGradient5.setColorAt(1.0, buttonBrush.color().darker(107)); + sunkenLeftLineGradientBrush = QBrush(buttonGradient5); + + QLinearGradient buttonGradient6(buttonRect.topLeft(), buttonRect.bottomLeft()); + buttonGradient6.setColorAt(0.0, buttonBrush.color().darker(108)); + buttonGradient6.setColorAt(1.0, buttonBrush.color().darker(103)); + sunkenRightLineGradientBrush = QBrush(buttonGradient6); + } + + // Main fill + painter->fillRect(upRect.adjusted(2, 2, -2, -2), + qMapBrushToRect(upSunken ? sunkenButtonGradientBrush + : buttonGradientBrush, upRect)); + painter->fillRect(downRect.adjusted(2, 2, -2, -2), + qMapBrushToRect(downSunken ? sunkenButtonGradientBrush + : buttonGradientBrush, downRect)); + + // Top line + painter->setPen(QPen(qBrushLight(qMapBrushToRect(upSunken ? sunkenButtonGradientBrush + : buttonGradientBrush, upRect), 105), 0)); + if (!reverse) { + painter->drawLine(upRect.left() + 1, upRect.top() + 1, + upRect.right() - 2, upRect.top() + 1); + } else { + painter->drawLine(upRect.right() - 1, upRect.top() + 1, + upRect.left() + 2, upRect.top() + 1); + } + painter->setPen(QPen(qBrushLight(qMapBrushToRect(downSunken ? sunkenButtonGradientBrush + : buttonGradientBrush, downRect), 105), 0)); + if (!reverse) { + painter->drawLine(downRect.left() + 1, downRect.top() + 1, + downRect.right() - 1, downRect.top() + 1); + } else { + painter->drawLine(downRect.right() - 1, downRect.top() + 1, + downRect.left() + 1, downRect.top() + 1); + } + + // Left line + painter->setPen(QPen(qMapBrushToRect(upSunken ? sunkenLeftLineGradientBrush + : leftLineGradientBrush, upRect), 1)); + if (!reverse) { + painter->drawLine(upRect.left() + 1, upRect.top() + 2, + upRect.left() + 1, upRect.bottom() - 1); + } else { + painter->drawLine(upRect.left() + 1, upRect.top() + 2, + upRect.left() + 1, upRect.bottom() - 1); + } + painter->setPen(QPen(qMapBrushToRect(downSunken ? sunkenLeftLineGradientBrush + : leftLineGradientBrush, downRect), 1)); + if (!reverse) { + painter->drawLine(downRect.left() + 1, downRect.top() + 2, + downRect.left() + 1, downRect.bottom() - 1); + } else { + painter->drawLine(downRect.left() + 1, downRect.top() + 1, + downRect.left() + 1, downRect.bottom() - 2); + } + + // Bottom line + painter->setPen(QPen(qBrushDark(qMapBrushToRect(upSunken ? sunkenButtonGradientBrush + : buttonGradientBrush, upRect), 105), 0)); + if (!reverse) { + painter->drawLine(upRect.left() + 2, upRect.bottom() - 1, + upRect.right() - 1, upRect.bottom() - 1); + } else { + painter->drawLine(upRect.right() - 2, upRect.bottom() - 1, + upRect.left() + 1, upRect.bottom() - 1); + } + painter->setPen(QPen(qBrushDark(qMapBrushToRect(downSunken ? sunkenButtonGradientBrush + : buttonGradientBrush, downRect), 105), 0)); + if (!reverse) { + painter->drawLine(downRect.left() + 2, downRect.bottom() - 1, + downRect.right() - 2, downRect.bottom() - 1); + } else { + painter->drawLine(downRect.right() - 2, downRect.bottom() - 1, + downRect.left() + 2, downRect.bottom() - 1); + } + + // Right line + painter->setPen(QPen(qMapBrushToRect(upSunken ? sunkenRightLineGradientBrush + : rightLineGradientBrush, upRect), 1)); + if (!reverse) { + painter->drawLine(upRect.right() - 1, upRect.top() + 2, + upRect.right() - 1, upRect.bottom() - 1); + } else { + painter->drawLine(upRect.right() - 1, upRect.top() + 2, + upRect.right() - 1, upRect.bottom() - 1); + } + painter->setPen(QPen(qMapBrushToRect(downSunken ? sunkenRightLineGradientBrush + : rightLineGradientBrush, downRect), 1)); + if (!reverse) { + painter->drawLine(downRect.right() - 1, downRect.top() + 1, + downRect.right() - 1, downRect.bottom() - 2); + } else { + painter->drawLine(downRect.right() - 1, downRect.top() + 2, + downRect.right() - 1, downRect.bottom() - 1); + } + + QBrush indicatorBrush = qMapBrushToRect(option->palette.buttonText(), buttonRect); + painter->setPen(QPen(indicatorBrush, 0)); + if (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) { + QPoint center; + if (spinBox->subControls & SC_SpinBoxUp) { + // ....... + // ...X... + // ...X... + // .XXXXX. + // ...X... + // ...X... + // ....... + center = upRect.center(); + if (upSunken) { + ++center.rx(); + ++center.ry(); + } + painter->drawLine(center.x(), center.y() - 2, center.x(), center.y() + 2); + painter->drawLine(center.x() - 2, center.y(), center.x() + 2, center.y()); + } + if (spinBox->subControls & SC_SpinBoxDown) { + // ....... + // ....... + // ....... + // .XXXXX. + // ....... + // ....... + // ....... + center = downRect.center(); + if (downSunken) { + ++center.rx(); + ++center.ry(); + } + painter->drawLine(center.x() - 2, center.y(), center.x() + 2, center.y()); + } + } else { + int offset; + int centerX; + if (spinBox->subControls & SC_SpinBoxUp) { + // ........... + // .....X..... + // ....XXX.... + // ...XXXXX... + // ..XXXXXXX.. + // ........... + offset = upSunken ? 1 : 0; + QRect upArrowRect(upRect.center().x() - 3 + offset, upRect.center().y() - 2 + offset, 7, 4); + centerX = upArrowRect.center().x(); + painter->drawPoint(centerX, upArrowRect.top()); + const QLine lines[3] = { + QLine(centerX - 1, upArrowRect.top() + 1, centerX + 1, upArrowRect.top() + 1), + QLine(centerX - 2, upArrowRect.top() + 2, centerX + 2, upArrowRect.top() + 2), + QLine(centerX - 3, upArrowRect.top() + 3, centerX + 3, upArrowRect.top() + 3) }; + painter->drawLines(lines, 3); + } + if (spinBox->subControls & SC_SpinBoxDown) { + // ........... + // ..XXXXXXX.. + // ...XXXXX... + // ....XXX.... + // .....X..... + // ........... + offset = downSunken ? 1 : 0; + QRect downArrowRect(downRect.center().x() - 3 + offset, downRect.center().y() - 2 + offset + 1, 7, 4); + centerX = downArrowRect.center().x(); + const QLine lines[3] = { + QLine(centerX - 3, downArrowRect.top(), centerX + 3, downArrowRect.top()), + QLine(centerX - 2, downArrowRect.top() + 1, centerX + 2, downArrowRect.top() + 1), + QLine(centerX - 1, downArrowRect.top() + 2, centerX + 1, downArrowRect.top() + 2) }; + painter->drawLines(lines, 3); + painter->drawPoint(centerX, downArrowRect.top() + 3); + } + } + painter->restore(); + } + break; +#endif // QT_NO_SPINBOX +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *comboBox = qstyleoption_cast(option)) { + bool sunken = comboBox->state & State_On; // play dead if combobox has no items + bool reverse = comboBox->direction == Qt::RightToLeft; + int menuButtonWidth = 16; + int xoffset = sunken ? (reverse ? -1 : 1) : 0; + int yoffset = sunken ? 1 : 0; + QRect rect = comboBox->rect; + QPen oldPen = painter->pen(); + + // Fill + if (comboBox->editable) { + // Button colors + QBrush alphaCornerBrush = qBrushDark(option->palette.button(), 165); + qBrushSetAlphaF(&alphaCornerBrush, 0.5); + QBrush buttonGradientBrush; + QBrush leftLineGradientBrush; + QBrush rightLineGradientBrush; + QBrush sunkenButtonGradientBrush; + QBrush sunkenLeftLineGradientBrush; + QBrush sunkenRightLineGradientBrush; + QBrush button = option->palette.button(); + if (button.gradient() || !button.texture().isNull()) { + buttonGradientBrush = button; + sunkenButtonGradientBrush = qBrushDark(button, 108); + leftLineGradientBrush = qBrushLight(button, 105); + rightLineGradientBrush = qBrushDark(button, 105); + sunkenLeftLineGradientBrush = qBrushDark(button, 110); + sunkenRightLineGradientBrush = qBrushDark(button, 106); + } else { + // Generate gradients + QLinearGradient buttonGradient(option->rect.topLeft(), option->rect.bottomLeft()); + buttonGradient.setColorAt(0.0, button.color().lighter(104)); + buttonGradient.setColorAt(1.0, button.color().darker(110)); + buttonGradientBrush = QBrush(buttonGradient); + + QLinearGradient buttonGradient2(option->rect.topLeft(), option->rect.bottomLeft()); + buttonGradient2.setColorAt(0.0, button.color().darker(113)); + buttonGradient2.setColorAt(1.0, button.color().darker(103)); + sunkenButtonGradientBrush = QBrush(buttonGradient2); + + QLinearGradient buttonGradient3(option->rect.topLeft(), option->rect.bottomLeft()); + buttonGradient3.setColorAt(0.0, button.color().lighter(105)); + buttonGradient3.setColorAt(1.0, button.color()); + leftLineGradientBrush = QBrush(buttonGradient3); + + QLinearGradient buttonGradient4(option->rect.topLeft(), option->rect.bottomLeft()); + buttonGradient4.setColorAt(0.0, button.color()); + buttonGradient4.setColorAt(1.0, button.color().darker(110)); + rightLineGradientBrush = QBrush(buttonGradient4); + + QLinearGradient buttonGradient5(option->rect.topLeft(), option->rect.bottomLeft()); + buttonGradient5.setColorAt(0.0, button.color().darker(113)); + buttonGradient5.setColorAt(1.0, button.color().darker(107)); + sunkenLeftLineGradientBrush = QBrush(buttonGradient5); + + QLinearGradient buttonGradient6(option->rect.topLeft(), option->rect.bottomLeft()); + buttonGradient6.setColorAt(0.0, button.color().darker(108)); + buttonGradient6.setColorAt(1.0, button.color().darker(103)); + sunkenRightLineGradientBrush = QBrush(buttonGradient6); + } + + // ComboBox starts with a lineedit in place already. + QRect buttonRect; + if (!reverse) { + buttonRect.setRect(rect.right() - menuButtonWidth, rect.top(), menuButtonWidth + 1, rect.height()); + } else { + buttonRect.setRect(rect.left(), rect.top(), menuButtonWidth + 1, rect.height()); + } + + Q_D(const QPlastiqueStyle); + d->drawPartialFrame(painter, + option, + proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget), + widget); + + QBrush border = qMapBrushToRect(option->palette.shadow(), buttonRect); + qBrushSetAlphaF(&border, qreal(0.4)); + painter->setPen(QPen(border, 0)); + if (!reverse) + painter->drawLine(buttonRect.topLeft() + QPoint(0, 1), buttonRect.bottomLeft() + QPoint(0, -1)); + else + painter->drawLine(buttonRect.topRight() + QPoint(0, -1), buttonRect.bottomRight() + QPoint(0, 1)); + + // Outline the button border + if (!reverse) { + const QLine lines[3] = { + QLine(buttonRect.left(), buttonRect.top(), + buttonRect.right() - 2, buttonRect.top()), + QLine(buttonRect.right(), buttonRect.top() + 2, + buttonRect.right(), buttonRect.bottom() - 2), + QLine(buttonRect.left(), buttonRect.bottom(), + buttonRect.right() - 2, buttonRect.bottom()) }; + painter->drawLines(lines, 3); + { + const QPoint points[2] = { + QPoint(buttonRect.right() - 1, buttonRect.top() + 1), + QPoint(buttonRect.right() - 1, buttonRect.bottom() - 1) }; + painter->drawPoints(points, 2); + } + + QBrush corner = qMapBrushToRect(option->palette.shadow(), buttonRect); + qBrushSetAlphaF(&corner, qreal(0.16)); + painter->setPen(QPen(corner, 0)); + { + const QPoint points[4] = { + QPoint(buttonRect.right() - 1, buttonRect.top()), + QPoint(buttonRect.right() - 1, buttonRect.bottom()), + QPoint(buttonRect.right(), buttonRect.top() + 1), + QPoint(buttonRect.right(), buttonRect.bottom() - 1) }; + painter->drawPoints(points, 4); + } + } else { + const QLine lines[3] = { + QLine(buttonRect.right(), buttonRect.top(), + buttonRect.left() + 2, buttonRect.top()), + QLine(buttonRect.left(), buttonRect.top() + 2, + buttonRect.left(), buttonRect.bottom() - 2), + QLine(buttonRect.right(), buttonRect.bottom(), + buttonRect.left() + 2, buttonRect.bottom()) }; + painter->drawLines(lines, 3); + { + const QPoint points[2] = { + QPoint(buttonRect.left() + 1, buttonRect.top() + 1), + QPoint(buttonRect.left() + 1, buttonRect.bottom() - 1) }; + painter->drawPoints(points, 2); + } + + QBrush corner = qMapBrushToRect(option->palette.shadow(), buttonRect); + qBrushSetAlphaF(&corner, qreal(0.16)); + painter->setPen(QPen(corner, 0)); + { + const QPoint points[4] = { + QPoint(buttonRect.left() + 1, buttonRect.top()), + QPoint(buttonRect.left() + 1, buttonRect.bottom()), + QPoint(buttonRect.left(), buttonRect.top() + 1), + QPoint(buttonRect.left(), buttonRect.bottom() - 1) }; + painter->drawPoints(points, 4); + } + } + + QRect fillRect = buttonRect.adjusted(2, 2, -2, -2); + // Main fill + painter->fillRect(fillRect, + qMapBrushToRect(sunken ? sunkenButtonGradientBrush + : buttonGradientBrush, option->rect)); + + // Top line + painter->setPen(QPen(qBrushLight(qMapBrushToRect(sunken ? sunkenButtonGradientBrush + : buttonGradientBrush, option->rect), 105), 0)); + if (!reverse) { + painter->drawLine(QPointF(buttonRect.left() + 1, buttonRect.top() + 1), + QPointF(buttonRect.right() - 2, buttonRect.top() + 1)); + } else { + painter->drawLine(QPointF(buttonRect.right() - 1, buttonRect.top() + 1), + QPointF(buttonRect.left() + 2, buttonRect.top() + 1)); + } + + // Bottom line + painter->setPen(QPen(qBrushDark(qMapBrushToRect(sunken ? sunkenButtonGradientBrush + : buttonGradientBrush, option->rect), 105), 0)); + if (!reverse) { + painter->drawLine(QPointF(buttonRect.left() + 1, buttonRect.bottom() - 1), + QPointF(buttonRect.right() - 2, buttonRect.bottom() - 1)); + } else { + painter->drawLine(QPointF(buttonRect.right() - 1, buttonRect.bottom() - 1), + QPointF(buttonRect.left() + 2, buttonRect.bottom() - 1)); + } + + // Left line + painter->setPen(QPen(qMapBrushToRect(sunken ? sunkenLeftLineGradientBrush + : leftLineGradientBrush, option->rect), 1)); + if (!reverse) { + painter->drawLine(QPointF(buttonRect.left() + 1, buttonRect.top() + 2), + QPointF(buttonRect.left() + 1, buttonRect.bottom() - 2)); + } else { + painter->drawLine(QPointF(buttonRect.left() + 1, buttonRect.top() + 2), + QPointF(buttonRect.left() + 1, buttonRect.bottom() - 2)); + } + + // Right line + painter->setPen(QPen(qMapBrushToRect(sunken ? sunkenRightLineGradientBrush + : rightLineGradientBrush, option->rect), 1)); + if (!reverse) { + painter->drawLine(QPointF(buttonRect.right() - 1, buttonRect.top() + 2), + QPointF(buttonRect.right() - 1, buttonRect.bottom() - 2)); + } else { + painter->drawLine(QPointF(buttonRect.right() - 1, buttonRect.top() + 2), + QPointF(buttonRect.right() - 1, buttonRect.bottom() - 2)); + } + } else { + // Start with a standard panel button fill + QStyleOptionButton buttonOption; + buttonOption.QStyleOption::operator=(*comboBox); + if (!sunken) { + buttonOption.state &= ~State_Sunken; + } + proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, painter, widget); + + // Draw the menu button separator line + QBrush border = qMapBrushToRect(option->palette.shadow(), rect); + qBrushSetAlphaF(&border, qreal(0.35)); + painter->setPen(QPen(border, 0)); + if (!reverse) { + painter->drawLine(rect.right() - menuButtonWidth + xoffset, rect.top() + 1, + rect.right() - menuButtonWidth + xoffset, rect.bottom() - 1); + } else { + painter->drawLine(rect.left() + menuButtonWidth + xoffset, rect.top() + 1, + rect.left() + menuButtonWidth + xoffset, rect.bottom() - 1); + } + } + + // Draw the little arrow + if (comboBox->subControls & SC_ComboBoxArrow) { + int left = !reverse ? rect.right() - menuButtonWidth : rect.left(); + int right = !reverse ? rect.right() : rect.left() + menuButtonWidth; + QRect arrowRect((left + right) / 2 - 3 + xoffset, + rect.center().y() - 1 + yoffset, 7, 4); + painter->setPen(QPen(qMapBrushToRect(option->palette.buttonText(), rect), 0)); + const QLine lines[3] = { + QLine(arrowRect.topLeft(), arrowRect.topRight()), + QLine(arrowRect.left() + 1, arrowRect.top() + 1, + arrowRect.right() - 1, arrowRect.top() + 1), + QLine(arrowRect.left() + 2, arrowRect.top() + 2, + arrowRect.right() - 2, arrowRect.top() + 2) }; + painter->drawLines(lines, 3); + painter->drawPoint(arrowRect.center().x(), arrowRect.bottom()); + } + + // Draw the focus rect + if ((option->state & State_HasFocus) && !comboBox->editable + && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) { + QStyleOptionFocusRect focus; + focus.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget) + .adjusted(-2, 0, 2, 0); + proxy()->drawPrimitive(PE_FrameFocusRect, &focus, painter, widget); + } + + painter->setPen(oldPen); + } + break; +#endif // QT_NO_COMBOBOX + case CC_TitleBar: + if (const QStyleOptionTitleBar *titleBar = qstyleoption_cast(option)) { + painter->save(); + bool active = (titleBar->titleBarState & State_Active); + QRect fullRect = titleBar->rect; + + // ### use palette colors instead + QColor titleBarGradientStart(active ? 0x3b508a : 0x6e6e6e); + QColor titleBarGradientStop(active ? 0x5d6e9e : 0x818181); + QColor titleBarFrameBorder(0x393939); + QColor titleBarAlphaCorner(active ? 0x4b5e7f : 0x6a6a6a); + QColor titleBarInnerTopLine(active ? 0x8e98ba : 0xa4a4a4); + QColor titleBarInnerInnerTopLine(active ? 0x57699b : 0x808080); + QColor leftCorner(active ? 0x6f7ea8 : 0x8e8e8e); + QColor rightCorner(active ? 0x44537d : 0x676767); + QColor textColor(active ? 0x282e40 : 0x282e40); + QColor textAlphaColor(active ? 0x3f4862 : 0x3f4862); + +#ifdef QT3_SUPPORT + if (widget && widget->inherits("Q3DockWindowTitleBar")) { + QStyleOptionDockWidgetV2 dockwidget; + dockwidget.QStyleOption::operator=(*option); + dockwidget.title = titleBar->text; + proxy()->drawControl(CE_DockWidgetTitle, &dockwidget, painter, widget); + } else +#endif // QT3_SUPPORT + + { + // Fill title bar gradient + qt_plastique_draw_gradient(painter, option->rect.adjusted(1, 1, -1, 0), + titleBarGradientStart, + titleBarGradientStop); + + // Frame and rounded corners + painter->setPen(titleBarFrameBorder); + + // top border line + { + const QLine lines[3] = { + QLine(fullRect.left() + 2, fullRect.top(), fullRect.right() - 2, fullRect.top()), + QLine(fullRect.left(), fullRect.top() + 2, fullRect.left(), fullRect.bottom()), + QLine(fullRect.right(), fullRect.top() + 2, fullRect.right(), fullRect.bottom()) }; + painter->drawLines(lines, 3); + const QPoint points[2] = { + QPoint(fullRect.left() + 1, fullRect.top() + 1), + QPoint(fullRect.right() - 1, fullRect.top() + 1) }; + painter->drawPoints(points, 2); + } + + // alpha corners + painter->setPen(titleBarAlphaCorner); + { + const QPoint points[4] = { + QPoint(fullRect.left() + 2, fullRect.top() + 1), + QPoint(fullRect.left() + 1, fullRect.top() + 2), + QPoint(fullRect.right() - 2, fullRect.top() + 1), + QPoint(fullRect.right() - 1, fullRect.top() + 2) }; + painter->drawPoints(points, 4); + } + + // inner top line + painter->setPen(titleBarInnerTopLine); + painter->drawLine(fullRect.left() + 3, fullRect.top() + 1, fullRect.right() - 3, fullRect.top() + 1); + + // inner inner top line + painter->setPen(titleBarInnerInnerTopLine); + painter->drawLine(fullRect.left() + 2, fullRect.top() + 2, fullRect.right() - 2, fullRect.top() + 2); + + // left and right inner + painter->setPen(leftCorner); + painter->drawLine(fullRect.left() + 1, fullRect.top() + 3, fullRect.left() + 1, fullRect.bottom()); + painter->setPen(rightCorner); + painter->drawLine(fullRect.right() - 1, fullRect.top() + 3, fullRect.right() - 1, fullRect.bottom()); + + if (titleBar->titleBarState & Qt::WindowMinimized) { + painter->setPen(titleBarFrameBorder); + painter->drawLine(fullRect.left() + 2, fullRect.bottom(), fullRect.right() - 2, fullRect.bottom()); + { + const QPoint points[2] = { + QPoint(fullRect.left() + 1, fullRect.bottom() - 1), + QPoint(fullRect.right() - 1, fullRect.bottom() - 1) }; + painter->drawPoints(points, 2); + } + painter->setPen(rightCorner); + painter->drawLine(fullRect.left() + 2, fullRect.bottom() - 1, fullRect.right() - 2, fullRect.bottom() - 1); + painter->setPen(titleBarAlphaCorner); + { + const QPoint points[4] = { + QPoint(fullRect.left() + 1, fullRect.bottom() - 2), + QPoint(fullRect.left() + 2, fullRect.bottom() - 1), + QPoint(fullRect.right() - 1, fullRect.bottom() - 2), + QPoint(fullRect.right() - 2, fullRect.bottom() - 1) }; + painter->drawPoints(points, 4); + } + } + // draw title + QRect textRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget); + + QFont font = painter->font(); + font.setBold(true); + painter->setFont(font); + painter->setPen(titleBar->palette.text().color()); + + // Attempt to align left if there is not enough room for the title + // text. Otherwise, align center. QWorkspace does elliding for us, + // and it doesn't know about the bold title, so we need to work + // around some of the width mismatches. + bool tooWide = (QFontMetrics(font).width(titleBar->text) > textRect.width()); + QTextOption option((tooWide ? Qt::AlignLeft : Qt::AlignHCenter) | Qt::AlignVCenter); + option.setWrapMode(QTextOption::NoWrap); + + painter->drawText(textRect.adjusted(1, 1, 1, 1), titleBar->text, option); + painter->setPen(titleBar->palette.highlightedText().color()); + painter->drawText(textRect, titleBar->text, option); + } + + // min button + if ((titleBar->subControls & SC_TitleBarMinButton) + && (titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) + && !(titleBar->titleBarState & Qt::WindowMinimized)) { + bool hover = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_Sunken); + + QRect minButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget); + qt_plastique_draw_mdibutton(painter, titleBar, minButtonRect, hover, sunken); + + int xoffset = minButtonRect.width() / 3; + int yoffset = minButtonRect.height() / 3; + + QRect minButtonIconRect(minButtonRect.left() + xoffset, minButtonRect.top() + yoffset, + minButtonRect.width() - xoffset * 2, minButtonRect.height() - yoffset * 2); + + painter->setPen(textColor); + { + const QLine lines[2] = { + QLine(minButtonIconRect.center().x() - 2, + minButtonIconRect.center().y() + 3, + minButtonIconRect.center().x() + 3, + minButtonIconRect.center().y() + 3), + QLine(minButtonIconRect.center().x() - 2, + minButtonIconRect.center().y() + 4, + minButtonIconRect.center().x() + 3, + minButtonIconRect.center().y() + 4) }; + painter->drawLines(lines, 2); + } + painter->setPen(textAlphaColor); + { + const QLine lines[2] = { + QLine(minButtonIconRect.center().x() - 3, + minButtonIconRect.center().y() + 3, + minButtonIconRect.center().x() - 3, + minButtonIconRect.center().y() + 4), + QLine(minButtonIconRect.center().x() + 4, + minButtonIconRect.center().y() + 3, + minButtonIconRect.center().x() + 4, + minButtonIconRect.center().y() + 4) }; + painter->drawLines(lines, 2); + } + } + + // max button + if ((titleBar->subControls & SC_TitleBarMaxButton) + && (titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) + && !(titleBar->titleBarState & Qt::WindowMaximized)) { + bool hover = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_Sunken); + + QRect maxButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget); + qt_plastique_draw_mdibutton(painter, titleBar, maxButtonRect, hover, sunken); + + int xoffset = maxButtonRect.width() / 3; + int yoffset = maxButtonRect.height() / 3; + + QRect maxButtonIconRect(maxButtonRect.left() + xoffset, maxButtonRect.top() + yoffset, + maxButtonRect.width() - xoffset * 2, maxButtonRect.height() - yoffset * 2); + + painter->setPen(textColor); + painter->drawRect(maxButtonIconRect.adjusted(0, 0, -1, -1)); + painter->drawLine(maxButtonIconRect.left() + 1, maxButtonIconRect.top() + 1, + maxButtonIconRect.right() - 1, maxButtonIconRect.top() + 1); + painter->setPen(textAlphaColor); + const QPoint points[4] = { + maxButtonIconRect.topLeft(), maxButtonIconRect.topRight(), + maxButtonIconRect.bottomLeft(), maxButtonIconRect.bottomRight() }; + painter->drawPoints(points, 4); + } + + // close button + if (titleBar->subControls & SC_TitleBarCloseButton && titleBar->titleBarFlags & Qt::WindowSystemMenuHint) { + bool hover = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_Sunken); + + QRect closeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget); + qt_plastique_draw_mdibutton(painter, titleBar, closeButtonRect, hover, sunken); + + int xoffset = closeButtonRect.width() / 3; + int yoffset = closeButtonRect.height() / 3; + + QRect closeIconRect(closeButtonRect.left() + xoffset, closeButtonRect.top() + yoffset, + closeButtonRect.width() - xoffset * 2, closeButtonRect.height() - yoffset * 2); + + painter->setPen(textAlphaColor); + { + const QLine lines[4] = { + QLine(closeIconRect.left() + 1, closeIconRect.top(), + closeIconRect.right(), closeIconRect.bottom() - 1), + QLine(closeIconRect.left(), closeIconRect.top() + 1, + closeIconRect.right() - 1, closeIconRect.bottom()), + QLine(closeIconRect.right() - 1, closeIconRect.top(), + closeIconRect.left(), closeIconRect.bottom() - 1), + QLine(closeIconRect.right(), closeIconRect.top() + 1, + closeIconRect.left() + 1, closeIconRect.bottom()) }; + painter->drawLines(lines, 4); + const QPoint points[4] = { + closeIconRect.topLeft(), closeIconRect.topRight(), + closeIconRect.bottomLeft(), closeIconRect.bottomRight() }; + painter->drawPoints(points, 4); + } + painter->setPen(textColor); + { + const QLine lines[2] = { + QLine(closeIconRect.left() + 1, closeIconRect.top() + 1, + closeIconRect.right() - 1, closeIconRect.bottom() - 1), + QLine(closeIconRect.left() + 1, closeIconRect.bottom() - 1, + closeIconRect.right() - 1, closeIconRect.top() + 1) }; + painter->drawLines(lines, 2); + } + } + + // normalize button + if ((titleBar->subControls & SC_TitleBarNormalButton) && + (((titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) && + (titleBar->titleBarState & Qt::WindowMinimized)) || + ((titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) && + (titleBar->titleBarState & Qt::WindowMaximized)))) { + bool hover = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_Sunken); + + QRect normalButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget); + qt_plastique_draw_mdibutton(painter, titleBar, normalButtonRect, hover, sunken); + int xoffset = int(normalButtonRect.width() / 3.5); + int yoffset = int(normalButtonRect.height() / 3.5); + + QRect normalButtonIconRect(normalButtonRect.left() + xoffset, normalButtonRect.top() + yoffset, + normalButtonRect.width() - xoffset * 2, normalButtonRect.height() - yoffset * 2); + + QRect frontWindowRect = normalButtonIconRect.adjusted(0, 3, -3, 0); + painter->setPen(textColor); + painter->drawRect(frontWindowRect.adjusted(0, 0, -1, -1)); + painter->drawLine(frontWindowRect.left() + 1, frontWindowRect.top() + 1, + frontWindowRect.right() - 1, frontWindowRect.top() + 1); + painter->setPen(textAlphaColor); + { + const QPoint points[4] = { + frontWindowRect.topLeft(), frontWindowRect.topRight(), + frontWindowRect.bottomLeft(), frontWindowRect.bottomRight() }; + painter->drawPoints(points, 4); + } + + QRect backWindowRect = normalButtonIconRect.adjusted(3, 0, 0, -3); + QRegion clipRegion = backWindowRect; + clipRegion -= frontWindowRect; + painter->save(); + painter->setClipRegion(clipRegion); + painter->setPen(textColor); + painter->drawRect(backWindowRect.adjusted(0, 0, -1, -1)); + painter->drawLine(backWindowRect.left() + 1, backWindowRect.top() + 1, + backWindowRect.right() - 1, backWindowRect.top() + 1); + painter->setPen(textAlphaColor); + { + const QPoint points[4] = { + backWindowRect.topLeft(), backWindowRect.topRight(), + backWindowRect.bottomLeft(), backWindowRect.bottomRight() }; + painter->drawPoints(points, 4); + } + painter->restore(); + } + + // context help button + if (titleBar->subControls & SC_TitleBarContextHelpButton + && (titleBar->titleBarFlags & Qt::WindowContextHelpButtonHint)) { + bool hover = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_Sunken); + + QRect contextHelpButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget); + + qt_plastique_draw_mdibutton(painter, titleBar, contextHelpButtonRect, hover, sunken); + + QColor blend; + // ### Use palette colors + if (active) { + blend = mergedColors(QColor(hover ? 0x7d8bb1 : 0x55689a), + QColor(hover ? 0x939ebe : 0x7381ab)); + } else { + blend = mergedColors(QColor(hover ? 0x9e9e9e : 0x818181), + QColor(hover ? 0xababab : 0x929292)); + } + QImage image(qt_titlebar_context_help); + image.setColor(4, textColor.rgba()); + image.setColor(3, mergedColors(blend, textColor, 30).rgba()); + image.setColor(2, mergedColors(blend, textColor, 70).rgba()); + image.setColor(1, mergedColors(blend, textColor, 90).rgba()); + + painter->drawImage(contextHelpButtonRect, image); + } + + // shade button + if (titleBar->subControls & SC_TitleBarShadeButton) { + bool hover = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_Sunken); + + QRect shadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget); + qt_plastique_draw_mdibutton(painter, titleBar, shadeButtonRect, hover, sunken); + + int xoffset = shadeButtonRect.width() / 3; + int yoffset = shadeButtonRect.height() / 3; + + QRect shadeButtonIconRect(shadeButtonRect.left() + xoffset, shadeButtonRect.top() + yoffset, + shadeButtonRect.width() - xoffset * 2, shadeButtonRect.height() - yoffset * 2); + + QPainterPath path(shadeButtonIconRect.bottomLeft()); + path.lineTo(shadeButtonIconRect.center().x(), shadeButtonIconRect.bottom() - shadeButtonIconRect.height() / 2); + path.lineTo(shadeButtonIconRect.bottomRight()); + path.lineTo(shadeButtonIconRect.bottomLeft()); + + painter->setPen(textAlphaColor); + painter->setBrush(textColor); + painter->drawPath(path); + } + + // unshade button + if (titleBar->subControls & SC_TitleBarUnshadeButton) { + bool hover = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_Sunken); + + QRect unshadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget); + qt_plastique_draw_mdibutton(painter, titleBar, unshadeButtonRect, hover, sunken); + + int xoffset = unshadeButtonRect.width() / 3; + int yoffset = unshadeButtonRect.height() / 3; + + QRect unshadeButtonIconRect(unshadeButtonRect.left() + xoffset, unshadeButtonRect.top() + yoffset, + unshadeButtonRect.width() - xoffset * 2, unshadeButtonRect.height() - yoffset * 2); + + int midY = unshadeButtonIconRect.bottom() - unshadeButtonIconRect.height() / 2; + QPainterPath path(QPoint(unshadeButtonIconRect.left(), midY)); + path.lineTo(unshadeButtonIconRect.right(), midY); + path.lineTo(unshadeButtonIconRect.center().x(), unshadeButtonIconRect.bottom()); + path.lineTo(unshadeButtonIconRect.left(), midY); + + painter->setPen(textAlphaColor); + painter->setBrush(textColor); + painter->drawPath(path); + } + + // from qwindowsstyle.cpp + if ((titleBar->subControls & SC_TitleBarSysMenu) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) { + bool hover = (titleBar->activeSubControls & SC_TitleBarSysMenu) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarSysMenu) && (titleBar->state & State_Sunken); + + QRect iconRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget); + if (hover) + qt_plastique_draw_mdibutton(painter, titleBar, iconRect, hover, sunken); + + if (!titleBar->icon.isNull()) { + titleBar->icon.paint(painter, iconRect); + } else { + QStyleOption tool(0); + tool.palette = titleBar->palette; + QPixmap pm = standardPixmap(SP_TitleBarMenuButton, &tool, widget); + tool.rect = iconRect; + painter->save(); + proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm); + painter->restore(); + } + } + painter->restore(); + } + break; +#ifndef QT_NO_DIAL + case CC_Dial: + if (const QStyleOptionSlider *dial = qstyleoption_cast(option)) + QStyleHelper::drawDial(dial, painter); + break; +#endif // QT_NO_DIAL + default: + QWindowsStyle::drawComplexControl(control, option, painter, widget); + break; + } +} + +/*! + \reimp +*/ +QSize QPlastiqueStyle::sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const +{ + QSize newSize = QWindowsStyle::sizeFromContents(type, option, size, widget); + + switch (type) { + case CT_RadioButton: + ++newSize.rheight(); + ++newSize.rwidth(); + break; +#ifndef QT_NO_SLIDER + case CT_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget); + if (slider->tickPosition & QSlider::TicksBelow) { + if (slider->orientation == Qt::Horizontal) + newSize.rheight() += tickSize; + else + newSize.rwidth() += tickSize; + } + if (slider->tickPosition & QSlider::TicksAbove) { + if (slider->orientation == Qt::Horizontal) + newSize.rheight() += tickSize; + else + newSize.rwidth() += tickSize; + } + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_SCROLLBAR + case CT_ScrollBar: + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast(option)) { + int scrollBarExtent = proxy()->pixelMetric(PM_ScrollBarExtent, option, widget); + int scrollBarSliderMinimum = proxy()->pixelMetric(PM_ScrollBarSliderMin, option, widget); + if (scrollBar->orientation == Qt::Horizontal) { + newSize = QSize(scrollBarExtent * 3 + scrollBarSliderMinimum, scrollBarExtent); + } else { + newSize = QSize(scrollBarExtent, scrollBarExtent * 3 + scrollBarSliderMinimum); + } + } + break; +#endif // QT_NO_SCROLLBAR +#ifndef QT_NO_SPINBOX + case CT_SpinBox: + // Make sure the size is odd + newSize.setHeight(sizeFromContents(CT_LineEdit, option, size, widget).height()); + newSize.rheight() -= ((1 - newSize.rheight()) & 1); + break; +#endif +#ifndef QT_NO_TOOLBUTTON + case CT_ToolButton: + newSize.rheight() += 3; + newSize.rwidth() += 3; + break; +#endif +#ifndef QT_NO_COMBOBOX + case CT_ComboBox: + newSize = sizeFromContents(CT_PushButton, option, size, widget); + newSize.rwidth() += 30; // Make room for drop-down indicator + newSize.rheight() += 4; + break; +#endif + case CT_MenuItem: + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast(option)) { + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) + newSize.setHeight(menuItem->text.isEmpty() ? 2 : menuItem->fontMetrics.height()); + } + break; + case CT_MenuBarItem: + newSize.setHeight(newSize.height()); + break; + default: + break; + } + + return newSize; +} + +/*! + \reimp +*/ +QRect QPlastiqueStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const +{ + QRect rect; + switch (element) { + case SE_RadioButtonIndicator: + rect = visualRect(option->direction, option->rect, + QWindowsStyle::subElementRect(element, option, widget)).adjusted(0, 0, 1, 1); + break; +#ifndef QT_NO_PROGRESSBAR + case SE_ProgressBarLabel: + case SE_ProgressBarContents: + case SE_ProgressBarGroove: + return option->rect; +#endif // QT_NO_PROGRESSBAR + default: + return QWindowsStyle::subElementRect(element, option, widget); + } + + return visualRect(option->direction, option->rect, rect); +} + +/*! + \reimp +*/ +QRect QPlastiqueStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, + SubControl subControl, const QWidget *widget) const +{ + QRect rect = QWindowsStyle::subControlRect(control, option, subControl, widget); + + switch (control) { +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget); + + switch (subControl) { + case SC_SliderHandle: + if (slider->orientation == Qt::Horizontal) { + rect.setWidth(11); + rect.setHeight(15); + int centerY = slider->rect.center().y() - rect.height() / 2; + if (slider->tickPosition & QSlider::TicksAbove) + centerY += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + centerY -= tickSize; + rect.moveTop(centerY); + } else { + rect.setWidth(15); + rect.setHeight(11); + int centerX = slider->rect.center().x() - rect.width() / 2; + if (slider->tickPosition & QSlider::TicksAbove) + centerX += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + centerX -= tickSize; + rect.moveLeft(centerX); + } + break; + case SC_SliderGroove: { + QPoint grooveCenter = slider->rect.center(); + if (slider->orientation == Qt::Horizontal) { + rect.setHeight(14); + --grooveCenter.ry(); + if (slider->tickPosition & QSlider::TicksAbove) + grooveCenter.ry() += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + grooveCenter.ry() -= tickSize; + } else { + rect.setWidth(14); + --grooveCenter.rx(); + if (slider->tickPosition & QSlider::TicksAbove) + grooveCenter.rx() += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + grooveCenter.rx() -= tickSize; + } + rect.moveCenter(grooveCenter); + break; + } + default: + break; + } + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast(option)) { + int scrollBarExtent = proxy()->pixelMetric(PM_ScrollBarExtent, scrollBar, widget); + int sliderMaxLength = ((scrollBar->orientation == Qt::Horizontal) ? + scrollBar->rect.width() : scrollBar->rect.height()) - (scrollBarExtent * 3); + int sliderMinLength = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollBar, widget); + int sliderLength; + + // calculate slider length + if (scrollBar->maximum != scrollBar->minimum) { + uint valueRange = scrollBar->maximum - scrollBar->minimum; + sliderLength = (scrollBar->pageStep * sliderMaxLength) / (valueRange + scrollBar->pageStep); + + if (sliderLength < sliderMinLength || valueRange > INT_MAX / 2) + sliderLength = sliderMinLength; + if (sliderLength > sliderMaxLength) + sliderLength = sliderMaxLength; + } else { + sliderLength = sliderMaxLength; + } + + int sliderStart = scrollBarExtent + sliderPositionFromValue(scrollBar->minimum, + scrollBar->maximum, + scrollBar->sliderPosition, + sliderMaxLength - sliderLength, + scrollBar->upsideDown); + + QRect scrollBarRect = scrollBar->rect; + + switch (subControl) { + case SC_ScrollBarSubLine: // top/left button + if (scrollBar->orientation == Qt::Horizontal) { + rect.setRect(scrollBarRect.left(), scrollBarRect.top(), scrollBarRect.width() - scrollBarExtent, scrollBarRect.height()); + } else { + rect.setRect(scrollBarRect.left(), scrollBarRect.top(), scrollBarRect.width(), scrollBarRect.height() - scrollBarExtent); + } + break; + case SC_ScrollBarAddLine: // bottom/right button + if (scrollBar->orientation == Qt::Horizontal) { + rect.setRect(scrollBarRect.right() - (scrollBarExtent - 1), scrollBarRect.top(), scrollBarExtent, scrollBarRect.height()); + } else { + rect.setRect(scrollBarRect.left(), scrollBarRect.bottom() - (scrollBarExtent - 1), scrollBarRect.width(), scrollBarExtent); + } + break; + case SC_ScrollBarSubPage: + if (scrollBar->orientation == Qt::Horizontal) { + rect.setRect(scrollBarRect.left() + scrollBarExtent, scrollBarRect.top(), + sliderStart - (scrollBarRect.left() + scrollBarExtent), scrollBarRect.height()); + } else { + rect.setRect(scrollBarRect.left(), scrollBarRect.top() + scrollBarExtent, + scrollBarRect.width(), sliderStart - (scrollBarRect.left() + scrollBarExtent)); + } + break; + case SC_ScrollBarAddPage: + if (scrollBar->orientation == Qt::Horizontal) + rect.setRect(sliderStart + sliderLength, 0, + sliderMaxLength - sliderStart - sliderLength + scrollBarExtent, scrollBarRect.height()); + else + rect.setRect(0, sliderStart + sliderLength, + scrollBarRect.width(), sliderMaxLength - sliderStart - sliderLength + scrollBarExtent); + break; + case SC_ScrollBarGroove: + if (scrollBar->orientation == Qt::Horizontal) { + rect = scrollBarRect.adjusted(scrollBarExtent, 0, -2 * scrollBarExtent, 0); + } else { + rect = scrollBarRect.adjusted(0, scrollBarExtent, 0, -2 * scrollBarExtent); + } + break; + case SC_ScrollBarSlider: + if (scrollBar->orientation == Qt::Horizontal) { + rect.setRect(sliderStart, 0, sliderLength, scrollBarRect.height()); + } else { + rect.setRect(0, sliderStart, scrollBarRect.width(), sliderLength); + } + break; + default: + break; + } + rect = visualRect(scrollBar->direction, scrollBarRect, rect); + } + break; +#endif // QT_NO_SCROLLBAR +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { + int center = spinBox->rect.height() / 2; + switch (subControl) { + case SC_SpinBoxUp: + if (spinBox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + rect = visualRect(spinBox->direction, spinBox->rect, rect); + rect.setRect(spinBox->rect.right() - 16, spinBox->rect.top(), 17, center + 1); + rect = visualRect(spinBox->direction, spinBox->rect, rect); + break; + case SC_SpinBoxDown: + if (spinBox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + rect = visualRect(spinBox->direction, spinBox->rect, rect); + rect.setRect(spinBox->rect.right() - 16, spinBox->rect.top() + center, 17, spinBox->rect.height() - center); + rect = visualRect(spinBox->direction, spinBox->rect, rect); + break; + case SC_SpinBoxEditField: + if (spinBox->buttonSymbols != QAbstractSpinBox::NoButtons) { + rect = spinBox->rect.adjusted(0, 0, -16, 0); + } else { + rect = spinBox->rect; + } + rect.adjust(blueFrameWidth, blueFrameWidth, -blueFrameWidth, -blueFrameWidth); + rect = visualRect(spinBox->direction, spinBox->rect, rect); + break; + default: + break; + } + } + break; +#endif // QT_NO_SPINBOX +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + switch (subControl) { + case SC_ComboBoxArrow: + rect = visualRect(option->direction, option->rect, rect); + rect.setRect(rect.right() - 17, rect.top() - 2, + 19, rect.height() + 4); + rect = visualRect(option->direction, option->rect, rect); + break; + case SC_ComboBoxEditField: { + if (const QStyleOptionComboBox *box = qstyleoption_cast(option)) { + int frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth); + rect = visualRect(option->direction, option->rect, rect); + + if (box->editable) { + rect = box->rect.adjusted(blueFrameWidth, blueFrameWidth, -blueFrameWidth, -blueFrameWidth); + rect.setRight(rect.right() - 16); // Overlaps the combobox button by 2 pixels + } else { + rect.setRect(option->rect.left() + frameWidth, option->rect.top() + frameWidth, + option->rect.width() - 16 - 2 * frameWidth, + option->rect.height() - 2 * frameWidth); + rect.setLeft(rect.left() + 2); + rect.setRight(rect.right() - 2); + if (box->state & (State_Sunken | State_On)) + rect.translate(1, 1); + } + rect = visualRect(option->direction, option->rect, rect); + } + break; + } + default: + break; + } + break; +#endif // QT_NO_COMBOBOX + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(option)) { + SubControl sc = subControl; + QRect &ret = rect; + const int indent = 3; + const int controlTopMargin = 4; + const int controlBottomMargin = 3; + const int controlWidthMargin = 1; + const int controlHeight = tb->rect.height() - controlTopMargin - controlBottomMargin; + const int delta = controlHeight + controlWidthMargin; + int offset = 0; + + bool isMinimized = tb->titleBarState & Qt::WindowMinimized; + bool isMaximized = tb->titleBarState & Qt::WindowMaximized; + + switch (sc) { + case SC_TitleBarLabel: + if (tb->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) { + ret = tb->rect; + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + ret.adjust(delta, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowShadeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) + ret.adjust(0, 0, -delta, 0); + ret.adjusted(indent, 0, -indent, 0); + } + break; + case SC_TitleBarContextHelpButton: + if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) + offset += delta; + case SC_TitleBarMinButton: + if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarMinButton) + break; + case SC_TitleBarNormalButton: + if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarNormalButton) + break; + case SC_TitleBarMaxButton: + if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarMaxButton) + break; + case SC_TitleBarShadeButton: + if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarShadeButton) + break; + case SC_TitleBarUnshadeButton: + if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarUnshadeButton) + break; + case SC_TitleBarCloseButton: + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + offset += delta; + else if (sc == SC_TitleBarCloseButton) + break; + ret.setRect(tb->rect.right() - indent - offset, tb->rect.top() + controlTopMargin, + controlHeight, controlHeight); + break; + case SC_TitleBarSysMenu: + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) { + ret.setRect(tb->rect.left() + controlWidthMargin + indent, tb->rect.top() + controlTopMargin, + controlHeight, controlHeight); + } + break; + default: + break; + } + ret = visualRect(tb->direction, tb->rect, ret); + } + break; + default: + break; + } + + return rect; +} + +/*! + \reimp +*/ +int QPlastiqueStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, + QStyleHintReturn *returnData) const +{ + int ret = 0; + switch (hint) { + case SH_WindowFrame_Mask: + ret = 1; + if (QStyleHintReturnMask *mask = qstyleoption_cast(returnData)) { + mask->region = option->rect; + mask->region -= QRect(option->rect.left(), option->rect.top(), 2, 1); + mask->region -= QRect(option->rect.right() - 1, option->rect.top(), 2, 1); + mask->region -= QRect(option->rect.left(), option->rect.top() + 1, 1, 1); + mask->region -= QRect(option->rect.right(), option->rect.top() + 1, 1, 1); + + const QStyleOptionTitleBar *titleBar = qstyleoption_cast(option); + if (titleBar && (titleBar->titleBarState & Qt::WindowMinimized)) { + mask->region -= QRect(option->rect.left(), option->rect.bottom(), 2, 1); + mask->region -= QRect(option->rect.right() - 1, option->rect.bottom(), 2, 1); + mask->region -= QRect(option->rect.left(), option->rect.bottom() - 1, 1, 1); + mask->region -= QRect(option->rect.right(), option->rect.bottom() - 1, 1, 1); + } else { + mask->region -= QRect(option->rect.bottomLeft(), QSize(1, 1)); + mask->region -= QRect(option->rect.bottomRight(), QSize(1, 1)); + } + } + break; + case SH_TitleBar_NoBorder: + ret = 1; + break; + case SH_TitleBar_AutoRaise: + ret = 1; + break; + case SH_ItemView_ShowDecorationSelected: + ret = true; + break; + case SH_ToolBox_SelectedPageTitleBold: + case SH_ScrollBar_MiddleClickAbsolutePosition: + ret = true; + break; + case SH_MainWindow_SpaceBelowMenuBar: + ret = 0; + break; + case SH_FormLayoutWrapPolicy: + ret = QFormLayout::DontWrapRows; + break; + case SH_FormLayoutFieldGrowthPolicy: + ret = QFormLayout::ExpandingFieldsGrow; + break; + case SH_FormLayoutFormAlignment: + ret = Qt::AlignLeft | Qt::AlignTop; + break; + case SH_FormLayoutLabelAlignment: + ret = Qt::AlignRight; + break; + case SH_MessageBox_TextInteractionFlags: + ret = Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse; + break; + case SH_LineEdit_PasswordCharacter: + ret = QCommonStyle::styleHint(hint, option, widget, returnData); + break; + case SH_ItemView_ArrowKeysNavigateIntoChildren: + ret = true; + break; + case SH_Menu_SubMenuPopupDelay: + ret = 96; // from Plastik + break; +#ifdef Q_WS_X11 + case SH_DialogButtonBox_ButtonsHaveIcons: + ret = true; + break; +#endif +#ifndef Q_OS_WIN + case SH_Menu_AllowActiveAndDisabled: + ret = false; + break; +#endif + default: + ret = QWindowsStyle::styleHint(hint, option, widget, returnData); + break; + } + return ret; +} + +/*! + \reimp +*/ +QStyle::SubControl QPlastiqueStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, + const QPoint &pos, const QWidget *widget) const +{ + SubControl ret = SC_None; + switch (control) { +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast(option)) { + QRect slider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget); + if (slider.contains(pos)) { + ret = SC_ScrollBarSlider; + break; + } + + QRect scrollBarAddLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget); + if (scrollBarAddLine.contains(pos)) { + ret = SC_ScrollBarAddLine; + break; + } + + QRect scrollBarSubPage = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubPage, widget); + if (scrollBarSubPage.contains(pos)) { + ret = SC_ScrollBarSubPage; + break; + } + + QRect scrollBarAddPage = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddPage, widget); + if (scrollBarAddPage.contains(pos)) { + ret = SC_ScrollBarAddPage; + break; + } + + QRect scrollBarSubLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget); + if (scrollBarSubLine.contains(pos)) { + ret = SC_ScrollBarSubLine; + break; + } + } + break; +#endif // QT_NO_SCROLLBAR + default: + break; + } + + return ret != SC_None ? ret : QWindowsStyle::hitTestComplexControl(control, option, pos, widget); +} + +/*! + \reimp +*/ +int QPlastiqueStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const +{ + int ret = -1; + switch (metric) { + case PM_MenuVMargin: + case PM_MenuHMargin: + ret = 0; + break; + case PM_ButtonShiftHorizontal: + case PM_ButtonShiftVertical: + ret = 1; + break; + case PM_ButtonDefaultIndicator: + ret = 0; + break; +#ifndef QT_NO_SLIDER + case PM_SliderThickness: + ret = 15; + break; + case PM_SliderLength: + case PM_SliderControlThickness: + ret = 11; + break; + case PM_SliderTickmarkOffset: + ret = 5; + break; + case PM_SliderSpaceAvailable: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + int size = 15; + if (slider->tickPosition & QSlider::TicksBelow) + ++size; + if (slider->tickPosition & QSlider::TicksAbove) + ++size; + ret = size; + break; + } +#endif // QT_NO_SLIDER + case PM_ScrollBarExtent: + ret = 16; + break; + case PM_ScrollBarSliderMin: + ret = 26; + break; + case PM_ProgressBarChunkWidth: + ret = 1; + break; + case PM_MenuBarItemSpacing: + ret = 3; + break; + case PM_MenuBarVMargin: + ret = 2; + break; + case PM_MenuBarHMargin: + ret = 0; + break; + case PM_MenuBarPanelWidth: + ret = 1; + break; + case PM_ToolBarHandleExtent: + ret = 9; + break; + case PM_ToolBarSeparatorExtent: + ret = 2; + break; + case PM_ToolBarItemSpacing: + ret = 1; + break; + case PM_ToolBarItemMargin: + ret = 1; + break; + case PM_ToolBarFrameWidth: + ret = 2; + break; + case PM_SplitterWidth: + ret = 6; + break; + case PM_DockWidgetSeparatorExtent: + ret = 6; + break; + case PM_DockWidgetHandleExtent: + ret = 20; + break; + case PM_DefaultFrameWidth: +#ifndef QT_NO_MENU + if (qobject_cast(widget)) { + ret = 1; + break; + } +#endif + ret = 2; + break; + case PM_MdiSubWindowFrameWidth: + ret = 4; + break; + case PM_TitleBarHeight: +#ifdef QT3_SUPPORT + if (widget && widget->inherits("Q3DockWindowTitleBar")) { + // Q3DockWindow has smaller title bars than QDockWidget + ret = qMax(widget->fontMetrics().height(), 20); + } else +#endif + ret = qMax(widget ? widget->fontMetrics().height() : + (option ? option->fontMetrics.height() : 0), 30); + break; + case PM_MaximumDragDistance: + return -1; + case PM_DockWidgetTitleMargin: + return 2; + case PM_LayoutHorizontalSpacing: + case PM_LayoutVerticalSpacing: + return -1; // rely on layoutHorizontalSpacing() + case PM_LayoutLeftMargin: + case PM_LayoutTopMargin: + case PM_LayoutRightMargin: + case PM_LayoutBottomMargin: + { + bool isWindow = false; + if (option) { + isWindow = (option->state & State_Window); + } else if (widget) { + isWindow = widget->isWindow(); + } + + if (isWindow) { + ret = 11; + } else { + ret = 9; + } + } + default: + break; + } + + return ret != -1 ? ret : QWindowsStyle::pixelMetric(metric, option, widget); +} + +/*! + \reimp +*/ +QPalette QPlastiqueStyle::standardPalette() const +{ + QPalette palette; + + palette.setBrush(QPalette::Disabled, QPalette::WindowText, QColor(QRgb(0xff808080))); + palette.setBrush(QPalette::Disabled, QPalette::Button, QColor(QRgb(0xffdddfe4))); + palette.setBrush(QPalette::Disabled, QPalette::Light, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Disabled, QPalette::Midlight, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Disabled, QPalette::Dark, QColor(QRgb(0xff555555))); + palette.setBrush(QPalette::Disabled, QPalette::Mid, QColor(QRgb(0xffc7c7c7))); + palette.setBrush(QPalette::Disabled, QPalette::Text, QColor(QRgb(0xffc7c7c7))); + palette.setBrush(QPalette::Disabled, QPalette::BrightText, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Disabled, QPalette::ButtonText, QColor(QRgb(0xff808080))); + palette.setBrush(QPalette::Disabled, QPalette::Base, QColor(QRgb(0xffefefef))); + palette.setBrush(QPalette::Disabled, QPalette::AlternateBase, palette.color(QPalette::Disabled, QPalette::Base).darker(110)); + palette.setBrush(QPalette::Disabled, QPalette::Window, QColor(QRgb(0xffefefef))); + palette.setBrush(QPalette::Disabled, QPalette::Shadow, QColor(QRgb(0xff000000))); + palette.setBrush(QPalette::Disabled, QPalette::Highlight, QColor(QRgb(0xff567594))); + palette.setBrush(QPalette::Disabled, QPalette::HighlightedText, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Disabled, QPalette::Link, QColor(QRgb(0xff0000ee))); + palette.setBrush(QPalette::Disabled, QPalette::LinkVisited, QColor(QRgb(0xff52188b))); + palette.setBrush(QPalette::Active, QPalette::WindowText, QColor(QRgb(0xff000000))); + palette.setBrush(QPalette::Active, QPalette::Button, QColor(QRgb(0xffdddfe4))); + palette.setBrush(QPalette::Active, QPalette::Light, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Active, QPalette::Midlight, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Active, QPalette::Dark, QColor(QRgb(0xff555555))); + palette.setBrush(QPalette::Active, QPalette::Mid, QColor(QRgb(0xffc7c7c7))); + palette.setBrush(QPalette::Active, QPalette::Text, QColor(QRgb(0xff000000))); + palette.setBrush(QPalette::Active, QPalette::BrightText, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Active, QPalette::ButtonText, QColor(QRgb(0xff000000))); + palette.setBrush(QPalette::Active, QPalette::Base, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Active, QPalette::AlternateBase, palette.color(QPalette::Active, QPalette::Base).darker(110)); + palette.setBrush(QPalette::Active, QPalette::Window, QColor(QRgb(0xffefefef))); + palette.setBrush(QPalette::Active, QPalette::Shadow, QColor(QRgb(0xff000000))); + palette.setBrush(QPalette::Active, QPalette::Highlight, QColor(QRgb(0xff678db2))); + palette.setBrush(QPalette::Active, QPalette::HighlightedText, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Active, QPalette::Link, QColor(QRgb(0xff0000ee))); + palette.setBrush(QPalette::Active, QPalette::LinkVisited, QColor(QRgb(0xff52188b))); + palette.setBrush(QPalette::Inactive, QPalette::WindowText, QColor(QRgb(0xff000000))); + palette.setBrush(QPalette::Inactive, QPalette::Button, QColor(QRgb(0xffdddfe4))); + palette.setBrush(QPalette::Inactive, QPalette::Light, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Inactive, QPalette::Midlight, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Inactive, QPalette::Dark, QColor(QRgb(0xff555555))); + palette.setBrush(QPalette::Inactive, QPalette::Mid, QColor(QRgb(0xffc7c7c7))); + palette.setBrush(QPalette::Inactive, QPalette::Text, QColor(QRgb(0xff000000))); + palette.setBrush(QPalette::Inactive, QPalette::BrightText, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Inactive, QPalette::ButtonText, QColor(QRgb(0xff000000))); + palette.setBrush(QPalette::Inactive, QPalette::Base, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Inactive, QPalette::AlternateBase, palette.color(QPalette::Inactive, QPalette::Base).darker(110)); + palette.setBrush(QPalette::Inactive, QPalette::Window, QColor(QRgb(0xffefefef))); + palette.setBrush(QPalette::Inactive, QPalette::Shadow, QColor(QRgb(0xff000000))); + palette.setBrush(QPalette::Inactive, QPalette::Highlight, QColor(QRgb(0xff678db2))); + palette.setBrush(QPalette::Inactive, QPalette::HighlightedText, QColor(QRgb(0xffffffff))); + palette.setBrush(QPalette::Inactive, QPalette::Link, QColor(QRgb(0xff0000ee))); + palette.setBrush(QPalette::Inactive, QPalette::LinkVisited, QColor(QRgb(0xff52188b))); + return palette; +} + +/*! + \reimp +*/ +void QPlastiqueStyle::polish(QWidget *widget) +{ + if (qobject_cast(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast(widget) +#endif +#ifndef QT_NO_SPINBOX + || qobject_cast(widget) +#endif + || qobject_cast(widget) +#ifndef QT_NO_GROUPBOX + || qobject_cast(widget) +#endif + || qobject_cast(widget) +#ifndef QT_NO_SPLITTER + || qobject_cast(widget) +#endif +#ifndef QT_NO_TABBAR + || qobject_cast(widget) +#endif + ) { + widget->setAttribute(Qt::WA_Hover); + } + + if (widget->inherits("QWorkspaceTitleBar") + || widget->inherits("QDockSeparator") + || widget->inherits("QDockWidgetSeparator") + || widget->inherits("Q3DockWindowResizeHandle")) { + widget->setAttribute(Qt::WA_Hover); + } + + if (false // to simplify the #ifdefs +#ifndef QT_NO_MENUBAR + || qobject_cast(widget) +#endif +#ifdef QT3_SUPPORT + || widget->inherits("Q3ToolBar") +#endif +#ifndef QT_NO_TOOLBAR + || qobject_cast(widget) + || (widget && qobject_cast(widget->parent())) +#endif + ) { + widget->setBackgroundRole(QPalette::Window); + } + +#ifndef QT_NO_PROGRESSBAR + if (AnimateBusyProgressBar && qobject_cast(widget)) + widget->installEventFilter(this); +#endif + +#if defined QPlastique_MaskButtons + if (qobject_cast(widget) || qobject_cast(widget)) + widget->installEventFilter(this); +#endif +} + +/*! + \reimp +*/ +void QPlastiqueStyle::unpolish(QWidget *widget) +{ + if (qobject_cast(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast(widget) +#endif +#ifndef QT_NO_SPINBOX + || qobject_cast(widget) +#endif + || qobject_cast(widget) +#ifndef QT_NO_GROUPBOX + || qobject_cast(widget) +#endif +#ifndef QT_NO_SPLITTER + || qobject_cast(widget) +#endif +#ifndef QT_NO_TABBAR + || qobject_cast(widget) +#endif + || qobject_cast(widget)) { + widget->setAttribute(Qt::WA_Hover, false); + } + + if (widget->inherits("QWorkspaceTitleBar") + || widget->inherits("QDockSeparator") + || widget->inherits("QDockWidgetSeparator") + || widget->inherits("Q3DockWindowResizeHandle")) { + widget->setAttribute(Qt::WA_Hover, false); + } + + if (false // to simplify the #ifdefs +#ifndef QT_NO_MENUBAR + || qobject_cast(widget) +#endif +#ifndef QT_NO_TOOLBOX + || qobject_cast(widget) +#endif +#ifdef QT3_SUPPORT + || widget->inherits("Q3ToolBar") +#endif +#ifndef QT_NO_TOOLBAR + || qobject_cast(widget) + || (widget && qobject_cast(widget->parent())) +#endif + ) { + widget->setBackgroundRole(QPalette::Button); + } + +#ifndef QT_NO_PROGRESSBAR + if (AnimateBusyProgressBar && qobject_cast(widget)) { + Q_D(QPlastiqueStyle); + widget->removeEventFilter(this); + d->bars.removeAll(static_cast(widget)); + } +#endif + +#if defined QPlastique_MaskButtons + if (qobject_cast(widget) || qobject_cast(widget)) + widget->removeEventFilter(this); +#endif +} + +/*! + \reimp +*/ +void QPlastiqueStyle::polish(QApplication *app) +{ + QWindowsStyle::polish(app); +} + +/*! + \reimp +*/ +void QPlastiqueStyle::polish(QPalette &pal) +{ + QWindowsStyle::polish(pal); +#ifdef Q_WS_MAC + pal.setBrush(QPalette::Shadow, Qt::black); +#endif +} + +/*! + \reimp +*/ +void QPlastiqueStyle::unpolish(QApplication *app) +{ + QWindowsStyle::unpolish(app); +} + +/*! + \internal +*/ +QIcon QPlastiqueStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget) const +{ + return QWindowsStyle::standardIconImplementation(standardIcon, option, widget); +} + +/*! + \reimp +*/ +QPixmap QPlastiqueStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget) const +{ + return QWindowsStyle::standardPixmap(standardPixmap, opt, widget); +} + +// this works as long as we have at most 16 different control types +#define CT1(c) CT2(c, c) +#define CT2(c1, c2) (((uint)c1 << 16) | (uint)c2) + +/*! + \internal +*/ +int QPlastiqueStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1, + QSizePolicy::ControlType control2, + Qt::Orientation orientation, + const QStyleOption * /* option */, + const QWidget * /* widget */) const +{ + const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton; + + if (control2 == QSizePolicy::ButtonBox) + return 11; + + if ((control1 | control2) & ButtonMask) + return (orientation == Qt::Horizontal) ? 10 : 9; + + switch (CT2(control1, control2)) { + case CT1(QSizePolicy::Label): + case CT2(QSizePolicy::Label, QSizePolicy::DefaultType): + case CT2(QSizePolicy::Label, QSizePolicy::CheckBox): + case CT2(QSizePolicy::Label, QSizePolicy::ComboBox): + case CT2(QSizePolicy::Label, QSizePolicy::LineEdit): + case CT2(QSizePolicy::Label, QSizePolicy::RadioButton): + case CT2(QSizePolicy::Label, QSizePolicy::Slider): + case CT2(QSizePolicy::Label, QSizePolicy::SpinBox): + case CT2(QSizePolicy::Label, QSizePolicy::ToolButton): + return 5; + case CT2(QSizePolicy::CheckBox, QSizePolicy::RadioButton): + case CT2(QSizePolicy::RadioButton, QSizePolicy::CheckBox): + case CT1(QSizePolicy::CheckBox): + if (orientation == Qt::Vertical) + return 2; + case CT1(QSizePolicy::RadioButton): + if (orientation == Qt::Vertical) + return 1; + } + + if (orientation == Qt::Horizontal + && (control2 & (QSizePolicy::CheckBox | QSizePolicy::RadioButton))) + return 8; + + if ((control1 | control2) & (QSizePolicy::Frame + | QSizePolicy::GroupBox + | QSizePolicy::TabWidget)) { + return 11; + } + + if ((control1 | control2) & (QSizePolicy::Line | QSizePolicy::Slider + | QSizePolicy::LineEdit | QSizePolicy::ComboBox + | QSizePolicy::SpinBox)) + return 7; + + return 6; +} + +/*! + \reimp +*/ +bool QPlastiqueStyle::eventFilter(QObject *watched, QEvent *event) +{ +#ifndef QT_NO_PROGRESSBAR + Q_D(QPlastiqueStyle); + + switch (event->type()) { + case QEvent::Show: + if (QProgressBar *bar = qobject_cast(watched)) { + d->bars.append(bar); + if (d->bars.size() == 1) { + Q_ASSERT(ProgressBarFps > 0); + d->timer.start(); + d->progressBarAnimateTimer = startTimer(1000 / ProgressBarFps); + } + } + break; + case QEvent::Destroy: + case QEvent::Hide: + if(!d->bars.isEmpty()) { + d->bars.removeAll(reinterpret_cast(watched)); + if (d->bars.isEmpty()) { + killTimer(d->progressBarAnimateTimer); + d->progressBarAnimateTimer = 0; + } + } + break; +#if defined QPlastique_MaskButtons + case QEvent::Resize: + if (qobject_cast(watched) || qobject_cast(watched)) { + QWidget *widget = qobject_cast(watched); + QRect rect = widget->rect(); + QRegion region(rect); + region -= QRect(rect.left(), rect.top(), 2, 1); + region -= QRect(rect.left(), rect.top() + 1, 1, 1); + region -= QRect(rect.left(), rect.bottom(), 2, 1); + region -= QRect(rect.left(), rect.bottom() - 1, 1, 1); + region -= QRect(rect.right() - 1, rect.top(), 2, 1); + region -= QRect(rect.right(), rect.top() + 1, 1, 1); + region -= QRect(rect.right() - 1, rect.bottom(), 2, 1); + region -= QRect(rect.right(), rect.bottom() - 1, 1, 1); + widget->setMask(region); + } + break; +#endif + default: + break; + } +#endif // QT_NO_PROGRESSBAR + + return QWindowsStyle::eventFilter(watched, event); +} + +/*! + \reimp +*/ +void QPlastiqueStyle::timerEvent(QTimerEvent *event) +{ +#ifndef QT_NO_PROGRESSBAR + Q_D(QPlastiqueStyle); + + if (event->timerId() == d->progressBarAnimateTimer) { + Q_ASSERT(ProgressBarFps > 0); + d->animateStep = d->timer.elapsed() / (1000 / ProgressBarFps); + foreach (QProgressBar *bar, d->bars) { + if (AnimateProgressBar || (bar->minimum() == 0 && bar->maximum() == 0)) + bar->update(); + } + } +#endif // QT_NO_PROGRESSBAR + event->ignore(); +} + +QT_END_NAMESPACE + +#endif // !defined(QT_NO_STYLE_PLASTIQUE) || defined(QT_PLUGIN) diff --git a/src/widgets/styles/qplastiquestyle.h b/src/widgets/styles/qplastiquestyle.h new file mode 100644 index 0000000000..20d2f490a6 --- /dev/null +++ b/src/widgets/styles/qplastiquestyle.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLASTIQUESTYLE_H +#define QPLASTIQUESTYLE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_STYLE_PLASTIQUE) + +class QPlastiqueStylePrivate; +class Q_GUI_EXPORT QPlastiqueStyle : public QWindowsStyle +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QPlastiqueStyle) +public: + QPlastiqueStyle(); + ~QPlastiqueStyle(); + + void drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget = 0) const; + void drawControl(ControlElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const; + void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const; + QSize sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const; + + QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const; + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, + SubControl sc, const QWidget *widget) const; + + int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, + QStyleHintReturn *returnData = 0) const; + SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, + const QPoint &pos, const QWidget *widget = 0) const; + + int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const; + + QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget = 0) const; + + void polish(QWidget *widget); + void polish(QApplication *app); + void polish(QPalette &pal); + void unpolish(QWidget *widget); + void unpolish(QApplication *app); + + QPalette standardPalette() const; + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt = 0, + const QWidget *widget = 0) const; + int layoutSpacingImplementation(QSizePolicy::ControlType control1, + QSizePolicy::ControlType control2, + Qt::Orientation orientation, + const QStyleOption *option = 0, + const QWidget *widget = 0) const; + +protected: + bool eventFilter(QObject *watched, QEvent *event); + void timerEvent(QTimerEvent *event); + +private: + Q_DISABLE_COPY(QPlastiqueStyle) + void *reserved; +}; + +#endif // QT_NO_STYLE_PLASTIQUE + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLASTIQUESTYLE_H diff --git a/src/widgets/styles/qproxystyle.cpp b/src/widgets/styles/qproxystyle.cpp new file mode 100644 index 0000000000..516d17fa69 --- /dev/null +++ b/src/widgets/styles/qproxystyle.cpp @@ -0,0 +1,420 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include "qproxystyle.h" +#include "qstylefactory.h" +#include + +#if !defined(QT_NO_STYLE_PROXY) || defined(QT_PLUGIN) + +QT_BEGIN_NAMESPACE + +/*! + \class QProxyStyle + + \brief The QProxyStyle class is a convenience class that simplifies + dynamically overriding QStyle elements. + + \since 4.6 + + A QProxyStyle wraps a QStyle (usually the default system style) for the + purpose of dynamically overriding painting or other specific style behavior. + + The following example shows how to override the shortcut underline + behavior on any platform: + + \snippet doc/src/snippets/code/src_gui_qproxystyle.cpp 1 + + Warning: The \l {QCommonStyle} {common styles} provided by Qt will + respect this hint, because they call QStyle::proxy(), but there is + no guarantee that QStyle::proxy() will be called for user defined + or system controlled styles. It would not work on a Mac, for + example, where menus are handled by the operating system. + + \sa QStyle +*/ + +void QProxyStylePrivate::ensureBaseStyle() const +{ + Q_Q(const QProxyStyle); + + if (baseStyle) + return; + + if (!baseStyle && !QApplicationPrivate::styleOverride.isEmpty()) { + baseStyle = QStyleFactory::create(QApplicationPrivate::styleOverride); + if (baseStyle) { + // If baseStyle is an instance of the same proxyStyle + // we destroy it and fall back to the desktop style + if (qstrcmp(baseStyle->metaObject()->className(), + q->metaObject()->className()) == 0) { + delete baseStyle; + baseStyle = 0; + } + } + } + + if (!baseStyle) // Use application desktop style + baseStyle = QStyleFactory::create(QApplicationPrivate::desktopStyleKey()); + + if (!baseStyle) // Fallback to windows style + baseStyle = QStyleFactory::create(QLatin1String("windows")); + + baseStyle->setProxy(const_cast(q)); + baseStyle->setParent(const_cast(q)); // Take ownership +} + +/*! + Constructs a QProxyStyle object for overriding behavior in \a style + or in the current application \l{QStyle}{style} if \a style is 0 + (default). Normally \a style is 0, because you want to override + behavior in the system style. + + Ownership of \a style is transferred to QProxyStyle. +*/ +QProxyStyle::QProxyStyle(QStyle *style) : + QCommonStyle(*new QProxyStylePrivate()) +{ + Q_D(QProxyStyle); + if (style) { + style->setProxy(this); + style->setParent(this); // Take ownership + d->baseStyle = style; + } +} + +/*! + Destroys the QProxyStyle object. +*/ +QProxyStyle::~QProxyStyle() +{ +} + +/*! + Returns the proxy base style object. If no base style + is set on the proxy style, QProxyStyle will create + an instance of the application style instead. + + \sa setBaseStyle(), QStyle +*/ +QStyle *QProxyStyle::baseStyle() const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle; +} + +/*! + Sets the base style that should be proxied. + + Ownership of \a style is transferred to QProxyStyle. + + If style is zero, a desktop-dependant style will be + assigned automatically. +*/ +void QProxyStyle::setBaseStyle(QStyle *style) +{ + Q_D (QProxyStyle); + + if (d->baseStyle && d->baseStyle->parent() == this) + d->baseStyle->deleteLater(); + + d->baseStyle = style; + + if (d->baseStyle) { + d->baseStyle->setProxy(this); + d->baseStyle->setParent(this); + } +} + +/*! \reimp + */ +void QProxyStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + d->baseStyle->drawPrimitive(element, option, painter, widget); +} + +/*! + \reimp + */ +void QProxyStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + d->baseStyle->drawControl(element, option, painter, widget); +} + +/*! \reimp + */ +void QProxyStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + d->baseStyle->drawComplexControl(control, option, painter, widget); +} + +/*! \reimp + */ +void QProxyStyle::drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled, + const QString &text, QPalette::ColorRole textRole) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + d->baseStyle->drawItemText(painter, rect, flags, pal, enabled, text, textRole); +} + +/*! \reimp + */ +void QProxyStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + d->baseStyle->drawItemPixmap(painter, rect, alignment, pixmap); +} + +/*! \reimp + */ +QSize QProxyStyle::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->sizeFromContents(type, option, size, widget); +} + +/*! \reimp + */ +QRect QProxyStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->subElementRect(element, option, widget); +} + +/*! \reimp + */ +QRect QProxyStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc, const QWidget *widget) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->subControlRect(cc, option, sc, widget); +} + +/*! \reimp + */ +QRect QProxyStyle::itemTextRect(const QFontMetrics &fm, const QRect &r, int flags, bool enabled, const QString &text) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->itemTextRect(fm, r, flags, enabled, text); +} + +/*! \reimp + */ +QRect QProxyStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->itemPixmapRect(r, flags, pixmap); +} + +/*! \reimp + */ +QStyle::SubControl QProxyStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->hitTestComplexControl(control, option, pos, widget); +} + +/*! \reimp + */ +int QProxyStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->styleHint(hint, option, widget, returnData); +} + +/*! \reimp + */ +int QProxyStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->pixelMetric(metric, option, widget); +} + +/*! \reimp + */ +QPixmap QProxyStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->standardPixmap(standardPixmap, opt, widget); +} + +/*! \reimp + */ +QPixmap QProxyStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->generatedIconPixmap(iconMode, pixmap, opt); +} + +/*! \reimp + */ +QPalette QProxyStyle::standardPalette() const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->standardPalette(); +} + +/*! \reimp + */ +void QProxyStyle::polish(QWidget *widget) +{ + Q_D (QProxyStyle); + d->ensureBaseStyle(); + d->baseStyle->polish(widget); +} + +/*! \reimp + */ +void QProxyStyle::polish(QPalette &pal) +{ + Q_D (QProxyStyle); + d->ensureBaseStyle(); + d->baseStyle->polish(pal); +} + +/*! \reimp + */ +void QProxyStyle::polish(QApplication *app) +{ + Q_D (QProxyStyle); + d->ensureBaseStyle(); + d->baseStyle->polish(app); +} + +/*! \reimp + */ +void QProxyStyle::unpolish(QWidget *widget) +{ + Q_D (QProxyStyle); + d->ensureBaseStyle(); + d->baseStyle->unpolish(widget); +} + +/*! \reimp + */ +void QProxyStyle::unpolish(QApplication *app) +{ + Q_D (QProxyStyle); + d->ensureBaseStyle(); + d->baseStyle->unpolish(app); +} + +/*! \reimp + */ +bool QProxyStyle::event(QEvent *e) +{ + Q_D (QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->event(e); +} + +/*! + Returns an icon for the given \a standardIcon. + + Reimplement this slot to provide your own icons in a QStyle + subclass. The \a option argument can be used to pass extra + information required to find the appropriate icon. The \a widget + argument is optional and can also be used to help find the icon. + + \note Because of binary compatibility constraints, standardIcon() + introduced in Qt 4.1 is not virtual. Therefore it must dynamically + detect and call \e this slot. This default implementation simply + calls standardIcon() with the given parameters. + + \sa standardIcon() + */ +QIcon QProxyStyle::standardIconImplementation(StandardPixmap standardIcon, + const QStyleOption *option, + const QWidget *widget) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->standardIcon(standardIcon, option, widget); +} + +/*! + This slot is called by layoutSpacing() to determine the spacing that + should be used between \a control1 and \a control2 in a layout. \a + orientation specifies whether the controls are laid out side by side + or stacked vertically. The \a option parameter can be used to pass + extra information about the parent widget. The \a widget parameter + is optional and can also be used if \a option is 0. + + The default implementation returns -1. + + \sa layoutSpacing(), combinedLayoutSpacing() + */ +int QProxyStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1, + QSizePolicy::ControlType control2, + Qt::Orientation orientation, + const QStyleOption *option, + const QWidget *widget) const +{ + Q_D (const QProxyStyle); + d->ensureBaseStyle(); + return d->baseStyle->layoutSpacing(control1, control2, orientation, option, widget); +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_PROXY diff --git a/src/widgets/styles/qproxystyle.h b/src/widgets/styles/qproxystyle.h new file mode 100644 index 0000000000..9d4a5cc56c --- /dev/null +++ b/src/widgets/styles/qproxystyle.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPROXYSTYLE_H +#define QPROXYSTYLE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_STYLE_PROXY) + +class QProxyStylePrivate; +class Q_GUI_EXPORT QProxyStyle : public QCommonStyle +{ + Q_OBJECT + +public: + QProxyStyle(QStyle *baseStyle = 0); + ~QProxyStyle(); + + QStyle *baseStyle() const; + void setBaseStyle(QStyle *style); + + void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const; + void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const; + void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = 0) const; + void drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled, + const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const; + virtual void drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const; + + QSize sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const; + + QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const; + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const; + QRect itemTextRect(const QFontMetrics &fm, const QRect &r, int flags, bool enabled, const QString &text) const; + QRect itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const; + + SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget = 0) const; + int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const; + int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const; + + QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget = 0) const; + QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const; + QPalette standardPalette() const; + + void polish(QWidget *widget); + void polish(QPalette &pal); + void polish(QApplication *app); + + void unpolish(QWidget *widget); + void unpolish(QApplication *app); + +protected: + bool event(QEvent *e); + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const; + int layoutSpacingImplementation(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, + Qt::Orientation orientation, const QStyleOption *option = 0, const QWidget *widget = 0) const; +private: + Q_DISABLE_COPY(QProxyStyle) + Q_DECLARE_PRIVATE(QProxyStyle) +}; + +#endif // QT_NO_STYLE_PROXY + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPROXYSTYLE_H diff --git a/src/widgets/styles/qproxystyle_p.h b/src/widgets/styles/qproxystyle_p.h new file mode 100644 index 0000000000..8c330d0330 --- /dev/null +++ b/src/widgets/styles/qproxystyle_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPROXYSTYLE_P_H +#define QPROXYSTYLE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qcommonstyle.h" +#include "qcommonstyle_p.h" +#include "qproxystyle.h" + +#ifndef QT_NO_STYLE_PROXY + +QT_BEGIN_NAMESPACE + +class QProxyStylePrivate : public QCommonStylePrivate +{ + Q_DECLARE_PUBLIC(QProxyStyle) +public: + void ensureBaseStyle() const; +private: + QProxyStylePrivate() : + QCommonStylePrivate(), baseStyle(0) {} + mutable QPointer baseStyle; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_PROXY + +#endif //QPROXYSTYLE_P_H diff --git a/src/widgets/styles/qs60style.cpp b/src/widgets/styles/qs60style.cpp new file mode 100644 index 0000000000..fa6eeb7b36 --- /dev/null +++ b/src/widgets/styles/qs60style.cpp @@ -0,0 +1,3618 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qs60style_p.h" + +#include "qapplication.h" +#include "qpainter.h" +#include "qstyleoption.h" +#include "qevent.h" +#include "qpixmapcache.h" + +#include "qcalendarwidget.h" +#include "qdial.h" +#include "qdialog.h" +#include "qmessagebox.h" +#include "qgroupbox.h" +#include "qheaderview.h" +#include "qlist.h" +#include "qlistwidget.h" +#include "qlistview.h" +#include "qmenu.h" +#include "qmenubar.h" +#include "qpushbutton.h" +#include "qscrollarea.h" +#include "qscrollbar.h" +#include "qtabbar.h" +#include "qtableview.h" +#include "qtextedit.h" +#include "qtoolbar.h" +#include "qtoolbutton.h" +#include "qfocusframe.h" +#include "qformlayout.h" +#include "qradiobutton.h" +#include "qcheckbox.h" +#include "qdesktopwidget.h" +#include "qprogressbar.h" +#include "qlabel.h" + +#include "private/qtoolbarextension_p.h" +#include "private/qcombobox_p.h" +#include "private/qwidget_p.h" +#include "private/qapplication_p.h" +#include "private/qfont_p.h" + +#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN) + +QT_BEGIN_NAMESPACE + +const QS60StylePrivate::SkinElementFlags QS60StylePrivate::KDefaultSkinElementFlags = + SkinElementFlags(SF_PointNorth | SF_StateEnabled); + +static const qreal goldenRatio = 1.618; + +const layoutHeader QS60StylePrivate::m_layoutHeaders[] = { +// *** generated layout data *** +{240,320,1,19,"QVGA Landscape"}, +{320,240,1,19,"QVGA Portrait"}, +{360,640,1,19,"NHD Landscape"}, +{640,360,1,19,"NHD Portrait"}, +{352,800,1,12,"E90 Landscape"}, +{480,640,1,19,"VGA Landscape"} +// *** End of generated data *** +}; +const int QS60StylePrivate::m_numberOfLayouts = + (int)sizeof(QS60StylePrivate::m_layoutHeaders)/sizeof(QS60StylePrivate::m_layoutHeaders[0]); + +const short QS60StylePrivate::data[][MAX_PIXELMETRICS] = { +// *** generated pixel metrics *** +{5,0,-909,0,0,2,0,2,-1,7,12,22,15,15,7,198,-909,-909,-909,20,13,2,0,0,21,7,18,30,3,3,1,-909,-909,0,1,0,0,12,20,15,15,18,18,1,115,18,0,-909,-909,-909,-909,0,0,16,2,-909,0,0,-909,16,-909,-909,-909,-909,32,18,55,24,55,4,4,4,9,13,-909,5,51,11,5,0,3,3,6,8,3,3,-909,2,-909,-909,-909,-909,5,5,3,1,106}, +{5,0,-909,0,0,1,0,2,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,8,27,28,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,3,3,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,2,-909,-909,-909,-909,6,6,3,1,106}, +{7,0,-909,0,0,2,0,5,-1,25,69,46,37,37,9,258,-909,-909,-909,23,19,11,0,0,32,25,72,44,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,13,3,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1,135}, +{7,0,-909,0,0,2,0,5,-1,25,68,46,37,37,9,258,-909,-909,-909,31,19,13,0,0,32,25,60,52,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,96,35,96,12,3,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1,135}, +{7,0,-909,0,0,2,0,2,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,7,32,30,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1,106}, +{9,0,-909,0,0,2,0,5,-1,34,99,76,51,51,25,352,-909,-909,-909,29,25,7,0,0,43,34,42,76,7,7,2,-909,-909,0,9,14,0,23,39,30,30,37,37,9,391,40,0,-909,-909,-909,-909,0,0,29,2,-909,0,0,-909,29,-909,-909,-909,-909,115,37,96,48,96,19,19,9,1,25,-909,9,101,24,9,0,7,7,7,16,7,7,-909,3,-909,-909,-909,-909,9,9,3,1,184} +// *** End of generated data *** +}; + +const short *QS60StylePrivate::m_pmPointer = QS60StylePrivate::data[0]; + +// theme background texture +QPixmap *QS60StylePrivate::m_background = 0; +QPixmap *QS60StylePrivate::m_placeHolderTexture = 0; + +// theme palette +QPalette *QS60StylePrivate::m_themePalette = 0; + +qint64 QS60StylePrivate::m_webPaletteKey = 0; + +QPointer QS60StylePrivate::m_pressedWidget = 0; + +const struct QS60StylePrivate::frameElementCenter QS60StylePrivate::m_frameElementsData[] = { + {SE_ButtonNormal, QS60StyleEnums::SP_QsnFrButtonTbCenter}, + {SE_ButtonPressed, QS60StyleEnums::SP_QsnFrButtonTbCenterPressed}, + {SE_FrameLineEdit, QS60StyleEnums::SP_QsnFrInputCenter}, + {SE_ListHighlight, QS60StyleEnums::SP_QsnFrListCenter}, + {SE_PopupBackground, QS60StyleEnums::SP_QsnFrPopupCenter}, + {SE_SettingsList, QS60StyleEnums::SP_QsnFrSetOptCenter}, + {SE_TableItem, QS60StyleEnums::SP_QsnFrCaleCenter}, + {SE_TableHeaderItem, QS60StyleEnums::SP_QsnFrCaleHeadingCenter}, + {SE_ToolTip, QS60StyleEnums::SP_QsnFrPopupPreviewCenter}, + {SE_ToolBar, QS60StyleEnums::SP_QsnFrPopupSubCenter}, + {SE_ToolBarButton, QS60StyleEnums::SP_QgnFrSctrlButtonCenter}, + {SE_ToolBarButtonPressed, QS60StyleEnums::SP_QgnFrSctrlButtonCenterPressed}, + {SE_PanelBackground, QS60StyleEnums::SP_QsnFrSetOptCenter}, + {SE_ButtonInactive, QS60StyleEnums::SP_QsnFrButtonCenterInactive}, + {SE_Editor, QS60StyleEnums::SP_QsnFrInputCenter}, + {SE_TableItemPressed, QS60StyleEnums::SP_QsnFrGridCenterPressed}, + {SE_ListItemPressed, QS60StyleEnums::SP_QsnFrListCenterPressed}, +}; + +static const int frameElementsCount = + int(sizeof(QS60StylePrivate::m_frameElementsData)/sizeof(QS60StylePrivate::m_frameElementsData[0])); + +const int KNotFound = -909; +const double KTabFontMul = 0.72; + +QS60StylePrivate::~QS60StylePrivate() +{ + clearCaches(); //deletes also background image + if (m_placeHolderTexture) { + delete m_placeHolderTexture; + m_placeHolderTexture = 0; + } + deleteThemePalette(); +#ifdef Q_WS_S60 + removeAnimations(); +#endif +} + +void QS60StylePrivate::drawSkinElement(SkinElements element, QPainter *painter, + const QRect &rect, SkinElementFlags flags) +{ + switch (element) { + case SE_ButtonNormal: + drawFrame(SF_ButtonNormal, painter, rect, flags | SF_PointNorth); + break; + case SE_ButtonPressed: + drawFrame(SF_ButtonPressed, painter, rect, flags | SF_PointNorth); + break; + case SE_FrameLineEdit: + drawFrame(SF_FrameLineEdit, painter, rect, flags | SF_PointNorth); + break; + case SE_ProgressBarGrooveHorizontal: + drawRow(QS60StyleEnums::SP_QgnGrafBarFrameSideL, QS60StyleEnums::SP_QgnGrafBarFrameCenter, + QS60StyleEnums::SP_QgnGrafBarFrameSideR, Qt::Horizontal, painter, rect, flags | SF_PointNorth); + break; + case SE_ProgressBarGrooveVertical: + drawRow(QS60StyleEnums::SP_QgnGrafBarFrameSideL, QS60StyleEnums::SP_QgnGrafBarFrameCenter, + QS60StyleEnums::SP_QgnGrafBarFrameSideR, Qt::Vertical, painter, rect, flags | SF_PointEast); + break; + case SE_ProgressBarIndicatorHorizontal: + drawPart(QS60StyleEnums::SP_QgnGrafBarProgress, painter, rect, flags | SF_PointNorth); + break; + case SE_ProgressBarIndicatorVertical: + drawPart(QS60StyleEnums::SP_QgnGrafBarProgress, painter, rect, flags | SF_PointWest); + break; + case SE_ScrollBarGrooveHorizontal: + drawRow(QS60StyleEnums::SP_QsnCpScrollBgBottom, QS60StyleEnums::SP_QsnCpScrollBgMiddle, + QS60StyleEnums::SP_QsnCpScrollBgTop, Qt::Horizontal, painter, rect, flags | SF_PointEast); + break; + case SE_ScrollBarGrooveVertical: + drawRow(QS60StyleEnums::SP_QsnCpScrollBgTop, QS60StyleEnums::SP_QsnCpScrollBgMiddle, + QS60StyleEnums::SP_QsnCpScrollBgBottom, Qt::Vertical, painter, rect, flags | SF_PointNorth); + break; + case SE_ScrollBarHandleHorizontal: + drawRow(QS60StyleEnums::SP_QsnCpScrollHandleBottom, QS60StyleEnums::SP_QsnCpScrollHandleMiddle, + QS60StyleEnums::SP_QsnCpScrollHandleTop, Qt::Horizontal, painter, rect, flags | SF_PointEast); + break; + case SE_ScrollBarHandleVertical: + drawRow(QS60StyleEnums::SP_QsnCpScrollHandleTop, QS60StyleEnums::SP_QsnCpScrollHandleMiddle, + QS60StyleEnums::SP_QsnCpScrollHandleBottom, Qt::Vertical, painter, rect, flags | SF_PointNorth); + break; + case SE_SliderHandleHorizontal: + drawPart(QS60StyleEnums::SP_QgnGrafNsliderMarker, painter, rect, flags | SF_PointNorth); + break; + case SE_SliderHandleVertical: + drawPart(QS60StyleEnums::SP_QgnGrafNsliderMarker, painter, rect, flags | SF_PointEast); + break; + case SE_SliderHandleSelectedHorizontal: + drawPart(QS60StyleEnums::SP_QgnGrafNsliderMarkerSelected, painter, rect, flags | SF_PointNorth); + break; + case SE_SliderHandleSelectedVertical: + drawPart(QS60StyleEnums::SP_QgnGrafNsliderMarkerSelected, painter, rect, flags | SF_PointEast); + break; + case SE_SliderGrooveVertical: + drawRow(QS60StyleEnums::SP_QgnGrafNsliderEndLeft, QS60StyleEnums::SP_QgnGrafNsliderMiddle, + QS60StyleEnums::SP_QgnGrafNsliderEndRight, Qt::Vertical, painter, rect, flags | SF_PointEast); + break; + case SE_SliderGrooveHorizontal: + drawRow(QS60StyleEnums::SP_QgnGrafNsliderEndLeft, QS60StyleEnums::SP_QgnGrafNsliderMiddle, + QS60StyleEnums::SP_QgnGrafNsliderEndRight, Qt::Horizontal, painter, rect, flags | SF_PointNorth); + break; + case SE_TabBarTabEastActive: + drawRow(QS60StyleEnums::SP_QgnGrafTabActiveL, QS60StyleEnums::SP_QgnGrafTabActiveM, + QS60StyleEnums::SP_QgnGrafTabActiveR, Qt::Vertical, painter, rect, flags | SF_PointEast); + break; + case SE_TabBarTabEastInactive: + drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveL, QS60StyleEnums::SP_QgnGrafTabPassiveM, + QS60StyleEnums::SP_QgnGrafTabPassiveR, Qt::Vertical, painter, rect, flags | SF_PointEast); + break; + case SE_TabBarTabNorthActive: + drawRow(QS60StyleEnums::SP_QgnGrafTabActiveL, QS60StyleEnums::SP_QgnGrafTabActiveM, + QS60StyleEnums::SP_QgnGrafTabActiveR, Qt::Horizontal, painter, rect, flags | SF_PointNorth); + break; + case SE_TabBarTabNorthInactive: + drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveL, QS60StyleEnums::SP_QgnGrafTabPassiveM, + QS60StyleEnums::SP_QgnGrafTabPassiveR, Qt::Horizontal, painter, rect, flags | SF_PointNorth); + break; + case SE_TabBarTabSouthActive: + drawRow(QS60StyleEnums::SP_QgnGrafTabActiveR, QS60StyleEnums::SP_QgnGrafTabActiveM, + QS60StyleEnums::SP_QgnGrafTabActiveL, Qt::Horizontal, painter, rect, flags | SF_PointSouth); + break; + case SE_TabBarTabSouthInactive: + drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveR, QS60StyleEnums::SP_QgnGrafTabPassiveM, + QS60StyleEnums::SP_QgnGrafTabPassiveL, Qt::Horizontal, painter, rect, flags | SF_PointSouth); + break; + case SE_TabBarTabWestActive: + drawRow(QS60StyleEnums::SP_QgnGrafTabActiveR, QS60StyleEnums::SP_QgnGrafTabActiveM, + QS60StyleEnums::SP_QgnGrafTabActiveL, Qt::Vertical, painter, rect, flags | SF_PointWest); + break; + case SE_TabBarTabWestInactive: + drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveR, QS60StyleEnums::SP_QgnGrafTabPassiveM, + QS60StyleEnums::SP_QgnGrafTabPassiveL, Qt::Vertical, painter, rect, flags | SF_PointWest); + break; + case SE_ListHighlight: + drawFrame(SF_ListHighlight, painter, rect, flags | SF_PointNorth); + break; + case SE_PopupBackground: + drawFrame(SF_PopupBackground, painter, rect, flags | SF_PointNorth); + break; + case SE_SettingsList: + drawFrame(SF_SettingsList, painter, rect, flags | SF_PointNorth); + break; + case SE_TableItem: + drawFrame(SF_TableItem, painter, rect, flags | SF_PointNorth); + break; + case SE_TableHeaderItem: + drawFrame(SF_TableHeaderItem, painter, rect, flags | SF_PointNorth); + break; + case SE_ToolTip: + drawFrame(SF_ToolTip, painter, rect, flags | SF_PointNorth); + break; + case SE_ToolBar: + drawFrame(SF_ToolBar, painter, rect, flags | SF_PointNorth); + break; + case SE_ToolBarButton: + drawFrame(SF_ToolBarButton, painter, rect, flags | SF_PointNorth); + break; + case SE_ToolBarButtonPressed: + drawFrame(SF_ToolBarButtonPressed, painter, rect, flags | SF_PointNorth); + break; + case SE_PanelBackground: + drawFrame(SF_PanelBackground, painter, rect, flags | SF_PointNorth); + break; + case SE_ScrollBarHandlePressedHorizontal: + drawRow(QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed, QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed, + QS60StyleEnums::SP_QsnCpScrollHandleTopPressed, Qt::Horizontal, painter, rect, flags | SF_PointEast); + break; + case SE_ScrollBarHandlePressedVertical: + drawRow(QS60StyleEnums::SP_QsnCpScrollHandleTopPressed, QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed, + QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed, Qt::Vertical, painter, rect, flags | SF_PointNorth); + break; + case SE_ButtonInactive: + drawFrame(SF_ButtonInactive, painter, rect, flags | SF_PointNorth); + break; + case SE_Editor: + drawFrame(SF_FrameLineEdit, painter, rect, flags | SF_PointNorth); + break; + case SE_DropArea: + drawPart(QS60StyleEnums::SP_QgnGrafOrgBgGrid, painter, rect, flags | SF_PointNorth); + break; + case SE_TableItemPressed: + drawFrame(SF_TableItemPressed, painter, rect, flags | SF_PointNorth); + break; + case SE_ListItemPressed: + drawFrame(SF_ListItemPressed, painter, rect, flags | SF_PointNorth); + break; + default: + break; + } +} + +void QS60StylePrivate::drawSkinPart(QS60StyleEnums::SkinParts part, + QPainter *painter, const QRect &rect, SkinElementFlags flags) +{ + drawPart(part, painter, rect, flags); +} + +short QS60StylePrivate::pixelMetric(int metric) +{ + //If it is a custom value, need to strip away the base to map to internal + //pixel metric value table + if (metric & QStyle::PM_CustomBase) { + metric -= QStyle::PM_CustomBase; + metric += MAX_NON_CUSTOM_PIXELMETRICS - 1; + } + + Q_ASSERT(metric < MAX_PIXELMETRICS); + const short returnValue = m_pmPointer[metric]; + return returnValue; +} + +QColor QS60StylePrivate::stateColor(const QColor &color, const QStyleOption *option) +{ + QColor retColor (color); + if (option && !(option->state & QStyle::State_Enabled)) { + QColor hsvColor = retColor.toHsv(); + int colorSat = hsvColor.saturation(); + int colorVal = hsvColor.value(); + colorSat = (colorSat != 0) ? (colorSat >> 1) : 128; + colorVal = (colorVal != 0) ? (colorVal >> 1) : 128; + hsvColor.setHsv(hsvColor.hue(), colorSat, colorVal); + retColor = hsvColor.toRgb(); + } + return retColor; +} + +QColor QS60StylePrivate::lighterColor(const QColor &baseColor) +{ + QColor result(baseColor); + bool modifyColor = false; + if (result.saturation() == 0) { + result.setHsv(result.hue(), 128, result.value()); + modifyColor = true; + } + if (result.value() == 0) { + result.setHsv(result.hue(), result.saturation(), 128); + modifyColor = true; + } + if (modifyColor) + result = result.lighter(175); + else + result = result.lighter(225); + return result; +} + +bool QS60StylePrivate::drawsOwnThemeBackground(const QWidget *widget) +{ + return (widget ? (widget->windowType() == Qt::Dialog) : false); +} + +QFont QS60StylePrivate::s60Font( + QS60StyleEnums::FontCategories fontCategory, + int pointSize, bool resolveFontSize) const +{ + QFont result; + int actualPointSize = pointSize; + if (actualPointSize <= 0) { + const QFont appFont = QApplication::font(); + actualPointSize = appFont.pointSize(); + if (actualPointSize <= 0) + actualPointSize = appFont.pixelSize() * 72 / qt_defaultDpiY(); + } + Q_ASSERT(actualPointSize > 0); + const QPair key(fontCategory, actualPointSize); + if (!m_mappedFontsCache.contains(key)) { + result = s60Font_specific(fontCategory, actualPointSize, resolveFontSize); + m_mappedFontsCache.insert(key, result); + } else { + result = m_mappedFontsCache.value(key); + if (result.pointSize() != actualPointSize) + result.setPointSize(actualPointSize); + } + return result; +} + +void QS60StylePrivate::clearCaches(CacheClearReason reason) +{ + switch(reason){ + case CC_LayoutChange: + // when layout changes, the colors remain in cache, but graphics and fonts can change + m_mappedFontsCache.clear(); + QPixmapCache::clear(); + break; + case CC_ThemeChange: + QPixmapCache::clear(); +#ifdef Q_WS_S60 + deleteStoredSettings(); +#endif + deleteBackground(); + break; + case CC_UndefinedChange: + default: + m_mappedFontsCache.clear(); + QPixmapCache::clear(); + deleteBackground(); + break; + } +} + +QColor QS60StylePrivate::calculatedColor(SkinFrameElements frame) const +{ + const int frameCornerWidth = pixelMetric(PM_FrameCornerWidth); + const int frameCornerHeight = pixelMetric(PM_FrameCornerHeight); + Q_ASSERT(2 * frameCornerWidth < 32); + Q_ASSERT(2 * frameCornerHeight < 32); + + const QImage frameImage = QS60StylePrivate::frame(frame, QSize(32, 32)).toImage(); + Q_ASSERT(frameImage.bytesPerLine() > 0); + if (frameImage.isNull()) + return Qt::black; + + const QRgb *pixelRgb = (const QRgb*)frameImage.constBits(); + const int pixels = frameImage.byteCount() / sizeof(QRgb); + + int estimatedRed = 0; + int estimatedGreen = 0; + int estimatedBlue = 0; + + int skips = 0; + int estimations = 0; + + const int topBorderLastPixel = frameCornerHeight * frameImage.width() - 1; + const int bottomBorderFirstPixel = frameImage.width() * frameImage.height() - topBorderLastPixel; + const int rightBorderFirstPixel = frameImage.width() - frameCornerWidth; + const int leftBorderLastPixel = frameCornerWidth; + + while ((skips + estimations) < pixels) { + if ((skips + estimations) > topBorderLastPixel && + (skips + estimations) < bottomBorderFirstPixel) { + for (int rowIndex = 0; rowIndex < frameImage.width(); rowIndex++) { + if (rowIndex > leftBorderLastPixel && + rowIndex < rightBorderFirstPixel) { + estimatedRed += qRed(*pixelRgb); + estimatedGreen += qGreen(*pixelRgb); + estimatedBlue += qBlue(*pixelRgb); + } + pixelRgb++; + estimations++; + } + } else { + pixelRgb++; + skips++; + } + } + QColor frameColor(estimatedRed/estimations, estimatedGreen/estimations, estimatedBlue/estimations); + return !estimations ? Qt::black : frameColor; +} + +void QS60StylePrivate::setThemePalette(QApplication *app) const +{ + Q_UNUSED(app) + QPalette widgetPalette = QPalette(Qt::white); + setThemePalette(&widgetPalette); +} + +QPalette* QS60StylePrivate::themePalette() +{ + return m_themePalette; +} + +bool QS60StylePrivate::equalToThemePalette(QColor color, QPalette::ColorRole role) +{ + if (!m_themePalette) + return false; + if (color == m_themePalette->color(role)) + return true; + return false; +} + +bool QS60StylePrivate::equalToThemePalette(qint64 cacheKey, QPalette::ColorRole role) +{ + if (!m_themePalette) + return false; + if (cacheKey == m_themePalette->brush(role).texture().cacheKey()) + return true; + return false; +} + +void QS60StylePrivate::setBackgroundTexture(QApplication *app) const +{ + Q_UNUSED(app) + QPalette applicationPalette = QApplication::palette(); + // The initial QPalette::Window is just a placeHolder QPixmap to save RAM + // if the actual texture is not needed. The real texture is created just before + // painting it in qt_s60_fill_background(). + applicationPalette.setBrush(QPalette::Window, placeHolderTexture()); + setThemePalette(&applicationPalette); +} + +void QS60StylePrivate::deleteBackground() +{ + if (m_background) { + delete m_background; + m_background = 0; + } +} + +void QS60StylePrivate::setCurrentLayout(int index) +{ + m_pmPointer = data[index]; +} + +void QS60StylePrivate::drawPart(QS60StyleEnums::SkinParts skinPart, + QPainter *painter, const QRect &rect, SkinElementFlags flags) +{ + static const bool doCache = +#if defined(Q_WS_S60) + // Freezes on 3.1. Anyways, caching is only really needed on touch UI + !(QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2); +#else + true; +#endif + + const QPixmap skinPartPixMap((doCache ? cachedPart : part)(skinPart, rect.size(), painter, flags)); + if (!skinPartPixMap.isNull()) + painter->drawPixmap(rect.topLeft(), skinPartPixMap); +} + +void QS60StylePrivate::drawFrame(SkinFrameElements frameElement, QPainter *painter, const QRect &rect, SkinElementFlags flags) +{ + static const bool doCache = +#if defined(Q_WS_S60) + // Freezes on 3.1. Anyways, caching is only really needed on touch UI + !(QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2); +#else + true; +#endif + const QPixmap frameElementPixMap((doCache ? cachedFrame : frame)(frameElement, rect.size(), flags)); + if (!frameElementPixMap.isNull()) + painter->drawPixmap(rect.topLeft(), frameElementPixMap); +} + +void QS60StylePrivate::drawRow(QS60StyleEnums::SkinParts start, + QS60StyleEnums::SkinParts middle, QS60StyleEnums::SkinParts end, + Qt::Orientation orientation, QPainter *painter, const QRect &rect, + SkinElementFlags flags) +{ + QSize startEndSize(partSize(start, flags)); + startEndSize.scale(rect.size(), Qt::KeepAspectRatio); + + QRect startRect = QRect(rect.topLeft(), startEndSize); + QRect middleRect = rect; + QRect endRect; + + if (orientation == Qt::Horizontal) { + startRect.setHeight(rect.height()); + startRect.setWidth(qMin((rect.width() >> 1) - 1, startRect.width())); + endRect = startRect.translated(rect.width() - startRect.width(), 0); + middleRect.adjust(startRect.width(), 0, -startRect.width(), 0); + if (startRect.bottomRight().x() > endRect.topLeft().x()) { + const int overlap = (startRect.bottomRight().x() - endRect.topLeft().x()) >> 1; + startRect.setWidth(startRect.width() - overlap); + endRect.adjust(overlap, 0, 0, 0); + } + } else { + startRect.setWidth(rect.width()); + startRect.setHeight(qMin((rect.height() >> 1) - 1, startRect.height())); + endRect = startRect.translated(0, rect.height() - startRect.height()); + middleRect.adjust(0, startRect.height(), 0, -startRect.height()); + if (startRect.topRight().y() > endRect.bottomLeft().y()) { + const int overlap = (startRect.topRight().y() - endRect.bottomLeft().y()) >> 1; + startRect.setHeight(startRect.height() - overlap); + endRect.adjust(0, overlap, 0, 0); + } + } + +#if 0 + painter->save(); + painter->setOpacity(.3); + painter->fillRect(startRect, Qt::red); + painter->fillRect(middleRect, Qt::green); + painter->fillRect(endRect, Qt::blue); + painter->restore(); +#else + drawPart(start, painter, startRect, flags); + if (middleRect.isValid()) + drawPart(middle, painter, middleRect, flags); + drawPart(end, painter, endRect, flags); +#endif +} + +QPixmap QS60StylePrivate::cachedPart(QS60StyleEnums::SkinParts part, + const QSize &size, QPainter *painter, SkinElementFlags flags) +{ + QPixmap result; + const int animationFrame = (flags & SF_Animation) ? currentAnimationFrame(part) : 0; + + const QString cacheKey = + QString::fromLatin1("S60Style: SkinParts=%1 QSize=%2|%3 SkinPartFlags=%4 AnimationFrame=%5") + .arg((int)part).arg(size.width()).arg(size.height()).arg((int)flags).arg(animationFrame); + if (!QPixmapCache::find(cacheKey, result)) { + result = QS60StylePrivate::part(part, size, painter, flags); + QPixmapCache::insert(cacheKey, result); + } + return result; +} + +QPixmap QS60StylePrivate::cachedFrame(SkinFrameElements frame, const QSize &size, SkinElementFlags flags) +{ + QPixmap result; + const QString cacheKey = + QString::fromLatin1("S60Style: SkinFrameElements=%1 QSize=%2|%3 SkinElementFlags=%4") + .arg((int)frame).arg(size.width()).arg(size.height()).arg((int)flags); + if (!QPixmapCache::find(cacheKey, result)) { + result = QS60StylePrivate::frame(frame, size, flags); + QPixmapCache::insert(cacheKey, result); + } + return result; +} + +void QS60StylePrivate::setFont(QWidget *widget) const +{ + QS60StyleEnums::FontCategories fontCategory = QS60StyleEnums::FC_Undefined; + if (!widget) + return; + if (qobject_cast(widget)){ + fontCategory = QS60StyleEnums::FC_Primary; + } else if (qobject_cast(widget)){ + fontCategory = QS60StyleEnums::FC_Primary; + } else if (qobject_cast(widget)){ + fontCategory = QS60StyleEnums::FC_Secondary; + } else if (qobject_cast(widget)){ + fontCategory = QS60StyleEnums::FC_Title; + } else if (qobject_cast(widget)){ + fontCategory = QS60StyleEnums::FC_Primary; + } else if (qobject_cast(widget)){ + fontCategory = QS60StyleEnums::FC_Primary; + } else if (qobject_cast(widget)){ + fontCategory = QS60StyleEnums::FC_Secondary; + } + if (fontCategory != QS60StyleEnums::FC_Undefined) { + const bool resolveFontSize = widget->testAttribute(Qt::WA_SetFont) + && (widget->font().resolve() & QFont::SizeResolved); + const QFont suggestedFont = + s60Font(fontCategory, widget->font().pointSizeF(), resolveFontSize); + widget->setFont(suggestedFont); + } +} + +void QS60StylePrivate::setThemePalette(QWidget *widget) +{ + if(!widget) + return; + + //header view and its viewport need to be set 100% transparent button color, since drawing code will + //draw transparent theme graphics to table column and row headers. + if (qobject_cast(widget)){ + QPalette widgetPalette = QApplication::palette(widget); + widgetPalette.setColor(QPalette::Active, QPalette::ButtonText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 23, 0)); + QHeaderView* header = qobject_cast(widget); + widgetPalette.setColor(QPalette::Button, Qt::transparent ); + if (header->viewport()) + header->viewport()->setPalette(widgetPalette); + QApplication::setPalette(widgetPalette, "QHeaderView"); + } else if (qobject_cast(widget)) { + if (widget->window() && widget->window()->windowType() == Qt::Dialog) { + QPalette widgetPalette = widget->palette(); + widgetPalette.setColor(QPalette::WindowText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 19, 0)); + widget->setPalette(widgetPalette); + } + } +} + +void QS60StylePrivate::setThemePalette(QPalette *palette) const +{ + if (!palette) + return; + + // basic colors + palette->setColor(QPalette::WindowText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0)); + palette->setColor(QPalette::ButtonText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 20, 0)); + palette->setColor(QPalette::Text, + s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0)); + palette->setColor(QPalette::ToolTipText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 55, 0)); + palette->setColor(QPalette::BrightText, palette->color(QPalette::WindowText).lighter()); + palette->setColor(QPalette::HighlightedText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0)); + palette->setColor(QPalette::Link, + s60Color(QS60StyleEnums::CL_QsnHighlightColors, 3, 0)); + palette->setColor(QPalette::LinkVisited, palette->color(QPalette::Link).darker()); + palette->setColor(QPalette::Highlight, + s60Color(QS60StyleEnums::CL_QsnHighlightColors, 2, 0)); + // The initial QPalette::Window is just a placeHolder QPixmap to save RAM + // if the actual texture is not needed. The real texture is created just before + // painting it in qt_s60_fill_background(). + palette->setBrush(QPalette::Window, placeHolderTexture()); + // set as transparent so that styled full screen theme background is visible + palette->setBrush(QPalette::Base, Qt::transparent); + // set button color based on pixel colors +#ifndef Q_WS_S60 + //For emulated style, just calculate the color every time + const QColor buttonColor = calculatedColor(SF_ButtonNormal); +#else + const QColor buttonColor = colorFromFrameGraphics(SF_ButtonNormal); +#endif + palette->setColor(QPalette::Button, buttonColor); + palette->setColor(QPalette::Light, palette->color(QPalette::Button).lighter()); + palette->setColor(QPalette::Dark, palette->color(QPalette::Button).darker()); + palette->setColor(QPalette::Midlight, palette->color(QPalette::Button).lighter(125)); + palette->setColor(QPalette::Mid, palette->color(QPalette::Button).darker(150)); + palette->setColor(QPalette::Shadow, Qt::black); + QColor alternateBase = palette->light().color(); + alternateBase.setAlphaF(0.8); + palette->setColor(QPalette::AlternateBase, alternateBase); + + QApplication::setPalette(*palette); //calling QApplication::setPalette clears palette hash + setThemePaletteHash(palette); + storeThemePalette(palette); +} + +void QS60StylePrivate::deleteThemePalette() +{ + if (m_themePalette) { + delete m_themePalette; + m_themePalette = 0; + } +} + +void QS60StylePrivate::storeThemePalette(QPalette *palette) +{ + deleteThemePalette(); + //store specified palette for latter use. + m_themePalette = new QPalette(*palette); +} + +// set widget specific palettes +void QS60StylePrivate::setThemePaletteHash(QPalette *palette) +{ + if (!palette) + return; + + //store the original palette + QPalette widgetPalette = *palette; + const QColor mainAreaTextColor = + s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0); + + widgetPalette.setColor(QPalette::WindowText, + s60Color(QS60StyleEnums::CL_QsnLineColors, 8, 0)); + QApplication::setPalette(widgetPalette, "QSlider"); + // return to original palette after each widget + widgetPalette = *palette; + + widgetPalette.setColor(QPalette::Active, QPalette::ButtonText, mainAreaTextColor); + widgetPalette.setColor(QPalette::Inactive, QPalette::ButtonText, mainAreaTextColor); + const QStyleOption opt; + widgetPalette.setColor(QPalette::Disabled, QPalette::ButtonText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 6, &opt)); + QApplication::setPalette(widgetPalette, "QPushButton"); + widgetPalette = *palette; + + widgetPalette.setColor(QPalette::Active, QPalette::ButtonText, mainAreaTextColor); + widgetPalette.setColor(QPalette::Inactive, QPalette::ButtonText, mainAreaTextColor); + QApplication::setPalette(widgetPalette, "QToolButton"); + widgetPalette = *palette; + + widgetPalette.setColor(QPalette::Active, QPalette::ButtonText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 23, 0)); + QApplication::setPalette(widgetPalette, "QHeaderView"); + widgetPalette = *palette; + + widgetPalette.setColor(QPalette::ButtonText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 8, 0)); + QApplication::setPalette(widgetPalette, "QMenuBar"); + widgetPalette = *palette; + + widgetPalette.setColor(QPalette::Text, + s60Color(QS60StyleEnums::CL_QsnTextColors, 22, 0)); + widgetPalette.setColor(QPalette::HighlightedText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0)); + QApplication::setPalette(widgetPalette, "QMenu"); + widgetPalette = *palette; + + widgetPalette.setColor(QPalette::WindowText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 4, 0)); + widgetPalette.setColor(QPalette::HighlightedText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 3, 0)); + QApplication::setPalette(widgetPalette, "QTabBar"); + widgetPalette = *palette; + + widgetPalette.setColor(QPalette::HighlightedText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0)); + QApplication::setPalette(widgetPalette, "QListView"); + widgetPalette = *palette; + + widgetPalette.setColor(QPalette::Text, + s60Color(QS60StyleEnums::CL_QsnTextColors, 22, 0)); + widgetPalette.setColor(QPalette::HighlightedText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0)); + QApplication::setPalette(widgetPalette, "QTableView"); + widgetPalette = *palette; + + widgetPalette.setColor(QPalette::Text, + s60Color(QS60StyleEnums::CL_QsnTextColors, 27, 0)); + widgetPalette.setColor(QPalette::HighlightedText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0)); + QApplication::setPalette(widgetPalette, "QLineEdit"); + QApplication::setPalette(widgetPalette, "QTextEdit"); + QApplication::setPalette(widgetPalette, "QComboBox"); + QApplication::setPalette(widgetPalette, "QSpinBox"); + widgetPalette = *palette; + + widgetPalette.setColor(QPalette::WindowText, s60Color(QS60StyleEnums::CL_QsnTextColors, 7, 0)); + widgetPalette.setColor(QPalette::HighlightedText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0)); + QApplication::setPalette(widgetPalette, "QRadioButton"); + QApplication::setPalette(widgetPalette, "QCheckBox"); + widgetPalette = *palette; + + widgetPalette.setColor(QPalette::WindowText, mainAreaTextColor); + widgetPalette.setColor(QPalette::Button, QApplication::palette().color(QPalette::Button)); + widgetPalette.setColor(QPalette::Dark, mainAreaTextColor.darker()); + widgetPalette.setColor(QPalette::Light, mainAreaTextColor.lighter()); + QApplication::setPalette(widgetPalette, "QDial"); + widgetPalette = *palette; + + widgetPalette.setBrush(QPalette::Window, QBrush()); + QApplication::setPalette(widgetPalette, "QScrollArea"); + widgetPalette = *palette; + + //Webpages should not use S60 theme colors as they are designed to work + //with themeBackground and do not generally mesh well with web page backgrounds. + QPalette webPalette = *palette; + webPalette.setColor(QPalette::WindowText, Qt::black); + webPalette.setColor(QPalette::Text, Qt::black); + webPalette.setBrush(QPalette::Base, Qt::white); + + QApplication::setPalette(webPalette, "QWebView"); + QApplication::setPalette(webPalette, "QGraphicsWebView"); + + m_webPaletteKey = webPalette.cacheKey(); +} + +QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlags flags) +{ + QSize result(20, 20); + switch (part) + { + case QS60StyleEnums::SP_QgnGrafBarProgress: + result.setWidth(pixelMetric(QStyle::PM_ProgressBarChunkWidth)); + break; + case QS60StyleEnums::SP_QgnGrafTabActiveM: + case QS60StyleEnums::SP_QgnGrafTabPassiveM: + case QS60StyleEnums::SP_QgnGrafTabActiveR: + case QS60StyleEnums::SP_QgnGrafTabPassiveR: + case QS60StyleEnums::SP_QgnGrafTabPassiveL: + case QS60StyleEnums::SP_QgnGrafTabActiveL: + //Returned QSize for tabs must not be square, but narrow rectangle with width:height + //ratio of 1:2 for horizontal tab bars (and 2:1 for vertical ones). + result.setWidth(result.height() >> 1); + break; + + case QS60StyleEnums::SP_QgnGrafNsliderEndLeft: + case QS60StyleEnums::SP_QgnGrafNsliderEndRight: + case QS60StyleEnums::SP_QgnGrafNsliderMiddle: + break; + + case QS60StyleEnums::SP_QgnGrafNsliderMarker: + case QS60StyleEnums::SP_QgnGrafNsliderMarkerSelected: + result.scale(pixelMetric(QStyle::PM_SliderLength), + pixelMetric(QStyle::PM_SliderControlThickness), Qt::IgnoreAspectRatio); + break; + + case QS60StyleEnums::SP_QgnGrafBarFrameSideL: + case QS60StyleEnums::SP_QgnGrafBarFrameSideR: + result.setWidth(pixelMetric(PM_FrameCornerWidth)); + break; + + case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed: + case QS60StyleEnums::SP_QsnCpScrollBgBottom: + case QS60StyleEnums::SP_QsnCpScrollBgTop: + case QS60StyleEnums::SP_QsnCpScrollHandleBottom: + case QS60StyleEnums::SP_QsnCpScrollHandleTop: + case QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed: + result.setHeight(pixelMetric(QStyle::PM_ScrollBarExtent)); + result.setWidth(pixelMetric(QStyle::PM_ScrollBarExtent)); + break; + case QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed: + case QS60StyleEnums::SP_QsnCpScrollBgMiddle: + case QS60StyleEnums::SP_QsnCpScrollHandleMiddle: + result.setHeight(pixelMetric(QStyle::PM_ScrollBarExtent)); + result.setWidth(pixelMetric(QStyle::PM_ScrollBarSliderMin)); + break; + default: + // Generic frame part size gathering. + for (int i = 0; i < frameElementsCount; ++i) + { + switch (m_frameElementsData[i].center - part) { + case 8: /* CornerTl */ + case 7: /* CornerTr */ + case 6: /* CornerBl */ + case 5: /* CornerBr */ + result.setWidth(pixelMetric(PM_FrameCornerWidth)); + // Falltrough intended... + case 4: /* SideT */ + case 3: /* SideB */ + result.setHeight(pixelMetric(PM_FrameCornerHeight)); + break; + case 2: /* SideL */ + case 1: /* SideR */ + result.setWidth(pixelMetric(PM_FrameCornerWidth)); + break; + case 0: /* center */ + default: + break; + } + } + break; + } + if (flags & (SF_PointEast | SF_PointWest)) { + const int temp = result.width(); + result.setWidth(result.height()); + result.setHeight(temp); + } + return result; +} + +bool QS60StylePrivate::canDrawThemeBackground(const QBrush &backgroundBrush, const QWidget *widget) +{ + // Always return true for web pages. + if (widget && m_webPaletteKey == QApplication::palette(widget).cacheKey()) + return true; + //If brush is not changed from style's default values, draw theme graphics. + return (backgroundBrush.color() == Qt::transparent || + backgroundBrush.style() == Qt::NoBrush) ? true : false; +} + +bool QS60StylePrivate::isWidgetPressed(const QWidget *widget) +{ + return (widget && widget == m_pressedWidget); +} + +// Generates 1*1 white pixmap as a placeholder for real texture. +// The actual theme texture is drawn in qt_s60_fill_background(). +QPixmap QS60StylePrivate::placeHolderTexture() +{ + if (!m_placeHolderTexture) { + m_placeHolderTexture = new QPixmap(1,1); + m_placeHolderTexture->fill(Qt::green); + } + return *m_placeHolderTexture; +} + +/*! + \class QS60Style + \brief The QS60Style class provides a look and feel suitable for applications on S60. + \since 4.6 + \ingroup appearance + + \sa QMacStyle, QWindowsStyle, QWindowsXPStyle, QWindowsVistaStyle, QPlastiqueStyle, QCleanlooksStyle, QMotifStyle +*/ + + +/*! + Destroys the style. +*/ +QS60Style::~QS60Style() +{ +} + +/*! + \reimp +*/ +void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const +{ + const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled; + SubControls sub = option->subControls; + + switch (control) { +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + if (const QStyleOptionSlider *optionSlider = qstyleoption_cast(option)) { + const bool horizontal = optionSlider->orientation == Qt::Horizontal; + + const QRect scrollBarSlider = subControlRect(control, optionSlider, SC_ScrollBarSlider, widget); + const QRect grooveRect = subControlRect(control, optionSlider, SC_ScrollBarGroove, widget); + + const QS60StylePrivate::SkinElements grooveElement = + horizontal ? QS60StylePrivate::SE_ScrollBarGrooveHorizontal : QS60StylePrivate::SE_ScrollBarGrooveVertical; + QS60StylePrivate::drawSkinElement(grooveElement, painter, grooveRect, flags); + + const SubControls subControls = optionSlider->subControls; + + // select correct slider (horizontal/vertical/pressed) + const bool sliderPressed = ((optionSlider->state & State_Sunken) && (subControls & SC_ScrollBarSlider)); + const QS60StylePrivate::SkinElements handleElement = + horizontal ? + ( sliderPressed ? + QS60StylePrivate::SE_ScrollBarHandlePressedHorizontal : + QS60StylePrivate::SE_ScrollBarHandleHorizontal ) : + ( sliderPressed ? + QS60StylePrivate::SE_ScrollBarHandlePressedVertical : + QS60StylePrivate::SE_ScrollBarHandleVertical); + QS60StylePrivate::drawSkinElement(handleElement, painter, scrollBarSlider, flags); + } + break; +#endif // QT_NO_SCROLLBAR +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *optionSlider = qstyleoption_cast(option)) { + + const QRect sliderGroove = subControlRect(control, optionSlider, SC_SliderGroove, widget); + const bool horizontal = optionSlider->orientation == Qt::Horizontal; + + //Highlight +/* if (optionSlider->state & State_HasFocus) + drawPrimitive(PE_FrameFocusRect, optionSlider, painter, widget);*/ + + //Groove graphics + if (QS60StylePrivate::hasSliderGrooveGraphic()) { + const QS60StylePrivate::SkinElements grooveElement = horizontal ? + QS60StylePrivate::SE_SliderGrooveHorizontal : + QS60StylePrivate::SE_SliderGrooveVertical; + QS60StylePrivate::drawSkinElement(grooveElement, painter, sliderGroove, flags); + } else { + const QPoint sliderGrooveCenter = sliderGroove.center(); + const bool horizontal = optionSlider->orientation == Qt::Horizontal; + painter->save(); + if (widget) + painter->setPen(widget->palette().windowText().color()); + if (horizontal) + painter->drawLine(0, sliderGrooveCenter.y(), sliderGroove.right(), sliderGrooveCenter.y()); + else + painter->drawLine(sliderGrooveCenter.x(), 0, sliderGrooveCenter.x(), sliderGroove.bottom()); + painter->restore(); + } + + //Handle graphics + const QRect sliderHandle = subControlRect(control, optionSlider, SC_SliderHandle, widget); + QS60StylePrivate::SkinElements handleElement; + if (optionSlider->state & State_Sunken) + handleElement = + horizontal ? QS60StylePrivate::SE_SliderHandleSelectedHorizontal : QS60StylePrivate::SE_SliderHandleSelectedVertical; + else + handleElement = + horizontal ? QS60StylePrivate::SE_SliderHandleHorizontal : QS60StylePrivate::SE_SliderHandleVertical; + QS60StylePrivate::drawSkinElement(handleElement, painter, sliderHandle, flags); + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) { + const QRect cmbxEditField = subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget); + const QRect cmbxFrame = subControlRect(CC_ComboBox, option, SC_ComboBoxFrame, widget); + const bool direction = cmb->direction == Qt::LeftToRight; + + // Button frame + QStyleOptionFrame buttonOption; + buttonOption.QStyleOption::operator=(*cmb); + const int maxButtonSide = cmbxFrame.width() - cmbxEditField.width(); + const int newTop = cmbxEditField.center().y() - maxButtonSide / 2; + const int topLeftPoint = direction ? + (cmbxEditField.right() + 1) : (cmbxEditField.left() + 1 - maxButtonSide); + const QRect buttonRect(topLeftPoint, newTop, maxButtonSide, maxButtonSide); + buttonOption.rect = buttonRect; + buttonOption.state = cmb->state; + drawPrimitive(PE_PanelButtonCommand, &buttonOption, painter, widget); + + // draw label background - label itself is drawn separately + const QS60StylePrivate::SkinElements skinElement = QS60StylePrivate::SE_FrameLineEdit; + QS60StylePrivate::drawSkinElement(skinElement, painter, cmbxEditField, flags); + + // Draw the combobox arrow + if (sub & SC_ComboBoxArrow) { + // Make rect slightly smaller + buttonOption.rect.adjust(1, 1, -1, -1); + painter->save(); + painter->setPen(option->palette.buttonText().color()); + drawPrimitive(PE_IndicatorSpinDown, &buttonOption, painter, widget); + painter->restore(); + } + } + break; +#endif // QT_NO_COMBOBOX +#ifndef QT_NO_TOOLBUTTON + case CC_ToolButton: + if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast(option)) { + State bflags = toolBtn->state & ~State_Sunken; + + if (bflags & State_AutoRaise) { + if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) { + bflags &= ~State_Raised; + } + } + State mflags = bflags; + if (toolBtn->state & State_Sunken) { + bflags |= State_Sunken; + mflags |= State_Sunken; + } + + const QRect button(subControlRect(control, toolBtn, SC_ToolButton, widget)); + QRect menuRect = QRect(); + if (toolBtn->subControls & SC_ToolButtonMenu) + menuRect = subControlRect(control, toolBtn, SC_ToolButtonMenu, widget); + + if (toolBtn->subControls & SC_ToolButton) { + QStyleOption tool(0); + tool.palette = toolBtn->palette; + + if (bflags & (State_Sunken | State_On | State_Raised | State_Enabled)) { + tool.rect = button.unite(menuRect); + tool.state = bflags; + drawPrimitive(PE_PanelButtonTool, &tool, painter, widget); + } + if (toolBtn->subControls & SC_ToolButtonMenu) { + tool.rect = menuRect; + tool.state = mflags; + drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget); + } + } + QStyleOptionToolButton toolButton = *toolBtn; + if (toolBtn->features & QStyleOptionToolButton::Arrow) { + PrimitiveElement pe; + switch (toolBtn->arrowType) { + case Qt::LeftArrow: + pe = PE_IndicatorArrowLeft; + break; + case Qt::RightArrow: + pe = PE_IndicatorArrowRight; + break; + case Qt::UpArrow: + pe = PE_IndicatorArrowUp; + break; + case Qt::DownArrow: + pe = PE_IndicatorArrowDown; + break; + default: + break; } + toolButton.rect = button; + drawPrimitive(pe, &toolButton, painter, widget); + } + + if (toolBtn->text.length() > 0 || + !toolBtn->icon.isNull()) { + const int frameWidth = pixelMetric(PM_DefaultFrameWidth, option, widget); + toolButton.rect = button.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth); + drawControl(CE_ToolButtonLabel, &toolButton, painter, widget); + } + } + break; +#endif //QT_NO_TOOLBUTTON +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { + QStyleOptionSpinBox copy = *spinBox; + PrimitiveElement pe; + + if (spinBox->subControls & SC_SpinBoxUp) { + copy.subControls = SC_SpinBoxUp; + QPalette spinBoxPal = spinBox->palette; + if (!(spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled)) { + spinBoxPal.setCurrentColorGroup(QPalette::Disabled); + copy.state &= ~State_Enabled; + copy.palette = spinBoxPal; + } + + if (spinBox->activeSubControls == SC_SpinBoxUp && (spinBox->state & State_Sunken)) { + copy.state |= State_On; + copy.state |= State_Sunken; + } else { + copy.state |= State_Raised; + copy.state &= ~State_Sunken; + } + pe = (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) ? + PE_IndicatorSpinPlus : + PE_IndicatorSpinUp; + + copy.rect = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxUp, widget); + drawPrimitive(PE_PanelButtonBevel, ©, painter, widget); + copy.rect.adjust(1, 1, -1, -1); + drawPrimitive(pe, ©, painter, widget); + } + + if (spinBox->subControls & SC_SpinBoxDown) { + copy.subControls = SC_SpinBoxDown; + copy.state = spinBox->state; + QPalette spinBoxPal = spinBox->palette; + if (!(spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled)) { + spinBoxPal.setCurrentColorGroup(QPalette::Disabled); + copy.state &= ~State_Enabled; + copy.palette = spinBoxPal; + } + + if (spinBox->activeSubControls == SC_SpinBoxDown && (spinBox->state & State_Sunken)) { + copy.state |= State_On; + copy.state |= State_Sunken; + } else { + copy.state |= State_Raised; + copy.state &= ~State_Sunken; + } + pe = (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) ? + PE_IndicatorSpinMinus : + PE_IndicatorSpinDown; + + copy.rect = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxDown, widget); + drawPrimitive(PE_PanelButtonBevel, ©, painter, widget); + copy.rect.adjust(1, 1, -1, -1); + drawPrimitive(pe, ©, painter, widget); + } + } + break; +#endif //QT_NO_SPINBOX +#ifndef QT_NO_GROUPBOX + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(option)) { + // Draw frame + const QRect textRect = subControlRect(CC_GroupBox, option, SC_GroupBoxLabel, widget); + const QRect checkBoxRect = subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget); + if (groupBox->subControls & SC_GroupBoxFrame) { + QStyleOptionFrameV2 frame; + frame.QStyleOption::operator=(*groupBox); + frame.features = groupBox->features; + frame.lineWidth = groupBox->lineWidth; + frame.midLineWidth = groupBox->midLineWidth; + frame.rect = subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget); + drawPrimitive(PE_FrameGroupBox, &frame, painter, widget); + } + + // Draw title + if ((groupBox->subControls & SC_GroupBoxLabel) && !groupBox->text.isEmpty()) { + const QColor textColor = groupBox->textColor; + painter->save(); + + if (textColor.isValid()) + painter->setPen(textColor); + int alignment = int(groupBox->textAlignment); + if (!styleHint(SH_UnderlineShortcut, option, widget)) + alignment |= Qt::TextHideMnemonic; + + drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | Qt::AlignVCenter | alignment, + groupBox->palette, groupBox->state & State_Enabled, groupBox->text, + textColor.isValid() ? QPalette::NoRole : QPalette::WindowText); + painter->restore(); + } + + // Draw checkbox + if (groupBox->subControls & SC_GroupBoxCheckBox) { + QStyleOptionButton box; + box.QStyleOption::operator=(*groupBox); + box.rect = checkBoxRect; + drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget); + } + } + break; +#endif //QT_NO_GROUPBOX + default: + QCommonStyle::drawComplexControl(control, option, painter, widget); + } +} + +/*! + \reimp +*/ +void QS60Style::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + Q_D(const QS60Style); + const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled; + switch (element) { + case CE_CheckBox: + case CE_RadioButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + bool isRadio = (element == CE_RadioButton); + QStyleOptionButton subopt = *btn; + + // Highlight needs to be drawn first, as it goes "underneath" the text and indicator. + if (btn->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*btn); + fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect + : SE_CheckBoxFocusRect, btn, widget); + drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + + subopt.palette.setColor(QPalette::Active, QPalette::WindowText, + subopt.palette.highlightedText().color()); + } + + subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator + : SE_CheckBoxIndicator, btn, widget); + drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox, + &subopt, painter, widget); + subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents + : SE_CheckBoxContents, btn, widget); + + drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget); + } + break; + + case CE_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + + drawControl(CE_PushButtonBevel, btn, painter, widget); + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); + + drawControl(CE_PushButtonLabel, &subopt, painter, widget); + } + break; + case CE_PushButtonBevel: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + const bool isDisabled = !(option->state & State_Enabled); + const bool isFlat = button->features & QStyleOptionButton::Flat; + QS60StyleEnums::SkinParts skinPart; + QS60StylePrivate::SkinElements skinElement; + if (!isDisabled) { + const bool isPressed = (option->state & State_Sunken) || + (option->state & State_On); + if (isFlat) { + skinPart = + isPressed ? QS60StyleEnums::SP_QsnFrButtonTbCenterPressed : QS60StyleEnums::SP_QsnFrButtonTbCenter; + } else { + skinElement = + isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal; + } + } else { + if (isFlat) + skinPart =QS60StyleEnums::SP_QsnFrButtonCenterInactive; + else + skinElement = QS60StylePrivate::SE_ButtonInactive; + } + if (isFlat) + QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags); + else + QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags); + } + break; +#ifndef QT_NO_TOOLBUTTON + case CE_ToolButtonLabel: + if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast(option)) { + QStyleOptionToolButton optionToolButton = *toolBtn; + + if (!optionToolButton.icon.isNull() && (optionToolButton.state & State_Sunken) + && (optionToolButton.state & State_Enabled)) { + + const QIcon::State state = optionToolButton.state & State_On ? QIcon::On : QIcon::Off; + const QPixmap pm(optionToolButton.icon.pixmap(optionToolButton.rect.size().boundedTo(optionToolButton.iconSize), + QIcon::Normal, state)); + optionToolButton.icon = generatedIconPixmap(QIcon::Selected, pm, &optionToolButton); + } + + QCommonStyle::drawControl(element, &optionToolButton, painter, widget); + } + break; +#endif //QT_NO_TOOLBUTTON +#ifndef QT_NO_COMBOBOX + case CE_ComboBoxLabel: + if (const QStyleOptionComboBox *comboBox = qstyleoption_cast(option)) { + QStyleOption optionComboBox = *comboBox; + optionComboBox.palette.setColor(QPalette::Active, QPalette::WindowText, + optionComboBox.palette.text().color() ); + optionComboBox.palette.setColor(QPalette::Inactive, QPalette::WindowText, + optionComboBox.palette.text().color() ); + QRect editRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget); + const int frameW = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget); + + if (!comboBox->currentIcon.isNull()) { + const QIcon::Mode mode = comboBox->state & State_Enabled ? QIcon::Normal : QIcon::Disabled; + const QPixmap pixmap = comboBox->currentIcon.pixmap(comboBox->iconSize, mode); + QRect iconRect(editRect); + iconRect.setWidth(comboBox->iconSize.width() + frameW); + iconRect = alignedRect(comboBox->direction, + Qt::AlignLeft | Qt::AlignVCenter, + iconRect.size(), editRect); + if (comboBox->editable) + painter->fillRect(iconRect, optionComboBox.palette.brush(QPalette::Base)); + drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); + + if (comboBox->direction == Qt::RightToLeft) + editRect.setRight(editRect.right() - frameW - comboBox->iconSize.width()); + else + editRect.setLeft(comboBox->iconSize.width() + frameW); + } + if (!comboBox->currentText.isEmpty() && !comboBox->editable) { + const Qt::TextElideMode elideMode = (comboBox->direction == Qt::LeftToRight) ? Qt::ElideRight : Qt::ElideLeft; + const QString text = comboBox->fontMetrics.elidedText(comboBox->currentText, elideMode, editRect.width()); + + QCommonStyle::drawItemText(painter, + editRect.adjusted(QS60StylePrivate::pixelMetric(PM_FrameCornerWidth), 0, -1, 0), + visualAlignment(comboBox->direction, Qt::AlignLeft | Qt::AlignVCenter), + comboBox->palette, comboBox->state & State_Enabled, text); + } + } + break; +#endif //QT_NO_COMBOBOX +#ifndef QT_NO_ITEMVIEWS + case CE_ItemViewItem: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(option)) { + QStyleOptionViewItemV4 voptAdj = *vopt; + painter->save(); + + painter->setClipRect(voptAdj.rect); + const bool isSelected = (vopt->state & State_Selected); + const bool hasFocus = (vopt->state & State_HasFocus); + + bool isScrollBarVisible = false; + int scrollBarWidth = 0; + QList scrollBars = widget->findChildren(); + for (int i = 0; i < scrollBars.size(); ++i) { + QScrollBar *scrollBar = scrollBars.at(i); + if (scrollBar && scrollBar->orientation() == Qt::Vertical) { + isScrollBarVisible = scrollBar->isVisible(); + scrollBarWidth = scrollBar->size().width(); + break; + } + } + + int rightValue = widget ? widget->contentsRect().right() : voptAdj.rect.right(); + + if (isScrollBarVisible) + rightValue -= scrollBarWidth; + + if (voptAdj.rect.right() > rightValue) + voptAdj.rect.setRight(rightValue); + + const QRect iconRect = subElementRect(SE_ItemViewItemDecoration, &voptAdj, widget); + QRect textRect = subElementRect(SE_ItemViewItemText, &voptAdj, widget); + const QAbstractItemView *itemView = qobject_cast(widget); + + const bool singleSelection = itemView && + ((itemView->selectionMode() == QAbstractItemView::SingleSelection || + itemView->selectionMode() == QAbstractItemView::NoSelection)); + const bool selectItems = itemView && (itemView->selectionBehavior() == QAbstractItemView::SelectItems); + + // draw themed background for itemview unless background brush has been defined. + if (vopt->backgroundBrush == Qt::NoBrush) { + if (itemView) { + //With single item selection, use highlight focus as selection indicator. + if (singleSelection && isSelected){ + voptAdj.state = voptAdj.state | State_HasFocus; + if (!hasFocus && selectItems) { + painter->save(); + painter->setOpacity(0.5); + } + } + drawPrimitive(PE_PanelItemViewItem, &voptAdj, painter, widget); + if (singleSelection && isSelected && !hasFocus && selectItems) + painter->restore(); + } + } else { QCommonStyle::drawPrimitive(PE_PanelItemViewItem, &voptAdj, painter, widget);} + + // draw the icon + const QIcon::Mode mode = (voptAdj.state & State_Enabled) ? QIcon::Normal : QIcon::Disabled; + const QIcon::State state = (voptAdj.state & State_Open) ? QIcon::On : QIcon::Off; + voptAdj.icon.paint(painter, iconRect, voptAdj.decorationAlignment, mode, state); + + // Draw selection check mark or checkbox + if (itemView && (!singleSelection || (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator))) { + const QRect selectionRect = subElementRect(SE_ItemViewItemCheckIndicator, &voptAdj, widget); + + QStyleOptionViewItemV4 checkMarkOption(voptAdj); + if (selectionRect.isValid()) + checkMarkOption.rect = selectionRect; + // Draw selection mark. + if (isSelected && selectItems) { + proxy()->drawPrimitive(PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget); + // @todo: this should happen in the rect retrievel i.e. subElementRect() + if (textRect.right() > selectionRect.left()) + textRect.setRight(selectionRect.left()); + } else if (voptAdj.features & QStyleOptionViewItemV2::HasCheckIndicator) { + checkMarkOption.state = checkMarkOption.state & ~State_HasFocus; + + switch (vopt->checkState) { + case Qt::Unchecked: + checkMarkOption.state |= State_Off; + break; + case Qt::PartiallyChecked: + checkMarkOption.state |= State_NoChange; + break; + case Qt::Checked: + checkMarkOption.state |= State_On; + break; + } + drawPrimitive(PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget); + } + } + + // draw the text + if (!voptAdj.text.isEmpty()) { + if (hasFocus) + painter->setPen(voptAdj.palette.highlightedText().color()); + else + painter->setPen(voptAdj.palette.text().color()); + d->viewItemDrawText(painter, &voptAdj, textRect); + } + painter->restore(); + } + break; +#endif // QT_NO_ITEMVIEWS +#ifndef QT_NO_TABBAR + case CE_TabBarTabShape: + if (const QStyleOptionTabV3 *optionTab = qstyleoption_cast(option)) { + QStyleOptionTabV3 optionTabAdj = *optionTab; + const bool isSelected = optionTab->state & State_Selected; + const bool directionMirrored = (optionTab->direction == Qt::RightToLeft); + QS60StylePrivate::SkinElements skinElement; + switch (optionTab->shape) { + case QTabBar::TriangularEast: + case QTabBar::RoundedEast: + skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabEastActive: + QS60StylePrivate::SE_TabBarTabEastInactive; + break; + case QTabBar::TriangularSouth: + case QTabBar::RoundedSouth: + skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabSouthActive: + QS60StylePrivate::SE_TabBarTabSouthInactive; + break; + case QTabBar::TriangularWest: + case QTabBar::RoundedWest: + skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabWestActive: + QS60StylePrivate::SE_TabBarTabWestInactive; + break; + case QTabBar::TriangularNorth: + case QTabBar::RoundedNorth: + default: + skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabNorthActive: + QS60StylePrivate::SE_TabBarTabNorthInactive; + break; + } + if (skinElement == QS60StylePrivate::SE_TabBarTabEastInactive || + skinElement == QS60StylePrivate::SE_TabBarTabNorthInactive || + skinElement == QS60StylePrivate::SE_TabBarTabSouthInactive || + skinElement == QS60StylePrivate::SE_TabBarTabWestInactive || + skinElement == QS60StylePrivate::SE_TabBarTabEastActive || + skinElement == QS60StylePrivate::SE_TabBarTabNorthActive || + skinElement == QS60StylePrivate::SE_TabBarTabSouthActive || + skinElement==QS60StylePrivate::SE_TabBarTabWestActive) { + const int borderThickness = + QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); + int tabOverlap = pixelMetric(PM_TabBarTabOverlap); + if (tabOverlap > borderThickness) + tabOverlap -= borderThickness; + + const bool usesScrollButtons = + (widget) ? (qobject_cast(widget))->usesScrollButtons() : false; + const int roomForScrollButton = + usesScrollButtons ? QS60StylePrivate::pixelMetric(PM_TabBarScrollButtonWidth) : 0; + + // adjust for overlapping tabs and scrollbuttons, if necessary + if (skinElement == QS60StylePrivate::SE_TabBarTabEastInactive || + skinElement == QS60StylePrivate::SE_TabBarTabEastActive || + skinElement == QS60StylePrivate::SE_TabBarTabWestInactive || + skinElement == QS60StylePrivate::SE_TabBarTabWestActive){ + if (optionTabAdj.position == QStyleOptionTabV3::Beginning) + optionTabAdj.rect.adjust(0, roomForScrollButton, 0, tabOverlap); + else if (optionTabAdj.position == QStyleOptionTabV3::End) + optionTabAdj.rect.adjust(0, 0, 0, tabOverlap); + else + optionTabAdj.rect.adjust(0, 0, 0, tabOverlap); + } else { + if (directionMirrored) { + if (optionTabAdj.position == QStyleOptionTabV3::Beginning) + optionTabAdj.rect.adjust(-tabOverlap, 0, -roomForScrollButton, 0); + else + optionTabAdj.rect.adjust(-tabOverlap, 0, 0, 0); + } else { + if (optionTabAdj.position == QStyleOptionTabV3::Beginning) + optionTabAdj.rect.adjust(roomForScrollButton, 0, tabOverlap, 0); + else + optionTabAdj.rect.adjust(0, 0, tabOverlap, 0); + } + } + } + QS60StylePrivate::drawSkinElement(skinElement, painter, optionTabAdj.rect, flags); + } + break; + case CE_TabBarTabLabel: + if (const QStyleOptionTabV3 *tab = qstyleoption_cast(option)) { + QStyleOptionTabV3 optionTab = *tab; + QRect tr = optionTab.rect; + const bool directionMirrored = (optionTab.direction == Qt::RightToLeft); + const int borderThickness = + QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); + int tabOverlap = pixelMetric(PM_TabBarTabOverlap); + if (tabOverlap > borderThickness) + tabOverlap -= borderThickness; + const bool usesScrollButtons = + (widget) ? (qobject_cast(widget))->usesScrollButtons() : false; + const int roomForScrollButton = + usesScrollButtons ? QS60StylePrivate::pixelMetric(PM_TabBarScrollButtonWidth) : 0; + + switch (tab->shape) { + case QTabBar::TriangularWest: + case QTabBar::RoundedWest: + case QTabBar::TriangularEast: + case QTabBar::RoundedEast: + tr.adjust(0, 0, 0, tabOverlap); + break; + case QTabBar::TriangularSouth: + case QTabBar::RoundedSouth: + case QTabBar::TriangularNorth: + case QTabBar::RoundedNorth: + default: + if (directionMirrored) + tr.adjust(-tabOverlap, 0, 0, 0); + else + tr.adjust(0, 0, tabOverlap, 0); + break; + } + painter->save(); + QFont f = painter->font(); + f.setPointSizeF(f.pointSizeF() * KTabFontMul); + painter->setFont(f); + + const bool selected = optionTab.state & State_Selected; + if (selected) + optionTab.palette.setColor(QPalette::Active, QPalette::WindowText, + optionTab.palette.highlightedText().color()); + + const bool verticalTabs = optionTab.shape == QTabBar::RoundedEast + || optionTab.shape == QTabBar::RoundedWest + || optionTab.shape == QTabBar::TriangularEast + || optionTab.shape == QTabBar::TriangularWest; + + //make room for scrollbuttons + if (!verticalTabs) { + if ((tab->position == QStyleOptionTabV3::Beginning && !directionMirrored)) + tr.adjust(roomForScrollButton, 0, 0, 0); + else if ((tab->position == QStyleOptionTabV3::Beginning && directionMirrored)) + tr.adjust(0, 0, -roomForScrollButton, 0); + } else { + if (tab->position == QStyleOptionTabV3::Beginning) + tr.adjust(0, roomForScrollButton, 0, 0); + } + + if (verticalTabs) { + painter->save(); + int newX, newY, newRotation; + if (optionTab.shape == QTabBar::RoundedEast || optionTab.shape == QTabBar::TriangularEast) { + newX = tr.width(); + newY = tr.y(); + newRotation = 90; + } else { + newX = 0; + newY = tr.y() + tr.height(); + newRotation = -90; + } + tr.setRect(0, 0, tr.height(), tr.width()); + QTransform m; + m.translate(newX, newY); + m.rotate(newRotation); + painter->setTransform(m, true); + } + tr.adjust(0, 0, pixelMetric(PM_TabBarTabShiftHorizontal, tab, widget), + pixelMetric(PM_TabBarTabShiftVertical, tab, widget)); + + if (selected) { + tr.setBottom(tr.bottom() - pixelMetric(PM_TabBarTabShiftVertical, tab, widget)); + tr.setRight(tr.right() - pixelMetric(PM_TabBarTabShiftHorizontal, tab, widget)); + } + + int alignment = Qt::AlignCenter | Qt::TextShowMnemonic; + if (!styleHint(SH_UnderlineShortcut, &optionTab, widget)) + alignment |= Qt::TextHideMnemonic; + if (!optionTab.icon.isNull()) { + QSize iconSize = optionTab.iconSize; + if (!iconSize.isValid()) { + const int iconExtent = pixelMetric(PM_TabBarIconSize); + iconSize = QSize(iconExtent, iconExtent); + } + QPixmap tabIcon = optionTab.icon.pixmap(iconSize, + (optionTab.state & State_Enabled) ? QIcon::Normal : QIcon::Disabled); + if (tab->text.isEmpty()) + painter->drawPixmap(tr.center().x() - (tabIcon.height() >> 1), + tr.center().y() - (tabIcon.height() >> 1), + tabIcon); + else + painter->drawPixmap(tr.left() + tabOverlap, + tr.center().y() - (tabIcon.height() >> 1), + tabIcon); + tr.setLeft(tr.left() + iconSize.width() + 4); //todo: magic four + } + + QCommonStyle::drawItemText(painter, tr, alignment, optionTab.palette, tab->state & State_Enabled, tab->text, QPalette::WindowText); + if (verticalTabs) + painter->restore(); + + painter->restore(); + } + break; +#endif // QT_NO_TABBAR +#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBarContents: + if (const QStyleOptionProgressBarV2 *optionProgressBar = qstyleoption_cast(option)) { + QRect progressRect = optionProgressBar->rect; + + if (optionProgressBar->minimum == optionProgressBar->maximum && optionProgressBar->minimum == 0) { + // busy indicator + const QS60StylePrivate::SkinElementFlag orientationFlag = optionProgressBar->orientation == Qt::Horizontal ? + QS60StylePrivate::SF_PointNorth : QS60StylePrivate::SF_PointWest; + + QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnGrafBarWaitAnim, + painter, progressRect, flags | orientationFlag | QS60StylePrivate::SF_Animation ); + } else { + const qreal progressFactor = (optionProgressBar->minimum == optionProgressBar->maximum) ? 1.0 + : (qreal)optionProgressBar->progress / optionProgressBar->maximum; + const int frameWidth = pixelMetric(PM_DefaultFrameWidth, option, widget); + if (optionProgressBar->orientation == Qt::Horizontal) { + progressRect.setWidth(int(progressRect.width() * progressFactor)); + if(optionProgressBar->direction == Qt::RightToLeft) + progressRect.translate(optionProgressBar->rect.width() - progressRect.width(), 0); + progressRect.adjust(frameWidth, 0, -frameWidth, 0); + } else { + progressRect.adjust(0, frameWidth, 0, -frameWidth); + progressRect.setTop(progressRect.bottom() - int(progressRect.height() * progressFactor)); + } + + const QS60StylePrivate::SkinElements skinElement = optionProgressBar->orientation == Qt::Horizontal ? + QS60StylePrivate::SE_ProgressBarIndicatorHorizontal : QS60StylePrivate::SE_ProgressBarIndicatorVertical; + QS60StylePrivate::drawSkinElement(skinElement, painter, progressRect, flags); + } + } + break; + case CE_ProgressBarGroove: + if (const QStyleOptionProgressBarV2 *optionProgressBar = qstyleoption_cast(option)) { + const QS60StylePrivate::SkinElements skinElement = optionProgressBar->orientation == Qt::Horizontal ? + QS60StylePrivate::SE_ProgressBarGrooveHorizontal : QS60StylePrivate::SE_ProgressBarGrooveVertical; + QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags); + } + break; + case CE_ProgressBarLabel: + if (const QStyleOptionProgressBarV2 *progressbar = qstyleoption_cast(option)) { + QStyleOptionProgressBarV2 optionProgressBar = *progressbar; + QCommonStyle::drawItemText(painter, progressbar->rect, flags | Qt::AlignCenter | Qt::TextSingleLine, optionProgressBar.palette, + progressbar->state & State_Enabled, progressbar->text, QPalette::WindowText); + } + break; +#endif // QT_NO_PROGRESSBAR +#ifndef QT_NO_MENU + case CE_MenuItem: + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast(option)) { + QStyleOptionMenuItem optionMenuItem = *menuItem; + + bool drawSubMenuIndicator = false; + bool drawSeparator = false; + switch(menuItem->menuItemType) { + case QStyleOptionMenuItem::Separator: + drawSeparator = true; + break; + case QStyleOptionMenuItem::Scroller: + return; // no scrollers in S60 menus + case QStyleOptionMenuItem::SubMenu: + drawSubMenuIndicator = true; + break; + default: + break; + } + if (drawSeparator) { + painter->save(); + painter->setPen(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 10, 0)); + painter->drawLine(optionMenuItem.rect.topLeft(), optionMenuItem.rect.bottomRight()); + painter->restore(); + return; + } + const bool enabled = optionMenuItem.state & State_Enabled; + const bool checkable = optionMenuItem.checkType != QStyleOptionMenuItem::NotCheckable; + bool ignoreCheckMark = false; + +#ifndef QT_NO_COMBOBOX + if (qobject_cast(widget)) + ignoreCheckMark = true; //ignore the checkmarks provided by the QComboMenuDelegate +#endif + + uint text_flags = Qt::AlignLeading | Qt::TextShowMnemonic | Qt::TextDontClip + | Qt::TextSingleLine | Qt::AlignVCenter; + if (!styleHint(SH_UnderlineShortcut, menuItem, widget)) + text_flags |= Qt::TextHideMnemonic; + + QRect iconRect = subElementRect(SE_ItemViewItemDecoration, &optionMenuItem, widget); + QRect textRect = subElementRect(SE_ItemViewItemText, &optionMenuItem, widget); + + QStyleOptionMenuItem optionCheckBox; + + //Regardless of checkbox visibility, make room for it, this mirrors native implementation, + //where text and icon placement is static regardless of content of menu item. + optionCheckBox.QStyleOptionMenuItem::operator=(*menuItem); + optionCheckBox.rect.setWidth(pixelMetric(PM_IndicatorWidth)); + optionCheckBox.rect.setHeight(pixelMetric(PM_IndicatorHeight)); + + const int vSpacing = QS60StylePrivate::pixelMetric(PM_LayoutVerticalSpacing); + //The vertical spacing is doubled; it needs one spacing to separate checkbox from + //highlight and then it needs one to separate it whatever is shown after it (text/icon/both). + const int moveByX = optionCheckBox.rect.width() + 2 * vSpacing; + optionCheckBox.rect.moveCenter(QPoint( + optionCheckBox.rect.center().x() + moveByX >> 1, + menuItem->rect.center().y())); + + if (optionMenuItem.direction != Qt::LeftToRight) + optionCheckBox.rect.translate(textRect.width() + iconRect.width(), 0); + + + const bool selected = (option->state & State_Selected) && (option->state & State_Enabled); + if (selected) { + const int spacing = ignoreCheckMark ? (vSpacing + QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth)) : 0; + const int start = optionMenuItem.rect.left() + spacing; + const int end = optionMenuItem.rect.right() - spacing; + //-1 adjustment to avoid highlight being on top of possible separator item + const QRect highlightRect = QRect( + QPoint(start, option->rect.top()), + QPoint(end, option->rect.bottom() - 1)); + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, highlightRect, flags); + } + + if (checkable && !ignoreCheckMark) + drawPrimitive(PE_IndicatorMenuCheckMark, &optionCheckBox, painter, widget); + + //draw icon and/or checkState + QPixmap pix = menuItem->icon.pixmap(pixelMetric(PM_SmallIconSize), + enabled ? QIcon::Normal : QIcon::Disabled); + const bool itemWithIcon = !pix.isNull(); + if (itemWithIcon) { + drawItemPixmap(painter, iconRect, text_flags, pix); + if (optionMenuItem.direction == Qt::LeftToRight) + textRect.translate(vSpacing, 0); + else + textRect.translate(-vSpacing, 0); + textRect.setWidth(textRect.width() - vSpacing); + } + + //draw indicators + if (drawSubMenuIndicator) { + QStyleOptionMenuItem arrowOptions; + arrowOptions.QStyleOption::operator=(*menuItem); + const int indicatorWidth = (pixelMetric(PM_ListViewIconSize, option, widget) >> 1) + + pixelMetric(PM_LayoutVerticalSpacing, option, widget); + if (optionMenuItem.direction == Qt::LeftToRight) + arrowOptions.rect.setLeft(textRect.right()); + arrowOptions.rect.setWidth(indicatorWidth); + //by default sub menu indicator in S60 points to east,so here icon + // direction is set to north (and south when in RightToLeft) + const QS60StylePrivate::SkinElementFlag arrowDirection = (arrowOptions.direction == Qt::LeftToRight) ? + QS60StylePrivate::SF_PointNorth : QS60StylePrivate::SF_PointSouth; + painter->save(); + painter->setPen(option->palette.windowText().color()); + QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnIndiSubmenu, painter, arrowOptions.rect, + (flags | QS60StylePrivate::SF_ColorSkinned | arrowDirection)); + painter->restore(); + } + + //draw text + if (!enabled){ + //In s60, if something becomes disabled, it is removed from menu, so no native look-alike available. + optionMenuItem.palette.setColor(QPalette::Disabled, QPalette::Text, QS60StylePrivate::lighterColor( + optionMenuItem.palette.color(QPalette::Disabled, QPalette::Text))); + painter->save(); + painter->setOpacity(0.5); + } + if (selected) + optionMenuItem.palette.setColor( + QPalette::Active, QPalette::Text, optionMenuItem.palette.highlightedText().color()); + + QCommonStyle::drawItemText(painter, textRect, text_flags, + optionMenuItem.palette, enabled, + optionMenuItem.text, QPalette::Text); + + //In Sym^3, native menu items have "lines" between them + if (QS60StylePrivate::isSingleClickUi()) { + int diff = widget->geometry().bottom() - optionMenuItem.rect.bottom(); + if (const QComboBox *cb = qobject_cast(widget)) + diff = cb->view()->geometry().bottom() - optionMenuItem.rect.bottom(); + + // Skip drawing the horizontal line for the last menu item. + if (diff > optionMenuItem.rect.height()) { + const QColor lineColorAlpha = QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 15, 0); + //native platform sets each color byte to same value for "line 16" which just defines alpha for + //menuitem lines; lets use first byte "red". + QColor lineColor = optionMenuItem.palette.text().color(); + if (lineColorAlpha.isValid()) + lineColor.setAlpha(lineColorAlpha.red()); + painter->save(); + painter->setPen(lineColor); + const int horizontalMargin = 2 * QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) - QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); + const int lineStartX = optionMenuItem.rect.left() + horizontalMargin; + const int lineEndX = optionMenuItem.rect.right() - horizontalMargin; + painter->drawLine(QPoint(lineStartX, optionMenuItem.rect.bottom()), QPoint(lineEndX, optionMenuItem.rect.bottom())); + painter->restore(); + } + } + if (!enabled) + painter->restore(); + } + break; + case CE_MenuEmptyArea: + break; +#endif //QT_NO_MENU + +#ifndef QT_NO_MENUBAR + case CE_MenuBarEmptyArea: + break; +#endif //QT_NO_MENUBAR + + case CE_HeaderSection: + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + painter->save(); + QPen linePen = QPen(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 1, header)); + const int penWidth = (header->orientation == Qt::Horizontal) ? + linePen.width() + QS60StylePrivate::pixelMetric(PM_BoldLineWidth) + : linePen.width() + QS60StylePrivate::pixelMetric(PM_ThinLineWidth); + linePen.setWidth(penWidth); + painter->setPen(linePen); + if (header->orientation == Qt::Horizontal){ + painter->drawLine(header->rect.bottomLeft(), header->rect.bottomRight()); + } else { + if ( header->direction == Qt::LeftToRight ) { + painter->drawLine(header->rect.topRight(), header->rect.bottomRight()); + } else { + painter->drawLine(header->rect.topLeft(), header->rect.bottomLeft()); + } + } + painter->restore(); + + //Draw corner button as normal pushButton. + if (qobject_cast(widget)) { + //Make cornerButton slightly smaller so that it is not on top of table border graphic. + QStyleOptionHeader subopt = *header; + const int borderTweak = + QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) >> 1; + if (subopt.direction == Qt::LeftToRight) + subopt.rect.adjust(borderTweak, borderTweak, 0, -borderTweak); + else + subopt.rect.adjust(0, borderTweak, -borderTweak, -borderTweak); + drawPrimitive(PE_PanelButtonBevel, &subopt, painter, widget); + } else if ((header->palette.brush(QPalette::Button) != Qt::transparent)) { + //Draw non-themed background. Background for theme is drawn in CE_ShapedFrame + //to get continuous theme graphic across all the header cells. + qDrawShadePanel(painter, header->rect, header->palette, + header->state & (State_Sunken | State_On), penWidth, + &header->palette.brush(QPalette::Button)); + } + } + break; + case CE_HeaderEmptyArea: // no need to draw this + break; + case CE_Header: + if ( const QStyleOptionHeader *header = qstyleoption_cast(option)) { + drawControl(CE_HeaderSection, header, painter, widget); + QStyleOptionHeader subopt = *header; + subopt.rect = subElementRect(SE_HeaderLabel, header, widget); + if (subopt.rect.isValid()) + drawControl(CE_HeaderLabel, &subopt, painter, widget); + if (header->sortIndicator != QStyleOptionHeader::None) { + subopt.rect = subElementRect(SE_HeaderArrow, option, widget); + drawPrimitive(PE_IndicatorHeaderArrow, &subopt, painter, widget); + } + } + break; +#ifndef QT_NO_TOOLBAR + case CE_ToolBar: + if (const QStyleOptionToolBar *toolBar = qstyleoption_cast(option)) { + const QToolBar *tbWidget = qobject_cast(widget); + + //toolbar within a toolbar, skip + if (!tbWidget || (widget && qobject_cast(widget->parentWidget()))) + break; + + // Normally in S60 5.0+ there is no background for toolbar, but in some cases with versatile QToolBar, + // it looks a bit strange. So, lets fillRect with Button. + if (!QS60StylePrivate::isToolBarBackground()) { + QList actions = tbWidget->actions(); + bool justToolButtonsInToolBar = true; + for (int i = 0; i < actions.size(); ++i) { + QWidget *childWidget = tbWidget->widgetForAction(actions.at(i)); + const QToolButton *button = qobject_cast(childWidget); + if (!button){ + justToolButtonsInToolBar = false; + } + } + + // Draw frame background + // for vertical toolbars with text only and + // for toolbars with extension buttons and + // for toolbars with widgets in them. + if (!justToolButtonsInToolBar || + (tbWidget && + (tbWidget->orientation() == Qt::Vertical) && + (tbWidget->toolButtonStyle() == Qt::ToolButtonTextOnly))) { + painter->save(); + if (widget) + painter->setBrush(widget->palette().button()); + painter->setOpacity(0.3); + painter->fillRect(toolBar->rect, painter->brush()); + painter->restore(); + } + } else { + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBar, painter, toolBar->rect, flags); + } + } + break; +#endif //QT_NO_TOOLBAR + case CE_ShapedFrame: + if (const QTextEdit *textEdit = qobject_cast(widget)) { + const QStyleOptionFrame *frame = qstyleoption_cast(option); + if (frame && QS60StylePrivate::canDrawThemeBackground(frame->palette.base(), widget)) + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_Editor, painter, option->rect, flags); + else + QCommonStyle::drawControl(element, option, painter, widget); + } else if (qobject_cast(widget)) { + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableItem, painter, option->rect, flags); + } else if (const QHeaderView *header = qobject_cast(widget)) { + //QS60style draws header background here instead of in each headersection, to get + //continuous graphic from section to section. + QS60StylePrivate::SkinElementFlags adjustableFlags = flags; + QRect headerRect = option->rect; + if (header->orientation() != Qt::Horizontal) { + //todo: update to horizontal table graphic + adjustableFlags = (adjustableFlags | QS60StylePrivate::SF_PointWest); + } else { + const int frameWidth = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); + if (option->direction == Qt::LeftToRight) + headerRect.adjust(-2 * frameWidth, 0, 0, 0); + else + headerRect.adjust(0, 0, 2 * frameWidth, 0); + } + if (option->palette.brush(QPalette::Button).color() == Qt::transparent) + QS60StylePrivate::drawSkinElement( + QS60StylePrivate::SE_TableHeaderItem, painter, headerRect, adjustableFlags); + + } else if (qobject_cast(widget)) { + QCommonStyle::drawControl(element, option, painter, widget); + } + break; + case CE_MenuScroller: + break; + case CE_FocusFrame: { +#ifdef QT_KEYPAD_NAVIGATION + bool editFocus = false; + if (const QFocusFrame *focusFrame = qobject_cast(widget)) { + if (focusFrame->widget() && focusFrame->widget()->hasEditFocus()) + editFocus = true; + } + const qreal opacity = editFocus ? 1 : 0.75; // Trial and error factors. Feel free to improve. +#else + const qreal opacity = 0.85; +#endif + // We need to reduce the focus frame size if LayoutSpacing is smaller than FocusFrameMargin + // Otherwise, we would overlay adjacent widgets. + const int frameHeightReduction = + qMin(0, pixelMetric(PM_LayoutVerticalSpacing) + - pixelMetric(PM_FocusFrameVMargin)); + const int frameWidthReduction = + qMin(0, pixelMetric(PM_LayoutHorizontalSpacing) + - pixelMetric(PM_FocusFrameHMargin)); + const int rounding = + qMin(pixelMetric(PM_FocusFrameVMargin), + pixelMetric(PM_LayoutVerticalSpacing)); + const QRect frameRect = + option->rect.adjusted(-frameWidthReduction, -frameHeightReduction, + frameWidthReduction, frameHeightReduction); + QPainterPath framePath; + framePath.addRoundedRect(frameRect, rounding, rounding); + + painter->save(); + painter->setRenderHint(QPainter::Antialiasing); + painter->setOpacity(opacity); + painter->fillPath(framePath, option->palette.color(QPalette::Text)); + painter->restore(); + } + break; + case CE_Splitter: + if (option->state & State_Sunken && option->state & State_Enabled && QS60StylePrivate::themePalette()) { + painter->save(); + painter->setOpacity(0.5); + painter->setBrush(QS60StylePrivate::themePalette()->light()); + painter->setRenderHint(QPainter::Antialiasing); + const qreal roundRectRadius = 4 * goldenRatio; + painter->drawRoundedRect(option->rect, roundRectRadius, roundRectRadius); + painter->restore(); + } + break; + default: + QCommonStyle::drawControl(element, option, painter, widget); + } +} + +/*! + \reimp +*/ +void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled; + bool commonStyleDraws = false; + + switch (element) { + case PE_FrameFocusRect: { + //Draw themed highlight to radiobuttons and checkboxes. + //For other widgets skip, unless palette has been modified. In that case, draw with commonstyle. + if (QS60StylePrivate::equalToThemePalette(option->palette.highlight().color(), QPalette::Highlight)) { + if ((qstyleoption_cast(option) && + (qobject_cast(widget) || qobject_cast(widget)))) + QS60StylePrivate::drawSkinElement( + QS60StylePrivate::isWidgetPressed(widget) ? + QS60StylePrivate::SE_ListItemPressed : + QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags); + } else { + commonStyleDraws = true; + } + } + break; +#ifndef QT_NO_LINEEDIT + case PE_PanelLineEdit: + if (const QStyleOptionFrame *lineEdit = qstyleoption_cast(option)) { +#ifndef QT_NO_COMBOBOX + if (widget && qobject_cast(widget->parentWidget())) + break; +#endif + if (QS60StylePrivate::canDrawThemeBackground(option->palette.base(), widget)) + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_FrameLineEdit, painter, option->rect, flags); + else + commonStyleDraws = true; + } + break; +#endif // QT_NO_LINEEDIT + case PE_IndicatorCheckBox: { + // Draw checkbox indicator as color skinned graphics. + const QS60StyleEnums::SkinParts skinPart = (option->state & State_On) ? + QS60StyleEnums::SP_QgnIndiCheckboxOn : QS60StyleEnums::SP_QgnIndiCheckboxOff; + painter->save(); + + if (QS60StylePrivate::equalToThemePalette(option->palette.windowText().color(), QPalette::WindowText)) + painter->setPen(option->palette.windowText().color()); + + QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags | QS60StylePrivate::SF_ColorSkinned ); + painter->restore(); + } + break; + case PE_IndicatorViewItemCheck: +#ifndef QT_NO_ITEMVIEWS + if (const QAbstractItemView *itemView = (qobject_cast(widget))) { + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(option)) { + const bool checkBoxVisible = vopt->features & QStyleOptionViewItemV2::HasCheckIndicator; + const bool singleSelection = itemView->selectionMode() == + QAbstractItemView::SingleSelection || itemView->selectionMode() == QAbstractItemView::NoSelection; + // draw either checkbox at the beginning + if (checkBoxVisible && singleSelection) { + drawPrimitive(PE_IndicatorCheckBox, option, painter, widget); + // ... or normal "tick" selection at the end. + } else if (option->state & State_Selected) { + QRect tickRect = option->rect; + const int frameBorderWidth = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth); + // adjust tickmark rect to exclude frame border + tickRect.adjust(0, -frameBorderWidth, 0, -frameBorderWidth); + QS60StyleEnums::SkinParts skinPart = QS60StyleEnums::SP_QgnIndiMarkedAdd; + QS60StylePrivate::drawSkinPart(skinPart, painter, tickRect, + (flags | QS60StylePrivate::SF_ColorSkinned)); + } + } + } +#endif //QT_NO_ITEMVIEWS + break; + case PE_IndicatorRadioButton: { + QRect buttonRect = option->rect; + //there is empty (a. 33%) space in svg graphics for radiobutton + const qreal reduceWidth = (qreal)buttonRect.width() / 3.0; + const qreal rectWidth = (qreal)option->rect.width() != 0 ? option->rect.width() : 1.0; + // Try to occupy the full area + const qreal scaler = 1 + (reduceWidth/rectWidth); + buttonRect.setWidth((int)((buttonRect.width()-reduceWidth) * scaler)); + buttonRect.setHeight((int)(buttonRect.height() * scaler)); + // move the rect up for half of the new height-gain + const int newY = (buttonRect.bottomRight().y() - option->rect.bottomRight().y()) >> 1 ; + buttonRect.adjust(0, -newY, -1, -newY); + + painter->save(); + const QColor themeColor = QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 6, option); + const QColor buttonTextColor = option->palette.buttonText().color(); + if (themeColor != buttonTextColor) + painter->setPen(buttonTextColor); + else + painter->setPen(themeColor); + + // Draw radiobutton indicator as color skinned graphics. + QS60StyleEnums::SkinParts skinPart = (option->state & State_On) ? + QS60StyleEnums::SP_QgnIndiRadiobuttOn : QS60StyleEnums::SP_QgnIndiRadiobuttOff; + QS60StylePrivate::drawSkinPart(skinPart, painter, buttonRect, + (flags | QS60StylePrivate::SF_ColorSkinned)); + painter->restore(); + } + break; + case PE_PanelButtonCommand: + case PE_PanelButtonTool: + case PE_PanelButtonBevel: + case PE_FrameButtonBevel: + if (QS60StylePrivate::canDrawThemeBackground(option->palette.base(), widget)) { + const bool isPressed = (option->state & State_Sunken) || (option->state & State_On); + QS60StylePrivate::SkinElements skinElement; + if (element == PE_PanelButtonTool) + skinElement = isPressed ? QS60StylePrivate::SE_ToolBarButtonPressed : QS60StylePrivate::SE_ToolBarButton; + else + skinElement = isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal; + QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags); + } else { + commonStyleDraws = true; + } + break; +#ifndef QT_NO_TOOLBUTTON + case PE_IndicatorArrowDown: + case PE_IndicatorArrowLeft: + case PE_IndicatorArrowRight: + case PE_IndicatorArrowUp: { + QS60StyleEnums::SkinParts skinPart; + if (element==PE_IndicatorArrowDown) + skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowDown; + else if (element==PE_IndicatorArrowLeft) + skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowLeft; + else if (element==PE_IndicatorArrowRight) + skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowRight; + else if (element==PE_IndicatorArrowUp) + skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowUp; + + QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags); + } + break; +#endif //QT_NO_TOOLBUTTON +#ifndef QT_NO_SPINBOX + case PE_IndicatorSpinDown: + case PE_IndicatorSpinUp: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { + if (QS60StylePrivate::canDrawThemeBackground(spinBox->palette.base(), widget)) { + QStyleOptionSpinBox optionSpinBox = *spinBox; + const QS60StyleEnums::SkinParts part = (element == PE_IndicatorSpinUp) ? + QS60StyleEnums::SP_QgnGrafScrollArrowUp : + QS60StyleEnums::SP_QgnGrafScrollArrowDown; + const int iconMargin = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) >> 1; + optionSpinBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? iconMargin : -iconMargin ); + QS60StylePrivate::drawSkinPart(part, painter, optionSpinBox.rect, flags); + } else { + commonStyleDraws = true; + } + } +#endif //QT_NO_SPINBOX +#ifndef QT_NO_COMBOBOX + if (const QStyleOptionFrame *cmb = qstyleoption_cast(option)) { + if (QS60StylePrivate::canDrawThemeBackground( option->palette.base(), widget)) { + // We want to draw down arrow here for comboboxes as well. + QStyleOptionFrame optionsComboBox = *cmb; + const QS60StyleEnums::SkinParts part = QS60StyleEnums::SP_QgnGrafScrollArrowDown; + const int iconMargin = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) >> 1; + optionsComboBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? iconMargin : -iconMargin ); + QS60StylePrivate::drawSkinPart(part, painter, optionsComboBox.rect, flags); + } else { + commonStyleDraws = true; + } + } +#endif //QT_NO_COMBOBOX + break; + case PE_IndicatorSpinMinus: + case PE_IndicatorSpinPlus: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { + QStyleOptionSpinBox optionSpinBox = *spinBox; + QCommonStyle::drawPrimitive(element, &optionSpinBox, painter, widget); + } +#ifndef QT_NO_COMBOBOX + else if (const QStyleOptionFrame *cmb = qstyleoption_cast(option)) { + // We want to draw down arrow here for comboboxes as well. + QStyleOptionFrame comboBox = *cmb; + const int frameWidth = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); + comboBox.rect.adjust(0, frameWidth, 0, -frameWidth); + QCommonStyle::drawPrimitive(element, &comboBox, painter, widget); + } +#endif //QT_NO_COMBOBOX + break; + case PE_Widget: + if (QS60StylePrivate::drawsOwnThemeBackground(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast(widget) +#endif //QT_NO_COMBOBOX +#ifndef QT_NO_MENU + || qobject_cast (widget) +#endif //QT_NO_MENU + ) { + //Need extra check since dialogs have their own theme background + if (QS60StylePrivate::canDrawThemeBackground(option->palette.base(), widget) + && QS60StylePrivate::equalToThemePalette(option->palette.window().texture().cacheKey(), QPalette::Window)) { + const bool comboMenu = qobject_cast(widget); + // Add margin area to the background, to avoid background being cut for first and last item. + const int verticalMenuAdjustment = comboMenu ? QS60StylePrivate::pixelMetric(PM_MenuVMargin) : 0; + const QRect adjustedMenuRect = option->rect.adjusted(0, -verticalMenuAdjustment, 0, verticalMenuAdjustment); + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_PopupBackground, painter, adjustedMenuRect, flags); + } else { + commonStyleDraws = true; + } + } + break; + case PE_FrameWindow: + case PE_FrameTabWidget: + if (const QStyleOptionTabWidgetFrame *tabFrame = qstyleoption_cast(option)) { + QStyleOptionTabWidgetFrame optionTabFrame = *tabFrame; + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_PanelBackground, painter, optionTabFrame.rect, flags); + } + break; + case PE_IndicatorHeaderArrow: + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + if (header->sortIndicator & QStyleOptionHeader::SortUp) + drawPrimitive(PE_IndicatorArrowUp, header, painter, widget); + else if (header->sortIndicator & QStyleOptionHeader::SortDown) + drawPrimitive(PE_IndicatorArrowDown, header, painter, widget); + } // QStyleOptionHeader::None is not drawn => not needed + break; +#ifndef QT_NO_GROUPBOX + case PE_FrameGroupBox: + if (const QStyleOptionFrameV2 *frame = qstyleoption_cast(option)) + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_SettingsList, painter, frame->rect, flags); + break; +#endif //QT_NO_GROUPBOX + + // Qt3 primitives are not supported + case PE_Q3CheckListController: + case PE_Q3CheckListExclusiveIndicator: + case PE_Q3CheckListIndicator: + case PE_Q3DockWindowSeparator: + case PE_Q3Separator: + Q_ASSERT(false); + break; + case PE_Frame: + break; +#ifndef QT_NO_ITEMVIEWS + case PE_PanelItemViewItem: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(option)) { + const bool isSelected = (vopt->state & State_Selected); + const bool hasFocus = (vopt->state & State_HasFocus); + const bool isPressed = QS60StylePrivate::isWidgetPressed(widget); + + if (QS60StylePrivate::equalToThemePalette(option->palette.highlight().color(), QPalette::Highlight)) { + QRect highlightRect = vopt->rect.adjusted(1,1,-1,-1); + const QAbstractItemView *itemView = qobject_cast(widget); + QAbstractItemView::SelectionBehavior selectionBehavior = + itemView ? itemView->selectionBehavior() : QAbstractItemView::SelectItems; + // Set the draw area for highlights (focus, select rect or pressed rect) + if (hasFocus || isPressed) { + if (selectionBehavior != QAbstractItemView::SelectItems) { + // set highlight rect so that it is continuous from cell to cell, yet sligthly + // smaller than cell rect + int xBeginning = 0, yBeginning = 0, xEnd = 0, yEnd = 0; + if (selectionBehavior == QAbstractItemView::SelectRows) { + yBeginning = 1; yEnd = -1; + if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning) + xBeginning = 1; + else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End) + xEnd = -1; + } else if (selectionBehavior == QAbstractItemView::SelectColumns) { + xBeginning = 1; xEnd = -1; + if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning) + yBeginning = 1; + else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End) + yEnd = -1; + } + highlightRect = option->rect.adjusted(xBeginning, yBeginning, xEnd, yEnd); + } + } + bool tableView = false; + if (itemView && qobject_cast(widget)) + tableView = true; + + QS60StylePrivate::SkinElements element; + bool themeGraphicDefined = false; + QRect elementRect = option->rect; + + //draw item is drawn as pressed, if it already has focus. + if (isPressed && hasFocus) { + themeGraphicDefined = true; + element = tableView ? QS60StylePrivate::SE_TableItemPressed : QS60StylePrivate::SE_ListItemPressed; + } else if (hasFocus || (isSelected && selectionBehavior != QAbstractItemView::SelectItems)) { + element = QS60StylePrivate::SE_ListHighlight; + elementRect = highlightRect; + themeGraphicDefined = true; + } + if (themeGraphicDefined) + QS60StylePrivate::drawSkinElement(element, painter, elementRect, flags); + } else { + QCommonStyle::drawPrimitive(element, option, painter, widget); + } + } + break; +#endif //QT_NO_ITEMVIEWS + + case PE_IndicatorMenuCheckMark: + if (const QStyleOptionMenuItem *checkBox = qstyleoption_cast(option)){ + QStyleOptionMenuItem optionCheckBox = *checkBox; + if (optionCheckBox.checked) + optionCheckBox.state = (optionCheckBox.state | State_On); + drawPrimitive(PE_IndicatorCheckBox, &optionCheckBox, painter, widget); + } + break; +#ifndef QT_NO_TOOLBAR + case PE_IndicatorToolBarHandle: + // no toolbar handles in S60/AVKON UI + case PE_IndicatorToolBarSeparator: + // no separators in S60/AVKON UI + break; +#endif //QT_NO_TOOLBAR + + case PE_PanelMenuBar: + case PE_FrameMenu: + break; //disable frame in menu + + case PE_IndicatorBranch: +#if defined(Q_WS_S60) + // 3.1 AVKON UI does not have tree view component, use common style for drawing there + if (QSysInfo::s60Version() == QSysInfo::SV_S60_3_1) { +#else + if (true) { +#endif + QCommonStyle::drawPrimitive(element, option, painter, widget); + } else { + if (const QStyleOptionViewItemV2 *vopt = qstyleoption_cast(option)) { + const bool rightLine = option->state & State_Item; + const bool downLine = option->state & State_Sibling; + const bool upLine = option->state & (State_Open | State_Children | State_Item | State_Sibling); + QS60StylePrivate::SkinElementFlags adjustedFlags = flags; + + QS60StyleEnums::SkinParts skinPart; + bool drawSkinPart = false; + if (rightLine && downLine && upLine) { + skinPart = QS60StyleEnums::SP_QgnIndiHlLineBranch; + drawSkinPart = true; + } else if (rightLine && upLine) { + skinPart = QS60StyleEnums::SP_QgnIndiHlLineEnd; + drawSkinPart = true; + } else if (upLine && downLine) { + skinPart = QS60StyleEnums::SP_QgnIndiHlLineStraight; + drawSkinPart = true; + } + + if (option->direction == Qt::RightToLeft) + adjustedFlags |= QS60StylePrivate::SF_Mirrored_X_Axis; + + if (drawSkinPart) + QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, adjustedFlags); + + if (option->state & State_Children) { + QS60StyleEnums::SkinParts skinPart = + (option->state & State_Open) ? QS60StyleEnums::SP_QgnIndiHlColSuper : QS60StyleEnums::SP_QgnIndiHlExpSuper; + const QRect selectionRect = subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget); + const int minDimension = qMin(option->rect.width(), option->rect.height()); + const int magicTweak = (option->direction == Qt::RightToLeft) ? -3 : 3; //@todo: magic + //The branch indicator icon in S60 is supposed to be superimposed on top of branch lines. + QRect iconRect(QPoint(option->rect.left() + magicTweak, selectionRect.top() + 1), QSize(minDimension, minDimension)); + if (!QS60StylePrivate::isTouchSupported()) + iconRect.translate(0, -4); //@todo: magic + QS60StylePrivate::drawSkinPart(skinPart, painter, iconRect, adjustedFlags); + } + } + } + break; + case PE_PanelItemViewRow: // ### Qt 5: remove +#ifndef QT_NO_ITEMVIEWS + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(option)) { + if (!QS60StylePrivate::equalToThemePalette(vopt->palette.base().texture().cacheKey(), QPalette::Base)) { + //QPalette::Base has been changed, let commonstyle draw the item + commonStyleDraws = true; + } else { + QPalette::ColorGroup cg = vopt->state & State_Enabled ? QPalette::Normal : QPalette::Disabled; + if (cg == QPalette::Normal && !(vopt->state & State_Active)) + cg = QPalette::Inactive; + if (vopt->features & QStyleOptionViewItemV2::Alternate) + painter->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::AlternateBase)); + //apart from alternate base, no background for list item is drawn for S60Style + } + } +#endif + break; + case PE_PanelScrollAreaCorner: + break; + case PE_IndicatorItemViewItemDrop: + if (QS60StylePrivate::isTouchSupported()) + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_DropArea, painter, option->rect, flags); + else + commonStyleDraws = true; + break; + // todo: items are below with #ifdefs "just in case". in final version, remove all non-required cases + case PE_FrameLineEdit: + case PE_IndicatorDockWidgetResizeHandle: + case PE_PanelTipLabel: + +#ifndef QT_NO_TABBAR + case PE_IndicatorTabTear: // No tab tear in S60 +#endif // QT_NO_TABBAR + case PE_FrameDefaultButton: +#ifndef QT_NO_DOCKWIDGET + case PE_FrameDockWidget: +#endif //QT_NO_DOCKWIDGET +#ifndef QT_NO_PROGRESSBAR + case PE_IndicatorProgressChunk: +#endif //QT_NO_PROGRESSBAR +#ifndef QT_NO_TOOLBAR + case PE_PanelToolBar: +#endif //QT_NO_TOOLBAR +#ifndef QT_NO_COLUMNVIEW + case PE_IndicatorColumnViewArrow: +#endif //QT_NO_COLUMNVIEW + case PE_FrameTabBarBase: // since tabs are in S60 always in navipane, let's use common style for tab base in Qt. + default: + commonStyleDraws = true; + } + if (commonStyleDraws) { + QCommonStyle::drawPrimitive(element, option, painter, widget); + } +} + +/*! \reimp */ +int QS60Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const +{ + int metricValue = QS60StylePrivate::pixelMetric(metric); + if (metricValue == KNotFound) + metricValue = QCommonStyle::pixelMetric(metric, option, widget); + + // Menu scrollers should be set to zero height for combobox popups + if (metric == PM_MenuScrollerHeight && !qobject_cast(widget)) + metricValue = 0; + + //if layout direction is mirrored, switch left and right border margins + if (option && option->direction == Qt::RightToLeft) { + if (metric == PM_LayoutLeftMargin) + metricValue = QS60StylePrivate::pixelMetric(PM_LayoutRightMargin); + else if (metric == PM_LayoutRightMargin) + metricValue = QS60StylePrivate::pixelMetric(PM_LayoutLeftMargin); + } + + if (widget && (metric == PM_LayoutTopMargin || metric == PM_LayoutLeftMargin || metric == PM_LayoutRightMargin)) + if (widget->windowType() == Qt::Dialog) + //double the layout margins (except bottom) for dialogs, it is very close to real value + //without having to define custom pixel metric + metricValue *= 2; + +#if defined(Q_WS_S60) + if (metric == PM_TabBarTabOverlap && (QSysInfo::s60Version() > QSysInfo::SV_S60_5_2)) + metricValue = 0; +#endif + + return metricValue; +} + +/*! \reimp */ +QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt, + const QSize &csz, const QWidget *widget) const +{ + QSize sz(csz); + switch (ct) { + case CT_ToolButton: + sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); + //FIXME properly - style should calculate the location of border frame-part + sz += QSize(2 * pixelMetric(PM_ButtonMargin), 2 * pixelMetric(PM_ButtonMargin)); + if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast(opt)) + if (toolBtn->subControls & SC_ToolButtonMenu) + sz += QSize(pixelMetric(PM_MenuButtonIndicator), 0); + + //Make toolbuttons in toolbar stretch the whole screen area + if (widget && qobject_cast(widget->parentWidget())) { + const QToolBar *tb = qobject_cast(widget->parentWidget()); + const bool parentCanGrowHorizontally = !(tb->sizePolicy().horizontalPolicy() == QSizePolicy::Fixed || + tb->sizePolicy().horizontalPolicy() == QSizePolicy::Maximum) && tb->orientation() == Qt::Horizontal; + + if (parentCanGrowHorizontally) { + int buttons = 0; + //Make the auto-stretch to happen only for horizontal orientation + if (tb && tb->orientation() == Qt::Horizontal) { + QList actionList = tb->actions(); + for (int i = 0; i < actionList.count(); i++) { + buttons++; + } + } + + if (widget->parentWidget() && buttons > 0) { + QWidget *w = const_cast(widget); + int toolBarMaxWidth = 0; + int totalMargin = 0; + while (w) { + //honor fixed width parents + if (w->maximumWidth() == w->minimumWidth()) + toolBarMaxWidth = qMax(toolBarMaxWidth, w->maximumWidth()); + if (w->layout() && w->windowType() == Qt::Widget) { + totalMargin += w->layout()->contentsMargins().left() + + w->layout()->contentsMargins().right(); + } + w = w->parentWidget(); + } + totalMargin += 2 * pixelMetric(QStyle::PM_ToolBarFrameWidth); + + if (toolBarMaxWidth == 0) + toolBarMaxWidth = + QApplication::desktop()->availableGeometry(widget->parentWidget()).width(); + //Reduce the margins, toolbar frame, item spacing and internal margin from available area + toolBarMaxWidth -= totalMargin; + + //ensure that buttons are side-by-side and not on top of each other + const int toolButtonWidth = (toolBarMaxWidth / buttons) + - pixelMetric(QStyle::PM_ToolBarItemSpacing) + - pixelMetric(QStyle::PM_ToolBarItemMargin) + //toolbar frame needs to be reduced again, since QToolBarLayout adds it for each toolbar action + - 2 * pixelMetric(QStyle::PM_ToolBarFrameWidth) - 1; + sz.setWidth(qMax(toolButtonWidth, sz.width())); + } + } + } + break; + case CT_PushButton: + sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); + //FIXME properly - style should calculate the location of border frame-part + if (const QAbstractButton *buttonWidget = (qobject_cast(widget))) { + if (buttonWidget->isCheckable()) + sz += QSize(pixelMetric(PM_IndicatorWidth) + pixelMetric(PM_CheckBoxLabelSpacing), 0); + const int iconHeight = (!buttonWidget->icon().isNull()) ? buttonWidget->iconSize().height() : 0; + const int textHeight = (buttonWidget->text().length() > 0) ? + buttonWidget->fontMetrics().size(Qt::TextSingleLine, buttonWidget->text()).height() : opt->fontMetrics.height(); + const int decoratorHeight = (buttonWidget->isCheckable()) ? pixelMetric(PM_IndicatorHeight) : 0; + + const int contentHeight = + qMax(qMax(iconHeight, decoratorHeight) + pixelMetric(PM_ButtonMargin), + textHeight + 2*pixelMetric(PM_ButtonMargin)); + sz.setHeight(qMax(sz.height(), contentHeight)); + sz += QSize(2 * pixelMetric(PM_ButtonMargin), 0); + } + break; + case CT_LineEdit: + if (const QStyleOptionFrame *f = qstyleoption_cast(opt)) + sz += QSize(2 * f->lineWidth, 4 * f->lineWidth); + break; + case CT_TabBarTab: { + sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); + // Adjust beginning tabbar item size, if scrollbuttons are used. This is to ensure that the + // tabbar item content fits, since scrollbuttons are making beginning tabbar item smaller. + int scrollButtonSize = 0; + if (const QTabBar *tabBar = qobject_cast(widget)) + scrollButtonSize = tabBar->usesScrollButtons() ? pixelMetric(PM_TabBarScrollButtonWidth) : 0; + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + const bool verticalTabs = tab->shape == QTabBar::RoundedEast + || tab->shape == QTabBar::RoundedWest + || tab->shape == QTabBar::TriangularEast + || tab->shape == QTabBar::TriangularWest; + if (tab->position == QStyleOptionTab::Beginning) + sz += QSize(verticalTabs ? 0 : scrollButtonSize, !verticalTabs ? 0 : scrollButtonSize); + } + } + break; + case CT_MenuItem: + case CT_ItemViewItem: + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast(opt)) { + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + sz = QSize(menuItem->rect.width() - 2 * pixelMetric(PM_MenuHMargin) - 2 * QS60StylePrivate::pixelMetric(PM_FrameCornerWidth), 1); + break; + } + } + sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); + if (QS60StylePrivate::isTouchSupported()) { + //Make itemview easier to use in touch devices + sz.setHeight(sz.height() + 2 * pixelMetric(PM_FocusFrameVMargin)); + //QCommonStyle does not adjust height with horizontal margin, it only adjusts width + if (ct == CT_MenuItem) + sz.setHeight(sz.height() - 8); //QCommonstyle adds 8 to height that this style handles through PM values + } + break; +#ifndef QT_NO_COMBOBOX + case CT_ComboBox: { + // Fixing Ui design issues with too wide QComboBoxes and greedy SizeHints + // Make sure, that the combobox stays within the screen. + const QSize desktopContentSize = QApplication::desktop()->availableGeometry().size() + - QSize(pixelMetric(PM_LayoutLeftMargin) + pixelMetric(PM_LayoutRightMargin), 0); + sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget). + boundedTo(desktopContentSize); + } + break; +#endif + default: + sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); + break; + } + if (!sz.isValid()) + sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); + return sz; +} + +/*! \reimp */ +int QS60Style::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *widget, + QStyleHintReturn *hret) const +{ + int retValue = 0; + switch (sh) { + case SH_RequestSoftwareInputPanel: + if (QS60StylePrivate::isSingleClickUi()) + retValue = RSIP_OnMouseClick; + else + retValue = RSIP_OnMouseClickAndAlreadyFocused; + break; + case SH_ComboBox_Popup: + retValue = true; + break; + case SH_Table_GridLineColor: + retValue = int(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 2, 0).rgba()); + break; + case SH_GroupBox_TextLabelColor: + retValue = int(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0).rgba()); + break; + case SH_ScrollBar_ScrollWhenPointerLeavesControl: + retValue = true; + break; + case SH_Slider_SnapToValue: + retValue = true; + break; + case SH_Slider_StopMouseOverSlider: + retValue = true; + break; + case SH_LineEdit_PasswordCharacter: + retValue = '*'; + break; + case SH_ComboBox_PopupFrameStyle: + retValue = QFrame::NoFrame | QFrame::Plain; + break; + case SH_Dial_BackgroundRole: + retValue = QPalette::Base; + break; + case SH_ItemView_ActivateItemOnSingleClick: { + if (QS60StylePrivate::isSingleClickUi()) + retValue = true; + else if (opt && opt->state & QStyle::State_Selected) + retValue = true; + break; + } + case SH_ProgressDialog_TextLabelAlignment: + retValue = (QApplication::layoutDirection() == Qt::LeftToRight) ? + Qt::AlignLeft : + Qt::AlignRight; + break; + case SH_Menu_SubMenuPopupDelay: + retValue = 300; + break; + case SH_Menu_Scrollable: + retValue = true; + break; + case SH_Menu_SelectionWrap: + retValue = true; + break; + case SH_Menu_MouseTracking: + retValue = true; + break; + case SH_ItemView_ShowDecorationSelected: + retValue = true; + break; + case SH_ToolBar_Movable: + retValue = false; + break; + case SH_BlinkCursorWhenTextSelected: + retValue = true; + break; + case SH_UnderlineShortcut: + retValue = 0; + break; + case SH_FormLayoutWrapPolicy: + retValue = QFormLayout::WrapLongRows; + break; + case SH_ScrollBar_ContextMenu: + retValue = false; + break; + default: + retValue = QCommonStyle::styleHint(sh, opt, widget, hret); + break; + } + return retValue; +} + +/*! \reimp */ +QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl scontrol, const QWidget *widget) const +{ + QRect ret; + switch (control) { +#ifndef QT_NO_SCROLLBAR + // This implementation of subControlRect(CC_ScrollBar..) basically just removes the SC_ScrollBarSubLine and SC_ScrollBarAddLine + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollbarOption = qstyleoption_cast(option)) { + const QRect scrollBarRect = scrollbarOption->rect; + const bool isHorizontal = scrollbarOption->orientation == Qt::Horizontal; + const int maxlen = isHorizontal ? scrollBarRect.width() : scrollBarRect.height(); + int sliderlen; + + // calculate slider length + if (scrollbarOption->maximum != scrollbarOption->minimum) { + const uint range = scrollbarOption->maximum - scrollbarOption->minimum; + sliderlen = (qint64(scrollbarOption->pageStep) * maxlen) / (range + scrollbarOption->pageStep); + + const int slidermin = pixelMetric(PM_ScrollBarSliderMin, scrollbarOption, widget); + if (sliderlen < slidermin || range > (INT_MAX >> 1)) + sliderlen = slidermin; + if (sliderlen > maxlen) + sliderlen = maxlen; + } else { + sliderlen = maxlen; + } + + const int sliderstart = sliderPositionFromValue(scrollbarOption->minimum, + scrollbarOption->maximum, + scrollbarOption->sliderPosition, + maxlen - sliderlen, + scrollbarOption->upsideDown); + + switch (scontrol) { + case SC_ScrollBarSubPage: // between top/left button and slider + if (isHorizontal) + ret.setRect(0, 0, sliderstart, scrollBarRect.height()); + else + ret.setRect(0, 0, scrollBarRect.width(), sliderstart); + break; + case SC_ScrollBarAddPage: { // between bottom/right button and slider + const int addPageLength = sliderstart + sliderlen; + if (isHorizontal) + ret = scrollBarRect.adjusted(addPageLength, 0, 0, 0); + else + ret = scrollBarRect.adjusted(0, addPageLength, 0, 0); + } + break; + case SC_ScrollBarGroove: + ret = scrollBarRect; + break; + case SC_ScrollBarSlider: + if (scrollbarOption->orientation == Qt::Horizontal) + ret.setRect(sliderstart, 0, sliderlen, scrollBarRect.height()); + else + ret.setRect(0, sliderstart, scrollBarRect.width(), sliderlen); + break; + case SC_ScrollBarSubLine: // top/left button + case SC_ScrollBarAddLine: // bottom/right button + default: + break; + } + ret = visualRect(scrollbarOption->direction, scrollBarRect, ret); + } + break; +#endif // QT_NO_SCROLLBAR + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(option)) { + const int frameThickness = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0; + const int buttonMargin = spinbox->frame ? 2 : 0; + const int buttonContentWidth = QS60StylePrivate::pixelMetric(PM_ButtonIconSize) + 2 * buttonMargin; + // Spinbox buttons should be no larger than one fourth of total width. + // Thus, side-by-side buttons would take half of the total width. + const int maxSize = qMax(spinbox->rect.width() / 4, buttonContentWidth); + QSize buttonSize; + buttonSize.setHeight(qMin(maxSize, qMax(8, spinbox->rect.height() - frameThickness))); + //width should at least be equal to height + buttonSize.setWidth(qMax(buttonSize.height(), buttonContentWidth)); + buttonSize = buttonSize.expandedTo(QApplication::globalStrut()); + + // Normally spinbuttons should be side-by-side, but if spinbox grows very big + // and spinbuttons reach their maximum size, they can be deployed one top of the other. + const bool sideBySide = (buttonSize.height() * 2 < spinbox->rect.height()) ? false : true; + const int y = frameThickness + spinbox->rect.y() + + (spinbox->rect.height() - (sideBySide ? 1 : 2) * buttonSize.height()) / 2; + const int x = spinbox->rect.x() + + spinbox->rect.width() - frameThickness - (sideBySide ? 2 : 1) * buttonSize.width(); + + switch (scontrol) { + case SC_SpinBoxUp: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + ret = QRect(x, y, buttonSize.width(), buttonSize.height()); + break; + case SC_SpinBoxDown: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + ret = QRect(x + (sideBySide ? buttonSize.width() : 0), + y + (sideBySide ? 0 : buttonSize.height()), + buttonSize.width(), buttonSize.height()); + break; + case SC_SpinBoxEditField: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + ret = QRect( + frameThickness, + frameThickness, + spinbox->rect.width() - 2 * frameThickness, + spinbox->rect.height() - 2 * frameThickness); + else + ret = QRect( + frameThickness, + frameThickness, + x - frameThickness, + spinbox->rect.height() - 2 * frameThickness); + break; + case SC_SpinBoxFrame: + ret = spinbox->rect; + break; + default: + break; + } + ret = visualRect(spinbox->direction, spinbox->rect, ret); + } + break; + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) { + ret = cmb->rect; + const int width = cmb->rect.width(); + const int height = cmb->rect.height(); + const int buttonMargin = cmb->frame ? 2 : 0; + // lets use spinbox frame here as well, as no combobox specific value available. + const int frameThickness = cmb->frame ? pixelMetric(PM_SpinBoxFrameWidth, cmb, widget) : 0; + const int buttonMinSize = QS60StylePrivate::pixelMetric(PM_ButtonIconSize) + 2 * buttonMargin; + QSize buttonSize; + //allow button to grow to one fourth of the frame height, if the frame is really tall + buttonSize.setHeight(qMin(height, qMax(width / 4, buttonMinSize))); + buttonSize.setWidth(buttonSize.height()); + buttonSize = buttonSize.expandedTo(QApplication::globalStrut()); + switch (scontrol) { + case SC_ComboBoxArrow: { + const int xposMod = cmb->rect.x() + width - buttonMargin - buttonSize.width(); + const int ypos = cmb->rect.y(); + ret.setRect(xposMod, ypos + buttonMargin, buttonSize.width(), height - 2 * buttonMargin); + } + break; + case SC_ComboBoxEditField: { + ret = QRect(0, 0, cmb->rect.x() + width - buttonSize.width(), height); + } + break; + case SC_ComboBoxListBoxPopup: { + ret = QApplication::desktop()->availableGeometry(); + } + break; + default: + break; + } + ret = visualRect(cmb->direction, cmb->rect, ret); + } + break; + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(option)) { + ret = QCommonStyle::subControlRect(control, option, scontrol, widget); + switch (scontrol) { + case SC_GroupBoxCheckBox: //fallthrough + case SC_GroupBoxLabel: { + //slightly indent text and boxes, so that dialog border does not mess with them. + const int horizontalSpacing = + QS60StylePrivate::pixelMetric(PM_LayoutHorizontalSpacing); + ret.adjust(2, horizontalSpacing - 3, 0, 0); + } + break; + case SC_GroupBoxFrame: { + const QRect textBox = subControlRect(control, option, SC_GroupBoxLabel, widget); + const int tbHeight = textBox.height(); + ret.translate(0, -ret.y()); + // include title to within the groupBox frame + ret.setHeight(ret.height() + tbHeight); + if (widget && ret.bottom() > widget->rect().bottom()) + ret.setBottom(widget->rect().bottom()); + } + break; + default: + break; + } + } + break; + case CC_ToolButton: + if (const QStyleOptionToolButton *toolButton = qstyleoption_cast(option)) { + const int indicatorRect = pixelMetric(PM_MenuButtonIndicator) + 2 * pixelMetric(PM_ButtonMargin); + const int border = pixelMetric(PM_ButtonMargin) + pixelMetric(PM_DefaultFrameWidth); + ret = toolButton->rect; + const bool popup = (toolButton->features & + (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay)) + == QStyleOptionToolButton::MenuButtonPopup; + switch (scontrol) { + case SC_ToolButton: + if (popup) + ret.adjust(0, 0, -indicatorRect, 0); + break; + case SC_ToolButtonMenu: + if (popup) + ret.adjust(ret.width() - indicatorRect, border, -pixelMetric(PM_ButtonMargin), -border); + break; + default: + break; + } + ret = visualRect(toolButton->direction, toolButton->rect, ret); + } + break; + default: + ret = QCommonStyle::subControlRect(control, option, scontrol, widget); + } + return ret; +} + +/*! + \reimp +*/ +QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, const QWidget *widget) const +{ + QRect ret; + switch (element) { + case SE_RadioButtonFocusRect: + ret = opt->rect; + break; + case SE_LineEditContents: { + // in S60 the input text box doesn't start from line Edit's TL, but + // a bit indented (8 pixels). + const int KLineEditDefaultIndention = 8; + ret = visualRect( + opt->direction, opt->rect, opt->rect.adjusted(KLineEditDefaultIndention, 0, 0, 0)); + } + break; + case SE_TabBarTearIndicator: + ret = QRect(0, 0, 0, 0); + break; + case SE_TabWidgetTabBar: + if (const QStyleOptionTabWidgetFrame *optionTab = qstyleoption_cast(opt)) { + ret = QCommonStyle::subElementRect(element, opt, widget); + + if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast(opt)) { + const int borderThickness = + QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth); + int tabOverlap = pixelMetric(PM_TabBarTabOverlap); + if (tabOverlap > borderThickness) + tabOverlap -= borderThickness; + const QTabWidget *tab = qobject_cast(widget); + int gain = (tab) ? tabOverlap * tab->count() : 0; + switch (twf->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: { + if (widget) { + // make sure that gain does not set the rect outside of widget boundaries + if (twf->direction == Qt::RightToLeft) { + if ((ret.left() - gain) < widget->rect().left()) + gain = widget->rect().left() - ret.left(); + ret.adjust(-gain, 0, 0, 0); + } else { + if ((ret.right() + gain) > widget->rect().right()) + gain = widget->rect().right() - ret.right(); + ret.adjust(0, 0, gain, 0); + } + } + break; + } + default: { + if (widget) { + if ((ret.bottom() + gain) > widget->rect().bottom()) + gain = widget->rect().bottom() - ret.bottom(); + ret.adjust(0, 0, 0, gain); + } + break; + } + } + } + } + break; + case SE_ItemViewItemText: + case SE_ItemViewItemDecoration: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(opt)) { + const QAbstractItemView *listItem = qobject_cast(widget); + const bool multiSelection = !listItem ? false : + listItem->selectionMode() == QAbstractItemView::MultiSelection || + listItem->selectionMode() == QAbstractItemView::ExtendedSelection || + listItem->selectionMode() == QAbstractItemView::ContiguousSelection; + ret = QCommonStyle::subElementRect(element, opt, widget); + // If both multiselect & check-state, then remove checkbox and move + // text and decoration towards the beginning + if (listItem && + multiSelection && + (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator)) { + const int verticalSpacing = + QS60StylePrivate::pixelMetric(PM_LayoutVerticalSpacing); + //const int horizontalSpacing = QS60StylePrivate::pixelMetric(PM_LayoutHorizontalSpacing); + const int checkBoxRectWidth = subElementRect(SE_ItemViewItemCheckIndicator, opt, widget).width(); + ret.adjust(-checkBoxRectWidth - verticalSpacing, 0, -checkBoxRectWidth - verticalSpacing, 0); + } + } else if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast(opt)) { + const bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable; + const int indicatorWidth = checkable ? + pixelMetric(PM_ListViewIconSize, opt, widget) : + pixelMetric(PM_SmallIconSize, opt, widget); + ret = menuItem->rect; + + QRect checkBoxRect = checkable ? menuItem->rect : QRect(); + if (checkable) { + checkBoxRect.setWidth(pixelMetric(PM_IndicatorWidth)); + checkBoxRect.setHeight(pixelMetric(PM_IndicatorHeight)); + } + + const int vSpacing = QS60StylePrivate::pixelMetric(PM_LayoutVerticalSpacing); + //The vertical spacing is doubled; it needs one spacing to separate checkbox from + //highlight and then it needs one to separate it whatever is shown after it (text/icon/both). + const int moveByX = checkBoxRect.width() + 2 * vSpacing; + + if (element == SE_ItemViewItemDecoration) { + if (menuItem->icon.isNull()) { + ret = QRect(); + } else { + if (menuItem->direction == Qt::RightToLeft) + ret.translate(ret.width() - indicatorWidth - moveByX, 0); + else + ret.translate(moveByX, 0); + ret.setWidth(indicatorWidth); + } + } else { + if (!menuItem->icon.isNull()) { + if (menuItem->direction == Qt::LeftToRight) + ret.adjust(indicatorWidth, 0, 0, 0); + else + ret.adjust(0, 0, -indicatorWidth, 0); + } + if (menuItem->direction == Qt::LeftToRight) + ret.adjust(moveByX, 0, 0, 0); + else + ret.adjust(0, 0, -moveByX, 0); + + // Make room for submenu indicator + if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu){ + // submenu indicator is very small, so lets halve the rect + if (menuItem->direction == Qt::LeftToRight) + ret.adjust(0, 0, -(indicatorWidth >> 1), 0); + else + ret.adjust((indicatorWidth >> 1), 0, 0, 0); + } + } + } + break; + case SE_ItemViewItemCheckIndicator: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(opt)) { + const QAbstractItemView *listItem = qobject_cast(widget); + + const bool singleSelection = listItem && + (listItem->selectionMode() == QAbstractItemView::SingleSelection || + listItem->selectionMode() == QAbstractItemView::NoSelection); + const bool checkBoxOnly = (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator) && + listItem && + singleSelection && vopt->text.isEmpty() && vopt->icon.isNull(); + + // Selection check mark rect. + const int indicatorWidth = QS60StylePrivate::pixelMetric(PM_IndicatorWidth); + const int indicatorHeight = QS60StylePrivate::pixelMetric(PM_IndicatorHeight); + const int spacing = QS60StylePrivate::pixelMetric(PM_CheckBoxLabelSpacing); + + const int itemHeight = opt->rect.height(); + int heightOffset = 0; + if (indicatorHeight < itemHeight) + heightOffset = ((itemHeight - indicatorHeight) >> 1); + if (checkBoxOnly) { + // Move rect and make it slightly smaller, so that + // a) highlight border does not cross the rect + // b) in s60 list checkbox is smaller than normal checkbox + //todo; magic three + ret.setRect(opt->rect.left() + 3, opt->rect.top() + heightOffset, + indicatorWidth - 3, indicatorHeight - 3); + } else { + ret.setRect(opt->rect.right() - indicatorWidth - spacing, opt->rect.top() + heightOffset, + indicatorWidth, indicatorHeight); + } + } else { + ret = QCommonStyle::subElementRect(element, opt, widget); + } + break; + case SE_HeaderLabel: + ret = QCommonStyle::subElementRect(element, opt, widget); + if (qstyleoption_cast(opt)) { + // Subtract area needed for line + if (opt->state & State_Horizontal) + ret.setHeight(ret.height() - QS60StylePrivate::pixelMetric(PM_BoldLineWidth)); + else + ret.setWidth(ret.width() - QS60StylePrivate::pixelMetric(PM_ThinLineWidth)); + } + ret = visualRect(opt->direction, opt->rect, ret); + break; + case SE_RadioButtonIndicator: { + const int height = pixelMetric(PM_ExclusiveIndicatorHeight, opt, widget); + ret.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - height) >> 1), + pixelMetric(PM_ExclusiveIndicatorWidth, opt, widget), height); + ret.translate(2, 0); //move indicator slightly to avoid highlight crossing over it + ret = visualRect(opt->direction, opt->rect, ret); + } + break; + case SE_CheckBoxIndicator: { + const int height = pixelMetric(PM_IndicatorHeight, opt, widget); + ret.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - height) >> 1), + pixelMetric(PM_IndicatorWidth, opt, widget), height); + ret.translate(2, 0); //move indicator slightly to avoid highlight crossing over it + ret = visualRect(opt->direction, opt->rect, ret); + } + break; + case SE_CheckBoxFocusRect: + ret = opt->rect; + break; + case SE_ProgressBarLabel: + case SE_ProgressBarContents: + case SE_ProgressBarGroove: + ret = opt->rect; + break; + default: + ret = QCommonStyle::subElementRect(element, opt, widget); + } + return ret; +} + +/*! + \reimp + */ +void QS60Style::polish(QWidget *widget) +{ + Q_D(const QS60Style); + QCommonStyle::polish(widget); + + if (!widget) + return; + + //Currently we only support animations in QProgressBar. +#ifndef QT_NO_PROGRESSBAR + if (qobject_cast(widget)) + widget->installEventFilter(this); +#endif + + if (false +#ifndef QT_NO_SCROLLBAR + || qobject_cast(widget) +#endif + ) { + widget->setAttribute(Qt::WA_OpaquePaintEvent, false); + } + + if (QS60StylePrivate::drawsOwnThemeBackground(widget)) { + widget->setAttribute(Qt::WA_StyledBackground); + } else if (false +#ifndef QT_NO_MENU + || qobject_cast (widget) +#endif // QT_NO_MENU + ) { + widget->setAttribute(Qt::WA_StyledBackground); + } else if (false +#ifndef QT_NO_COMBOBOX + || qobject_cast(widget) +#endif //QT_NO_COMBOBOX + ) { + widget->setAttribute(Qt::WA_StyledBackground); + } + d->setThemePalette(widget); + d->setFont(widget); +} + +/*! + \reimp + */ +void QS60Style::unpolish(QWidget *widget) +{ + Q_D(QS60Style); + + if (false + #ifndef QT_NO_SCROLLBAR + || qobject_cast(widget) + #endif + ) + widget->setAttribute(Qt::WA_OpaquePaintEvent); + + if (QS60StylePrivate::drawsOwnThemeBackground(widget)) { + widget->setAttribute(Qt::WA_StyledBackground, false); + } else if (false +#ifndef QT_NO_MENU + || qobject_cast (widget) +#endif // QT_NO_MENU + ) { + widget->setAttribute(Qt::WA_StyledBackground, false); + } else if (false +#ifndef QT_NO_COMBOBOX + || qobject_cast(widget) +#endif //QT_NO_COMBOBOX + ) { + widget->setAttribute(Qt::WA_StyledBackground, false); + } + + if (widget) + widget->setPalette(QPalette()); + +#if defined(Q_WS_S60) && !defined(QT_NO_PROGRESSBAR) + if (QProgressBar *bar = qobject_cast(widget)) { + widget->removeEventFilter(this); + d->m_bars.removeAll(bar); + } +#else + Q_UNUSED(d) +#endif + QCommonStyle::unpolish(widget); +} + +/*! + \reimp + */ +void QS60Style::polish(QApplication *application) +{ + Q_D(QS60Style); + QCommonStyle::polish(qApp); + d->m_originalPalette = application->palette(); + d->setThemePalette(application); + if (QS60StylePrivate::isTouchSupported()) + qApp->installEventFilter(this); +} + +/*! + \reimp + */ +void QS60Style::unpolish(QApplication *application) +{ + Q_UNUSED(application) + + Q_D(QS60Style); + QCommonStyle::unpolish(qApp); + const QPalette newPalette = QApplication::style()->standardPalette(); + QApplication::setPalette(newPalette); + QApplicationPrivate::setSystemPalette(d->m_originalPalette); + if (QS60StylePrivate::isTouchSupported()) + qApp->removeEventFilter(this); +} + +/*! + \reimp + */ +bool QS60Style::event(QEvent *e) +{ +#ifdef QT_KEYPAD_NAVIGATION + Q_D(QS60Style); + const QEvent::Type eventType = e->type(); + if ((eventType == QEvent::FocusIn || + eventType == QEvent::FocusOut || + eventType == QEvent::EnterEditFocus || + eventType == QEvent::LeaveEditFocus) && + QS60StylePrivate::isTouchSupported()) + return false; +#endif + + switch (e->type()) { + case QEvent::Timer: { + QTimerEvent *te = static_cast(e); + timerEvent(te); + } + break; +#ifdef QT_KEYPAD_NAVIGATION + case QEvent::FocusIn: + if (QWidget *focusWidget = QApplication::focusWidget()) { + + // Menus and combobox popups do not draw focus frame around them + if (qobject_cast(focusWidget) || + qobject_cast(focusWidget)) + break; + + if (!d->m_focusFrame) + d->m_focusFrame = new QFocusFrame(focusWidget); + d->m_focusFrame->setWidget(focusWidget); + } else if (d->m_focusFrame) { + d->m_focusFrame->setWidget(0); + } + break; + case QEvent::FocusOut: + if (d->m_focusFrame) + d->m_focusFrame->setWidget(0); + break; + case QEvent::EnterEditFocus: + case QEvent::LeaveEditFocus: + if (d->m_focusFrame) + d->m_focusFrame->update(); + break; +#endif + default: + break; + } + return false; +} + +/*! + \internal + */ +QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon, + const QStyleOption *option, const QWidget *widget) const +{ + QS60StyleEnums::SkinParts part; + qreal iconHeightMultiplier = 1.0; + qreal iconWidthMultiplier = 1.0; + QS60StylePrivate::SkinElementFlags adjustedFlags; + if (option) + adjustedFlags = (option->state & State_Enabled || option->state == 0) ? + QS60StylePrivate::SF_StateEnabled : + QS60StylePrivate::SF_StateDisabled; + + switch(standardIcon) { + case SP_MessageBoxWarning: + // By default, S60 messagebox icons have 4:3 ratio. Value is from S60 LAF documentation. + iconHeightMultiplier = 1.33; + part = QS60StyleEnums::SP_QgnNoteWarning; + break; + case SP_MessageBoxInformation: + iconHeightMultiplier = 1.33; + part = QS60StyleEnums::SP_QgnNoteInfo; + break; + case SP_MessageBoxCritical: + iconHeightMultiplier = 1.33; + part = QS60StyleEnums::SP_QgnNoteError; + break; + case SP_MessageBoxQuestion: + iconHeightMultiplier = 1.33; + part = QS60StyleEnums::SP_QgnNoteQuery; + break; + case SP_ArrowRight: + part = QS60StyleEnums::SP_QgnIndiNaviArrowRight; + break; + case SP_ArrowLeft: + part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft; + break; + case SP_ArrowUp: + part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft; + adjustedFlags |= QS60StylePrivate::SF_PointEast; + break; + case SP_ArrowDown: + part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft; + adjustedFlags |= QS60StylePrivate::SF_PointWest; + break; + case SP_ArrowBack: + if (QApplication::layoutDirection() == Qt::RightToLeft) + return QS60Style::standardIcon(SP_ArrowRight, option, widget); + return QS60Style::standardIcon(SP_ArrowLeft, option, widget); + case SP_ArrowForward: + if (QApplication::layoutDirection() == Qt::RightToLeft) + return QS60Style::standardIcon(SP_ArrowLeft, option, widget); + return QS60Style::standardIcon(SP_ArrowRight, option, widget); + case SP_ComputerIcon: + part = QS60StyleEnums::SP_QgnPropPhoneMemcLarge; + break; + case SP_DirClosedIcon: + part = QS60StyleEnums::SP_QgnPropFolderSmall; + break; + case SP_DirOpenIcon: + part = QS60StyleEnums::SP_QgnPropFolderCurrent; + break; + case SP_DirIcon: + part = QS60StyleEnums::SP_QgnPropFolderSmall; + break; + case SP_FileDialogNewFolder: + part = QS60StyleEnums::SP_QgnPropFolderSmallNew; + break; + case SP_FileIcon: + part = QS60StyleEnums::SP_QgnPropFileSmall; + break; + case SP_TrashIcon: + part = QS60StyleEnums::SP_QgnNoteErased; + break; + case SP_ToolBarHorizontalExtensionButton: + part = QS60StyleEnums::SP_QgnIndiSubmenu; + if (QApplication::layoutDirection() == Qt::RightToLeft) + adjustedFlags |= QS60StylePrivate::SF_PointSouth; + break; + case SP_ToolBarVerticalExtensionButton: + adjustedFlags |= QS60StylePrivate::SF_PointEast; + part = QS60StyleEnums::SP_QgnIndiSubmenu; + break; + default: + return QCommonStyle::standardIconImplementation(standardIcon, option, widget); + } + const QS60StylePrivate::SkinElementFlags flags = adjustedFlags; + const int iconDimension = QS60StylePrivate::pixelMetric(PM_ToolBarIconSize); + const QRect iconSize = (!option) ? + QRect(0, 0, iconDimension * iconWidthMultiplier, iconDimension * iconHeightMultiplier) : option->rect; + const QPixmap cachedPixMap(QS60StylePrivate::cachedPart(part, iconSize.size(), 0, flags)); + return cachedPixMap.isNull() ? + QCommonStyle::standardIconImplementation(standardIcon, option, widget) : QIcon(cachedPixMap); +} + +/*! + \internal + Animate indeterminate progress bars only when visible +*/ +bool QS60Style::eventFilter(QObject *object, QEvent *event) +{ + Q_D(QS60Style); + switch(event->type()) { + case QEvent::MouseButtonPress: { + QWidget *w = QApplication::widgetAt(QCursor::pos()); + if (w) { + QWidget *focusW = w->focusProxy(); + if (qobject_cast(focusW) || + qobject_cast(focusW) || + qobject_cast(focusW)) + d->m_pressedWidget = focusW; + else if (qobject_cast(w)|| + qobject_cast(w) || + qobject_cast(w)) + d->m_pressedWidget = w; + + if (d->m_pressedWidget) + d->m_pressedWidget->update(); + } + break; + } + case QEvent::MouseButtonRelease: { + if (d->m_pressedWidget) { + d->m_pressedWidget->update(); + d->m_pressedWidget = 0; + } + break; + } + default: + break; + } + +#ifdef Q_WS_S60 +#ifndef QT_NO_PROGRESSBAR + switch(event->type()) { + case QEvent::StyleChange: + case QEvent::Show: + if (QProgressBar *bar = qobject_cast(object)) { + if (!d->m_bars.contains(bar)) + d->m_bars << bar; + if (d->m_bars.size() == 1) //only start with first animated progressbar + d->startAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim); + } + break; + case QEvent::Destroy: + case QEvent::Hide: + if (QProgressBar *bar = reinterpret_cast(object)) { + d->stopAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim); + d->m_bars.removeAll(bar); + } + break; + default: + break; + } +#endif // QT_NO_PROGRESSBAR +#endif // Q_WS_S60 + return QCommonStyle::eventFilter(object, event); +} + +/*! + \internal + Handle the timer \a event. +*/ +void QS60Style::timerEvent(QTimerEvent *event) +{ +#ifdef Q_WS_S60 +#ifndef QT_NO_PROGRESSBAR + Q_D(QS60Style); + + QS60StyleAnimation *progressBarAnimation = + QS60StylePrivate::animationDefinition(QS60StyleEnums::SP_QgnGrafBarWaitAnim); + + if (event->timerId() == progressBarAnimation->timerId()) { + + Q_ASSERT(progressBarAnimation->interval() > 0); + + if (progressBarAnimation->currentFrame() == progressBarAnimation->frameCount() ) + if (progressBarAnimation->playMode() == QS60StyleEnums::AM_Looping) + progressBarAnimation->setCurrentFrame(0); + else + d->stopAnimation(progressBarAnimation->animationId()); + + foreach (QProgressBar *bar, d->m_bars) { + if ((bar->minimum() == 0 && bar->maximum() == 0)) + bar->update(); + } + progressBarAnimation->setCurrentFrame(progressBarAnimation->currentFrame() + 1); + } +#endif // QT_NO_PROGRESSBAR +#endif // Q_WS_S60 + event->ignore(); +} + +extern QPoint qt_s60_fill_background_offset(const QWidget *targetWidget); + +bool qt_s60_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush) +{ + // Check if the widget's palette matches placeholder or actual background texture. + // When accessing backgroundTexture, use parameter value 'true' to avoid creating + // the texture, if it is not already created. + + const QPixmap placeHolder(QS60StylePrivate::placeHolderTexture()); + const QPixmap bg(QS60StylePrivate::backgroundTexture(true)); + if (placeHolder.cacheKey() != brush.texture().cacheKey() + && bg.cacheKey() != brush.texture().cacheKey()) + return false; + + const QPixmap backgroundTexture(QS60StylePrivate::backgroundTexture()); + + const QPaintDevice *target = painter->device(); + if (target->devType() == QInternal::Widget) { + const QWidget *widget = static_cast(target); + if (!widget->testAttribute(Qt::WA_TranslucentBackground)) { + const QVector &rects = rgn.rects(); + for (int i = 0; i < rects.size(); ++i) { + const QRect rect(rects.at(i)); + painter->drawPixmap(rect.topLeft(), backgroundTexture, + rect.translated(qt_s60_fill_background_offset(widget))); + } + } + } + return true; +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_S60 || QT_PLUGIN diff --git a/src/widgets/styles/qs60style.h b/src/widgets/styles/qs60style.h new file mode 100644 index 0000000000..5f44ca7b9b --- /dev/null +++ b/src/widgets/styles/qs60style.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QS60STYLE_H +#define QS60STYLE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +//Public custom pixel metrics values. +//These can be used to fetch custom pixel metric value from outside QS60Style. +enum { + PM_FrameCornerWidth = QStyle::PM_CustomBase + 1, + PM_FrameCornerHeight, + PM_BoldLineWidth, + PM_ThinLineWidth, + PM_MessageBoxHeight + }; + +class QS60StylePrivate; + +class Q_GUI_EXPORT QS60Style : public QCommonStyle +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QS60Style) + +public: + QS60Style(); + ~QS60Style(); + + void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = 0) const; + void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const; + void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const; + int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const; + QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w = 0) const; + int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0, + QStyleHintReturn *shret = 0) const; + QRect subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl scontrol, const QWidget *widget = 0) const; + QRect subElementRect(SubElement element, const QStyleOption *opt, const QWidget *widget = 0) const; + void polish(QWidget *widget); + void unpolish(QWidget *widget); + void polish(QApplication *application); + void unpolish(QApplication *application); +#ifndef Q_NO_USING_KEYWORD + using QCommonStyle::polish; +#endif + bool event(QEvent *e); + +#ifndef Q_OS_SYMBIAN + static QStringList partKeys(); + static QStringList colorListKeys(); + void setS60Theme(const QHash &parts, + const QHash, QColor> &colors); + bool loadS60ThemeFromBlob(const QString &blobFile); + bool saveS60ThemeToBlob(const QString &blobFile) const; +#endif // !Q_OS_SYMBIAN + +protected Q_SLOTS: + QIcon standardIconImplementation( + StandardPixmap standardIcon, const QStyleOption * option = 0, const QWidget * widget = 0 ) const; + +protected: + void timerEvent(QTimerEvent *event); + bool eventFilter(QObject *o, QEvent *e); +private: + Q_DISABLE_COPY(QS60Style) + friend class QStyleFactory; + friend class QApplicationPrivate; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QS60STYLE_H diff --git a/src/widgets/styles/qs60style_p.h b/src/widgets/styles/qs60style_p.h new file mode 100644 index 0000000000..e146a4e3ac --- /dev/null +++ b/src/widgets/styles/qs60style_p.h @@ -0,0 +1,638 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QS60STYLE_P_H +#define QS60STYLE_P_H + +#include "qs60style.h" +#include "qcommonstyle_p.h" +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +const int MAX_NON_CUSTOM_PIXELMETRICS = 92; +const int CUSTOMVALUESCOUNT = 5; + +const int MAX_PIXELMETRICS = MAX_NON_CUSTOM_PIXELMETRICS + CUSTOMVALUESCOUNT; + +typedef struct { + unsigned short height; + unsigned short width; + int major_version; + int minor_version; + const char* layoutName; +} layoutHeader; + +#ifdef Q_OS_SYMBIAN +NONSHARABLE_CLASS (QS60StyleEnums) +#else +class QS60StyleEnums +#endif +: public QObject +{ +#ifndef Q_WS_S60 + Q_OBJECT + Q_ENUMS(FontCategories) + Q_ENUMS(SkinParts) + Q_ENUMS(ColorLists) +#endif // !Q_WS_S60 + +public: + + // S60 definitions within theme + enum ThemeDefinitions { + TD_AnimationData, + }; + + //Defines which values are contained within animation data (retrieved using TD_AnimationData). + //Additionally defines the order in which the items are given out in QList. + enum AnimationData { + AD_Interval = 0, + AD_NumberOfFrames, + AD_AnimationPlayMode, //currently not used as themes seem to contain invalid data + }; + + // Animation modes + enum AnimationMode { + AM_PlayOnce = 0, //animation is played exactly once + AM_Looping, //animation is repeated until stopped + AM_Bounce //animation is played repeatedly until stopped, + //but frames are played in reverse order every second time + //(no support yet) + }; + + // S60 look-and-feel font categories + enum FontCategories { + FC_Undefined, + FC_Primary, + FC_Secondary, + FC_Title, + FC_PrimarySmall, + FC_Digital + }; + + enum SkinParts { + SP_QgnGrafBarWaitAnim, + SP_QgnGrafBarFrameCenter, + SP_QgnGrafBarFrameSideL, + SP_QgnGrafBarFrameSideR, + SP_QgnGrafBarProgress, + SP_QgnGrafOrgBgGrid, + SP_QgnGrafScrollArrowDown, + SP_QgnGrafScrollArrowLeft, + SP_QgnGrafScrollArrowRight, + SP_QgnGrafScrollArrowUp, + SP_QgnGrafTabActiveL, + SP_QgnGrafTabActiveM, + SP_QgnGrafTabActiveR, + SP_QgnGrafTabPassiveL, + SP_QgnGrafTabPassiveM, + SP_QgnGrafTabPassiveR, + SP_QgnGrafNsliderEndLeft, + SP_QgnGrafNsliderEndRight, + SP_QgnGrafNsliderMiddle, + SP_QgnIndiCheckboxOff, + SP_QgnIndiCheckboxOn, + SP_QgnIndiHlColSuper, // Available in S60 release 3.2 and later. + SP_QgnIndiHlExpSuper, // Available in S60 release 3.2 and later. + SP_QgnIndiHlLineBranch, // Available in S60 release 3.2 and later. + SP_QgnIndiHlLineEnd, // Available in S60 release 3.2 and later. + SP_QgnIndiHlLineStraight, // Available in S60 release 3.2 and later. + SP_QgnIndiMarkedAdd, + SP_QgnIndiNaviArrowLeft, + SP_QgnIndiNaviArrowRight, + SP_QgnIndiRadiobuttOff, + SP_QgnIndiRadiobuttOn, + SP_QgnGrafNsliderMarker, + SP_QgnGrafNsliderMarkerSelected, + SP_QgnIndiSubmenu, + SP_QgnNoteErased, + SP_QgnNoteError, + SP_QgnNoteInfo, + SP_QgnNoteOk, + SP_QgnNoteQuery, + SP_QgnNoteWarning, + SP_QgnPropFileSmall, + SP_QgnPropFolderCurrent, + SP_QgnPropFolderSmall, + SP_QgnPropFolderSmallNew, + SP_QgnPropPhoneMemcLarge, + SP_QgnFrSctrlButtonCornerTl, // Toolbar button + SP_QgnFrSctrlButtonCornerTr, + SP_QgnFrSctrlButtonCornerBl, + SP_QgnFrSctrlButtonCornerBr, + SP_QgnFrSctrlButtonSideT, + SP_QgnFrSctrlButtonSideB, + SP_QgnFrSctrlButtonSideL, + SP_QgnFrSctrlButtonSideR, + SP_QgnFrSctrlButtonCenter, + SP_QgnFrSctrlButtonCornerTlPressed, // Toolbar button, pressed + SP_QgnFrSctrlButtonCornerTrPressed, + SP_QgnFrSctrlButtonCornerBlPressed, + SP_QgnFrSctrlButtonCornerBrPressed, + SP_QgnFrSctrlButtonSideTPressed, + SP_QgnFrSctrlButtonSideBPressed, + SP_QgnFrSctrlButtonSideLPressed, + SP_QgnFrSctrlButtonSideRPressed, + SP_QgnFrSctrlButtonCenterPressed, + SP_QsnCpScrollHandleBottomPressed, //ScrollBar handle, pressed state + SP_QsnCpScrollHandleMiddlePressed, + SP_QsnCpScrollHandleTopPressed, + SP_QsnBgScreen, + SP_QsnCpScrollBgBottom, + SP_QsnCpScrollBgMiddle, + SP_QsnCpScrollBgTop, + SP_QsnCpScrollHandleBottom, + SP_QsnCpScrollHandleMiddle, + SP_QsnCpScrollHandleTop, + SP_QsnFrButtonTbCornerTl, // Button, normal state + SP_QsnFrButtonTbCornerTr, + SP_QsnFrButtonTbCornerBl, + SP_QsnFrButtonTbCornerBr, + SP_QsnFrButtonTbSideT, + SP_QsnFrButtonTbSideB, + SP_QsnFrButtonTbSideL, + SP_QsnFrButtonTbSideR, + SP_QsnFrButtonTbCenter, + SP_QsnFrButtonTbCornerTlPressed, // Button, pressed state + SP_QsnFrButtonTbCornerTrPressed, + SP_QsnFrButtonTbCornerBlPressed, + SP_QsnFrButtonTbCornerBrPressed, + SP_QsnFrButtonTbSideTPressed, + SP_QsnFrButtonTbSideBPressed, + SP_QsnFrButtonTbSideLPressed, + SP_QsnFrButtonTbSideRPressed, + SP_QsnFrButtonTbCenterPressed, + SP_QsnFrCaleCornerTl, // calendar grid item + SP_QsnFrCaleCornerTr, + SP_QsnFrCaleCornerBl, + SP_QsnFrCaleCornerBr, + SP_QsnFrCaleSideT, + SP_QsnFrCaleSideB, + SP_QsnFrCaleSideL, + SP_QsnFrCaleSideR, + SP_QsnFrCaleCenter, + SP_QsnFrCaleHeadingCornerTl, // calendar grid header + SP_QsnFrCaleHeadingCornerTr, + SP_QsnFrCaleHeadingCornerBl, + SP_QsnFrCaleHeadingCornerBr, + SP_QsnFrCaleHeadingSideT, + SP_QsnFrCaleHeadingSideB, + SP_QsnFrCaleHeadingSideL, + SP_QsnFrCaleHeadingSideR, + SP_QsnFrCaleHeadingCenter, + SP_QsnFrInputCornerTl, // Text input field + SP_QsnFrInputCornerTr, + SP_QsnFrInputCornerBl, + SP_QsnFrInputCornerBr, + SP_QsnFrInputSideT, + SP_QsnFrInputSideB, + SP_QsnFrInputSideL, + SP_QsnFrInputSideR, + SP_QsnFrInputCenter, + SP_QsnFrListCornerTl, // List background + SP_QsnFrListCornerTr, + SP_QsnFrListCornerBl, + SP_QsnFrListCornerBr, + SP_QsnFrListSideT, + SP_QsnFrListSideB, + SP_QsnFrListSideL, + SP_QsnFrListSideR, + SP_QsnFrListCenter, + SP_QsnFrPopupCornerTl, // Option menu background + SP_QsnFrPopupCornerTr, + SP_QsnFrPopupCornerBl, + SP_QsnFrPopupCornerBr, + SP_QsnFrPopupSideT, + SP_QsnFrPopupSideB, + SP_QsnFrPopupSideL, + SP_QsnFrPopupSideR, + SP_QsnFrPopupCenter, + SP_QsnFrPopupPreviewCornerTl, // tool tip background + SP_QsnFrPopupPreviewCornerTr, + SP_QsnFrPopupPreviewCornerBl, + SP_QsnFrPopupPreviewCornerBr, + SP_QsnFrPopupPreviewSideT, + SP_QsnFrPopupPreviewSideB, + SP_QsnFrPopupPreviewSideL, + SP_QsnFrPopupPreviewSideR, + SP_QsnFrPopupPreviewCenter, + SP_QsnFrSetOptCornerTl, // Settings list + SP_QsnFrSetOptCornerTr, + SP_QsnFrSetOptCornerBl, + SP_QsnFrSetOptCornerBr, + SP_QsnFrSetOptSideT, + SP_QsnFrSetOptSideB, + SP_QsnFrSetOptSideL, + SP_QsnFrSetOptSideR, + SP_QsnFrSetOptCenter, + SP_QsnFrPopupSubCornerTl, // Toolbar background + SP_QsnFrPopupSubCornerTr, + SP_QsnFrPopupSubCornerBl, + SP_QsnFrPopupSubCornerBr, + SP_QsnFrPopupSubSideT, + SP_QsnFrPopupSubSideB, + SP_QsnFrPopupSubSideL, + SP_QsnFrPopupSubSideR, + SP_QsnFrPopupSubCenter, + SP_QsnFrButtonCornerTlInactive, // Inactive button + SP_QsnFrButtonCornerTrInactive, + SP_QsnFrButtonCornerBlInactive, + SP_QsnFrButtonCornerBrInactive, + SP_QsnFrButtonSideTInactive, + SP_QsnFrButtonSideBInactive, + SP_QsnFrButtonSideLInactive, + SP_QsnFrButtonSideRInactive, + SP_QsnFrButtonCenterInactive, + SP_QsnFrGridCornerTlPressed, // Pressed table item + SP_QsnFrGridCornerTrPressed, + SP_QsnFrGridCornerBlPressed, + SP_QsnFrGridCornerBrPressed, + SP_QsnFrGridSideTPressed, + SP_QsnFrGridSideBPressed, + SP_QsnFrGridSideLPressed, + SP_QsnFrGridSideRPressed, + SP_QsnFrGridCenterPressed, + SP_QsnFrListCornerTlPressed, // Pressed list item + SP_QsnFrListCornerTrPressed, + SP_QsnFrListCornerBlPressed, + SP_QsnFrListCornerBrPressed, + SP_QsnFrListSideTPressed, + SP_QsnFrListSideBPressed, + SP_QsnFrListSideLPressed, + SP_QsnFrListSideRPressed, + SP_QsnFrListCenterPressed, + }; + + enum ColorLists { + CL_QsnHighlightColors, + CL_QsnIconColors, + CL_QsnLineColors, + CL_QsnOtherColors, + CL_QsnParentColors, + CL_QsnTextColors + }; +}; + +#ifdef Q_WS_S60 +class CAknBitmapAnimation; +NONSHARABLE_CLASS (AnimationData) : public QObject +{ +public: + AnimationData(const QS60StyleEnums::SkinParts part, int frames, int interval); + + const QS60StyleEnums::SkinParts m_id; + int m_frames; + int m_interval; + QS60StyleEnums::AnimationMode m_mode; +}; + + +NONSHARABLE_CLASS (AnimationDataV2) : public AnimationData +{ +public: + AnimationDataV2(const AnimationData &data); + ~AnimationDataV2(); + + CAknBitmapAnimation *m_animation; + int m_currentFrame; + bool m_resourceBased; + int m_timerId; +}; + + +class QS60StyleAnimation : public QObject +{ +public: + QS60StyleAnimation(const QS60StyleEnums::SkinParts part, int frames, int interval); + ~QS60StyleAnimation(); + +public: + QS60StyleEnums::SkinParts animationId() const {return m_currentData->m_id;} + int frameCount() const { return m_currentData->m_frames;} + int interval() const {return m_currentData->m_interval;} + QS60StyleEnums::AnimationMode playMode() const {return m_currentData->m_mode;} + CAknBitmapAnimation* animationObject() const {return m_currentData->m_animation;} + bool isResourceBased() const {return m_currentData->m_resourceBased;} + int timerId() const {return m_currentData->m_timerId;} + int currentFrame() const {return m_currentData->m_currentFrame;} + + void setFrameCount(int frameCount) {m_currentData->m_frames = frameCount;} + void setInterval(int interval) {m_currentData->m_interval = interval;} + void setAnimationObject(CAknBitmapAnimation* animation); + void setResourceBased(bool resourceBased) {m_currentData->m_resourceBased = resourceBased;} + void setTimerId(int timerId) {m_currentData->m_timerId = timerId;} + void setCurrentFrame(int currentFrame) {m_currentData->m_currentFrame = currentFrame;} + + void resetToDefaults(); + +private: //data members + //TODO: consider changing these to non-pointers as the classes are rather small anyway + AnimationData *m_defaultData; + AnimationDataV2 *m_currentData; +}; + +#endif //Q_WS_S60 + + +class QFocusFrame; +class QProgressBar; +class QS60StyleAnimation; + +// Private class +#ifdef Q_OS_SYMBIAN +NONSHARABLE_CLASS (QS60StylePrivate) +#else +class QS60StylePrivate +#endif +: public QCommonStylePrivate +{ + Q_DECLARE_PUBLIC(QS60Style) + +public: + QS60StylePrivate(); + ~QS60StylePrivate(); + + enum SkinElements { + SE_ButtonNormal, + SE_ButtonPressed, + SE_FrameLineEdit, + SE_ProgressBarGrooveHorizontal, + SE_ProgressBarIndicatorHorizontal, + SE_ProgressBarGrooveVertical, + SE_ProgressBarIndicatorVertical, + SE_ScrollBarGrooveHorizontal, + SE_ScrollBarGrooveVertical, + SE_ScrollBarHandleHorizontal, + SE_ScrollBarHandleVertical, + SE_SliderHandleHorizontal, + SE_SliderHandleVertical, + SE_SliderHandleSelectedHorizontal, + SE_SliderHandleSelectedVertical, + SE_SliderGrooveVertical, + SE_SliderGrooveHorizontal, + SE_TabBarTabEastActive, + SE_TabBarTabEastInactive, + SE_TabBarTabNorthActive, + SE_TabBarTabNorthInactive, + SE_TabBarTabSouthActive, + SE_TabBarTabSouthInactive, + SE_TabBarTabWestActive, + SE_TabBarTabWestInactive, + SE_ListHighlight, + SE_PopupBackground, + SE_SettingsList, + SE_TableItem, + SE_TableHeaderItem, + SE_ToolTip, //own graphic available on 3.2+ releases, + SE_ToolBar, + SE_ToolBarButton, + SE_ToolBarButtonPressed, + SE_PanelBackground, + SE_ScrollBarHandlePressedHorizontal, + SE_ScrollBarHandlePressedVertical, + SE_ButtonInactive, + SE_Editor, + SE_DropArea, + SE_TableItemPressed, + SE_ListItemPressed, + }; + + enum SkinFrameElements { + SF_ButtonNormal, + SF_ButtonPressed, + SF_FrameLineEdit, + SF_ListHighlight, + SF_PopupBackground, + SF_SettingsList, + SF_TableItem, + SF_TableHeaderItem, + SF_ToolTip, + SF_ToolBar, + SF_ToolBarButton, + SF_ToolBarButtonPressed, + SF_PanelBackground, + SF_ButtonInactive, + SF_TableItemPressed, + SF_ListItemPressed, + }; + + enum SkinElementFlag { + SF_PointNorth = 0x0001, // North = the default + SF_PointEast = 0x0002, + SF_PointSouth = 0x0004, + SF_PointWest = 0x0008, + + SF_StateEnabled = 0x0010, // Enabled = the default + SF_StateDisabled = 0x0020, + SF_ColorSkinned = 0x0040, // pixmap is colored with foreground pen color + SF_Animation = 0x0080, + SF_Mirrored_X_Axis = 0x0100, + SF_Mirrored_Y_Axis = 0x0200 + }; + + enum CacheClearReason { + CC_UndefinedChange = 0, + CC_LayoutChange, + CC_ThemeChange + }; + + Q_DECLARE_FLAGS(SkinElementFlags, SkinElementFlag) + + // draws skin element + static void drawSkinElement(SkinElements element, QPainter *painter, + const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags); + // draws a specific skin part + static void drawSkinPart(QS60StyleEnums::SkinParts part, QPainter *painter, + const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags); + // gets pixel metrics value + static short pixelMetric(int metric); + // gets color. 'index' is NOT 0-based. + // It corresponds to the enum key 1-based numbers of TAknsQsnXYZColorsIndex, not the values. + static QColor s60Color(QS60StyleEnums::ColorLists list, + int index, const QStyleOption *option); + // gets state specific color + static QColor stateColor(const QColor &color, const QStyleOption *option); + // gets lighter color than base color + static QColor lighterColor(const QColor &baseColor); + //deduces if the given widget should have separately themeable background + static bool drawsOwnThemeBackground(const QWidget *widget); + + QFont s60Font(QS60StyleEnums::FontCategories fontCategory, + int pointSize = -1, bool resolveFontSize = true) const; + // clears all style caches (fonts, colors, pixmaps) + void clearCaches(CacheClearReason reason = CC_UndefinedChange); + + // themed main background oprations + void setBackgroundTexture(QApplication *application) const; + static void deleteBackground(); + + static bool isTouchSupported(); + static bool isToolBarBackground(); + static bool hasSliderGrooveGraphic(); + static bool isSingleClickUi(); + static bool isWidgetPressed(const QWidget *widget); + +#ifdef Q_WS_S60 + static void deleteStoredSettings(); + // calculates average color based on theme graphics (minus borders). + QColor colorFromFrameGraphics(SkinFrameElements frame) const; +#endif + QColor calculatedColor(SkinFrameElements frame) const; + + //set theme palette for application + void setThemePalette(QApplication *application) const; + //access to theme palette + static QPalette* themePalette(); + + static const layoutHeader m_layoutHeaders[]; + static const short data[][MAX_PIXELMETRICS]; + + void setCurrentLayout(int layoutIndex); + void setActiveLayout(); + // Pointer + static short const *m_pmPointer; + // number of layouts supported by the style + static const int m_numberOfLayouts; + + mutable QHash, QFont> m_mappedFontsCache; + + // Has one entry per SkinFrameElements + static const struct frameElementCenter { + SkinElements element; + QS60StyleEnums::SkinParts center; + } m_frameElementsData[]; + + static QPixmap frame(SkinFrameElements frame, const QSize &size, + SkinElementFlags flags = KDefaultSkinElementFlags); + static QPixmap backgroundTexture(bool skipCreation = false); + static QPixmap placeHolderTexture(); + +#ifdef Q_WS_S60 + void handleDynamicLayoutVariantSwitch(); + void handleSkinChange(); +#endif // Q_WS_S60 + + //Checks that the current brush is transparent or has BrushStyle NoBrush, + //so that theme graphic background can be drawn. + static bool canDrawThemeBackground(const QBrush &backgroundBrush, const QWidget *widget); + + static int currentAnimationFrame(QS60StyleEnums::SkinParts part); +#ifdef Q_WS_S60 + + //No support for animations on emulated style + void startAnimation(QS60StyleEnums::SkinParts animation); + void stopAnimation(QS60StyleEnums::SkinParts animation); + static QS60StyleAnimation* animationDefinition(QS60StyleEnums::SkinParts part); + static void removeAnimations(); + +#endif + +private: + static void drawPart(QS60StyleEnums::SkinParts part, QPainter *painter, + const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags); + static void drawRow(QS60StyleEnums::SkinParts start, QS60StyleEnums::SkinParts middle, + QS60StyleEnums::SkinParts end, Qt::Orientation orientation, QPainter *painter, + const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags); + static void drawFrame(SkinFrameElements frame, QPainter *painter, + const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags); + + static QPixmap cachedPart(QS60StyleEnums::SkinParts part, const QSize &size, + QPainter *painter, SkinElementFlags flags = KDefaultSkinElementFlags); + static QPixmap cachedFrame(SkinFrameElements frame, const QSize &size, + SkinElementFlags flags = KDefaultSkinElementFlags); + + // set S60 font for widget + void setFont(QWidget *widget) const; + static void setThemePalette(QWidget *widget); + void setThemePalette(QPalette *palette) const; + static void setThemePaletteHash(QPalette *palette); + static void storeThemePalette(QPalette *palette); + static void deleteThemePalette(); + static bool equalToThemePalette(QColor color, QPalette::ColorRole role); + static bool equalToThemePalette(qint64 cacheKey, QPalette::ColorRole role); + + static QSize partSize(QS60StyleEnums::SkinParts part, + SkinElementFlags flags = KDefaultSkinElementFlags); + static QPixmap part(QS60StyleEnums::SkinParts part, const QSize &size, + QPainter *painter, SkinElementFlags flags = KDefaultSkinElementFlags); + + static QFont s60Font_specific(QS60StyleEnums::FontCategories fontCategory, + int pointSize, bool resolveFontSize); + + static QSize screenSize(); + + // Contains background texture. + static QPixmap *m_background; + // Placeholder pixmap for the real background texture. + static QPixmap *m_placeHolderTexture; + + const static SkinElementFlags KDefaultSkinElementFlags; + // defined theme palette + static QPalette *m_themePalette; + QPalette m_originalPalette; + + QPointer m_focusFrame; + static qint64 m_webPaletteKey; + + static QPointer m_pressedWidget; + +#ifdef Q_WS_S60 + //list of progress bars having animation running + QList m_bars; +#endif + +}; + +QT_END_NAMESPACE + +#endif // QS60STYLE_P_H diff --git a/src/widgets/styles/qs60style_s60.cpp b/src/widgets/styles/qs60style_s60.cpp new file mode 100644 index 0000000000..1e374cbc09 --- /dev/null +++ b/src/widgets/styles/qs60style_s60.cpp @@ -0,0 +1,1591 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qs60style.h" +#include "qs60style_p.h" +#include "qpainter.h" +#include "qstyleoption.h" +#include "qstyle.h" +#include "private/qt_s60_p.h" +#include "private/qpixmap_s60_p.h" +#include "private/qcore_symbian_p.h" +#include "private/qvolatileimage_p.h" +#include "qapplication.h" +#include "qsettings.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN) + +QT_BEGIN_NAMESPACE + +enum TDrawType { + EDrawIcon, + EDrawGulIcon, + EDrawBackground, + EDrawAnimation, + ENoDraw +}; + +const TUid personalisationUID = { 0x101F876F }; + +enum TSupportRelease { + ES60_None = 0x0000, //indicates that the commonstyle should draw the graphics + ES60_3_1 = 0x0001, + ES60_3_2 = 0x0002, + ES60_5_0 = 0x0004, + ES60_5_1 = 0x0008, + ES60_5_2 = 0x0010, + ES60_5_3 = 0x0020, + ES60_3_X = ES60_3_1 | ES60_3_2, + // Releases before Symbian Foundation + ES60_PreSF = ES60_3_1 | ES60_3_2 | ES60_5_0, + // Releases before the S60 5.2 + ES60_Pre52 = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1, + // Releases before S60 5.3 + ES60_Pre53 = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1 | ES60_5_2, + // Add all new releases here + ES60_All = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1 | ES60_5_2 | ES60_5_3 +}; + +typedef struct { + const TAknsItemID &skinID; // Determines default theme graphics ID. + TDrawType drawType; // Determines which native drawing routine is used to draw this item. + int supportInfo; // Defines the S60 versions that use the default graphics. + // These two, define new graphics that are used in releases other than partMapEntry.supportInfo defined releases. + // In general, these are given in numeric form to allow style compilation in earlier + // native releases that do not contain the new graphics. + int newMajorSkinId; + int newMinorSkinId; +} partMapEntry; + +AnimationData::AnimationData(const QS60StyleEnums::SkinParts part, int frames, int interval) : m_id(part), + m_frames(frames), m_interval(interval), m_mode(QS60StyleEnums::AM_Looping) +{ +} + +AnimationDataV2::AnimationDataV2(const AnimationData &data) : AnimationData(data.m_id, data.m_frames, data.m_interval), + m_animation(0), m_currentFrame(0), m_resourceBased(false), m_timerId(0) +{ +} +AnimationDataV2::~AnimationDataV2() +{ + delete m_animation; +} + +QS60StyleAnimation::QS60StyleAnimation(const QS60StyleEnums::SkinParts part, int frames, int interval) +{ + QT_TRAP_THROWING(m_defaultData = new (ELeave) AnimationData(part, frames, interval)); + QT_TRAP_THROWING(m_currentData = new (ELeave) AnimationDataV2(*m_defaultData)); +} + +QS60StyleAnimation::~QS60StyleAnimation() +{ + delete m_currentData; + delete m_defaultData; +} + +void QS60StyleAnimation::setAnimationObject(CAknBitmapAnimation* animation) +{ + Q_ASSERT(animation); + if (m_currentData->m_animation) + delete m_currentData->m_animation; + m_currentData->m_animation = animation; +} + +void QS60StyleAnimation::resetToDefaults() +{ + delete m_currentData; + m_currentData = 0; + QT_TRAP_THROWING(m_currentData = new (ELeave) AnimationDataV2(*m_defaultData)); +} + +class QS60StyleModeSpecifics +{ +public: + static QPixmap skinnedGraphics(QS60StyleEnums::SkinParts stylepart, + const QSize &size, QS60StylePrivate::SkinElementFlags flags); + static QPixmap skinnedGraphics(QS60StylePrivate::SkinFrameElements frameElement, const QSize &size, QS60StylePrivate::SkinElementFlags flags); + static QPixmap colorSkinnedGraphics(const QS60StyleEnums::SkinParts &stylepart, + const QSize &size, QPainter *painter, QS60StylePrivate::SkinElementFlags flags); + static QColor colorValue(const TAknsItemID &colorGroup, int colorIndex); + static QPixmap fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask, QS60StylePrivate::SkinElementFlags flags, const TSize& targetSize); + static bool disabledPartGraphic(QS60StyleEnums::SkinParts &part); + static bool disabledFrameGraphic(QS60StylePrivate::SkinFrameElements &frame); + static QPixmap generateMissingThemeGraphic(QS60StyleEnums::SkinParts &part, const QSize &size, QS60StylePrivate::SkinElementFlags flags); + static TAknsItemID partSpecificThemeId(int part); + + static QVariant themeDefinition(QS60StyleEnums::ThemeDefinitions definition, QS60StyleEnums::SkinParts part); + +private: + static QPixmap createSkinnedGraphicsLX(QS60StyleEnums::SkinParts part, + const QSize &size, QS60StylePrivate::SkinElementFlags flags); + static QPixmap createSkinnedGraphicsLX(QS60StylePrivate::SkinFrameElements frameElement, const QSize &size, QS60StylePrivate::SkinElementFlags flags); + static QPixmap colorSkinnedGraphicsLX(const QS60StyleEnums::SkinParts &stylepart, + const QSize &size, QPainter *painter, QS60StylePrivate::SkinElementFlags flags); + static void frameIdAndCenterId(QS60StylePrivate::SkinFrameElements frameElement, TAknsItemID &frameId, TAknsItemID ¢erId); + static TRect innerRectFromElement(QS60StylePrivate::SkinFrameElements frameElement, const TRect &outerRect); + static void fallbackInfo(const QS60StyleEnums::SkinParts &stylePart, TInt &fallbackIndex); + static bool checkSupport(const int supportedRelease); + // Array to match the skin ID, fallback graphics and Qt widget graphics. + static const partMapEntry m_partMap[]; +}; + +const partMapEntry QS60StyleModeSpecifics::m_partMap[] = { + /* SP_QgnGrafBarWaitAnim */ {KAknsIIDQgnGrafBarWaitAnim, EDrawAnimation, ES60_All, -1,-1}, + /* SP_QgnGrafBarFrameCenter */ {KAknsIIDQgnGrafBarFrameCenter, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnGrafBarFrameSideL */ {KAknsIIDQgnGrafBarFrameSideL, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnGrafBarFrameSideR */ {KAknsIIDQgnGrafBarFrameSideR, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnGrafBarProgress */ {KAknsIIDQgnGrafBarProgress, EDrawIcon, ES60_All, -1,-1}, + // No drop area for 3.x non-touch devices + /* SP_QgnGrafOrgBgGrid */ {KAknsIIDNone, EDrawIcon, ES60_3_X, EAknsMajorGeneric ,0x1eba}, //KAknsIIDQgnGrafOrgBgGrid + /* SP_QgnGrafScrollArrowDown */ {KAknsIIDQgnGrafScrollArrowDown, EDrawGulIcon, ES60_All, -1,-1}, + /* SP_QgnGrafScrollArrowLeft */ {KAknsIIDQgnGrafScrollArrowLeft, EDrawGulIcon, ES60_All, -1,-1}, + /* SP_QgnGrafScrollArrowRight */ {KAknsIIDQgnGrafScrollArrowRight, EDrawGulIcon, ES60_All, -1,-1}, + /* SP_QgnGrafScrollArrowUp */ {KAknsIIDQgnGrafScrollArrowUp, EDrawGulIcon, ES60_All, -1,-1}, + + // In S60 5.3 there is a new tab graphic + /* SP_QgnGrafTabActiveL */ {KAknsIIDQgnGrafTabActiveL, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x2219}, //KAknsIIDQtgFrTabActiveNormalL + /* SP_QgnGrafTabActiveM */ {KAknsIIDQgnGrafTabActiveM, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x221b}, //KAknsIIDQtgFrTabActiveNormalC + /* SP_QgnGrafTabActiveR */ {KAknsIIDQgnGrafTabActiveR, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x221a}, //KAknsIIDQtgFrTabActiveNormalR + /* SP_QgnGrafTabPassiveL */ {KAknsIIDQgnGrafTabPassiveL, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x2221}, //KAknsIIDQtgFrTabPassiveNormalL + /* SP_QgnGrafTabPassiveM */ {KAknsIIDQgnGrafTabPassiveM, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x2223}, //KAknsIIDQtgFrTabPassiveNormalC + /* SP_QgnGrafTabPassiveR */ {KAknsIIDQgnGrafTabPassiveR, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x2222}, //KAknsIIDQtgFrTabPassiveNormalR + + // In 3.1 there is no slider groove. + /* SP_QgnGrafNsliderEndLeft */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x19cf /* KAknsIIDQgnGrafNsliderEndLeft */}, + /* SP_QgnGrafNsliderEndRight */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x19d0 /* KAknsIIDQgnGrafNsliderEndRight */}, + /* SP_QgnGrafNsliderMiddle */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x19d2 /* KAknsIIDQgnGrafNsliderMiddle */}, + /* SP_QgnIndiCheckboxOff */ {KAknsIIDQgnIndiCheckboxOff, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnIndiCheckboxOn */ {KAknsIIDQgnIndiCheckboxOn, EDrawIcon, ES60_All, -1,-1}, + + // Following 5 items (SP_QgnIndiHlColSuper - SP_QgnIndiHlLineStraight) are available starting from S60 release 3.2. + // In 3.1 CommonStyle drawing is used for these QTreeView elements, since no similar icons in AVKON UI. + /* SP_QgnIndiHlColSuper */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d5 /* KAknsIIDQgnIndiHlColSuper */}, + /* SP_QgnIndiHlExpSuper */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d6 /* KAknsIIDQgnIndiHlExpSuper */}, + /* SP_QgnIndiHlLineBranch */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d7 /* KAknsIIDQgnIndiHlLineBranch */}, + /* SP_QgnIndiHlLineEnd */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d8 /* KAknsIIDQgnIndiHlLineEnd */}, + /* SP_QgnIndiHlLineStraight */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d9 /* KAknsIIDQgnIndiHlLineStraight */}, + /* SP_QgnIndiMarkedAdd */ {KAknsIIDQgnIndiMarkedAdd, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnIndiNaviArrowLeft */ {KAknsIIDQgnIndiNaviArrowLeft, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnIndiNaviArrowRight */ {KAknsIIDQgnIndiNaviArrowRight, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnIndiRadiobuttOff */ {KAknsIIDQgnIndiRadiobuttOff, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnIndiRadiobuttOn */ {KAknsIIDQgnIndiRadiobuttOn, EDrawIcon, ES60_All, -1,-1}, + + // In 3.1 there different slider graphic and no pressed state. + /* SP_QgnGrafNsliderMarker */ {KAknsIIDQgnIndiSliderEdit, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x19d1 /* KAknsIIDQgnGrafNsliderMarker */}, + /* SP_QgnGrafNsliderMarkerSelected */ {KAknsIIDQgnIndiSliderEdit, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x1a4a /* KAknsIIDQgnGrafNsliderMarkerSelected */}, + /* SP_QgnIndiSubmenu */ {KAknsIIDQgnIndiSubmenu, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnNoteErased */ {KAknsIIDQgnNoteErased, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnNoteError */ {KAknsIIDQgnNoteError, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnNoteInfo */ {KAknsIIDQgnNoteInfo, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnNoteOk */ {KAknsIIDQgnNoteOk, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnNoteQuery */ {KAknsIIDQgnNoteQuery, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnNoteWarning */ {KAknsIIDQgnNoteWarning, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnPropFileSmall */ {KAknsIIDQgnPropFileSmall, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnPropFolderCurrent */ {KAknsIIDQgnPropFolderCurrent, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnPropFolderSmall */ {KAknsIIDQgnPropFolderSmall, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnPropFolderSmallNew */ {KAknsIIDQgnPropFolderSmallNew, EDrawIcon, ES60_All, -1,-1}, + /* SP_QgnPropPhoneMemcLarge */ {KAknsIIDQgnPropPhoneMemcLarge, EDrawIcon, ES60_All, -1,-1}, + + // Toolbar graphics is different in 3.1/3.2 vs. 5.0 + /* SP_QgnFrSctrlButtonCornerTl */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2301}, /* KAknsIIDQgnFrSctrlButtonCornerTl*/ + /* SP_QgnFrSctrlButtonCornerTr */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2302}, + /* SP_QgnFrSctrlButtonCornerBl */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2303}, + /* SP_QgnFrSctrlButtonCornerBr */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2304}, + /* SP_QgnFrSctrlButtonSideT */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2305}, + /* SP_QgnFrSctrlButtonSideB */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2306}, + /* SP_QgnFrSctrlButtonSideL */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2307}, + /* SP_QgnFrSctrlButtonSideR */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2308}, + /* SP_QgnFrSctrlButtonCenter */ {KAknsIIDQsnFrButtonTbCenter, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2309}, /*KAknsIIDQgnFrSctrlButtonCenter*/ + + // No pressed state for toolbar button in 3.1/3.2. + /* SP_QgnFrSctrlButtonCornerTlPressed */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2621}, /*KAknsIIDQgnFrSctrlButtonCornerTlPressed*/ + /* SP_QgnFrSctrlButtonCornerTrPressed */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2622}, + /* SP_QgnFrSctrlButtonCornerBlPressed */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2623}, + /* SP_QgnFrSctrlButtonCornerBrPressed */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2624}, + /* SP_QgnFrSctrlButtonSideTPressed */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2625}, + /* SP_QgnFrSctrlButtonSideBPressed */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2626}, + /* SP_QgnFrSctrlButtonSideLPressed */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2627}, + /* SP_QgnFrSctrlButtonSideRPressed */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2628}, + /* SP_QgnFrSctrlButtonCenterPressed */ {KAknsIIDQsnFrButtonTbCenter, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2629}, + + // 3.1 & 3.2 do not have pressed state for scrollbar, so use normal scrollbar graphics instead. + /* SP_QsnCpScrollHandleBottomPressed*/ {KAknsIIDQsnCpScrollHandleBottom, EDrawIcon, ES60_3_X, EAknsMajorGeneric, 0x20f8}, /*KAknsIIDQsnCpScrollHandleBottomPressed*/ + /* SP_QsnCpScrollHandleMiddlePressed*/ {KAknsIIDQsnCpScrollHandleMiddle, EDrawIcon, ES60_3_X, EAknsMajorGeneric, 0x20f9}, /*KAknsIIDQsnCpScrollHandleMiddlePressed*/ + /* SP_QsnCpScrollHandleTopPressed*/ {KAknsIIDQsnCpScrollHandleTop, EDrawIcon, ES60_3_X, EAknsMajorGeneric, 0x20fa}, /*KAknsIIDQsnCpScrollHandleTopPressed*/ + + /* SP_QsnBgScreen */ {KAknsIIDQsnBgScreen, EDrawBackground, ES60_All, -1,-1}, + + /* SP_QsnCpScrollBgBottom */ {KAknsIIDQsnCpScrollBgBottom, EDrawIcon, ES60_All, -1,-1}, + /* SP_QsnCpScrollBgMiddle */ {KAknsIIDQsnCpScrollBgMiddle, EDrawIcon, ES60_All, -1,-1}, + /* SP_QsnCpScrollBgTop */ {KAknsIIDQsnCpScrollBgTop, EDrawIcon, ES60_All, -1,-1}, + + /* SP_QsnCpScrollHandleBottom */ {KAknsIIDQsnCpScrollHandleBottom, EDrawIcon, ES60_All, -1,-1}, + /* SP_QsnCpScrollHandleMiddle */ {KAknsIIDQsnCpScrollHandleMiddle, EDrawIcon, ES60_All, -1,-1}, + /* SP_QsnCpScrollHandleTop */ {KAknsIIDQsnCpScrollHandleTop, EDrawIcon, ES60_All, -1,-1}, + + /* SP_QsnFrButtonTbCornerTl */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_All, -1, -1}, + /* SP_QsnFrButtonTbCornerTr */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_All, -1, -1}, + /* SP_QsnFrButtonTbCornerBl */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_All, -1, -1}, + /* SP_QsnFrButtonTbCornerBr */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_All, -1, -1}, + /* SP_QsnFrButtonTbSideT */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_All, -1, -1}, + /* SP_QsnFrButtonTbSideB */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_All, -1, -1}, + /* SP_QsnFrButtonTbSideL */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_All, -1, -1}, + /* SP_QsnFrButtonTbSideR */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_All, -1, -1}, + /* SP_QsnFrButtonTbCenter */ {KAknsIIDQsnFrButtonTbCenter, EDrawIcon, ES60_All, -1, -1}, + + /* SP_QsnFrButtonTbCornerTlPressed */{KAknsIIDQsnFrButtonTbCornerTlPressed, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrButtonTbCornerTrPressed */{KAknsIIDQsnFrButtonTbCornerTrPressed, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrButtonTbCornerBlPressed */{KAknsIIDQsnFrButtonTbCornerBlPressed, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrButtonTbCornerBrPressed */{KAknsIIDQsnFrButtonTbCornerBrPressed, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrButtonTbSideTPressed */ {KAknsIIDQsnFrButtonTbSideTPressed, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrButtonTbSideBPressed */ {KAknsIIDQsnFrButtonTbSideBPressed, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrButtonTbSideLPressed */ {KAknsIIDQsnFrButtonTbSideLPressed, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrButtonTbSideRPressed */ {KAknsIIDQsnFrButtonTbSideRPressed, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrButtonTbCenterPressed */ {KAknsIIDQsnFrButtonTbCenterPressed, EDrawIcon, ES60_All, -1,-1}, + + /* SP_QsnFrCaleCornerTl */ {KAknsIIDQsnFrCaleCornerTl, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleCornerTr */ {KAknsIIDQsnFrCaleCornerTr, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleCornerBl */ {KAknsIIDQsnFrCaleCornerBl, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleCornerBr */ {KAknsIIDQsnFrCaleCornerBr, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleSideT */ {KAknsIIDQsnFrCaleSideT, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleSideB */ {KAknsIIDQsnFrCaleSideB, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleSideL */ {KAknsIIDQsnFrCaleSideL, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleSideR */ {KAknsIIDQsnFrCaleSideR, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleCenter */ {KAknsIIDQsnFrCaleCenter, ENoDraw, ES60_All, -1,-1}, + + /* SP_QsnFrCaleHeadingCornerTl */ {KAknsIIDQsnFrCaleHeadingCornerTl, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleHeadingCornerTr */ {KAknsIIDQsnFrCaleHeadingCornerTr, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleHeadingCornerBl */ {KAknsIIDQsnFrCaleHeadingCornerBl, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleHeadingCornerBr */ {KAknsIIDQsnFrCaleHeadingCornerBr, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleHeadingSideT */ {KAknsIIDQsnFrCaleHeadingSideT, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleHeadingSideB */ {KAknsIIDQsnFrCaleHeadingSideB, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleHeadingSideL */ {KAknsIIDQsnFrCaleHeadingSideL, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleHeadingSideR */ {KAknsIIDQsnFrCaleHeadingSideR, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrCaleHeadingCenter */ {KAknsIIDQsnFrCaleHeadingCenter, ENoDraw, ES60_All, -1,-1}, + + /* SP_QsnFrInputCornerTl */ {KAknsIIDQsnFrInputCornerTl, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrInputCornerTr */ {KAknsIIDQsnFrInputCornerTr, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrInputCornerBl */ {KAknsIIDQsnFrInputCornerBl, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrInputCornerBr */ {KAknsIIDQsnFrInputCornerBr, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrInputSideT */ {KAknsIIDQsnFrInputSideT, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrInputSideB */ {KAknsIIDQsnFrInputSideB, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrInputSideL */ {KAknsIIDQsnFrInputSideL, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrInputSideR */ {KAknsIIDQsnFrInputSideR, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrInputCenter */ {KAknsIIDQsnFrInputCenter, ENoDraw, ES60_All, -1,-1}, + + /* SP_QsnFrListCornerTl */ {KAknsIIDQsnFrListCornerTl, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrListCornerTr */ {KAknsIIDQsnFrListCornerTr, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrListCornerBl */ {KAknsIIDQsnFrListCornerBl, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrListCornerBr */ {KAknsIIDQsnFrListCornerBr, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrListSideT */ {KAknsIIDQsnFrListSideT, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrListSideB */ {KAknsIIDQsnFrListSideB, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrListSideL */ {KAknsIIDQsnFrListSideL, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrListSideR */ {KAknsIIDQsnFrListSideR, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrListCenter */ {KAknsIIDQsnFrListCenter, ENoDraw, ES60_All, -1,-1}, + + /* SP_QsnFrPopupCornerTl */ {KAknsIIDQsnFrPopupCornerTl, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrPopupCornerTr */ {KAknsIIDQsnFrPopupCornerTr, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrPopupCornerBl */ {KAknsIIDQsnFrPopupCornerBl, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrPopupCornerBr */ {KAknsIIDQsnFrPopupCornerBr, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrPopupSideT */ {KAknsIIDQsnFrPopupSideT, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrPopupSideB */ {KAknsIIDQsnFrPopupSideB, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrPopupSideL */ {KAknsIIDQsnFrPopupSideL, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrPopupSideR */ {KAknsIIDQsnFrPopupSideR, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrPopupCenter */ {KAknsIIDQsnFrPopupCenterSubmenu, ENoDraw, ES60_All, -1,-1}, + + // ToolTip graphics different in 3.1 vs. 3.2+. + /* SP_QsnFrPopupPreviewCornerTl */ {KAknsIIDQsnFrPopupCornerTl, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c5}, /* KAknsIIDQsnFrPopupPreviewCornerTl */ + /* SP_QsnFrPopupPreviewCornerTr */ {KAknsIIDQsnFrPopupCornerTr, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c6}, + /* SP_QsnFrPopupPreviewCornerBl */ {KAknsIIDQsnFrPopupCornerBl, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c3}, + /* SP_QsnFrPopupPreviewCornerBr */ {KAknsIIDQsnFrPopupCornerBr, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c4}, + /* SP_QsnFrPopupPreviewSideT */ {KAknsIIDQsnFrPopupSideT, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19ca}, + /* SP_QsnFrPopupPreviewSideB */ {KAknsIIDQsnFrPopupSideB, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c7}, + /* SP_QsnFrPopupPreviewSideL */ {KAknsIIDQsnFrPopupSideL, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c8}, + /* SP_QsnFrPopupPreviewSideR */ {KAknsIIDQsnFrPopupSideR, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c9}, + /* SP_QsnFrPopupPreviewCenter */ {KAknsIIDQsnFrPopupCenter, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c2}, + + /* SP_QsnFrSetOptCornerTl */ {KAknsIIDQsnFrSetOptCornerTl, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrSetOptCornerTr */ {KAknsIIDQsnFrSetOptCornerTr, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrSetOptCornerBl */ {KAknsIIDQsnFrSetOptCornerBl, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrSetOptCornerBr */ {KAknsIIDQsnFrSetOptCornerBr, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrSetOptSideT */ {KAknsIIDQsnFrSetOptSideT, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrSetOptSideB */ {KAknsIIDQsnFrSetOptSideB, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrSetOptSideL */ {KAknsIIDQsnFrSetOptSideL, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrSetOptSideR */ {KAknsIIDQsnFrSetOptSideR, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrSetOptCenter */ {KAknsIIDQsnFrSetOptCenter, ENoDraw, ES60_All, -1,-1}, + + // No toolbar frame for 5.0+ releases. + /* SP_QsnFrPopupSubCornerTl */ {KAknsIIDQsnFrPopupSubCornerTl, ENoDraw, ES60_3_X, -1,-1}, + /* SP_QsnFrPopupSubCornerTr */ {KAknsIIDQsnFrPopupSubCornerTr, ENoDraw, ES60_3_X, -1,-1}, + /* SP_QsnFrPopupSubCornerBl */ {KAknsIIDQsnFrPopupSubCornerBl, ENoDraw, ES60_3_X, -1,-1}, + /* SP_QsnFrPopupSubCornerBr */ {KAknsIIDQsnFrPopupSubCornerBr, ENoDraw, ES60_3_X, -1,-1}, + /* SP_QsnFrPopupSubSideT */ {KAknsIIDQsnFrPopupSubSideT, ENoDraw, ES60_3_X, -1,-1}, + /* SP_QsnFrPopupSubSideB */ {KAknsIIDQsnFrPopupSubSideB, ENoDraw, ES60_3_X, -1,-1}, + /* SP_QsnFrPopupSubSideL */ {KAknsIIDQsnFrPopupSubSideL, ENoDraw, ES60_3_X, -1,-1}, + /* SP_QsnFrPopupSubSideR */ {KAknsIIDQsnFrPopupSubSideR, ENoDraw, ES60_3_X, -1,-1}, + /* SP_QsnFrPopupSubCenter */ {KAknsIIDQsnFrPopupCenterSubmenu, ENoDraw, ES60_3_X, -1,-1}, + + // No inactive button graphics in 3.1/3.2 + /* SP_QsnFrButtonCornerTlInactive */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x21b1}, /*KAknsIIDQsnFrButtonCornerTlInactive*/ + /* SP_QsnFrButtonCornerTrInactive */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x21b2}, + /* SP_QsnFrButtonCornerBlInactive */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x21b3}, + /* SP_QsnFrButtonCornerTrInactive */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x21b4}, + /* SP_QsnFrButtonSideTInactive */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x21b5}, + /* SP_QsnFrButtonSideBInactive */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x21b6}, + /* SP_QsnFrButtonSideLInactive */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x21b7}, + /* SP_QsnFrButtonSideRInactive */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x21b8}, + /* SP_QsnFrButtonCenterInactive */ {KAknsIIDQsnFrButtonTbCenter, EDrawIcon, ES60_3_X, EAknsMajorSkin, 0x21b9}, + + // No pressed down grid in 3.1/3.2 + /* SP_QsnFrGridCornerTlPressed */ {KAknsIIDQsnFrGridCornerTl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2681}, /*KAknsIIDQsnFrGridCornerTlPressed*/ + /* SP_QsnFrGridCornerTrPressed */ {KAknsIIDQsnFrGridCornerTr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2682}, + /* SP_QsnFrGridCornerBlPressed */ {KAknsIIDQsnFrGridCornerBl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2683}, + /* SP_QsnFrGridCornerBrPressed */ {KAknsIIDQsnFrGridCornerBr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2684}, + /* SP_QsnFrGridSideTPressed */ {KAknsIIDQsnFrGridSideT, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2685}, + /* SP_QsnFrGridSideBPressed */ {KAknsIIDQsnFrGridSideB, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2686}, + /* SP_QsnFrGridSideLPressed */ {KAknsIIDQsnFrGridSideL, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2687}, + /* SP_QsnFrGridSideRPressed */ {KAknsIIDQsnFrGridSideR, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2688}, + /* SP_QsnFrGridCenterPressed */ {KAknsIIDQsnFrGridCenter, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2689}, + + // No pressed down list in 3.1/3.2 + /* SP_QsnFrListCornerTlPressed */ {KAknsIIDQsnFrListCornerTl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x268b}, /*KAknsIIDQsnFrListCornerTlPressed*/ + /* SP_QsnFrListCornerTrPressed */ {KAknsIIDQsnFrListCornerTr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x268c}, + /* SP_QsnFrListCornerBlPressed */ {KAknsIIDQsnFrListCornerBl, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x268d}, + /* SP_QsnFrListCornerBrPressed */ {KAknsIIDQsnFrListCornerBr, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x268e}, + /* SP_QsnFrListSideTPressed */ {KAknsIIDQsnFrListSideT, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x268f}, + /* SP_QsnFrListSideBPressed */ {KAknsIIDQsnFrListSideB, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2690}, + /* SP_QsnFrListSideLPressed */ {KAknsIIDQsnFrListSideL, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2691}, + /* SP_QsnFrListSideRPressed */ {KAknsIIDQsnFrListSideR, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2692}, + /* SP_QsnFrListCenterPressed */ {KAknsIIDQsnFrListCenter, ENoDraw, ES60_3_X, EAknsMajorSkin, 0x2693}, +}; + +QPixmap QS60StyleModeSpecifics::skinnedGraphics( + QS60StyleEnums::SkinParts stylepart, const QSize &size, + QS60StylePrivate::SkinElementFlags flags) +{ + QPixmap themedImage; + TRAPD( error, QT_TRYCATCH_LEAVING({ + const QPixmap skinnedImage = createSkinnedGraphicsLX(stylepart, size, flags); + themedImage = skinnedImage; + })); + if (error) + return themedImage = QPixmap(); + return themedImage; +} + +QPixmap QS60StyleModeSpecifics::skinnedGraphics( + QS60StylePrivate::SkinFrameElements frame, const QSize &size, QS60StylePrivate::SkinElementFlags flags) +{ + QPixmap themedImage; + TRAPD( error, QT_TRYCATCH_LEAVING({ + const QPixmap skinnedImage = createSkinnedGraphicsLX(frame, size, flags); + themedImage = skinnedImage; + })); + if (error) + return themedImage = QPixmap(); + return themedImage; +} + +QPixmap QS60StyleModeSpecifics::colorSkinnedGraphics( + const QS60StyleEnums::SkinParts &stylepart, const QSize &size, QPainter *painter, + QS60StylePrivate::SkinElementFlags flags) +{ + QPixmap colorGraphics; + TRAPD(error, QT_TRYCATCH_LEAVING(colorGraphics = colorSkinnedGraphicsLX(stylepart, size, painter, flags))); + return error ? QPixmap() : colorGraphics; +} + +void QS60StyleModeSpecifics::fallbackInfo(const QS60StyleEnums::SkinParts &stylePart, TInt &fallbackIndex) +{ + switch(stylePart) { + case QS60StyleEnums::SP_QgnGrafBarWaitAnim: + fallbackIndex = EMbmAvkonQgn_graf_bar_wait_1; + break; + case QS60StyleEnums::SP_QgnGrafBarFrameCenter: + fallbackIndex = EMbmAvkonQgn_graf_bar_frame_center; + break; + case QS60StyleEnums::SP_QgnGrafBarFrameSideL: + fallbackIndex = EMbmAvkonQgn_graf_bar_frame_side_l; + break; + case QS60StyleEnums::SP_QgnGrafBarFrameSideR: + fallbackIndex = EMbmAvkonQgn_graf_bar_frame_side_r; + break; + case QS60StyleEnums::SP_QgnGrafBarProgress: + fallbackIndex = EMbmAvkonQgn_graf_bar_progress; + break; + case QS60StyleEnums::SP_QgnGrafTabActiveL: + fallbackIndex = EMbmAvkonQgn_graf_tab_active_l; + break; + case QS60StyleEnums::SP_QgnGrafTabActiveM: + fallbackIndex = EMbmAvkonQgn_graf_tab_active_m; + break; + case QS60StyleEnums::SP_QgnGrafTabActiveR: + fallbackIndex = EMbmAvkonQgn_graf_tab_active_r; + break; + case QS60StyleEnums::SP_QgnGrafTabPassiveL: + fallbackIndex = EMbmAvkonQgn_graf_tab_passive_l; + break; + case QS60StyleEnums::SP_QgnGrafTabPassiveM: + fallbackIndex = EMbmAvkonQgn_graf_tab_passive_m; + break; + case QS60StyleEnums::SP_QgnGrafTabPassiveR: + fallbackIndex = EMbmAvkonQgn_graf_tab_passive_r; + break; + case QS60StyleEnums::SP_QgnIndiCheckboxOff: + fallbackIndex = EMbmAvkonQgn_indi_checkbox_off; + break; + case QS60StyleEnums::SP_QgnIndiCheckboxOn: + fallbackIndex = EMbmAvkonQgn_indi_checkbox_on; + break; + case QS60StyleEnums::SP_QgnIndiHlColSuper: + fallbackIndex = 0x4456; /* EMbmAvkonQgn_indi_hl_col_super */ + break; + case QS60StyleEnums::SP_QgnIndiHlExpSuper: + fallbackIndex = 0x4458; /* EMbmAvkonQgn_indi_hl_exp_super */ + break; + case QS60StyleEnums::SP_QgnIndiHlLineBranch: + fallbackIndex = 0x445A; /* EMbmAvkonQgn_indi_hl_line_branch */ + break; + case QS60StyleEnums::SP_QgnIndiHlLineEnd: + fallbackIndex = 0x445C; /* EMbmAvkonQgn_indi_hl_line_end */ + break; + case QS60StyleEnums::SP_QgnIndiHlLineStraight: + fallbackIndex = 0x445E; /* EMbmAvkonQgn_indi_hl_line_straight */ + break; + case QS60StyleEnums::SP_QgnIndiMarkedAdd: + fallbackIndex = EMbmAvkonQgn_indi_marked_add; + break; + case QS60StyleEnums::SP_QgnIndiNaviArrowLeft: + fallbackIndex = EMbmAvkonQgn_indi_navi_arrow_left; + break; + case QS60StyleEnums::SP_QgnIndiNaviArrowRight: + fallbackIndex = EMbmAvkonQgn_indi_navi_arrow_right; + break; + case QS60StyleEnums::SP_QgnIndiRadiobuttOff: + fallbackIndex = EMbmAvkonQgn_indi_radiobutt_off; + break; + case QS60StyleEnums::SP_QgnIndiRadiobuttOn: + fallbackIndex = EMbmAvkonQgn_indi_radiobutt_on; + break; + case QS60StyleEnums::SP_QgnGrafNsliderMarker: + fallbackIndex = 17572; /* EMbmAvkonQgn_graf_nslider_marker */ + break; + case QS60StyleEnums::SP_QgnGrafNsliderMarkerSelected: + fallbackIndex = 17574; /* EMbmAvkonQgn_graf_nslider_marker_selected */ + break; + case QS60StyleEnums::SP_QgnIndiSubmenu: + fallbackIndex = EMbmAvkonQgn_indi_submenu; + break; + case QS60StyleEnums::SP_QgnNoteErased: + fallbackIndex = EMbmAvkonQgn_note_erased; + break; + case QS60StyleEnums::SP_QgnNoteError: + fallbackIndex = EMbmAvkonQgn_note_error; + break; + case QS60StyleEnums::SP_QgnNoteInfo: + fallbackIndex = EMbmAvkonQgn_note_info; + break; + case QS60StyleEnums::SP_QgnNoteOk: + fallbackIndex = EMbmAvkonQgn_note_ok; + break; + case QS60StyleEnums::SP_QgnNoteQuery: + fallbackIndex = EMbmAvkonQgn_note_query; + break; + case QS60StyleEnums::SP_QgnNoteWarning: + fallbackIndex = EMbmAvkonQgn_note_warning; + break; + case QS60StyleEnums::SP_QgnPropFileSmall: + fallbackIndex = EMbmAvkonQgn_prop_file_small; + break; + case QS60StyleEnums::SP_QgnPropFolderCurrent: + fallbackIndex = EMbmAvkonQgn_prop_folder_current; + break; + case QS60StyleEnums::SP_QgnPropFolderSmall: + fallbackIndex = EMbmAvkonQgn_prop_folder_small; + break; + case QS60StyleEnums::SP_QgnPropFolderSmallNew: + fallbackIndex = EMbmAvkonQgn_prop_folder_small_new; + break; + case QS60StyleEnums::SP_QgnPropPhoneMemcLarge: + fallbackIndex = EMbmAvkonQgn_prop_phone_memc_large; + break; + default: + fallbackIndex = -1; + break; + } +} + +QPixmap QS60StyleModeSpecifics::colorSkinnedGraphicsLX( + const QS60StyleEnums::SkinParts &stylepart, + const QSize &size, QPainter *painter, QS60StylePrivate::SkinElementFlags flags) +{ + // this function can throw both exceptions and leaves. There are no cleanup dependencies between Qt and Symbian parts. + const int stylepartIndex = (int)stylepart; + const TAknsItemID skinId = m_partMap[stylepartIndex].skinID; + + TInt fallbackGraphicID = -1; + HBufC* iconFile = HBufC::NewLC( KMaxFileName ); + fallbackInfo(stylepart, fallbackGraphicID); + + TAknsItemID colorGroup = KAknsIIDQsnIconColors; + TRgb defaultColor = KRgbBlack; + int colorIndex = -1; //set a bogus value to color index to ensure that painter color is used + //to color the icon + if (painter) { + QRgb widgetColor = painter->pen().color().rgb(); + defaultColor = TRgb(qRed(widgetColor), qGreen(widgetColor), qBlue(widgetColor)); + } + + const bool rotatedBy90or270 = + (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest)); + const TSize targetSize = + rotatedBy90or270?TSize(size.height(), size.width()):TSize(size.width(), size.height()); + CFbsBitmap *icon = 0; + CFbsBitmap *iconMask = 0; + const TInt fallbackGraphicsMaskID = + fallbackGraphicID == KErrNotFound?KErrNotFound:fallbackGraphicID+1; //masks are auto-generated as next in mif files + MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + AknsUtils::CreateColorIconLC( + skinInstance, + skinId, + colorGroup, + colorIndex, + icon, + iconMask, + AknIconUtils::AvkonIconFileName(), + fallbackGraphicID, + fallbackGraphicsMaskID, + defaultColor); + + QPixmap result = fromFbsBitmap(icon, iconMask, flags, targetSize); + CleanupStack::PopAndDestroy(3); //icon, iconMask, iconFile + return result; +} + +QColor QS60StyleModeSpecifics::colorValue(const TAknsItemID &colorGroup, int colorIndex) +{ + TRgb skinnedColor; + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + AknsUtils::GetCachedColor(skin, skinnedColor, colorGroup, colorIndex); + return QColor(skinnedColor.Red(),skinnedColor.Green(),skinnedColor.Blue()); +} + +struct QAutoFbsBitmapHeapLock +{ + QAutoFbsBitmapHeapLock(CFbsBitmap* aBmp) : mBmp(aBmp) { mBmp->LockHeap(); } + ~QAutoFbsBitmapHeapLock() { mBmp->UnlockHeap(); } + CFbsBitmap* mBmp; +}; + +QPixmap QS60StyleModeSpecifics::fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask, QS60StylePrivate::SkinElementFlags flags, const TSize &targetSize) +{ + Q_ASSERT(icon); + + AknIconUtils::DisableCompression(icon); + TInt error = AknIconUtils::SetSize(icon, targetSize, EAspectRatioNotPreserved); + + if (mask && !error) { + AknIconUtils::DisableCompression(mask); + error = AknIconUtils::SetSize(mask, targetSize, EAspectRatioNotPreserved); + } + if (error) + return QPixmap(); + + QPixmap pixmap; + QScopedPointer pd(QPixmapData::create(0, 0, QPixmapData::PixmapType)); + if (mask) { + // Try the efficient path with less copying and conversion. + QVolatileImage img(icon, mask); + pd->fromNativeType(&img, QPixmapData::VolatileImage); + if (!pd->isNull()) + pixmap = QPixmap(pd.take()); + } + if (pixmap.isNull()) { + // Potentially more expensive path. + pd->fromNativeType(icon, QPixmapData::FbsBitmap); + pixmap = QPixmap(pd.take()); + if (mask) { + pixmap.setAlphaChannel(QPixmap::fromSymbianCFbsBitmap(mask)); + } + } + + if ((flags & QS60StylePrivate::SF_PointEast) || + (flags & QS60StylePrivate::SF_PointSouth) || + (flags & QS60StylePrivate::SF_PointWest)) { + QImage iconImage = pixmap.toImage(); + QTransform imageTransform; + if (flags & QS60StylePrivate::SF_PointEast) { + imageTransform.rotate(90); + } else if (flags & QS60StylePrivate::SF_PointSouth) { + imageTransform.rotate(180); + iconImage = iconImage.transformed(imageTransform); + } else if (flags & QS60StylePrivate::SF_PointWest) { + imageTransform.rotate(270); + } + if (imageTransform.isRotating()) + iconImage = iconImage.transformed(imageTransform); + + pixmap = QPixmap::fromImage(iconImage); + } + if ((flags & QS60StylePrivate::SF_Mirrored_X_Axis) || + (flags & QS60StylePrivate::SF_Mirrored_Y_Axis)) { + QImage iconImage = pixmap.toImage().mirrored( + flags & QS60StylePrivate::SF_Mirrored_X_Axis, + flags & QS60StylePrivate::SF_Mirrored_Y_Axis); + pixmap = QPixmap::fromImage(iconImage); + } + + return pixmap; +} + +bool QS60StylePrivate::isTouchSupported() +{ + return bool(AknLayoutUtils::PenEnabled()); +} + +bool QS60StylePrivate::isToolBarBackground() +{ + return (QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2); +} + +bool QS60StylePrivate::hasSliderGrooveGraphic() +{ + return QSysInfo::s60Version() != QSysInfo::SV_S60_3_1; +} + +bool QS60StylePrivate::isSingleClickUi() +{ + return (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0); +} + +void QS60StylePrivate::deleteStoredSettings() +{ + QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); + settings.beginGroup(QLatin1String("QS60Style")); + settings.remove(QString()); + settings.endGroup(); +} + +// Since S60Style has 'button' as a graphic, we don't have any native color which to use +// for QPalette::Button. Therefore S60Style needs to guesstimate palette color by calculating +// average rgb values for button pixels. +// Returns Qt::black if there is an issue with the graphics (image is NULL, or no constBits() found). +QColor QS60StylePrivate::colorFromFrameGraphics(SkinFrameElements frame) const +{ +#ifndef QT_NO_SETTINGS + TInt themeID = 0; + //First we need to fetch active theme ID. We need to store the themeID at the same time + //as color, so that we can later check if the stored color is still from the same theme. + //Native side stores active theme UID/Timestamp into central repository. + int error = 0; + QT_TRAP_THROWING( + CRepository *themeRepository = CRepository::NewLC(personalisationUID); + if (themeRepository) { + TBuf<32> value; //themeID is currently max of 8 + 1 + 8 characters, but lets have some extra space + const TUint32 key = 0x00000002; //active theme key in the repository + error = themeRepository->Get(key, value); + if (error == KErrNone) { + TLex lex(value); + TPtrC numberToken(lex.NextToken()); + if (numberToken.Length()) + error = TLex(numberToken).Val(themeID); + else + error = KErrArgument; + } + } + CleanupStack::PopAndDestroy(themeRepository); + ); + + QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); + settings.beginGroup(QLatin1String("QS60Style")); + if (themeID != 0) { + QVariant buttonColor = settings.value(QLatin1String("ButtonColor")); + if (!buttonColor.isNull()) { + //there is a stored color value, lets see if the theme ID matches + if (error == KErrNone) { + QVariant themeUID = settings.value(QLatin1String("ThemeUID")); + if (!themeUID.isNull() && themeUID.toInt() == themeID) { + QColor storedColor(buttonColor.value()); + if (storedColor.isValid()) + return storedColor; + } + } + settings.remove(QString()); //if color was invalid, or theme has been changed, just delete all stored settings + } + } +#endif + + QColor color = calculatedColor(frame); + +#ifndef QT_NO_SETTINGS + settings.setValue(QLatin1String("ThemeUID"), QVariant(themeID)); + if (frame == SF_ButtonNormal) //other colors are not currently calculated from graphics + settings.setValue(QLatin1String("ButtonColor"), QVariant(color)); + settings.endGroup(); +#endif + + return color; +} + +QPoint qt_s60_fill_background_offset(const QWidget *targetWidget) +{ + CCoeControl *control = targetWidget->effectiveWinId(); + TPoint pos(0,0); + if (control) + pos = control->PositionRelativeToScreen(); + return QPoint(pos.iX, pos.iY); +} + +QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX( + QS60StyleEnums::SkinParts part, const QSize &size, + QS60StylePrivate::SkinElementFlags flags) +{ + // this function can throw both exceptions and leaves. There are no cleanup dependencies between Qt and Symbian parts. + if (!size.isValid()) + return QPixmap(); + + // Check release support and change part, if necessary. + const TAknsItemID skinId = partSpecificThemeId((int)part); + const int stylepartIndex = (int)part; + const TDrawType drawType = m_partMap[stylepartIndex].drawType; + Q_ASSERT(drawType != ENoDraw); + const bool rotatedBy90or270 = + (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest)); + const TSize targetSize = + rotatedBy90or270 ? TSize(size.height(), size.width()) : qt_QSize2TSize(size); + + MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + static const TDisplayMode displayMode = S60->supportsPremultipliedAlpha ? Q_SYMBIAN_ECOLOR16MAP : EColor16MA; + static const TInt drawParam = S60->supportsPremultipliedAlpha ? KAknsDrawParamDefault : KAknsDrawParamRGBOnly; + + QPixmap result; + + switch (drawType) { + case EDrawGulIcon: { + CGulIcon* icon = AknsUtils::CreateGulIconL( AknsUtils::SkinInstance(), skinId, EFalse ); + if (icon) + result = fromFbsBitmap(icon->Bitmap(), icon->Mask(), flags, targetSize); + delete icon; + break; + } + case EDrawIcon: { + TInt fallbackGraphicID = -1; + fallbackInfo(part, fallbackGraphicID); + + CFbsBitmap *icon = 0; + CFbsBitmap *iconMask = 0; + const TInt fallbackGraphicsMaskID = + fallbackGraphicID == KErrNotFound?KErrNotFound:fallbackGraphicID+1; //masks are auto-generated as next in mif files + + AknsUtils::CreateIconL( + skinInstance, + skinId, + icon, + iconMask, + AknIconUtils::AvkonIconFileName(), + fallbackGraphicID , + fallbackGraphicsMaskID); + + result = fromFbsBitmap(icon, iconMask, flags, targetSize); + delete icon; + delete iconMask; + break; + } + case EDrawBackground: { + // QS60WindowSurface::unlockBitmapHeap(); + CFbsBitmap *background = new (ELeave) CFbsBitmap(); //offscreen + CleanupStack::PushL(background); + User::LeaveIfError(background->Create(targetSize, displayMode)); + + CFbsBitmapDevice *dev = CFbsBitmapDevice::NewL(background); + CleanupStack::PushL(dev); + CFbsBitGc *gc = NULL; + User::LeaveIfError(dev->CreateContext(gc)); + CleanupStack::PushL(gc); + + CAknsBasicBackgroundControlContext *bgContext = CAknsBasicBackgroundControlContext::NewL( + skinId, + targetSize, + EFalse); + CleanupStack::PushL(bgContext); + + const TBool drawn = AknsDrawUtils::DrawBackground( + skinInstance, + bgContext, + NULL, + *gc, + TPoint(), + targetSize, + drawParam); + + if (drawn) + result = fromFbsBitmap(background, NULL, flags, targetSize); + // if drawing fails in skin server, just ignore the background (probably OOM case) + + CleanupStack::PopAndDestroy(4, background); //background, dev, gc, bgContext + // QS60WindowSurface::lockBitmapHeap(); + break; + } + case EDrawAnimation: { + CFbsBitmap* animationFrame; + CFbsBitmap* frameMask; + CAknBitmapAnimation* aknAnimation = 0; + TBool constructedFromTheme = ETrue; + + QS60StyleAnimation* animation = QS60StylePrivate::animationDefinition(part); //ownership is not passed + if (animation) { + if (!animation->animationObject() && !animation->isResourceBased()) {// no pre-made item exists, create new animation + CAknBitmapAnimation* newAnimation = CAknBitmapAnimation::NewL(); + CleanupStack::PushL(newAnimation); + if (newAnimation) + constructedFromTheme = newAnimation->ConstructFromSkinL(skinId); + if (constructedFromTheme && newAnimation->BitmapAnimData()->FrameArray().Count() > 0) { + animation->setResourceBased(false); + animation->setAnimationObject(newAnimation); //animation takes ownership + } + CleanupStack::Pop(newAnimation); + } + //fill-in stored information + aknAnimation = animation->animationObject(); + constructedFromTheme = !animation->isResourceBased(); + } + + const int currentFrame = QS60StylePrivate::currentAnimationFrame(part); + if (constructedFromTheme && aknAnimation && aknAnimation->BitmapAnimData()->FrameArray().Count() > 0) { + //Animation was created successfully and contains frames, just fetch current frame + if(currentFrame >= aknAnimation->BitmapAnimData()->FrameArray().Count()) + User::Leave(KErrOverflow); + const CBitmapFrameData* frameData = aknAnimation->BitmapAnimData()->FrameArray().At(currentFrame); + if (frameData) { + animationFrame = frameData->Bitmap(); + frameMask = frameData->Mask(); + } + } else { + //Theme does not contain animation theming, create frames from resource file + TInt fallbackGraphicID = -1; + fallbackInfo(part, fallbackGraphicID); + fallbackGraphicID = fallbackGraphicID + (currentFrame * 2); //skip masks + TInt fallbackGraphicsMaskID = + (fallbackGraphicID == KErrNotFound) ? KErrNotFound : fallbackGraphicID + 1; //masks are auto-generated as next in mif files + if (fallbackGraphicsMaskID != KErrNotFound) + fallbackGraphicsMaskID = fallbackGraphicsMaskID + (currentFrame * 2); //skip actual graphics + + //Then draw animation frame + AknsUtils::CreateIconL( + skinInstance, + KAknsIIDDefault, //animation is not themed, lets force fallback graphics + animationFrame, + frameMask, + AknIconUtils::AvkonIconFileName(), + fallbackGraphicID , + fallbackGraphicsMaskID); + } + result = fromFbsBitmap(animationFrame, frameMask, flags, targetSize); + if (!constructedFromTheme) { + delete animationFrame; + animationFrame = 0; + delete frameMask; + frameMask = 0; + } + break; + } + } + if (!result) + result = QPixmap(); + + return result; +} + +QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX(QS60StylePrivate::SkinFrameElements frameElement, + const QSize &size, QS60StylePrivate::SkinElementFlags flags) +{ + // this function can throw both exceptions and leaves. There are no cleanup dependencies between Qt and Symbian parts. + if (!size.isValid()) + return QPixmap(); + + const bool rotatedBy90or270 = + (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest)); + const TSize targetSize = + rotatedBy90or270 ? TSize(size.height(), size.width()) : qt_QSize2TSize(size); + + MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + QPixmap result; + + static const TDisplayMode displayMode = S60->supportsPremultipliedAlpha ? Q_SYMBIAN_ECOLOR16MAP : EColor16MA; + static const TInt drawParam = S60->supportsPremultipliedAlpha ? KAknsDrawParamDefault : KAknsDrawParamNoClearUnderImage|KAknsDrawParamRGBOnly; + + CFbsBitmap *frame = new (ELeave) CFbsBitmap(); //offscreen + CleanupStack::PushL(frame); + User::LeaveIfError(frame->Create(targetSize, displayMode)); + + CFbsBitmapDevice* bitmapDev = CFbsBitmapDevice::NewL(frame); + CleanupStack::PushL(bitmapDev); + CFbsBitGc* bitmapGc = NULL; + User::LeaveIfError(bitmapDev->CreateContext(bitmapGc)); + CleanupStack::PushL(bitmapGc); + + frame->LockHeap(); + memset(frame->DataAddress(), 0, frame->SizeInPixels().iWidth * frame->SizeInPixels().iHeight * 4); // 4: argb bytes + frame->UnlockHeap(); + + const TRect outerRect(TPoint(0, 0), targetSize); + const TRect innerRect = innerRectFromElement(frameElement, outerRect); + + TAknsItemID frameSkinID, centerSkinID; + frameSkinID = centerSkinID = partSpecificThemeId(QS60StylePrivate::m_frameElementsData[frameElement].center); + frameIdAndCenterId(frameElement, frameSkinID, centerSkinID); + + TBool drawn = AknsDrawUtils::DrawFrame( + skinInstance, + *bitmapGc, + outerRect, + innerRect, + frameSkinID, + centerSkinID, + drawParam ); + + if (S60->supportsPremultipliedAlpha) { + if (drawn) { + result = fromFbsBitmap(frame, NULL, flags, targetSize); + } else { + // Drawing might fail due to OOM (we can do nothing about that), + // or due to skin item not being available. + // If the latter occurs, lets try switch to non-release specific items (if available) + // and re-try the drawing. + frameSkinID = centerSkinID = m_partMap[(int)QS60StylePrivate::m_frameElementsData[frameElement].center].skinID; + frameIdAndCenterId(frameElement, frameSkinID, centerSkinID); + drawn = AknsDrawUtils::DrawFrame( skinInstance, + *bitmapGc, outerRect, innerRect, + frameSkinID, centerSkinID, + drawParam ); + // in case drawing fails, even after using default graphics, ignore the error + if (drawn) + result = fromFbsBitmap(frame, NULL, flags, targetSize); + } + } else { + TDisplayMode maskDepth = EGray256; + // Query the skin item for possible frame graphics mask details. + if (skinInstance) { + CAknsMaskedBitmapItemData* skinMaskedBmp = static_cast( + skinInstance->GetCachedItemData(frameSkinID,EAknsITMaskedBitmap)); + if (skinMaskedBmp && skinMaskedBmp->Mask()) + maskDepth = skinMaskedBmp->Mask()->DisplayMode(); + } + if (maskDepth != ENone) { + CFbsBitmap *frameMask = new (ELeave) CFbsBitmap(); //offscreen + CleanupStack::PushL(frameMask); + User::LeaveIfError(frameMask->Create(targetSize, maskDepth)); + + CFbsBitmapDevice* maskBitmapDevice = CFbsBitmapDevice::NewL(frameMask); + CleanupStack::PushL(maskBitmapDevice); + CFbsBitGc* maskBitGc = NULL; + User::LeaveIfError(maskBitmapDevice->CreateContext(maskBitGc)); + CleanupStack::PushL(maskBitGc); + + if (drawn) { + //ensure that the mask is really transparent + maskBitGc->Activate( maskBitmapDevice ); + maskBitGc->SetPenStyle(CGraphicsContext::ENullPen); + maskBitGc->SetBrushStyle(CGraphicsContext::ESolidBrush); + maskBitGc->SetBrushColor(KRgbWhite); + maskBitGc->Clear(); + maskBitGc->SetBrushStyle(CGraphicsContext::ENullBrush); + + drawn = AknsDrawUtils::DrawFrame(skinInstance, + *maskBitGc, outerRect, innerRect, + frameSkinID, centerSkinID, + KAknsSDMAlphaOnly |KAknsDrawParamNoClearUnderImage); + if (drawn) + result = fromFbsBitmap(frame, frameMask, flags, targetSize); + } + CleanupStack::PopAndDestroy(3, frameMask); + } + } + CleanupStack::PopAndDestroy(3, frame); //frame, bitmapDev, bitmapGc + return result; +} + +void QS60StyleModeSpecifics::frameIdAndCenterId(QS60StylePrivate::SkinFrameElements frameElement, TAknsItemID &frameId, TAknsItemID ¢erId) +{ +// There are some major mix-ups in skin declarations for some frames. +// First, the frames are not declared in sequence. +// Second, the parts use different major than the frame-master. + + switch(frameElement) { + case QS60StylePrivate::SF_ToolTip: + if (QSysInfo::s60Version() != QSysInfo::SV_S60_3_1) { + centerId.Set(EAknsMajorGeneric, 0x19c2); + frameId.Set(EAknsMajorSkin, 0x5300); + } else { + centerId.Set(KAknsIIDQsnFrPopupCenter); + frameId.iMinor = centerId.iMinor - 9; + } + break; + case QS60StylePrivate::SF_ToolBar: + if (QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || + QSysInfo::s60Version() == QSysInfo::SV_S60_3_2) { + centerId.Set(KAknsIIDQsnFrPopupCenterSubmenu); + frameId.Set(KAknsIIDQsnFrPopupSub); + } + break; + case QS60StylePrivate::SF_PopupBackground: + centerId.Set(KAknsIIDQsnFrPopupCenterSubmenu); + frameId.Set(KAknsIIDQsnFrPopupSub); + break; + case QS60StylePrivate::SF_PanelBackground: + // remove center piece for panel graphics, so that only border is drawn + centerId.Set(KAknsIIDNone); + frameId.Set(KAknsIIDQsnFrSetOpt); + break; + default: + // center should be correct here + frameId.iMinor = centerId.iMinor - 9; + break; + } +} + +TRect QS60StyleModeSpecifics::innerRectFromElement(QS60StylePrivate::SkinFrameElements frameElement, const TRect &outerRect) +{ + TInt widthShrink = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth); + TInt heightShrink = QS60StylePrivate::pixelMetric(PM_FrameCornerHeight); + switch(frameElement) { + case QS60StylePrivate::SF_PanelBackground: + // panel should have slightly slimmer border to enable thin line of background graphics between closest component + widthShrink = widthShrink - 2; + heightShrink = heightShrink - 2; + break; + case QS60StylePrivate::SF_ToolTip: + widthShrink = widthShrink >> 1; + heightShrink = heightShrink >> 1; + break; + case QS60StylePrivate::SF_ListHighlight: + //In Sym^3 devices highlights are less blocky + if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) { + widthShrink += 2; + heightShrink += 2; + } else { + widthShrink -= 2; + heightShrink -= 2; + } + break; + case QS60StylePrivate::SF_PopupBackground: + widthShrink = widthShrink + 5; + heightShrink = heightShrink + 5; + break; + default: + break; + } + TRect innerRect(outerRect); + innerRect.Shrink(widthShrink, heightShrink); + return innerRect; +} + +bool QS60StyleModeSpecifics::checkSupport(const int supportedRelease) +{ + const QSysInfo::S60Version currentRelease = QSysInfo::s60Version(); + return ( (currentRelease == QSysInfo::SV_S60_3_1 && supportedRelease & ES60_3_1) || + (currentRelease == QSysInfo::SV_S60_3_2 && supportedRelease & ES60_3_2) || + (currentRelease == QSysInfo::SV_S60_5_0 && supportedRelease & ES60_5_0) || + (currentRelease == QSysInfo::SV_S60_5_1 && supportedRelease & ES60_5_1) || + (currentRelease == QSysInfo::SV_S60_5_2 && supportedRelease & ES60_5_2) || + (currentRelease == QSysInfo::SV_S60_5_3 && supportedRelease & ES60_5_3) ); +} + +TAknsItemID QS60StyleModeSpecifics::partSpecificThemeId(int part) +{ + TAknsItemID newSkinId; + if (!checkSupport(m_partMap[(int)part].supportInfo)) + newSkinId.Set(m_partMap[(int)part].newMajorSkinId, m_partMap[(int)part].newMinorSkinId); + else + newSkinId.Set(m_partMap[(int)part].skinID); + return newSkinId; +} + +QFont QS60StylePrivate::s60Font_specific( + QS60StyleEnums::FontCategories fontCategory, + int pointSize, bool resolveFontSize) +{ + Q_UNUSED(resolveFontSize); + + TAknFontCategory aknFontCategory = EAknFontCategoryUndefined; + switch (fontCategory) { + case QS60StyleEnums::FC_Primary: + aknFontCategory = EAknFontCategoryPrimary; + break; + case QS60StyleEnums::FC_Secondary: + aknFontCategory = EAknFontCategorySecondary; + break; + case QS60StyleEnums::FC_Title: + aknFontCategory = EAknFontCategoryTitle; + break; + case QS60StyleEnums::FC_PrimarySmall: + aknFontCategory = EAknFontCategoryPrimarySmall; + break; + case QS60StyleEnums::FC_Digital: + aknFontCategory = EAknFontCategoryDigital; + break; + case QS60StyleEnums::FC_Undefined: + default: + break; + } + + // Create AVKON font according the given parameters + CWsScreenDevice* dev = CCoeEnv::Static()->ScreenDevice(); + TAknFontSpecification spec(aknFontCategory, TFontSpec(), NULL); + if (pointSize > 0) { + const TInt pixelSize = dev->VerticalTwipsToPixels(pointSize * KTwipsPerPoint); + spec.SetTextPaneHeight(pixelSize + 4); // TODO: Is 4 a reasonable top+bottom margin? + } + + QFont result; + TRAPD( error, QT_TRYCATCH_LEAVING({ + const CAknLayoutFont* aknFont = + AknFontAccess::CreateLayoutFontFromSpecificationL(*dev, spec); + + result = qt_TFontSpec2QFontL(aknFont->DoFontSpecInTwips()); + if (result.pointSize() != pointSize) + result.setPointSize(pointSize); // Correct the font size returned by CreateLayoutFontFromSpecificationL() + + delete aknFont; + })); + if (error) result = QFont(); + return result; +} + +void QS60StylePrivate::setActiveLayout() +{ + const QSize activeScreenSize(screenSize()); + int activeLayoutIndex = -1; + const short screenHeight = (short)activeScreenSize.height(); + const short screenWidth = (short)activeScreenSize.width(); + for (int i=0; i, m_animations) + +QS60StylePrivate::QS60StylePrivate() +{ + //Animation defaults need to be created when style is instantiated + QS60StyleAnimation* progressBarAnimation = new QS60StyleAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim, 7, 100); + m_animations()->append(progressBarAnimation); + // No need to set active layout, if dynamic metrics API is available + setActiveLayout(); +} + +void QS60StylePrivate::removeAnimations() +{ + //currently only one animation in the list. + m_animations()->removeFirst(); +} + +QColor QS60StylePrivate::s60Color(QS60StyleEnums::ColorLists list, + int index, const QStyleOption *option) +{ + static const TAknsItemID *idMap[] = { + &KAknsIIDQsnHighlightColors, + &KAknsIIDQsnIconColors, + &KAknsIIDQsnLineColors, + &KAknsIIDQsnOtherColors, + &KAknsIIDQsnParentColors, + &KAknsIIDQsnTextColors + }; + Q_ASSERT((int)list < (int)sizeof(idMap)/sizeof(idMap[0])); + const QColor color = QS60StyleModeSpecifics::colorValue(*idMap[(int) list], index - 1); + return option ? QS60StylePrivate::stateColor(color, option) : color; +} + +// In some cases, the AVKON UI themegraphic is already in 'disabled state'. +// If so, return true for these parts. +bool QS60StyleModeSpecifics::disabledPartGraphic(QS60StyleEnums::SkinParts &part) +{ + bool disabledGraphic = false; + switch(part){ + // inactive button graphics are available from 5.0 onwards + case QS60StyleEnums::SP_QsnFrButtonCornerTlInactive: + case QS60StyleEnums::SP_QsnFrButtonCornerTrInactive: + case QS60StyleEnums::SP_QsnFrButtonCornerBlInactive: + case QS60StyleEnums::SP_QsnFrButtonCornerBrInactive: + case QS60StyleEnums::SP_QsnFrButtonSideTInactive: + case QS60StyleEnums::SP_QsnFrButtonSideBInactive: + case QS60StyleEnums::SP_QsnFrButtonSideLInactive: + case QS60StyleEnums::SP_QsnFrButtonSideRInactive: + case QS60StyleEnums::SP_QsnFrButtonCenterInactive: + if (!(QSysInfo::s60Version()==QSysInfo::SV_S60_3_1 || + QSysInfo::s60Version()==QSysInfo::SV_S60_3_2)) + disabledGraphic = true; + break; + default: + break; + } + return disabledGraphic; +} + +// In some cases, the AVKON UI themegraphic is already in 'disabled state'. +// If so, return true for these frames. +bool QS60StyleModeSpecifics::disabledFrameGraphic(QS60StylePrivate::SkinFrameElements &frame) +{ + bool disabledGraphic = false; + switch(frame){ + // inactive button graphics are available from 5.0 onwards + case QS60StylePrivate::SF_ButtonInactive: + if (!(QSysInfo::s60Version()==QSysInfo::SV_S60_3_1 || + QSysInfo::s60Version()==QSysInfo::SV_S60_3_2)) + disabledGraphic = true; + break; + default: + break; + } + return disabledGraphic; +} + +QPixmap QS60StyleModeSpecifics::generateMissingThemeGraphic(QS60StyleEnums::SkinParts &part, + const QSize &size, QS60StylePrivate::SkinElementFlags flags) +{ + if (!QS60StylePrivate::isTouchSupported()) + return QPixmap(); + + QS60StyleEnums::SkinParts updatedPart = part; + switch(part){ + // AVKON UI has a abnormal handling for scrollbar graphics. It is possible that the root + // skin does not contain mandatory graphics for scrollbar pressed states. Therefore, AVKON UI + // creates dynamically these graphics by modifying the normal state scrollbar graphics slightly. + // S60Style needs to work similarly. Therefore if skingraphics call provides to be a miss + // (i.e. result is not valid), style needs to draw normal graphics instead and apply some + // modifications (similar to generatedIconPixmap()) to the result. + case QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed: + updatedPart = QS60StyleEnums::SP_QsnCpScrollHandleBottom; + break; + case QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed: + updatedPart = QS60StyleEnums::SP_QsnCpScrollHandleMiddle; + break; + case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed: + updatedPart = QS60StyleEnums::SP_QsnCpScrollHandleTop; + break; + default: + break; + } + if (part==updatedPart) { + return QPixmap(); + } else { + QPixmap result = skinnedGraphics(updatedPart, size, flags); + QStyleOption opt; + QPalette *themePalette = QS60StylePrivate::themePalette(); + if (themePalette) + opt.palette = *themePalette; + + // For now, always generate new icon based on "selected". In the future possibly, expand + // this to consist other possibilities as well. + result = QApplication::style()->generatedIconPixmap(QIcon::Selected, result, &opt); + return result; + } +} + +QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part, + const QSize &size, QPainter *painter, SkinElementFlags flags) +{ + QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); + + QPixmap result = (flags & SF_ColorSkinned)? + QS60StyleModeSpecifics::colorSkinnedGraphics(part, size, painter, flags) + : QS60StyleModeSpecifics::skinnedGraphics(part, size, flags); + + lock.relock(); + + if (flags & SF_StateDisabled && !QS60StyleModeSpecifics::disabledPartGraphic(part)) { + QStyleOption opt; + QPalette *themePalette = QS60StylePrivate::themePalette(); + if (themePalette) + opt.palette = *themePalette; + result = QApplication::style()->generatedIconPixmap(QIcon::Disabled, result, &opt); + } + + if (!result) + result = QS60StyleModeSpecifics::generateMissingThemeGraphic(part, size, flags); + + return result; +} + +QPixmap QS60StylePrivate::frame(SkinFrameElements frame, const QSize &size, SkinElementFlags flags) +{ + QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); + QPixmap result = QS60StyleModeSpecifics::skinnedGraphics(frame, size, flags); + lock.relock(); + + if (flags & SF_StateDisabled && !QS60StyleModeSpecifics::disabledFrameGraphic(frame)) { + QStyleOption opt; + QPalette *themePalette = QS60StylePrivate::themePalette(); + if (themePalette) + opt.palette = *themePalette; + result = QApplication::style()->generatedIconPixmap(QIcon::Disabled, result, &opt); + } + return result; +} + +QPixmap QS60StylePrivate::backgroundTexture(bool skipCreation) +{ + bool createNewBackground = false; + TRect applicationRect = (static_cast(S60->appUi())->ApplicationRect()); + if (!m_background) { + createNewBackground = true; + } else { + //if background brush does not match screensize, re-create it + if (m_background->width() != applicationRect.Width() || + m_background->height() != applicationRect.Height()) { + delete m_background; + m_background = 0; + createNewBackground = true; + } + } + + if (createNewBackground && !skipCreation) { + QPixmap background = part(QS60StyleEnums::SP_QsnBgScreen, + QSize(applicationRect.Width(), applicationRect.Height()), 0, SkinElementFlags()); + m_background = new QPixmap(background); + + // Notify all widgets that palette is updated with the actual background texture. + QPalette pal = QApplication::palette(); + pal.setBrush(QPalette::Window, *m_background); + QApplication::setPalette(pal); + setThemePaletteHash(&pal); + storeThemePalette(&pal); + foreach (QWidget *widget, QApplication::allWidgets()){ + QEvent e(QEvent::PaletteChange); + QApplication::sendEvent(widget, &e); + setThemePalette(widget); + widget->ensurePolished(); + } + } + if (!m_background) + return QPixmap(); + return *m_background; +} + +QSize QS60StylePrivate::screenSize() +{ + return QSize(S60->screenWidthInPixels, S60->screenHeightInPixels); +} + +QS60Style::QS60Style() + : QCommonStyle(*new QS60StylePrivate) +{ +} + +#ifdef Q_WS_S60 +void QS60StylePrivate::handleDynamicLayoutVariantSwitch() +{ + clearCaches(QS60StylePrivate::CC_LayoutChange); + setBackgroundTexture(qApp); + setActiveLayout(); + foreach (QWidget *widget, QApplication::allWidgets()) + widget->ensurePolished(); +} + +void QS60StylePrivate::handleSkinChange() +{ + clearCaches(QS60StylePrivate::CC_ThemeChange); + setThemePalette(qApp); + foreach (QWidget *topLevelWidget, QApplication::allWidgets()){ + QEvent e(QEvent::StyleChange); + QApplication::sendEvent(topLevelWidget, &e); + setThemePalette(topLevelWidget); + topLevelWidget->ensurePolished(); + } +#ifndef QT_NO_PROGRESSBAR + //re-start animation timer + stopAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim); //todo: once we have more animations, we could say "stop all running ones" + startAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim); //and "re-start all previously running ones" +#endif +} + +int QS60StylePrivate::currentAnimationFrame(QS60StyleEnums::SkinParts part) +{ + QS60StyleAnimation *animation = animationDefinition(part); + // todo: looping could be done in QS60Style::timerEvent + if (animation->frameCount() == animation->currentFrame()) + animation->setCurrentFrame(0); + return animation->currentFrame(); +} + +QS60StyleAnimation* QS60StylePrivate::animationDefinition(QS60StyleEnums::SkinParts part) +{ + int i = 0; + const int animationsCount = m_animations()->isEmpty() ? 0 : m_animations()->count(); + for(; i < animationsCount; i++) { + if (part == m_animations()->at(i)->animationId()) + break; + } + return m_animations()->at(i); +} + +void QS60StylePrivate::startAnimation(QS60StyleEnums::SkinParts animationPart) +{ + Q_Q(QS60Style); + + //Query animation data from theme and store values to local struct. + QVariant themeAnimationDataVariant = QS60StyleModeSpecifics::themeDefinition( + QS60StyleEnums::TD_AnimationData, animationPart); + QList themeAnimationData = themeAnimationDataVariant.toList(); + + QS60StyleAnimation *animation = QS60StylePrivate::animationDefinition(animationPart); + if (animation) { + if (themeAnimationData.at(QS60StyleEnums::AD_Interval).toInt() != 0) + animation->setInterval(themeAnimationData.at(QS60StyleEnums::AD_Interval).toInt()); + + if (themeAnimationData.at(QS60StyleEnums::AD_NumberOfFrames).toInt() != 0) + animation->setFrameCount(themeAnimationData.at(QS60StyleEnums::AD_NumberOfFrames).toInt()); + + //todo: playmode is ignored for now, since it seems to return invalid data on some themes + //lets use the table values for play mode + + animation->setCurrentFrame(0); //always initialize + const int timerId = q->startTimer(animation->interval()); + animation->setTimerId(timerId); + } +} + +void QS60StylePrivate::stopAnimation(QS60StyleEnums::SkinParts animationPart) +{ + Q_Q(QS60Style); + + QS60StyleAnimation *animation = QS60StylePrivate::animationDefinition(animationPart); + if (animation) { + animation->setCurrentFrame(0); + if (animation->timerId() != 0) { + q->killTimer(animation->timerId()); + animation->setTimerId(0); + } + animation->resetToDefaults(); + } +} + +QVariant QS60StyleModeSpecifics::themeDefinition( + QS60StyleEnums::ThemeDefinitions definition, QS60StyleEnums::SkinParts part) +{ + MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + + Q_ASSERT(skinInstance); + + switch(definition) { + //Animation definitions + case QS60StyleEnums::TD_AnimationData: + { + CAknsBmpAnimItemData *animationData; + TAknsItemID animationSkinId = partSpecificThemeId(part); + QList list; + + TRAPD( error, QT_TRYCATCH_LEAVING( + animationData = static_cast(skinInstance->CreateUncachedItemDataL( + animationSkinId, EAknsITBmpAnim)))); + if (error) + return list; + + if (animationData) { + list.append((int)animationData->FrameInterval()); + list.append((int)animationData->NumberOfImages()); + + QS60StyleEnums::AnimationMode playMode; + switch(animationData->PlayMode()) { + case CBitmapAnimClientData::EPlay: + playMode = QS60StyleEnums::AM_PlayOnce; + break; + case CBitmapAnimClientData::ECycle: + playMode = QS60StyleEnums::AM_Looping; + break; + case CBitmapAnimClientData::EBounce: + playMode = QS60StyleEnums::AM_Bounce; + break; + default: + break; + } + list.append(QVariant((int)playMode)); + delete animationData; + } else { + list.append(0); + list.append(0); + } + return list; + } + break; + default: + break; + } + return QVariant(); +} + +#endif // Q_WS_S60 + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_S60 || QT_PLUGIN diff --git a/src/widgets/styles/qs60style_simulated.cpp b/src/widgets/styles/qs60style_simulated.cpp new file mode 100644 index 0000000000..a5aeac3fb9 --- /dev/null +++ b/src/widgets/styles/qs60style_simulated.cpp @@ -0,0 +1,457 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qs60style.h" +#include "qs60style_p.h" +#include "qfile.h" +#include "qhash.h" +#include "qapplication.h" +#include "qpainter.h" +#include "qpicture.h" +#include "qstyleoption.h" +#include "qtransform.h" +#include "qlayout.h" +#include "qpixmapcache.h" +#include "qmetaobject.h" +#include "qdebug.h" +#include "qbuffer.h" +#include "qdesktopwidget.h" + +#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN) + +QT_BEGIN_NAMESPACE + +static const quint32 blobVersion = 1; +static const int pictureSize = 256; + +#if defined(Q_CC_GNU) +#if __GNUC__ >= 2 +#define __FUNCTION__ __func__ +#endif +#endif + + +bool saveThemeToBlob(const QString &themeBlob, + const QHash &partPictures, + const QHash, QColor> &colors) +{ + QFile blob(themeBlob); + if (!blob.open(QIODevice::WriteOnly)) { + qWarning() << __FUNCTION__ << ": Could not create blob: " << themeBlob; + return false; + } + + QByteArray data; + QBuffer dataBuffer(&data); + dataBuffer.open(QIODevice::WriteOnly); + QDataStream dataOut(&dataBuffer); + + const int colorsCount = colors.count(); + dataOut << colorsCount; + const QList > colorKeys = colors.keys(); + for (int i = 0; i < colorsCount; ++i) { + const QPair &key = colorKeys.at(i); + dataOut << key; + const QColor color = colors.value(key); + dataOut << color; + } + + dataOut << partPictures.count(); + QHashIterator i(partPictures); + while (i.hasNext()) { + i.next(); + dataOut << i.key(); + dataOut << i.value(); // the QPicture + } + + QDataStream blobOut(&blob); + blobOut << blobVersion; + blobOut << qCompress(data); + return blobOut.status() == QDataStream::Ok; +} + +bool loadThemeFromBlob(const QString &themeBlob, + QHash &partPictures, + QHash, QColor> &colors) +{ + QFile blob(themeBlob); + if (!blob.open(QIODevice::ReadOnly)) { + qWarning() << __FUNCTION__ << ": Could not read blob: " << themeBlob; + return false; + } + QDataStream blobIn(&blob); + + quint32 version; + blobIn >> version; + + if (version != blobVersion) { + qWarning() << __FUNCTION__ << ": Invalid blob version: " << version << " ...expected: " << blobVersion; + return false; + } + + QByteArray data; + blobIn >> data; + data = qUncompress(data); + QBuffer dataBuffer(&data); + dataBuffer.open(QIODevice::ReadOnly); + QDataStream dataIn(&dataBuffer); + + int colorsCount; + dataIn >> colorsCount; + for (int i = 0; i < colorsCount; ++i) { + QPair key; + dataIn >> key; + QColor value; + dataIn >> value; + colors.insert(key, value); + } + + int picturesCount; + dataIn >> picturesCount; + for (int i = 0; i < picturesCount; ++i) { + QString key; + dataIn >> key; + QPicture value; + dataIn >> value; + value.setBoundingRect(QRect(0, 0, pictureSize, pictureSize)); // Bug? The forced bounding rect was not deserialized. + partPictures.insert(key, value); + } + + if (dataIn.status() != QDataStream::Ok) { + qWarning() << __FUNCTION__ << ": Invalid data blob: " << themeBlob; + return false; + } + return true; +} + +class QS60StyleModeSpecifics +{ +public: + static QPixmap skinnedGraphics(QS60StyleEnums::SkinParts stylepart, + const QSize &size, QS60StylePrivate::SkinElementFlags flags); + static QHash m_partPictures; + static QHash, QColor> m_colors; +}; +QHash QS60StyleModeSpecifics::m_partPictures; +QHash, QColor> QS60StyleModeSpecifics::m_colors; + +QS60StylePrivate::QS60StylePrivate() +{ + setCurrentLayout(0); +} + +QColor QS60StylePrivate::s60Color(QS60StyleEnums::ColorLists list, + int index, const QStyleOption *option) +{ + const QString listKey = QS60Style::colorListKeys().at(list); + return QS60StylePrivate::stateColor( + QS60StyleModeSpecifics::m_colors.value(QPair(listKey, index)), + option + ); +} + +QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part, const QSize &size, + QPainter *painter, QS60StylePrivate::SkinElementFlags flags) +{ + Q_UNUSED(painter); + + const QString partKey = QS60Style::partKeys().at(part); + const QPicture partPicture = QS60StyleModeSpecifics::m_partPictures.value(partKey); + QSize partSize(partPicture.boundingRect().size()); + if (flags & (SF_PointEast | SF_PointWest)) { + const int temp = partSize.width(); + partSize.setWidth(partSize.height()); + partSize.setHeight(temp); + } + const qreal scaleX = size.width() / (qreal)partSize.width(); + const qreal scaleY = size.height() / (qreal)partSize.height(); + + QImage partImage(size, QImage::Format_ARGB32); + partImage.fill(Qt::transparent); + QPainter resultPainter(&partImage); + QTransform t; + + if (flags & SF_PointEast) + t.translate(size.width(), 0); + else if (flags & SF_PointSouth) + t.translate(size.width(), size.height()); + else if (flags & SF_PointWest) + t.translate(0, size.height()); + + t.scale(scaleX, scaleY); + + if (flags & SF_PointEast) + t.rotate(90); + else if (flags & SF_PointSouth) + t.rotate(180); + else if (flags & SF_PointWest) + t.rotate(270); + + resultPainter.setTransform(t, true); + const_cast(&partPicture)->play(&resultPainter); + resultPainter.end(); + + QPixmap result = QPixmap::fromImage(partImage); + if (flags & SF_StateDisabled) { + QStyleOption opt; + QPalette *themePalette = QS60StylePrivate::themePalette(); + if (themePalette) + opt.palette = *themePalette; + result = QApplication::style()->generatedIconPixmap(QIcon::Disabled, result, &opt); + } + + return result; +} + +QPixmap QS60StylePrivate::frame(SkinFrameElements frame, const QSize &size, + SkinElementFlags flags) +{ + const QS60StyleEnums::SkinParts center = m_frameElementsData[frame].center; + const QS60StyleEnums::SkinParts topLeft = QS60StyleEnums::SkinParts(center - 8); + const QS60StyleEnums::SkinParts topRight = QS60StyleEnums::SkinParts(center - 7); + const QS60StyleEnums::SkinParts bottomLeft = QS60StyleEnums::SkinParts(center - 6); + const QS60StyleEnums::SkinParts bottomRight = QS60StyleEnums::SkinParts(center - 5); + const QS60StyleEnums::SkinParts top = QS60StyleEnums::SkinParts(center - 4); + const QS60StyleEnums::SkinParts bottom = QS60StyleEnums::SkinParts(center - 3); + const QS60StyleEnums::SkinParts left = QS60StyleEnums::SkinParts(center - 2); + const QS60StyleEnums::SkinParts right = QS60StyleEnums::SkinParts(center - 1); + + // The size of topLeft defines all other sizes + const QSize cornerSize(partSize(topLeft)); + // if frame is so small that corners would cover it completely, draw only center piece + const bool drawOnlyCenter = + 2 * cornerSize.width() + 1 >= size.width() || 2 * cornerSize.height() + 1 >= size.height(); + + const int cornerWidth = cornerSize.width(); + const int cornerHeight = cornerSize.height(); + const int rectWidth = size.width(); + const int rectHeight = size.height(); + const QRect rect(QPoint(), size); + + const QRect topLeftRect = QRect(rect.topLeft(), cornerSize); + const QRect topRect = rect.adjusted(cornerWidth, 0, -cornerWidth, -(rectHeight - cornerHeight)); + const QRect topRightRect = topLeftRect.translated(rectWidth - cornerWidth, 0); + const QRect rightRect = rect.adjusted(rectWidth - cornerWidth, cornerHeight, 0, -cornerHeight); + const QRect bottomRightRect = topRightRect.translated(0, rectHeight - cornerHeight); + const QRect bottomRect = topRect.translated(0, rectHeight - cornerHeight); + const QRect bottomLeftRect = topLeftRect.translated(0, rectHeight - cornerHeight); + const QRect leftRect = rightRect.translated(cornerWidth - rectWidth, 0); + const QRect centerRect = drawOnlyCenter ? rect : rect.adjusted(cornerWidth, cornerWidth, -cornerWidth, -cornerWidth); + + QPixmap result(size); + result.fill(Qt::transparent); + QPainter painter(&result); + +#if 0 + painter.save(); + painter.setOpacity(.3); + painter.fillRect(topLeftRect, Qt::red); + painter.fillRect(topRect, Qt::green); + painter.fillRect(topRightRect, Qt::blue); + painter.fillRect(rightRect, Qt::green); + painter.fillRect(bottomRightRect, Qt::red); + painter.fillRect(bottomRect, Qt::blue); + painter.fillRect(bottomLeftRect, Qt::green); + painter.fillRect(leftRect, Qt::blue); + painter.fillRect(centerRect, Qt::red); + painter.restore(); +#else + drawPart(topLeft, &painter, topLeftRect, flags); + drawPart(top, &painter, topRect, flags); + drawPart(topRight, &painter, topRightRect, flags); + drawPart(right, &painter, rightRect, flags); + drawPart(bottomRight, &painter, bottomRightRect, flags); + drawPart(bottom, &painter, bottomRect, flags); + drawPart(bottomLeft, &painter, bottomLeftRect, flags); + drawPart(left, &painter, leftRect, flags); + drawPart(center, &painter, centerRect, flags); +#endif + + return result; +} + +QPixmap QS60StylePrivate::backgroundTexture(bool /*skipCreation*/) +{ + if (!m_background) { + const QSize size = QApplication::desktop()->screen()->size(); + QPixmap background = part(QS60StyleEnums::SP_QsnBgScreen, size, 0); + m_background = new QPixmap(background); + } + return *m_background; +} + +bool QS60StylePrivate::isTouchSupported() +{ +#ifdef QT_KEYPAD_NAVIGATION + return !QApplication::keypadNavigationEnabled(); +#else + return true; +#endif +} + +bool QS60StylePrivate::isToolBarBackground() +{ + return true; +} + +bool QS60StylePrivate::hasSliderGrooveGraphic() +{ + return false; +} + +bool QS60StylePrivate::isSingleClickUi() +{ + return false; +} + +QFont QS60StylePrivate::s60Font_specific( + QS60StyleEnums::FontCategories fontCategory, + int pointSize, bool resolveFontSize) +{ + QFont result; + if (resolveFontSize) + result.setPointSize(pointSize); + switch (fontCategory) { + case QS60StyleEnums::FC_Primary: + result.setBold(true); + break; + case QS60StyleEnums::FC_Secondary: + case QS60StyleEnums::FC_Title: + case QS60StyleEnums::FC_PrimarySmall: + case QS60StyleEnums::FC_Digital: + case QS60StyleEnums::FC_Undefined: + default: + break; + } + return result; +} + +int QS60StylePrivate::currentAnimationFrame(QS60StyleEnums::SkinParts part) +{ + return 0; +} + +/*! + Constructs a QS60Style object. +*/ +QS60Style::QS60Style() + : QCommonStyle(*new QS60StylePrivate) +{ + const QString defaultBlob = QString::fromLatin1(":/trolltech/styles/s60style/images/defaults60theme.blob"); + if (QFile::exists(defaultBlob)) + loadS60ThemeFromBlob(defaultBlob); +} + +Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, enumPartKeys, { + const int enumIndex = QS60StyleEnums::staticMetaObject.indexOfEnumerator("SkinParts"); + Q_ASSERT(enumIndex >= 0); + const QMetaEnum metaEnum = QS60StyleEnums::staticMetaObject.enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) { + const QString enumKey = QString::fromLatin1(metaEnum.key(i)); + QString partKey; + // Following loop does following conversions: "SP_QgnNoteInfo" to "qgn_note_info"... + for (int charPosition = 3; charPosition < enumKey.length(); charPosition++) { + if (charPosition > 3 && enumKey[charPosition].isUpper()) + partKey.append(QChar::fromLatin1('_')); + partKey.append(enumKey[charPosition].toLower()); + } + x->append(partKey); + } +}) + +QStringList QS60Style::partKeys() +{ + return *enumPartKeys(); +} + +Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, enumColorListKeys, { + const int enumIndex = QS60StyleEnums::staticMetaObject.indexOfEnumerator("ColorLists"); + Q_ASSERT(enumIndex >= 0); + const QMetaEnum metaEnum = QS60StyleEnums::staticMetaObject.enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); i++) { + const QString enumKey = QString::fromLatin1(metaEnum.key(i)); + // Following line does following conversions: CL_QsnTextColors to "text"... + x->append(enumKey.mid(6, enumKey.length() - 12).toLower()); + } +}) + +QStringList QS60Style::colorListKeys() +{ + return *enumColorListKeys(); +} + +void QS60Style::setS60Theme(const QHash &parts, + const QHash, QColor> &colors) +{ + Q_D(QS60Style); + QS60StyleModeSpecifics::m_partPictures = parts; + QS60StyleModeSpecifics::m_colors = colors; + d->clearCaches(QS60StylePrivate::CC_ThemeChange); + d->setBackgroundTexture(qApp); + d->setThemePalette(qApp); +} + +bool QS60Style::loadS60ThemeFromBlob(const QString &blobFile) +{ + QHash partPictures; + QHash, QColor> colors; + + if (!loadThemeFromBlob(blobFile, partPictures, colors)) + return false; + setS60Theme(partPictures, colors); + return true; +} + +bool QS60Style::saveS60ThemeToBlob(const QString &blobFile) const +{ + return saveThemeToBlob(blobFile, + QS60StyleModeSpecifics::m_partPictures, QS60StyleModeSpecifics::m_colors); +} + +QPoint qt_s60_fill_background_offset(const QWidget *targetWidget) +{ + Q_UNUSED(targetWidget) + return QPoint(); +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_S60 || QT_PLUGIN diff --git a/src/widgets/styles/qs60style_stub.cpp b/src/widgets/styles/qs60style_stub.cpp new file mode 100644 index 0000000000..a3a5b9d0ec --- /dev/null +++ b/src/widgets/styles/qs60style_stub.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qs60style.h" +#include "qdebug.h" + +#if defined(QT_NO_STYLE_S60) +QT_BEGIN_NAMESPACE + +QS60Style::QS60Style() +{ + qWarning() << "QS60Style stub created"; +} + +QS60Style::~QS60Style() +{ +} + +void QS60Style::drawComplexControl(ComplexControl , const QStyleOptionComplex *, QPainter *, const QWidget *) const +{ +} + +void QS60Style::drawControl(ControlElement , const QStyleOption *, QPainter *, const QWidget *) const +{ +} + +void QS60Style::drawPrimitive(PrimitiveElement , const QStyleOption *, QPainter *, const QWidget *) const +{ +} + +int QS60Style::pixelMetric(PixelMetric , const QStyleOption *, const QWidget *) const +{ + return 0; +} + +QSize QS60Style::sizeFromContents(ContentsType , const QStyleOption *, const QSize &, const QWidget *) const +{ + return QSize(); +} + +int QS60Style::styleHint(StyleHint , const QStyleOption *, const QWidget *, QStyleHintReturn *) const +{ + return 0; +} + +QRect QS60Style::subControlRect(ComplexControl , const QStyleOptionComplex *, SubControl , const QWidget *) const +{ + return QRect(); +} + +QRect QS60Style::subElementRect(SubElement , const QStyleOption *, const QWidget *) const +{ + return QRect(); +} + +void QS60Style::polish(QWidget *) +{ +} + +void QS60Style::unpolish(QWidget *) +{ +} + +void QS60Style::polish(QApplication *) +{ +} + +void QS60Style::unpolish(QApplication *) +{ +} + +bool QS60Style::event(QEvent *) +{ + return false; +} + +QIcon QS60Style::standardIconImplementation(StandardPixmap , const QStyleOption *, const QWidget *) const +{ + return QIcon(); +} + +void QS60Style::timerEvent(QTimerEvent *) +{ +} + +bool QS60Style::eventFilter(QObject *, QEvent *) +{ + return false; +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_S60 diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp new file mode 100644 index 0000000000..ecb5ee51a1 --- /dev/null +++ b/src/widgets/styles/qstyle.cpp @@ -0,0 +1,2459 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstyle.h" +#include "qapplication.h" +#include "qpainter.h" +#include "qwidget.h" +#include "qbitmap.h" +#include "qpixmapcache.h" +#include "qstyleoption.h" +#include "private/qstyle_p.h" +#include "private/qguiapplication_p.h" +#ifndef QT_NO_DEBUG +#include "qdebug.h" +#endif + +#ifdef Q_WS_X11 +#include +#endif + +#include + +QT_BEGIN_NAMESPACE + +static const int MaxBits = 8 * sizeof(QSizePolicy::ControlType); + +static int unpackControlTypes(QSizePolicy::ControlTypes controls, QSizePolicy::ControlType *array) +{ + if (!controls) + return 0; + + // optimization: exactly one bit is set + if ((controls & (controls - 1)) == 0) { + array[0] = QSizePolicy::ControlType(uint(controls)); + return 1; + } + + int count = 0; + for (int i = 0; i < MaxBits; ++i) { + if (uint bit = (controls & (0x1 << i))) + array[count++] = QSizePolicy::ControlType(bit); + } + return count; +} + +/*! + \class QStyle + \brief The QStyle class is an abstract base class that encapsulates the look and feel of a GUI. + + \ingroup appearance + + Qt contains a set of QStyle subclasses that emulate the styles of + the different platforms supported by Qt (QWindowsStyle, + QMacStyle, QMotifStyle, etc.). By default, these styles are built + into the QtGui library. Styles can also be made available as + plugins. + + Qt's built-in widgets use QStyle to perform nearly all of their + drawing, ensuring that they look exactly like the equivalent + native widgets. The diagram below shows a QComboBox in eight + different styles. + + \img qstyle-comboboxes.png Eight combo boxes + + Topics: + + \tableofcontents + + \section1 Setting a Style + + The style of the entire application can be set using the + QApplication::setStyle() function. It can also be specified by the + user of the application, using the \c -style command-line option: + + \snippet doc/src/snippets/code/src_gui_styles_qstyle.cpp 0 + + If no style is specified, Qt will choose the most appropriate + style for the user's platform or desktop environment. + + A style can also be set on an individual widget using the + QWidget::setStyle() function. + + \section1 Developing Style-Aware Custom Widgets + + If you are developing custom widgets and want them to look good on + all platforms, you can use QStyle functions to perform parts of + the widget drawing, such as drawItemText(), drawItemPixmap(), + drawPrimitive(), drawControl(), and drawComplexControl(). + + Most QStyle draw functions take four arguments: + \list + \o an enum value specifying which graphical element to draw + \o a QStyleOption specifying how and where to render that element + \o a QPainter that should be used to draw the element + \o a QWidget on which the drawing is performed (optional) + \endlist + + For example, if you want to draw a focus rectangle on your + widget, you can write: + + \snippet doc/src/snippets/styles/styles.cpp 1 + + QStyle gets all the information it needs to render the graphical + element from QStyleOption. The widget is passed as the last + argument in case the style needs it to perform special effects + (such as animated default buttons on Mac OS X), but it isn't + mandatory. In fact, you can use QStyle to draw on any paint + device, not just widgets, by setting the QPainter properly. + + QStyleOption has various subclasses for the various types of + graphical elements that can be drawn. For example, + PE_FrameFocusRect expects a QStyleOptionFocusRect argument. + + To ensure that drawing operations are as fast as possible, + QStyleOption and its subclasses have public data members. See the + QStyleOption class documentation for details on how to use it. + + For convenience, Qt provides the QStylePainter class, which + combines a QStyle, a QPainter, and a QWidget. This makes it + possible to write + + \snippet doc/src/snippets/styles/styles.cpp 5 + \dots + \snippet doc/src/snippets/styles/styles.cpp 7 + + instead of + + \snippet doc/src/snippets/styles/styles.cpp 2 + \dots + \snippet doc/src/snippets/styles/styles.cpp 3 + + \section1 Creating a Custom Style + + You can create a custom look and feel for your application by + creating a custom style. There are two approaches to creating a + custom style. In the static approach, you either choose an + existing QStyle class, subclass it, and reimplement virtual + functions to provide the custom behavior, or you create an entire + QStyle class from scratch. In the dynamic approach, you modify the + behavior of your system style at runtime. The static approach is + described below. The dynamic approach is described in QProxyStyle. + + The first step in the static approach is to pick one of the styles + provided by Qt from which you will build your custom style. Your + choice of QStyle class will depend on which style resembles your + desired style the most. The most general class that you can use as + a base is QCommonStyle (not QStyle). This is because Qt requires + its styles to be \l{QCommonStyle}s. + + Depending on which parts of the base style you want to change, + you must reimplement the functions that are used to draw those + parts of the interface. To illustrate this, we will modify the + look of the spin box arrows drawn by QWindowsStyle. The arrows + are \e{primitive elements} that are drawn by the drawPrimitive() + function, so we need to reimplement that function. We need the + following class declaration: + + \snippet doc/src/snippets/customstyle/customstyle.h 0 + + To draw its up and down arrows, QSpinBox uses the + PE_IndicatorSpinUp and PE_IndicatorSpinDown primitive elements. + Here's how to reimplement the drawPrimitive() function to draw + them differently: + + \snippet doc/src/snippets/customstyle/customstyle.cpp 2 + \snippet doc/src/snippets/customstyle/customstyle.cpp 3 + \snippet doc/src/snippets/customstyle/customstyle.cpp 4 + + Notice that we don't use the \c widget argument, except to pass it + on to the QWindowStyle::drawPrimitive() function. As mentioned + earlier, the information about what is to be drawn and how it + should be drawn is specified by a QStyleOption object, so there is + no need to ask the widget. + + If you need to use the \c widget argument to obtain additional + information, be careful to ensure that it isn't 0 and that it is + of the correct type before using it. For example: + + \snippet doc/src/snippets/customstyle/customstyle.cpp 0 + \dots + \snippet doc/src/snippets/customstyle/customstyle.cpp 1 + + When implementing a custom style, you cannot assume that the + widget is a QSpinBox just because the enum value is called + PE_IndicatorSpinUp or PE_IndicatorSpinDown. + + The documentation for the \l{widgets/styles}{Styles} example + covers this topic in more detail. + + \warning Qt style sheets are currently not supported for custom QStyle + subclasses. We plan to address this in some future release. + + + \section1 Using a Custom Style + + There are several ways of using a custom style in a Qt + application. The simplest way is to pass the custom style to the + QApplication::setStyle() static function before creating the + QApplication object: + + \snippet snippets/customstyle/main.cpp using a custom style + + You can call QApplication::setStyle() at any time, but by calling + it before the constructor, you ensure that the user's preference, + set using the \c -style command-line option, is respected. + + You may want to make your custom style available for use in other + applications, which may not be yours and hence not available for + you to recompile. The Qt Plugin system makes it possible to create + styles as plugins. Styles created as plugins are loaded as shared + objects at runtime by Qt itself. Please refer to the \link + plugins-howto.html Qt Plugin\endlink documentation for more + information on how to go about creating a style plugin. + + Compile your plugin and put it into Qt's \c plugins/styles + directory. We now have a pluggable style that Qt can load + automatically. To use your new style with existing applications, + simply start the application with the following argument: + + \snippet doc/src/snippets/code/src_gui_styles_qstyle.cpp 1 + + The application will use the look and feel from the custom style you + implemented. + + \section1 Right-to-Left Desktops + + Languages written from right to left (such as Arabic and Hebrew) + usually also mirror the whole layout of widgets, and require the + light to come from the screen's top-right corner instead of + top-left. + + If you create a custom style, you should take special care when + drawing asymmetric elements to make sure that they also look + correct in a mirrored layout. An easy way to test your styles is + to run applications with the \c -reverse command-line option or + to call QApplication::setLayoutDirection() in your \c main() + function. + + Here are some things to keep in mind when making a style work well in a + right-to-left environment: + + \list + \o subControlRect() and subElementRect() return rectangles in screen coordinates + \o QStyleOption::direction indicates in which direction the item should be drawn in + \o If a style is not right-to-left aware it will display items as if it were left-to-right + \o visualRect(), visualPos(), and visualAlignment() are helpful functions that will + translate from logical to screen representations. + \o alignedRect() will return a logical rect aligned for the current direction + \endlist + + \section1 Styles in Item Views + + The painting of items in views is performed by a delegate. Qt's + default delegate, QStyledItemDelegate, is also used for for calculating bounding + rectangles of items, and their sub-elements for the various kind + of item \l{Qt::ItemDataRole}{data roles} + QStyledItemDelegate supports. See the QStyledItemDelegate class + description to find out which datatypes and roles are supported. You + can read more about item data roles in \l{Model/View Programming}. + + When QStyledItemDelegate paints its items, it draws + CE_ItemViewItem, and calculates their size with CT_ItemViewItem. + Note also that it uses SE_ItemViewItemText to set the size of + editors. When implementing a style to customize drawing of item + views, you need to check the implementation of QCommonStyle (and + any other subclasses from which your style + inherits). This way, you find out which and how + other style elements are painted, and you can then reimplement the + painting of elements that should be drawn differently. + + We include a small example where we customize the drawing of item + backgrounds. + + \snippet doc/src/snippets/customviewstyle.cpp 0 + + The primitive element PE_PanelItemViewItem is responsible for + painting the background of items, and is called from + \l{QCommonStyle}'s implementation of CE_ItemViewItem. + + To add support for drawing of new datatypes and item data roles, + it is necessary to create a custom delegate. But if you only + need to support the datatypes implemented by the default + delegate, a custom style does not need an accompanying + delegate. The QStyledItemDelegate class description gives more + information on custom delegates. + + The drawing of item view headers is also done by the style, giving + control over size of header items and row and column sizes. + + \sa QStyleOption, QStylePainter, {Styles Example}, + {Styles and Style Aware Widgets}, QStyledItemDelegate +*/ + +/*! + Constructs a style object. +*/ +QStyle::QStyle() + : QObject(*new QStylePrivate) +{ + Q_D(QStyle); + d->proxyStyle = this; +} + +/*! + \internal + + Constructs a style object. +*/ +QStyle::QStyle(QStylePrivate &dd) + : QObject(dd) +{ + Q_D(QStyle); + d->proxyStyle = this; +} + +/*! + Destroys the style object. +*/ +QStyle::~QStyle() +{ +} + +/*! + Initializes the appearance of the given \a widget. + + This function is called for every widget at some point after it + has been fully created but just \e before it is shown for the very + first time. + + Note that the default implementation does nothing. Reasonable + actions in this function might be to call the + QWidget::setBackgroundMode() function for the widget. Do not use + the function to set, for example, the geometry. Reimplementing + this function provides a back-door through which the appearance + of a widget can be changed, but with Qt's style engine it is + rarely necessary to implement this function; reimplement + drawItemPixmap(), drawItemText(), drawPrimitive(), etc. instead. + + The QWidget::inherits() function may provide enough information to + allow class-specific customizations. But because new QStyle + subclasses are expected to work reasonably with all current and \e + future widgets, limited use of hard-coded customization is + recommended. + + \sa unpolish() +*/ +void QStyle::polish(QWidget * /* widget */) +{ +} + +/*! + Uninitialize the given \a{widget}'s appearance. + + This function is the counterpart to polish(). It is called for + every polished widget whenever the style is dynamically changed; + the former style has to unpolish its settings before the new style + can polish them again. + + Note that unpolish() will only be called if the widget is + destroyed. This can cause problems in some cases, e.g, if you + remove a widget from the UI, cache it, and then reinsert it after + the style has changed; some of Qt's classes cache their widgets. + + \sa polish() +*/ +void QStyle::unpolish(QWidget * /* widget */) +{ +} + +/*! + \fn void QStyle::polish(QApplication * application) + \overload + + Late initialization of the given \a application object. +*/ +void QStyle::polish(QApplication * /* app */) +{ +} + +/*! + \fn void QStyle::unpolish(QApplication * application) + \overload + + Uninitialize the given \a application. +*/ +void QStyle::unpolish(QApplication * /* app */) +{ +} + +/*! + \fn void QStyle::polish(QPalette & palette) + \overload + + Changes the \a palette according to style specific requirements + for color palettes (if any). + + \sa QPalette, QApplication::setPalette() +*/ +void QStyle::polish(QPalette & /* pal */) +{ +} + +/*! + \fn QRect QStyle::itemTextRect(const QFontMetrics &metrics, const QRect &rectangle, int alignment, bool enabled, const QString &text) const + + Returns the area within the given \a rectangle in which to draw + the provided \a text according to the specified font \a metrics + and \a alignment. The \a enabled parameter indicates whether or + not the associated item is enabled. + + If the given \a rectangle is larger than the area needed to render + the \a text, the rectangle that is returned will be offset within + \a rectangle according to the specified \a alignment. For + example, if \a alignment is Qt::AlignCenter, the returned + rectangle will be centered within \a rectangle. If the given \a + rectangle is smaller than the area needed, the returned rectangle + will be the smallest rectangle large enough to render the \a text. + + \sa Qt::Alignment +*/ +QRect QStyle::itemTextRect(const QFontMetrics &metrics, const QRect &rect, int alignment, bool enabled, + const QString &text) const +{ + QRect result; + int x, y, w, h; + rect.getRect(&x, &y, &w, &h); + if (!text.isEmpty()) { + result = metrics.boundingRect(x, y, w, h, alignment, text); + if (!enabled && proxy()->styleHint(SH_EtchDisabledText)) { + result.setWidth(result.width()+1); + result.setHeight(result.height()+1); + } + } else { + result = QRect(x, y, w, h); + } + return result; +} + +/*! + \fn QRect QStyle::itemPixmapRect(const QRect &rectangle, int alignment, const QPixmap &pixmap) const + + Returns the area within the given \a rectangle in which to draw + the specified \a pixmap according to the defined \a alignment. +*/ +QRect QStyle::itemPixmapRect(const QRect &rect, int alignment, const QPixmap &pixmap) const +{ + QRect result; + int x, y, w, h; + rect.getRect(&x, &y, &w, &h); + if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter) + y += h/2 - pixmap.height()/2; + else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom) + y += h - pixmap.height(); + if ((alignment & Qt::AlignRight) == Qt::AlignRight) + x += w - pixmap.width(); + else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter) + x += w/2 - pixmap.width()/2; + else if ((alignment & Qt::AlignLeft) != Qt::AlignLeft && QApplication::isRightToLeft()) + x += w - pixmap.width(); + result = QRect(x, y, pixmap.width(), pixmap.height()); + return result; +} + +/*! + \fn void QStyle::drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, bool enabled, const QString& text, QPalette::ColorRole textRole) const + + Draws the given \a text in the specified \a rectangle using the + provided \a painter and \a palette. + + The text is drawn using the painter's pen, and aligned and wrapped + according to the specified \a alignment. If an explicit \a + textRole is specified, the text is drawn using the \a palette's + color for the given role. The \a enabled parameter indicates + whether or not the item is enabled; when reimplementing this + function, the \a enabled parameter should influence how the item is + drawn. + + \sa Qt::Alignment, drawItemPixmap() +*/ +void QStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal, + bool enabled, const QString& text, QPalette::ColorRole textRole) const +{ + if (text.isEmpty()) + return; + QPen savedPen; + if (textRole != QPalette::NoRole) { + savedPen = painter->pen(); + painter->setPen(QPen(pal.brush(textRole), savedPen.widthF())); + } + if (!enabled) { + if (proxy()->styleHint(SH_DitherDisabledText)) { + QRect br; + painter->drawText(rect, alignment, text, &br); + painter->fillRect(br, QBrush(painter->background().color(), Qt::Dense5Pattern)); + return; + } else if (proxy()->styleHint(SH_EtchDisabledText)) { + QPen pen = painter->pen(); + painter->setPen(pal.light().color()); + painter->drawText(rect.adjusted(1, 1, 1, 1), alignment, text); + painter->setPen(pen); + } + } + painter->drawText(rect, alignment, text); + if (textRole != QPalette::NoRole) + painter->setPen(savedPen); +} + +/*! + \fn void QStyle::drawItemPixmap(QPainter *painter, const QRect &rectangle, int alignment, + const QPixmap &pixmap) const + + Draws the given \a pixmap in the specified \a rectangle, according + to the specified \a alignment, using the provided \a painter. + + \sa drawItemText() +*/ + +void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, + const QPixmap &pixmap) const +{ + QRect aligned = alignedRect(QApplication::layoutDirection(), QFlag(alignment), pixmap.size(), rect); + QRect inter = aligned.intersected(rect); + + painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width(), inter.height()); +} + +/*! + \enum QStyle::PrimitiveElement + + This enum describes the various primitive elements. A + primitive element is a common GUI element, such as a checkbox + indicator or button bevel. + + \omitvalue PE_IndicatorViewItemCheck + \value PE_FrameStatusBar Frame + + \value PE_PanelButtonCommand Button used to initiate an action, for + example, a QPushButton. + + \value PE_FrameDefaultButton This frame around a default button, e.g. in a dialog. + \value PE_PanelButtonBevel Generic panel with a button bevel. + \value PE_PanelButtonTool Panel for a Tool button, used with QToolButton. + \value PE_PanelLineEdit Panel for a QLineEdit. + \value PE_IndicatorButtonDropDown Indicator for a drop down button, for example, a tool + button that displays a menu. + + \value PE_FrameFocusRect Generic focus indicator. + + \value PE_IndicatorArrowUp Generic Up arrow. + \value PE_IndicatorArrowDown Generic Down arrow. + \value PE_IndicatorArrowRight Generic Right arrow. + \value PE_IndicatorArrowLeft Generic Left arrow. + + \value PE_IndicatorSpinUp Up symbol for a spin widget, for example a QSpinBox. + \value PE_IndicatorSpinDown Down symbol for a spin widget. + \value PE_IndicatorSpinPlus Increase symbol for a spin widget. + \value PE_IndicatorSpinMinus Decrease symbol for a spin widget. + + \value PE_IndicatorItemViewItemCheck On/off indicator for a view item. + + \value PE_IndicatorCheckBox On/off indicator, for example, a QCheckBox. + \value PE_IndicatorRadioButton Exclusive on/off indicator, for example, a QRadioButton. + + \value PE_Q3DockWindowSeparator Item separator for Qt 3 compatible dock window + and toolbar contents. + \value PE_IndicatorDockWidgetResizeHandle Resize handle for dock windows. + + \value PE_Frame Generic frame + \value PE_FrameMenu Frame for popup windows/menus; see also QMenu. + \value PE_PanelMenuBar Panel for menu bars. + \value PE_PanelScrollAreaCorner Panel at the bottom-right (or + bottom-left) corner of a scroll area. + + \value PE_FrameDockWidget Panel frame for dock windows and toolbars. + \value PE_FrameTabWidget Frame for tab widgets. + \value PE_FrameLineEdit Panel frame for line edits. + \value PE_FrameGroupBox Panel frame around group boxes. + \value PE_FrameButtonBevel Panel frame for a button bevel. + \value PE_FrameButtonTool Panel frame for a tool button. + + \value PE_IndicatorHeaderArrow Arrow used to indicate sorting on a list or table + header. + \value PE_FrameStatusBarItem Frame for an item of a status bar; see also QStatusBar. + + \value PE_FrameWindow Frame around a MDI window or a docking window. + + \value PE_Q3Separator Qt 3 compatible generic separator. + + \value PE_IndicatorMenuCheckMark Check mark used in a menu. + + \value PE_IndicatorProgressChunk Section of a progress bar indicator; see also QProgressBar. + + \value PE_Q3CheckListController Qt 3 compatible controller part of a list view item. + \value PE_Q3CheckListIndicator Qt 3 compatible checkbox part of a list view item. + \value PE_Q3CheckListExclusiveIndicator Qt 3 compatible radio button part of a list view item. + + \value PE_IndicatorBranch Lines used to represent the branch of a tree in a tree view. + \value PE_IndicatorToolBarHandle The handle of a toolbar. + \value PE_IndicatorToolBarSeparator The separator in a toolbar. + \value PE_PanelToolBar The panel for a toolbar. + \value PE_PanelTipLabel The panel for a tip label. + \value PE_FrameTabBarBase The frame that is drawn for a tab bar, ususally drawn for a tab bar that isn't part of a tab widget. + \value PE_IndicatorTabTear An indicator that a tab is partially scrolled out of the visible tab bar when there are many tabs. + \value PE_IndicatorColumnViewArrow An arrow in a QColumnView. + + \value PE_Widget A plain QWidget. + + \value PE_CustomBase Base value for custom primitive elements. + All values above this are reserved for custom use. Custom values + must be greater than this value. + + \value PE_IndicatorItemViewItemDrop An indicator that is drawn to show where an item in an item view is about to be dropped + during a drag-and-drop operation in an item view. + \value PE_PanelItemViewItem The background for an item in an item view. + \value PE_PanelItemViewRow The background of a row in an item view. + + \value PE_PanelStatusBar The panel for a status bar. + + \value PE_IndicatorTabClose The close button on a tab bar. + \value PE_PanelMenu The panel for a menu. + + \sa drawPrimitive() +*/ + +/*! + \typedef QStyle::SFlags + \internal +*/ + +/*! + \typedef QStyle::SCFlags + \internal +*/ + +/*! + \enum QStyle::StateFlag + + This enum describes flags that are used when drawing primitive + elements. + + Note that not all primitives use all of these flags, and that the + flags may mean different things to different items. + + \value State_None Indicates that the widget does not have a state. + \value State_Active Indicates that the widget is active. + \value State_AutoRaise Used to indicate if auto-raise appearance should be usd on a tool button. + \value State_Children Used to indicate if an item view branch has children. + \value State_DownArrow Used to indicate if a down arrow should be visible on the widget. + \value State_Editing Used to indicate if an editor is opened on the widget. + \value State_Enabled Used to indicate if the widget is enabled. + \value State_HasEditFocus Used to indicate if the widget currently has edit focus. + \value State_HasFocus Used to indicate if the widget has focus. + \value State_Horizontal Used to indicate if the widget is laid out horizontally, for example. a tool bar. + \value State_KeyboardFocusChange Used to indicate if the focus was changed with the keyboard, e.g., tab, backtab or shortcut. + \value State_MouseOver Used to indicate if the widget is under the mouse. + \value State_NoChange Used to indicate a tri-state checkbox. + \value State_Off Used to indicate if the widget is not checked. + \value State_On Used to indicate if the widget is checked. + \value State_Raised Used to indicate if a button is raised. + \value State_ReadOnly Used to indicate if a widget is read-only. + \value State_Selected Used to indicate if a widget is selected. + \value State_Item Used by item views to indicate if a horizontal branch should be drawn. + \value State_Open Used by item views to indicate if the tree branch is open. + \value State_Sibling Used by item views to indicate if a vertical line needs to be drawn (for siblings). + \value State_Sunken Used to indicate if the widget is sunken or pressed. + \value State_UpArrow Used to indicate if an up arrow should be visible on the widget. + \value State_Mini Used to indicate a mini style Mac widget or button. + \value State_Small Used to indicate a small style Mac widget or button. + \omitvalue State_Window + \omitvalue State_Bottom + \omitvalue State_Default + \omitvalue State_FocusAtBorder + \omitvalue State_Top + + \sa drawPrimitive() +*/ + +/*! + \fn void QStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, \ + QPainter *painter, const QWidget *widget) const + + Draws the given primitive \a element with the provided \a painter using the style + options specified by \a option. + + The \a widget argument is optional and may contain a widget that may + aid in drawing the primitive element. + + The table below is listing the primitive elements and their + associated style option subclasses. The style options contain all + the parameters required to draw the elements, including + QStyleOption::state which holds the style flags that are used when + drawing. The table also describes which flags that are set when + casting the given option to the appropriate subclass. + + Note that if a primitive element is not listed here, it is because + it uses a plain QStyleOption object. + + \table + \header \o Primitive Element \o QStyleOption Subclass \o Style Flag \o Remark + \row \o \l PE_FrameFocusRect \o \l QStyleOptionFocusRect + \o \l State_FocusAtBorder + \o Whether the focus is is at the border or inside the widget. + \row \o{1,2} \l PE_IndicatorCheckBox \o{1,2} \l QStyleOptionButton + \o \l State_NoChange \o Indicates a "tri-state" checkbox. + \row \o \l State_On \o Indicates the indicator is checked. + \row \o \l PE_IndicatorRadioButton \o \l QStyleOptionButton + \o \l State_On \o Indicates that a radio button is selected. + \row \o{1,3} \l PE_Q3CheckListExclusiveIndicator, \l PE_Q3CheckListIndicator + \o{1,3} \l QStyleOptionQ3ListView \o \l State_On + \o Indicates whether or not the controller is selected. + \row \o \l State_NoChange \o Indicates a "tri-state" controller. + \row \o \l State_Enabled \o Indicates the controller is enabled. + \row \o{1,4} \l PE_IndicatorBranch \o{1,4} \l QStyleOption + \o \l State_Children \o Indicates that the control for expanding the tree to show child items, should be drawn. + \row \o \l State_Item \o Indicates that a horizontal branch (to show a child item), should be drawn. + \row \o \l State_Open \o Indicates that the tree branch is expanded. + \row \o \l State_Sibling \o Indicates that a vertical line (to show a sibling item), should be drawn. + \row \o \l PE_IndicatorHeaderArrow \o \l QStyleOptionHeader + \o \l State_UpArrow \o Indicates that the arrow should be drawn up; + otherwise it should be down. + \row \o \l PE_FrameGroupBox, \l PE_Frame, \l PE_FrameLineEdit, + \l PE_FrameMenu, \l PE_FrameDockWidget, \l PE_FrameWindow + \o \l QStyleOptionFrame \o \l State_Sunken + \o Indicates that the Frame should be sunken. + \row \o \l PE_IndicatorToolBarHandle \o \l QStyleOption + \o \l State_Horizontal \o Indicates that the window handle is horizontal + instead of vertical. + \row \o \l PE_Q3DockWindowSeparator \o \l QStyleOption + \o \l State_Horizontal \o Indicates that the separator is horizontal + instead of vertical. + \row \o \l PE_IndicatorSpinPlus, \l PE_IndicatorSpinMinus, \l PE_IndicatorSpinUp, + \l PE_IndicatorSpinDown, + \o \l QStyleOptionSpinBox + \o \l State_Sunken \o Indicates that the button is pressed. + \row \o{1,5} \l PE_PanelButtonCommand + \o{1,5} \l QStyleOptionButton + \o \l State_Enabled \o Set if the button is enabled. + \row \o \l State_HasFocus \o Set if the button has input focus. + \row \o \l State_Raised \o Set if the button is not down, not on and not flat. + \row \o \l State_On \o Set if the button is a toggle button and is toggled on. + \row \o \l State_Sunken + \o Set if the button is down (i.e., the mouse button or the + space bar is pressed on the button). + \endtable + + \sa drawComplexControl(), drawControl() +*/ + +/*! + \enum QStyle::ControlElement + + This enum represents a control element. A control element is a + part of a widget that performs some action or displays information + to the user. + + \value CE_PushButton A QPushButton, draws CE_PushButtonBevel, CE_PushButtonLabel and PE_FrameFocusRect. + \value CE_PushButtonBevel The bevel and default indicator of a QPushButton. + \value CE_PushButtonLabel The label (an icon with text or pixmap) of a QPushButton. + + \value CE_DockWidgetTitle Dock window title. + \value CE_Splitter Splitter handle; see also QSplitter. + + + \value CE_CheckBox A QCheckBox, draws a PE_IndicatorCheckBox, a CE_CheckBoxLabel and a PE_FrameFocusRect. + \value CE_CheckBoxLabel The label (text or pixmap) of a QCheckBox. + + \value CE_RadioButton A QRadioButton, draws a PE_IndicatorRadioButton, a CE_RadioButtonLabel and a PE_FrameFocusRect. + \value CE_RadioButtonLabel The label (text or pixmap) of a QRadioButton. + + \value CE_TabBarTab The tab and label within a QTabBar. + \value CE_TabBarTabShape The tab shape within a tab bar. + \value CE_TabBarTabLabel The label within a tab. + + \value CE_ProgressBar A QProgressBar, draws CE_ProgressBarGroove, CE_ProgressBarContents and CE_ProgressBarLabel. + \value CE_ProgressBarGroove The groove where the progress + indicator is drawn in a QProgressBar. + \value CE_ProgressBarContents The progress indicator of a QProgressBar. + \value CE_ProgressBarLabel The text label of a QProgressBar. + + \value CE_ToolButtonLabel A tool button's label. + + \value CE_MenuBarItem A menu item in a QMenuBar. + \value CE_MenuBarEmptyArea The empty area of a QMenuBar. + + \value CE_MenuItem A menu item in a QMenu. + \value CE_MenuScroller Scrolling areas in a QMenu when the + style supports scrolling. + \value CE_MenuTearoff A menu item representing the tear off section of + a QMenu. + \value CE_MenuEmptyArea The area in a menu without menu items. + \value CE_MenuHMargin The horizontal extra space on the left/right of a menu. + \value CE_MenuVMargin The vertical extra space on the top/bottom of a menu. + + \value CE_Q3DockWindowEmptyArea The empty area of a QDockWidget. + + \value CE_ToolBoxTab The toolbox's tab and label within a QToolBox. + \value CE_SizeGrip Window resize handle; see also QSizeGrip. + + \value CE_Header A header. + \value CE_HeaderSection A header section. + \value CE_HeaderLabel The header's label. + + \value CE_ScrollBarAddLine Scroll bar line increase indicator. + (i.e., scroll down); see also QScrollBar. + \value CE_ScrollBarSubLine Scroll bar line decrease indicator (i.e., scroll up). + \value CE_ScrollBarAddPage Scolllbar page increase indicator (i.e., page down). + \value CE_ScrollBarSubPage Scroll bar page decrease indicator (i.e., page up). + \value CE_ScrollBarSlider Scroll bar slider. + \value CE_ScrollBarFirst Scroll bar first line indicator (i.e., home). + \value CE_ScrollBarLast Scroll bar last line indicator (i.e., end). + + \value CE_RubberBand Rubber band used in for example an icon view. + + \value CE_FocusFrame Focus frame that is style controlled. + + \value CE_ItemViewItem An item inside an item view. + + \value CE_CustomBase Base value for custom control elements; + custom values must be greater than this value. + \value CE_ComboBoxLabel The label of a non-editable QComboBox. + \value CE_ToolBar A toolbar like QToolBar. + \value CE_ToolBoxTabShape The toolbox's tab shape. + \value CE_ToolBoxTabLabel The toolbox's tab label. + \value CE_HeaderEmptyArea The area of a header view where there are no header sections. + + \value CE_ShapedFrame The frame with the shape specified in the QStyleOptionFrameV3; see QFrame. + + \omitvalue CE_ColumnViewGrip + + \sa drawControl() +*/ + +/*! + \fn void QStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const + + Draws the given \a element with the provided \a painter with the + style options specified by \a option. + + The \a widget argument is optional and can be used as aid in + drawing the control. The \a option parameter is a pointer to a + QStyleOption object that can be cast to the correct subclass + using the qstyleoption_cast() function. + + The table below is listing the control elements and their + associated style option subclass. The style options contain all + the parameters required to draw the controls, including + QStyleOption::state which holds the style flags that are used when + drawing. The table also describes which flags that are set when + casting the given option to the appropriate subclass. + + Note that if a control element is not listed here, it is because + it uses a plain QStyleOption object. + + \table + \header \o Control Element \o QStyleOption Subclass \o Style Flag \o Remark + \row \o{1,5} \l CE_MenuItem, \l CE_MenuBarItem + \o{1,5} \l QStyleOptionMenuItem + \o \l State_Selected \o The menu item is currently selected item. + \row \o \l State_Enabled \o The item is enabled. + \row \o \l State_DownArrow \o Indicates that a scroll down arrow should be drawn. + \row \o \l State_UpArrow \o Indicates that a scroll up arrow should be drawn + \row \o \l State_HasFocus \o Set if the menu bar has input focus. + + \row \o{1,5} \l CE_PushButton, \l CE_PushButtonBevel, \l CE_PushButtonLabel + \o{1,5} \l QStyleOptionButton + \o \l State_Enabled \o Set if the button is enabled. + \row \o \l State_HasFocus \o Set if the button has input focus. + \row \o \l State_Raised \o Set if the button is not down, not on and not flat. + \row \o \l State_On \o Set if the button is a toggle button and is toggled on. + \row \o \l State_Sunken + \o Set if the button is down (i.e., the mouse button or the + space bar is pressed on the button). + + \row \o{1,6} \l CE_RadioButton, \l CE_RadioButtonLabel, + \l CE_CheckBox, \l CE_CheckBoxLabel + \o{1,6} \l QStyleOptionButton + \o \l State_Enabled \o Set if the button is enabled. + \row \o \l State_HasFocus \o Set if the button has input focus. + \row \o \l State_On \o Set if the button is checked. + \row \o \l State_Off \o Set if the button is not checked. + \row \o \l State_NoChange \o Set if the button is in the NoChange state. + \row \o \l State_Sunken + \o Set if the button is down (i.e., the mouse button or + the space bar is pressed on the button). + + \row \o{1,2} \l CE_ProgressBarContents, \l CE_ProgressBarLabel, + \l CE_ProgressBarGroove + \o{1,2} \l QStyleOptionProgressBar + \o \l State_Enabled \o Set if the progress bar is enabled. + \row \o \l State_HasFocus \o Set if the progress bar has input focus. + + \row \o \l CE_Header, \l CE_HeaderSection, \l CE_HeaderLabel \o \l QStyleOptionHeader \o \o + + \row \o{1,3} \l CE_TabBarTab, CE_TabBarTabShape, CE_TabBarTabLabel + \o{1,3} \l QStyleOptionTab + \o \l State_Enabled \o Set if the tab bar is enabled. + \row \o \l State_Selected \o The tab bar is the currently selected tab bar. + \row \o \l State_HasFocus \o Set if the tab bar tab has input focus. + + \row \o{1,7} \l CE_ToolButtonLabel + \o{1,7} \l QStyleOptionToolButton + \o \l State_Enabled \o Set if the tool button is enabled. + \row \o \l State_HasFocus \o Set if the tool button has input focus. + \row \o \l State_Sunken + \o Set if the tool button is down (i.e., a mouse button or + the space bar is pressed). + \row \o \l State_On \o Set if the tool button is a toggle button and is toggled on. + \row \o \l State_AutoRaise \o Set if the tool button has auto-raise enabled. + \row \o \l State_MouseOver \o Set if the mouse pointer is over the tool button. + \row \o \l State_Raised \o Set if the button is not down and is not on. + + \row \o \l CE_ToolBoxTab \o \l QStyleOptionToolBox + \o \l State_Selected \o The tab is the currently selected tab. + \row \o{1,3} \l CE_HeaderSection \o{1,3} \l QStyleOptionHeader + \o \l State_Sunken \o Indicates that the section is pressed. + \row \o \l State_UpArrow \o Indicates that the sort indicator should be pointing up. + \row \o \l State_DownArrow \o Indicates that the sort indicator should be pointing down. + \endtable + + \sa drawPrimitive(), drawComplexControl() +*/ + +/*! + \enum QStyle::SubElement + + This enum represents a sub-area of a widget. Style implementations + use these areas to draw the different parts of a widget. + + \value SE_PushButtonContents Area containing the label (icon + with text or pixmap). + \value SE_PushButtonFocusRect Area for the focus rect (usually + larger than the contents rect). + \value SE_PushButtonLayoutItem Area that counts for the parent layout. + + \value SE_CheckBoxIndicator Area for the state indicator (e.g., check mark). + \value SE_CheckBoxContents Area for the label (text or pixmap). + \value SE_CheckBoxFocusRect Area for the focus indicator. + \value SE_CheckBoxClickRect Clickable area, defaults to SE_CheckBoxFocusRect. + \value SE_CheckBoxLayoutItem Area that counts for the parent layout. + + \value SE_DateTimeEditLayoutItem Area that counts for the parent layout. + + \value SE_RadioButtonIndicator Area for the state indicator. + \value SE_RadioButtonContents Area for the label. + \value SE_RadioButtonFocusRect Area for the focus indicator. + \value SE_RadioButtonClickRect Clickable area, defaults to SE_RadioButtonFocusRect. + \value SE_RadioButtonLayoutItem Area that counts for the parent layout. + + \value SE_ComboBoxFocusRect Area for the focus indicator. + + \value SE_SliderFocusRect Area for the focus indicator. + \value SE_SliderLayoutItem Area that counts for the parent layout. + + \value SE_SpinBoxLayoutItem Area that counts for the parent layout. + + \value SE_Q3DockWindowHandleRect Area for the tear-off handle. + + \value SE_ProgressBarGroove Area for the groove. + \value SE_ProgressBarContents Area for the progress indicator. + \value SE_ProgressBarLabel Area for the text label. + \value SE_ProgressBarLayoutItem Area that counts for the parent layout. + + \omitvalue SE_DialogButtonAccept + \omitvalue SE_DialogButtonReject + \omitvalue SE_DialogButtonApply + \omitvalue SE_DialogButtonHelp + \omitvalue SE_DialogButtonAll + \omitvalue SE_DialogButtonRetry + \omitvalue SE_DialogButtonAbort + \omitvalue SE_DialogButtonIgnore + \omitvalue SE_DialogButtonCustom + \omitvalue SE_ViewItemCheckIndicator + + \value SE_FrameContents Area for a frame's contents. + \value SE_ShapedFrameContents Area for a frame's contents using the shape in QStyleOptionFrameV3; see QFrame + \value SE_FrameLayoutItem Area that counts for the parent layout. + + \value SE_HeaderArrow Area for the sort indicator for a header. + \value SE_HeaderLabel Area for the label in a header. + + \value SE_LabelLayoutItem Area that counts for the parent layout. + + \value SE_LineEditContents Area for a line edit's contents. + + \value SE_TabWidgetLeftCorner Area for the left corner widget in a tab widget. + \value SE_TabWidgetRightCorner Area for the right corner widget in a tab widget. + \value SE_TabWidgetTabBar Area for the tab bar widget in a tab widget. + \value SE_TabWidgetTabContents Area for the contents of the tab widget. + \value SE_TabWidgetTabPane Area for the pane of a tab widget. + \value SE_TabWidgetLayoutItem Area that counts for the parent layout. + + \value SE_ToolBoxTabContents Area for a toolbox tab's icon and label. + + \value SE_ToolButtonLayoutItem Area that counts for the parent layout. + + \value SE_ItemViewItemCheckIndicator Area for a view item's check mark. + + \value SE_TabBarTearIndicator Area for the tear indicator on a tab bar with scroll arrows. + + \value SE_TreeViewDisclosureItem Area for the actual disclosure item in a tree branch. + + \value SE_DialogButtonBoxLayoutItem Area that counts for the parent layout. + + \value SE_GroupBoxLayoutItem Area that counts for the parent layout. + + \value SE_CustomBase Base value for custom sub-elements. + Custom values must be greater than this value. + + \value SE_DockWidgetFloatButton The float button of a dock + widget. + \value SE_DockWidgetTitleBarText The text bounds of the dock + widgets title. + \value SE_DockWidgetCloseButton The close button of a dock + widget. + \value SE_DockWidgetIcon The icon of a dock widget. + \value SE_ComboBoxLayoutItem Area that counts for the parent layout. + + + \value SE_ItemViewItemDecoration Area for a view item's decoration (icon). + \value SE_ItemViewItemText Area for a view item's text. + \value SE_ItemViewItemFocusRect Area for a view item's focus rect. + + \value SE_TabBarTabLeftButton Area for a widget on the left side of a tab in a tab bar. + \value SE_TabBarTabRightButton Area for a widget on the right side of a tab in a tab bar. + \value SE_TabBarTabText Area for the text on a tab in a tab bar. + + \value SE_ToolBarHandle Area for the handle of a tool bar. + + \sa subElementRect() +*/ + +/*! + \fn QRect QStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const + + Returns the sub-area for the given \a element as described in the + provided style \a option. The returned rectangle is defined in + screen coordinates. + + The \a widget argument is optional and can be used to aid + determining the area. The QStyleOption object can be cast to the + appropriate type using the qstyleoption_cast() function. See the + table below for the appropriate \a option casts: + + \table + \header \o Sub Element \o QStyleOption Subclass + \row \o \l SE_PushButtonContents \o \l QStyleOptionButton + \row \o \l SE_PushButtonFocusRect \o \l QStyleOptionButton + \row \o \l SE_CheckBoxIndicator \o \l QStyleOptionButton + \row \o \l SE_CheckBoxContents \o \l QStyleOptionButton + \row \o \l SE_CheckBoxFocusRect \o \l QStyleOptionButton + \row \o \l SE_RadioButtonIndicator \o \l QStyleOptionButton + \row \o \l SE_RadioButtonContents \o \l QStyleOptionButton + \row \o \l SE_RadioButtonFocusRect \o \l QStyleOptionButton + \row \o \l SE_ComboBoxFocusRect \o \l QStyleOptionComboBox + \row \o \l SE_Q3DockWindowHandleRect \o \l QStyleOptionQ3DockWindow + \row \o \l SE_ProgressBarGroove \o \l QStyleOptionProgressBar + \row \o \l SE_ProgressBarContents \o \l QStyleOptionProgressBar + \row \o \l SE_ProgressBarLabel \o \l QStyleOptionProgressBar + \endtable +*/ + +/*! + \enum QStyle::ComplexControl + + This enum describes the available complex controls. Complex + controls have different behavior depending upon where the user + clicks on them or which keys are pressed. + + \value CC_SpinBox A spinbox, like QSpinBox. + \value CC_ComboBox A combobox, like QComboBox. + \value CC_ScrollBar A scroll bar, like QScrollBar. + \value CC_Slider A slider, like QSlider. + \value CC_ToolButton A tool button, like QToolButton. + \value CC_TitleBar A Title bar, like those used in QMdiSubWindow. + \value CC_Q3ListView Used for drawing the Q3ListView class. + \value CC_GroupBox A group box, like QGroupBox. + \value CC_Dial A dial, like QDial. + \value CC_MdiControls The minimize, close, and normal + button in the menu bar for a + maximized MDI subwindow. + + \value CC_CustomBase Base value for custom complex controls. Custom + values must be greater than this value. + + \sa SubControl drawComplexControl() +*/ + +/*! + \enum QStyle::SubControl + + This enum describes the available sub controls. A subcontrol is a + control element within a complex control (ComplexControl). + + \value SC_None Special value that matches no other sub control. + + \value SC_ScrollBarAddLine Scroll bar add line (i.e., down/right + arrow); see also QScrollBar. + \value SC_ScrollBarSubLine Scroll bar sub line (i.e., up/left arrow). + \value SC_ScrollBarAddPage Scroll bar add page (i.e., page down). + \value SC_ScrollBarSubPage Scroll bar sub page (i.e., page up). + \value SC_ScrollBarFirst Scroll bar first line (i.e., home). + \value SC_ScrollBarLast Scroll bar last line (i.e., end). + \value SC_ScrollBarSlider Scroll bar slider handle. + \value SC_ScrollBarGroove Special sub-control which contains the + area in which the slider handle may move. + + \value SC_SpinBoxUp Spin widget up/increase; see also QSpinBox. + \value SC_SpinBoxDown Spin widget down/decrease. + \value SC_SpinBoxFrame Spin widget frame. + \value SC_SpinBoxEditField Spin widget edit field. + + \value SC_ComboBoxEditField Combobox edit field; see also QComboBox. + \value SC_ComboBoxArrow Combobox arrow button. + \value SC_ComboBoxFrame Combobox frame. + \value SC_ComboBoxListBoxPopup The reference rectangle for the combobox popup. + Used to calculate the position of the popup. + + \value SC_SliderGroove Special sub-control which contains the area + in which the slider handle may move. + \value SC_SliderHandle Slider handle. + \value SC_SliderTickmarks Slider tickmarks. + + \value SC_ToolButton Tool button (see also QToolButton). + \value SC_ToolButtonMenu Sub-control for opening a popup menu in a + tool button; see also Q3PopupMenu. + + \value SC_TitleBarSysMenu System menu button (i.e., restore, close, etc.). + \value SC_TitleBarMinButton Minimize button. + \value SC_TitleBarMaxButton Maximize button. + \value SC_TitleBarCloseButton Close button. + \value SC_TitleBarLabel Window title label. + \value SC_TitleBarNormalButton Normal (restore) button. + \value SC_TitleBarShadeButton Shade button. + \value SC_TitleBarUnshadeButton Unshade button. + \value SC_TitleBarContextHelpButton Context Help button. + + \value SC_Q3ListView The list view area. + \value SC_Q3ListViewExpand Expand item (i.e., show/hide child items). + + \value SC_DialHandle The handle of the dial (i.e. what you use to control the dial). + \value SC_DialGroove The groove for the dial. + \value SC_DialTickmarks The tickmarks for the dial. + + \value SC_GroupBoxFrame The frame of a group box. + \value SC_GroupBoxLabel The title of a group box. + \value SC_GroupBoxCheckBox The optional check box of a group box. + \value SC_GroupBoxContents The group box contents. + + \value SC_MdiNormalButton The normal button for a MDI + subwindow in the menu bar. + \value SC_MdiMinButton The minimize button for a MDI + subwindow in the menu bar. + \value SC_MdiCloseButton The close button for a MDI subwindow + in the menu bar. + + \value SC_All Special value that matches all sub-controls. + \omitvalue SC_Q3ListViewBranch + \omitvalue SC_CustomBase + + \sa ComplexControl +*/ + +/*! + \fn void QStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const + + Draws the given \a control using the provided \a painter with the + style options specified by \a option. + + The \a widget argument is optional and can be used as aid in + drawing the control. + + The \a option parameter is a pointer to a QStyleOptionComplex + object that can be cast to the correct subclass using the + qstyleoption_cast() function. Note that the \c rect member of the + specified \a option must be in logical + coordinates. Reimplementations of this function should use + visualRect() to change the logical coordinates into screen + coordinates before calling the drawPrimitive() or drawControl() + function. + + The table below is listing the complex control elements and their + associated style option subclass. The style options contain all + the parameters required to draw the controls, including + QStyleOption::state which holds the \l {QStyle::StateFlag}{style + flags} that are used when drawing. The table also describes which + flags that are set when casting the given \a option to the + appropriate subclass. + + \table + \header \o Complex Control \o QStyleOptionComplex Subclass \o Style Flag \o Remark + \row \o{1,2} \l{CC_SpinBox} \o{1,2} \l QStyleOptionSpinBox + \o \l State_Enabled \o Set if the spin box is enabled. + \row \o \l State_HasFocus \o Set if the spin box has input focus. + + \row \o{1,2} \l {CC_ComboBox} \o{1,2} \l QStyleOptionComboBox + \o \l State_Enabled \o Set if the combobox is enabled. + \row \o \l State_HasFocus \o Set if the combobox has input focus. + + \row \o{1,2} \l {CC_ScrollBar} \o{1,2} \l QStyleOptionSlider + \o \l State_Enabled \o Set if the scroll bar is enabled. + \row \o \l State_HasFocus \o Set if the scroll bar has input focus. + + \row \o{1,2} \l {CC_Slider} \o{1,2} \l QStyleOptionSlider + \o \l State_Enabled \o Set if the slider is enabled. + \row \o \l State_HasFocus \o Set if the slider has input focus. + + \row \o{1,2} \l {CC_Dial} \o{1,2} \l QStyleOptionSlider + \o \l State_Enabled \o Set if the dial is enabled. + \row \o \l State_HasFocus \o Set if the dial has input focus. + + \row \o{1,6} \l {CC_ToolButton} \o{1,6} \l QStyleOptionToolButton + \o \l State_Enabled \o Set if the tool button is enabled. + \row \o \l State_HasFocus \o Set if the tool button has input focus. + \row \o \l State_DownArrow \o Set if the tool button is down (i.e., a mouse + button or the space bar is pressed). + \row \o \l State_On \o Set if the tool button is a toggle button + and is toggled on. + \row \o \l State_AutoRaise \o Set if the tool button has auto-raise enabled. + \row \o \l State_Raised \o Set if the button is not down, not on, and doesn't + contain the mouse when auto-raise is enabled. + + \row \o \l{CC_TitleBar} \o \l QStyleOptionTitleBar + \o \l State_Enabled \o Set if the title bar is enabled. + + \row \o \l{CC_Q3ListView} \o \l QStyleOptionQ3ListView + \o \l State_Enabled \o Set if the list view is enabled. + + \endtable + + \sa drawPrimitive(), drawControl() +*/ + + +/*! + \fn QRect QStyle::subControlRect(ComplexControl control, + const QStyleOptionComplex *option, SubControl subControl, + const QWidget *widget) const = 0 + + Returns the rectangle containing the specified \a subControl of + the given complex \a control (with the style specified by \a + option). The rectangle is defined in screen coordinates. + + The \a option argument is a pointer to QStyleOptionComplex or + one of its subclasses, and can be cast to the appropriate type + using the qstyleoption_cast() function. See drawComplexControl() + for details. The \a widget is optional and can contain additional + information for the function. + + \sa drawComplexControl() +*/ + +/*! + \fn QStyle::SubControl QStyle::hitTestComplexControl(ComplexControl control, + const QStyleOptionComplex *option, const QPoint &position, + const QWidget *widget) const = 0 + + Returns the sub control at the given \a position in the given + complex \a control (with the style options specified by \a + option). + + Note that the \a position is expressed in screen coordinates. + + The \a option argument is a pointer to a QStyleOptionComplex + object (or one of its subclasses). The object can be cast to the + appropriate type using the qstyleoption_cast() function. See + drawComplexControl() for details. The \a widget argument is + optional and can contain additional information for the function. + + \sa drawComplexControl(), subControlRect() +*/ + +/*! + \enum QStyle::PixelMetric + + This enum describes the various available pixel metrics. A pixel + metric is a style dependent size represented by a single pixel + value. + + \value PM_ButtonMargin Amount of whitespace between push button + labels and the frame. + \value PM_DockWidgetTitleBarButtonMargin Amount of whitespace between dock widget's + title bar button labels and the frame. + \value PM_ButtonDefaultIndicator Width of the default-button indicator frame. + \value PM_MenuButtonIndicator Width of the menu button indicator + proportional to the widget height. + \value PM_ButtonShiftHorizontal Horizontal contents shift of a + button when the button is down. + \value PM_ButtonShiftVertical Vertical contents shift of a button when the + button is down. + + \value PM_DefaultFrameWidth Default frame width (usually 2). + \value PM_SpinBoxFrameWidth Frame width of a spin box, defaults to PM_DefaultFrameWidth. + \value PM_ComboBoxFrameWidth Frame width of a combo box, defaults to PM_DefaultFrameWidth. + + \value PM_MDIFrameWidth Obsolete. Use PM_MdiSubWindowFrameWidth instead. + \value PM_MdiSubWindowFrameWidth Frame width of an MDI window. + \value PM_MDIMinimizedWidth Obsolete. Use PM_MdiSubWindowMinimizedWidth instead. + \value PM_MdiSubWindowMinimizedWidth Width of a minimized MDI window. + + \value PM_LayoutLeftMargin Default \l{QLayout::setContentsMargins()}{left margin} for a + QLayout. + \value PM_LayoutTopMargin Default \l{QLayout::setContentsMargins()}{top margin} for a QLayout. + \value PM_LayoutRightMargin Default \l{QLayout::setContentsMargins()}{right margin} for a + QLayout. + \value PM_LayoutBottomMargin Default \l{QLayout::setContentsMargins()}{bottom margin} for a + QLayout. + \value PM_LayoutHorizontalSpacing Default \l{QLayout::spacing}{horizontal spacing} for a + QLayout. + \value PM_LayoutVerticalSpacing Default \l{QLayout::spacing}{vertical spacing} for a QLayout. + + \value PM_MaximumDragDistance The maximum allowed distance between + the mouse and a scrollbar when dragging. Exceeding the specified + distance will cause the slider to jump back to the original + position; a value of -1 disables this behavior. + + \value PM_ScrollBarExtent Width of a vertical scroll bar and the + height of a horizontal scroll bar. + \value PM_ScrollBarSliderMin The minimum height of a vertical + scroll bar's slider and the minimum width of a horizontal + scroll bar's slider. + + \value PM_SliderThickness Total slider thickness. + \value PM_SliderControlThickness Thickness of the slider handle. + \value PM_SliderLength Length of the slider. + \value PM_SliderTickmarkOffset The offset between the tickmarks + and the slider. + \value PM_SliderSpaceAvailable The available space for the slider to move. + + \value PM_DockWidgetSeparatorExtent Width of a separator in a + horizontal dock window and the height of a separator in a + vertical dock window. + \value PM_DockWidgetHandleExtent Width of the handle in a + horizontal dock window and the height of the handle in a + vertical dock window. + \value PM_DockWidgetFrameWidth Frame width of a dock window. + \value PM_DockWidgetTitleMargin Margin of the dock window title. + + \value PM_MenuBarPanelWidth Frame width of a menu bar, defaults to PM_DefaultFrameWidth. + \value PM_MenuBarItemSpacing Spacing between menu bar items. + \value PM_MenuBarHMargin Spacing between menu bar items and left/right of bar. + \value PM_MenuBarVMargin Spacing between menu bar items and top/bottom of bar. + + \value PM_ToolBarFrameWidth Width of the frame around toolbars. + \value PM_ToolBarHandleExtent Width of a toolbar handle in a + horizontal toolbar and the height of the handle in a vertical toolbar. + \value PM_ToolBarItemMargin Spacing between the toolbar frame and the items. + \value PM_ToolBarItemSpacing Spacing between toolbar items. + \value PM_ToolBarSeparatorExtent Width of a toolbar separator in a + horizontal toolbar and the height of a separator in a vertical toolbar. + \value PM_ToolBarExtensionExtent Width of a toolbar extension + button in a horizontal toolbar and the height of the button in a + vertical toolbar. + + \value PM_TabBarTabOverlap Number of pixels the tabs should overlap. + (Currently only used in styles, not inside of QTabBar) + \value PM_TabBarTabHSpace Extra space added to the tab width. + \value PM_TabBarTabVSpace Extra space added to the tab height. + \value PM_TabBarBaseHeight Height of the area between the tab bar + and the tab pages. + \value PM_TabBarBaseOverlap Number of pixels the tab bar overlaps + the tab bar base. + \value PM_TabBarScrollButtonWidth + \value PM_TabBarTabShiftHorizontal Horizontal pixel shift when a + tab is selected. + \value PM_TabBarTabShiftVertical Vertical pixel shift when a + tab is selected. + + \value PM_ProgressBarChunkWidth Width of a chunk in a progress bar indicator. + + \value PM_SplitterWidth Width of a splitter. + + \value PM_TitleBarHeight Height of the title bar. + + \value PM_IndicatorWidth Width of a check box indicator. + \value PM_IndicatorHeight Height of a checkbox indicator. + \value PM_ExclusiveIndicatorWidth Width of a radio button indicator. + \value PM_ExclusiveIndicatorHeight Height of a radio button indicator. + + \value PM_MenuPanelWidth Border width (applied on all sides) for a QMenu. + \value PM_MenuHMargin Additional border (used on left and right) for a QMenu. + \value PM_MenuVMargin Additional border (used for bottom and top) for a QMenu. + \value PM_MenuScrollerHeight Height of the scroller area in a QMenu. + \value PM_MenuTearoffHeight Height of a tear off area in a QMenu. + \value PM_MenuDesktopFrameWidth The frame width for the menu on the desktop. + + \value PM_CheckListButtonSize Area (width/height) of the + checkbox/radio button in a Q3CheckListItem. + \value PM_CheckListControllerSize Area (width/height) of the + controller in a Q3CheckListItem. + + \omitvalue PM_DialogButtonsSeparator + \omitvalue PM_DialogButtonsButtonWidth + \omitvalue PM_DialogButtonsButtonHeight + + \value PM_HeaderMarkSize The size of the sort indicator in a header. + \value PM_HeaderGripMargin The size of the resize grip in a header. + \value PM_HeaderMargin The size of the margin between the sort indicator and the text. + \value PM_SpinBoxSliderHeight The height of the optional spin box slider. + + \value PM_ToolBarIconSize Default tool bar icon size + \value PM_SmallIconSize Default small icon size + \value PM_LargeIconSize Default large icon size + + \value PM_FocusFrameHMargin Horizontal margin that the focus frame will outset the widget by. + \value PM_FocusFrameVMargin Vertical margin that the focus frame will outset the widget by. + \value PM_IconViewIconSize The default size for icons in an icon view. + \value PM_ListViewIconSize The default size for icons in a list view. + + \value PM_ToolTipLabelFrameWidth The frame width for a tool tip label. + \value PM_CheckBoxLabelSpacing The spacing between a check box indicator and its label. + \value PM_RadioButtonLabelSpacing The spacing between a radio button indicator and its label. + \value PM_TabBarIconSize The default icon size for a tab bar. + \value PM_SizeGripSize The size of a size grip. + \value PM_MessageBoxIconSize The size of the standard icons in a message box + \value PM_ButtonIconSize The default size of button icons + \value PM_TextCursorWidth The width of the cursor in a line edit or text edit + \value PM_TabBar_ScrollButtonOverlap The distance between the left and right buttons in a tab bar. + + \value PM_TabCloseIndicatorWidth The default width of a close button on a tab in a tab bar. + \value PM_TabCloseIndicatorHeight The default height of a close button on a tab in a tab bar. + + \value PM_CustomBase Base value for custom pixel metrics. Custom + values must be greater than this value. + + The following values are obsolete: + + \value PM_DefaultTopLevelMargin Use PM_LayoutLeftMargin, + PM_LayoutTopMargin, + PM_LayoutRightMargin, and + PM_LayoutBottomMargin instead. + \value PM_DefaultChildMargin Use PM_LayoutLeftMargin, + PM_LayoutTopMargin, + PM_LayoutRightMargin, and + PM_LayoutBottomMargin instead. + \value PM_DefaultLayoutSpacing Use PM_LayoutHorizontalSpacing + and PM_LayoutVerticalSpacing + instead. + + \value PM_ScrollView_ScrollBarSpacing Distance between frame and scrollbar + with SH_ScrollView_FrameOnlyAroundContents set. + \value PM_SubMenuOverlap The horizontal overlap between a submenu and its parent. + + + \sa pixelMetric() +*/ + +/*! + \fn int QStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const; + + Returns the value of the given pixel \a metric. + + The specified \a option and \a widget can be used for calculating + the metric. In general, the \a widget argument is not used. The \a + option can be cast to the appropriate type using the + qstyleoption_cast() function. Note that the \a option may be zero + even for PixelMetrics that can make use of it. See the table below + for the appropriate \a option casts: + + \table + \header \o Pixel Metric \o QStyleOption Subclass + \row \o \l PM_SliderControlThickness \o \l QStyleOptionSlider + \row \o \l PM_SliderLength \o \l QStyleOptionSlider + \row \o \l PM_SliderTickmarkOffset \o \l QStyleOptionSlider + \row \o \l PM_SliderSpaceAvailable \o \l QStyleOptionSlider + \row \o \l PM_ScrollBarExtent \o \l QStyleOptionSlider + \row \o \l PM_TabBarTabOverlap \o \l QStyleOptionTab + \row \o \l PM_TabBarTabHSpace \o \l QStyleOptionTab + \row \o \l PM_TabBarTabVSpace \o \l QStyleOptionTab + \row \o \l PM_TabBarBaseHeight \o \l QStyleOptionTab + \row \o \l PM_TabBarBaseOverlap \o \l QStyleOptionTab + \endtable + + Some pixel metrics are called from widgets and some are only called + internally by the style. If the metric is not called by a widget, it is the + discretion of the style author to make use of it. For some styles, this + may not be appropriate. +*/ + +/*! + \enum QStyle::ContentsType + + This enum describes the available contents types. These are used to + calculate sizes for the contents of various widgets. + + \value CT_CheckBox A check box, like QCheckBox. + \value CT_ComboBox A combo box, like QComboBox. + \omitvalue CT_DialogButtons + \value CT_Q3DockWindow A Q3DockWindow. + \value CT_HeaderSection A header section, like QHeader. + \value CT_LineEdit A line edit, like QLineEdit. + \value CT_Menu A menu, like QMenu. + \value CT_Q3Header A Qt 3 header section, like Q3Header. + \value CT_MenuBar A menu bar, like QMenuBar. + \value CT_MenuBarItem A menu bar item, like the buttons in a QMenuBar. + \value CT_MenuItem A menu item, like QMenuItem. + \value CT_ProgressBar A progress bar, like QProgressBar. + \value CT_PushButton A push button, like QPushButton. + \value CT_RadioButton A radio button, like QRadioButton. + \value CT_SizeGrip A size grip, like QSizeGrip. + \value CT_Slider A slider, like QSlider. + \value CT_ScrollBar A scroll bar, like QScrollBar. + \value CT_SpinBox A spin box, like QSpinBox. + \value CT_Splitter A splitter, like QSplitter. + \value CT_TabBarTab A tab on a tab bar, like QTabBar. + \value CT_TabWidget A tab widget, like QTabWidget. + \value CT_ToolButton A tool button, like QToolButton. + \value CT_GroupBox A group box, like QGroupBox. + \value CT_ItemViewItem An item inside an item view. + + \value CT_CustomBase Base value for custom contents types. + Custom values must be greater than this value. + + \value CT_MdiControls The minimize, normal, and close button + in the menu bar for a maximized MDI + subwindow. + + \sa sizeFromContents() +*/ + +/*! + \fn QSize QStyle::sizeFromContents(ContentsType type, const QStyleOption *option, \ + const QSize &contentsSize, const QWidget *widget) const + + Returns the size of the element described by the specified + \a option and \a type, based on the provided \a contentsSize. + + The \a option argument is a pointer to a QStyleOption or one of + its subclasses. The \a option can be cast to the appropriate type + using the qstyleoption_cast() function. The \a widget is an + optional argument and can contain extra information used for + calculating the size. + + See the table below for the appropriate \a option casts: + + \table + \header \o Contents Type \o QStyleOption Subclass + \row \o \l CT_PushButton \o \l QStyleOptionButton + \row \o \l CT_CheckBox \o \l QStyleOptionButton + \row \o \l CT_RadioButton \o \l QStyleOptionButton + \row \o \l CT_ToolButton \o \l QStyleOptionToolButton + \row \o \l CT_ComboBox \o \l QStyleOptionComboBox + \row \o \l CT_Splitter \o \l QStyleOption + \row \o \l CT_Q3DockWindow \o \l QStyleOptionQ3DockWindow + \row \o \l CT_ProgressBar \o \l QStyleOptionProgressBar + \row \o \l CT_MenuItem \o \l QStyleOptionMenuItem + \endtable + + \sa ContentsType QStyleOption +*/ + +/*! + \enum QStyle::RequestSoftwareInputPanel + + This enum describes under what circumstances a software input panel will be + requested by input capable widgets. + + \value RSIP_OnMouseClickAndAlreadyFocused Requests an input panel if the user + clicks on the widget, but only if it is already focused. + \value RSIP_OnMouseClick Requests an input panel if the user clicks on the + widget. + + \sa QEvent::RequestSoftwareInputPanel, QInputContext +*/ + +/*! + \enum QStyle::StyleHint + + This enum describes the available style hints. A style hint is a general look + and/or feel hint. + + \value SH_EtchDisabledText Disabled text is "etched" as it is on Windows. + + \value SH_DitherDisabledText Disabled text is dithered as it is on Motif. + + \value SH_GUIStyle The GUI style to use. + + \value SH_ScrollBar_ContextMenu Whether or not a scroll bar has a context menu. + + \value SH_ScrollBar_MiddleClickAbsolutePosition A boolean value. + If true, middle clicking on a scroll bar causes the slider to + jump to that position. If false, middle clicking is + ignored. + + \value SH_ScrollBar_LeftClickAbsolutePosition A boolean value. + If true, left clicking on a scroll bar causes the slider to + jump to that position. If false, left clicking will + behave as appropriate for each control. + + \value SH_ScrollBar_ScrollWhenPointerLeavesControl A boolean + value. If true, when clicking a scroll bar SubControl, holding + the mouse button down and moving the pointer outside the + SubControl, the scroll bar continues to scroll. If false, the + scollbar stops scrolling when the pointer leaves the + SubControl. + + \value SH_ScrollBar_RollBetweenButtons A boolean value. + If true, when clicking a scroll bar button (SC_ScrollBarAddLine or + SC_ScrollBarSubLine) and dragging over to the opposite button (rolling) + will press the new button and release the old one. When it is false, the + original button is released and nothing happens (like a push button). + + \value SH_TabBar_Alignment The alignment for tabs in a + QTabWidget. Possible values are Qt::AlignLeft, + Qt::AlignCenter and Qt::AlignRight. + + \value SH_Header_ArrowAlignment The placement of the sorting + indicator may appear in list or table headers. Possible values + are Qt::Left or Qt::Right. + + \value SH_Slider_SnapToValue Sliders snap to values while moving, + as they do on Windows. + + \value SH_Slider_SloppyKeyEvents Key presses handled in a sloppy + manner, i.e., left on a vertical slider subtracts a line. + + \value SH_ProgressDialog_CenterCancelButton Center button on + progress dialogs, like Motif, otherwise right aligned. + + \value SH_ProgressDialog_TextLabelAlignment The alignment for text + labels in progress dialogs; Qt::AlignCenter on Windows, + Qt::AlignVCenter otherwise. + + \value SH_PrintDialog_RightAlignButtons Right align buttons in + the print dialog, as done on Windows. + + \value SH_MainWindow_SpaceBelowMenuBar One or two pixel space between + the menu bar and the dockarea, as done on Windows. + + \value SH_FontDialog_SelectAssociatedText Select the text in the + line edit, or when selecting an item from the listbox, or when + the line edit receives focus, as done on Windows. + + \value SH_Menu_KeyboardSearch Typing causes a menu to be search + for relevant items, otherwise only mnemnonic is considered. + + \value SH_Menu_AllowActiveAndDisabled Allows disabled menu + items to be active. + + \value SH_Menu_SpaceActivatesItem Pressing the space bar activates + the item, as done on Motif. + + \value SH_Menu_SubMenuPopupDelay The number of milliseconds + to wait before opening a submenu (256 on Windows, 96 on Motif). + + \value SH_Menu_Scrollable Whether popup menus must support scrolling. + + \value SH_Menu_SloppySubMenus Whether popupmenu's must support + sloppy submenu; as implemented on Mac OS. + + \value SH_ScrollView_FrameOnlyAroundContents Whether scrollviews + draw their frame only around contents (like Motif), or around + contents, scroll bars and corner widgets (like Windows). + + \value SH_MenuBar_AltKeyNavigation Menu bars items are navigable + by pressing Alt, followed by using the arrow keys to select + the desired item. + + \value SH_ComboBox_ListMouseTracking Mouse tracking in combobox + drop-down lists. + + \value SH_Menu_MouseTracking Mouse tracking in popup menus. + + \value SH_MenuBar_MouseTracking Mouse tracking in menu bars. + + \value SH_Menu_FillScreenWithScroll Whether scrolling popups + should fill the screen as they are scrolled. + + \value SH_Menu_SelectionWrap Whether popups should allow the selections + to wrap, that is when selection should the next item be the first item. + + \value SH_ItemView_ChangeHighlightOnFocus Gray out selected items + when losing focus. + + \value SH_Widget_ShareActivation Turn on sharing activation with + floating modeless dialogs. + + \value SH_TabBar_SelectMouseType Which type of mouse event should + cause a tab to be selected. + + \value SH_Q3ListViewExpand_SelectMouseType Which type of mouse event should + cause a list view expansion to be selected. + + \value SH_TabBar_PreferNoArrows Whether a tab bar should suggest a size + to prevent scoll arrows. + + \value SH_ComboBox_Popup Allows popups as a combobox drop-down + menu. + + \value SH_Workspace_FillSpaceOnMaximize The workspace should + maximize the client area. + + \value SH_TitleBar_NoBorder The title bar has no border. + + \value SH_ScrollBar_StopMouseOverSlider Obsolete. Use + SH_Slider_StopMouseOverSlider instead. + + \value SH_Slider_StopMouseOverSlider Stops auto-repeat when + the slider reaches the mouse position. + + \value SH_BlinkCursorWhenTextSelected Whether cursor should blink + when text is selected. + + \value SH_RichText_FullWidthSelection Whether richtext selections + should extend to the full width of the document. + + \value SH_GroupBox_TextLabelVerticalAlignment How to vertically align a + group box's text label. + + \value SH_GroupBox_TextLabelColor How to paint a group box's text label. + + \value SH_DialogButtons_DefaultButton Which button gets the + default status in a dialog's button widget. + + \value SH_ToolBox_SelectedPageTitleBold Boldness of the selected + page title in a QToolBox. + + \value SH_LineEdit_PasswordCharacter The Unicode character to be + used for passwords. + + \value SH_Table_GridLineColor The RGB value of the grid for a table. + + \value SH_UnderlineShortcut Whether shortcuts are underlined. + + \value SH_SpellCheckUnderlineStyle A + QTextCharFormat::UnderlineStyle value that specifies the way + misspelled words should be underlined. + + \value SH_SpinBox_AnimateButton Animate a click when up or down is + pressed in a spin box. + \value SH_SpinBox_KeyPressAutoRepeatRate Auto-repeat interval for + spinbox key presses. + \value SH_SpinBox_ClickAutoRepeatRate Auto-repeat interval for + spinbox mouse clicks. + \value SH_SpinBox_ClickAutoRepeatThreshold Auto-repeat threshold for + spinbox mouse clicks. + \value SH_ToolTipLabel_Opacity An integer indicating the opacity for + the tip label, 0 is completely transparent, 255 is completely + opaque. + \value SH_DrawMenuBarSeparator Indicates whether or not the menu bar draws separators. + \value SH_TitleBar_ModifyNotification Indicates if the title bar should show + a '*' for windows that are modified. + + \value SH_Button_FocusPolicy The default focus policy for buttons. + + \value SH_CustomBase Base value for custom style hints. + Custom values must be greater than this value. + + \value SH_MenuBar_DismissOnSecondClick A boolean indicating if a menu in + the menu bar should be dismissed when it is clicked on a second time. (Example: + Clicking and releasing on the File Menu in a menu bar and then + immediately clicking on the File Menu again.) + + \value SH_MessageBox_UseBorderForButtonSpacing A boolean indicating what the to + use the border of the buttons (computed as half the button height) for the spacing + of the button in a message box. + + \value SH_MessageBox_CenterButtons A boolean indicating whether the buttons in the + message box should be centered or not (see QDialogButtonBox::setCentered()). + + \value SH_MessageBox_TextInteractionFlags A boolean indicating if + the text in a message box should allow user interfactions (e.g. + selection) or not. + + \value SH_TitleBar_AutoRaise A boolean indicating whether + controls on a title bar ought to update when the mouse is over them. + + \value SH_ToolButton_PopupDelay An int indicating the popup delay in milliseconds + for menus attached to tool buttons. + + \value SH_FocusFrame_Mask The mask of the focus frame. + + \value SH_RubberBand_Mask The mask of the rubber band. + + \value SH_WindowFrame_Mask The mask of the window frame. + + \value SH_SpinControls_DisableOnBounds Determines if the spin controls will shown + as disabled when reaching the spin range boundary. + + \value SH_Dial_BackgroundRole Defines the style's preferred + background role (as QPalette::ColorRole) for a dial widget. + + \value SH_ScrollBar_BackgroundMode The background mode for a scroll bar. + + \value SH_ComboBox_LayoutDirection The layout direction for the + combo box. By default it should be the same as indicated by the + QStyleOption::direction variable. + + \value SH_ItemView_EllipsisLocation The location where ellipses should be + added for item text that is too long to fit in an view item. + + \value SH_ItemView_ShowDecorationSelected When an item in an item + view is selected, also highlight the branch or other decoration. + + \value SH_ItemView_ActivateItemOnSingleClick Emit the activated signal + when the user single clicks on an item in an item in an item view. + Otherwise the signal is emitted when the user double clicks on an item. + + \value SH_Slider_AbsoluteSetButtons Which mouse buttons cause a slider + to set the value to the position clicked on. + + \value SH_Slider_PageSetButtons Which mouse buttons cause a slider + to page step the value. + + \value SH_TabBar_ElideMode The default eliding style for a tab bar. + + \value SH_DialogButtonLayout Controls how buttons are laid out in a QDialogButtonBox, returns a QDialogButtonBox::ButtonLayout enum. + + \value SH_WizardStyle Controls the look and feel of a QWizard. Returns a QWizard::WizardStyle enum. + + \value SH_FormLayoutWrapPolicy Provides a default for how rows are wrapped in a QFormLayout. Returns a QFormLayout::RowWrapPolicy enum. + \value SH_FormLayoutFieldGrowthPolicy Provides a default for how fields can grow in a QFormLayout. Returns a QFormLayout::FieldGrowthPolicy enum. + \value SH_FormLayoutFormAlignment Provides a default for how a QFormLayout aligns its contents within the available space. Returns a Qt::Alignment enum. + \value SH_FormLayoutLabelAlignment Provides a default for how a QFormLayout aligns labels within the available space. Returns a Qt::Alignment enum. + + \value SH_ItemView_ArrowKeysNavigateIntoChildren Controls whether the tree view will select the first child when it is exapanded and the right arrow key is pressed. + \value SH_ComboBox_PopupFrameStyle The frame style used when drawing a combobox popup menu. + + \value SH_DialogButtonBox_ButtonsHaveIcons Indicates whether or not StandardButtons in QDialogButtonBox should have icons or not. + \value SH_ItemView_MovementWithoutUpdatingSelection The item view is able to indicate a current item without changing the selection. + \value SH_ToolTip_Mask The mask of a tool tip. + + \value SH_FocusFrame_AboveWidget The FocusFrame is stacked above the widget that it is "focusing on". + + \value SH_TextControl_FocusIndicatorTextCharFormat Specifies the text format used to highlight focused anchors in rich text + documents displayed for example in QTextBrowser. The format has to be a QTextCharFormat returned in the variant of the + QStyleHintReturnVariant return value. The QTextFormat::OutlinePen property is used for the outline and QTextFormat::BackgroundBrush + for the background of the highlighted area. + + \value SH_Menu_FlashTriggeredItem Flash triggered item. + \value SH_Menu_FadeOutOnHide Fade out the menu instead of hiding it immediately. + + \value SH_TabWidget_DefaultTabPosition Default position of the tab bar in a tab widget. + + \value SH_ToolBar_Movable Determines if the tool bar is movable by default. + + \value SH_ItemView_PaintAlternatingRowColorsForEmptyArea Whether QTreeView paints alternating row colors for the area that does not have any items. + + \value SH_Menu_Mask The mask for a popup menu. + + \value SH_ItemView_DrawDelegateFrame Determines if there should be a frame for a delegate widget. + + \value SH_TabBar_CloseButtonPosition Determines the position of the close button on a tab in a tab bar. + + \value SH_DockWidget_ButtonsHaveFrame Determines if dockwidget buttons should have frames. Default is true. + + \value SH_ToolButtonStyle Determines the default system style for tool buttons that uses Qt::ToolButtonFollowStyle. + + \value SH_RequestSoftwareInputPanel Determines when a software input panel should + be requested by input widgets. Returns an enum of type QStyle::RequestSoftwareInputPanel. + + \omitvalue SH_UnderlineAccelerator + + \sa styleHint() +*/ + +/*! + \fn int QStyle::styleHint(StyleHint hint, const QStyleOption *option, \ + const QWidget *widget, QStyleHintReturn *returnData) const + + Returns an integer representing the specified style \a hint for + the given \a widget described by the provided style \a option. + + \a returnData is used when the querying widget needs more detailed data than + the integer that styleHint() returns. See the QStyleHintReturn class + description for details. +*/ + +/*! + \enum QStyle::StandardPixmap + + This enum describes the available standard pixmaps. A standard pixmap is a pixmap that + can follow some existing GUI style or guideline. + + \value SP_TitleBarMinButton Minimize button on title bars (e.g., + in QMdiSubWindow). + \value SP_TitleBarMenuButton Menu button on a title bar. + \value SP_TitleBarMaxButton Maximize button on title bars. + \value SP_TitleBarCloseButton Close button on title bars. + \value SP_TitleBarNormalButton Normal (restore) button on title bars. + \value SP_TitleBarShadeButton Shade button on title bars. + \value SP_TitleBarUnshadeButton Unshade button on title bars. + \value SP_TitleBarContextHelpButton The Context help button on title bars. + \value SP_MessageBoxInformation The "information" icon. + \value SP_MessageBoxWarning The "warning" icon. + \value SP_MessageBoxCritical The "critical" icon. + \value SP_MessageBoxQuestion The "question" icon. + \value SP_DesktopIcon The "desktop" icon. + \value SP_TrashIcon The "trash" icon. + \value SP_ComputerIcon The "My computer" icon. + \value SP_DriveFDIcon The floppy icon. + \value SP_DriveHDIcon The harddrive icon. + \value SP_DriveCDIcon The CD icon. + \value SP_DriveDVDIcon The DVD icon. + \value SP_DriveNetIcon The network icon. + \value SP_DirHomeIcon The home directory icon. + \value SP_DirOpenIcon The open directory icon. + \value SP_DirClosedIcon The closed directory icon. + \value SP_DirIcon The directory icon. + \value SP_DirLinkIcon The link to directory icon. + \value SP_FileIcon The file icon. + \value SP_FileLinkIcon The link to file icon. + \value SP_FileDialogStart The "start" icon in a file dialog. + \value SP_FileDialogEnd The "end" icon in a file dialog. + \value SP_FileDialogToParent The "parent directory" icon in a file dialog. + \value SP_FileDialogNewFolder The "create new folder" icon in a file dialog. + \value SP_FileDialogDetailedView The detailed view icon in a file dialog. + \value SP_FileDialogInfoView The file info icon in a file dialog. + \value SP_FileDialogContentsView The contents view icon in a file dialog. + \value SP_FileDialogListView The list view icon in a file dialog. + \value SP_FileDialogBack The back arrow in a file dialog. + \value SP_DockWidgetCloseButton Close button on dock windows (see also QDockWidget). + \value SP_ToolBarHorizontalExtensionButton Extension button for horizontal toolbars. + \value SP_ToolBarVerticalExtensionButton Extension button for vertical toolbars. + \value SP_DialogOkButton Icon for a standard OK button in a QDialogButtonBox. + \value SP_DialogCancelButton Icon for a standard Cancel button in a QDialogButtonBox. + \value SP_DialogHelpButton Icon for a standard Help button in a QDialogButtonBox. + \value SP_DialogOpenButton Icon for a standard Open button in a QDialogButtonBox. + \value SP_DialogSaveButton Icon for a standard Save button in a QDialogButtonBox. + \value SP_DialogCloseButton Icon for a standard Close button in a QDialogButtonBox. + \value SP_DialogApplyButton Icon for a standard Apply button in a QDialogButtonBox. + \value SP_DialogResetButton Icon for a standard Reset button in a QDialogButtonBox. + \value SP_DialogDiscardButton Icon for a standard Discard button in a QDialogButtonBox. + \value SP_DialogYesButton Icon for a standard Yes button in a QDialogButtonBox. + \value SP_DialogNoButton Icon for a standard No button in a QDialogButtonBox. + \value SP_ArrowUp Icon arrow pointing up. + \value SP_ArrowDown Icon arrow pointing down. + \value SP_ArrowLeft Icon arrow pointing left. + \value SP_ArrowRight Icon arrow pointing right. + \value SP_ArrowBack Equivalent to SP_ArrowLeft when the current layout direction is Qt::LeftToRight, otherwise SP_ArrowRight. + \value SP_ArrowForward Equivalent to SP_ArrowRight when the current layout direction is Qt::LeftToRight, otherwise SP_ArrowLeft. + \value SP_CommandLink Icon used to indicate a Vista style command link glyph. + \value SP_VistaShield Icon used to indicate UAC prompts on Windows Vista. This will return a null pixmap or icon on all other platforms. + \value SP_BrowserReload Icon indicating that the current page should be reloaded. + \value SP_BrowserStop Icon indicating that the page loading should stop. + \value SP_MediaPlay Icon indicating that media should begin playback. + \value SP_MediaStop Icon indicating that media should stop playback. + \value SP_MediaPause Icon indicating that media should pause playback. + \value SP_MediaSkipForward Icon indicating that media should skip forward. + \value SP_MediaSkipBackward Icon indicating that media should skip backward. + \value SP_MediaSeekForward Icon indicating that media should seek forward. + \value SP_MediaSeekBackward Icon indicating that media should seek backward. + \value SP_MediaVolume Icon indicating a volume control. + \value SP_MediaVolumeMuted Icon indicating a muted volume control. + \value SP_CustomBase Base value for custom standard pixmaps; + custom values must be greater than this value. + + \sa standardIcon() +*/ + +/*! + \fn QPixmap QStyle::generatedIconPixmap(QIcon::Mode iconMode, + const QPixmap &pixmap, const QStyleOption *option) const + + Returns a copy of the given \a pixmap, styled to conform to the + specified \a iconMode and taking into account the palette + specified by \a option. + + The \a option parameter can pass extra information, but + it must contain a palette. + + Note that not all pixmaps will conform, in which case the returned + pixmap is a plain copy. + + \sa QIcon +*/ + +/*! + \fn QPixmap QStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option, \ + const QWidget *widget) const + + \obsolete + Returns a pixmap for the given \a standardPixmap. + + A standard pixmap is a pixmap that can follow some existing GUI + style or guideline. The \a option argument can be used to pass + extra information required when defining the appropriate + pixmap. The \a widget argument is optional and can also be used to + aid the determination of the pixmap. + + Developers calling standardPixmap() should instead call standardIcon() + Developers who re-implemented standardPixmap() should instead re-implement + the slot standardIconImplementation(). + + \sa standardIcon() +*/ + + +/*! + \fn QRect QStyle::visualRect(Qt::LayoutDirection direction, const QRect &boundingRectangle, const QRect &logicalRectangle) + + Returns the given \a logicalRectangle converted to screen + coordinates based on the specified \a direction. The \a + boundingRectangle is used when performing the translation. + + This function is provided to support right-to-left desktops, and + is typically used in implementations of the subControlRect() + function. + + \sa QWidget::layoutDirection +*/ +QRect QStyle::visualRect(Qt::LayoutDirection direction, const QRect &boundingRect, const QRect &logicalRect) +{ + if (direction == Qt::LeftToRight) + return logicalRect; + QRect rect = logicalRect; + rect.translate(2 * (boundingRect.right() - logicalRect.right()) + + logicalRect.width() - boundingRect.width(), 0); + return rect; +} + +/*! + \fn QPoint QStyle::visualPos(Qt::LayoutDirection direction, const QRect &boundingRectangle, const QPoint &logicalPosition) + + Returns the given \a logicalPosition converted to screen + coordinates based on the specified \a direction. The \a + boundingRectangle is used when performing the translation. + + \sa QWidget::layoutDirection +*/ +QPoint QStyle::visualPos(Qt::LayoutDirection direction, const QRect &boundingRect, const QPoint &logicalPos) +{ + if (direction == Qt::LeftToRight) + return logicalPos; + return QPoint(boundingRect.right() - logicalPos.x(), logicalPos.y()); +} + +/*! + Returns a new rectangle of the specified \a size that is aligned to the given \a + rectangle according to the specified \a alignment and \a direction. + */ +QRect QStyle::alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment, const QSize &size, const QRect &rectangle) +{ + alignment = visualAlignment(direction, alignment); + int x = rectangle.x(); + int y = rectangle.y(); + int w = size.width(); + int h = size.height(); + if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter) + y += rectangle.size().height()/2 - h/2; + else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom) + y += rectangle.size().height() - h; + if ((alignment & Qt::AlignRight) == Qt::AlignRight) + x += rectangle.size().width() - w; + else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter) + x += rectangle.size().width()/2 - w/2; + return QRect(x, y, w, h); +} + +/*! + Transforms an \a alignment of Qt::AlignLeft or Qt::AlignRight + without Qt::AlignAbsolute into Qt::AlignLeft or Qt::AlignRight with + Qt::AlignAbsolute according to the layout \a direction. The other + alignment flags are left untouched. + + If no horizontal alignment was specified, the function returns the + default alignment for the given layout \a direction. + + QWidget::layoutDirection +*/ +Qt::Alignment QStyle::visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment) +{ + return QGuiApplicationPrivate::visualAlignment(direction, alignment); +} + +/*! + Converts the given \a logicalValue to a pixel position. The \a min + parameter maps to 0, \a max maps to \a span and other values are + distributed evenly in-between. + + This function can handle the entire integer range without + overflow, providing that \a span is less than 4096. + + By default, this function assumes that the maximum value is on the + right for horizontal items and on the bottom for vertical items. + Set the \a upsideDown parameter to true to reverse this behavior. + + \sa sliderValueFromPosition() +*/ + +int QStyle::sliderPositionFromValue(int min, int max, int logicalValue, int span, bool upsideDown) +{ + if (span <= 0 || logicalValue < min || max <= min) + return 0; + if (logicalValue > max) + return upsideDown ? span : min; + + uint range = max - min; + uint p = upsideDown ? max - logicalValue : logicalValue - min; + + if (range > (uint)INT_MAX/4096) { + double dpos = (double(p))/(double(range)/span); + return int(dpos); + } else if (range > (uint)span) { + return (2 * p * span + range) / (2*range); + } else { + uint div = span / range; + uint mod = span % range; + return p * div + (2 * p * mod + range) / (2 * range); + } + // equiv. to (p * span) / range + 0.5 + // no overflow because of this implicit assumption: + // span <= 4096 +} + +/*! + \fn int QStyle::sliderValueFromPosition(int min, int max, int position, int span, bool upsideDown) + + Converts the given pixel \a position to a logical value. 0 maps to + the \a min parameter, \a span maps to \a max and other values are + distributed evenly in-between. + + This function can handle the entire integer range without + overflow. + + By default, this function assumes that the maximum value is on the + right for horizontal items and on the bottom for vertical + items. Set the \a upsideDown parameter to true to reverse this + behavior. + + \sa sliderPositionFromValue() +*/ + +int QStyle::sliderValueFromPosition(int min, int max, int pos, int span, bool upsideDown) +{ + if (span <= 0 || pos <= 0) + return upsideDown ? max : min; + if (pos >= span) + return upsideDown ? min : max; + + uint range = max - min; + + if ((uint)span > range) { + int tmp = (2 * pos * range + span) / (2 * span); + return upsideDown ? max - tmp : tmp + min; + } else { + uint div = range / span; + uint mod = range % span; + int tmp = pos * div + (2 * pos * mod + span) / (2 * span); + return upsideDown ? max - tmp : tmp + min; + } + // equiv. to min + (pos*range)/span + 0.5 + // no overflow because of this implicit assumption: + // pos <= span < sqrt(INT_MAX+0.0625)+0.25 ~ sqrt(INT_MAX) +} + +/*! + Returns the style's standard palette. + + Note that on systems that support system colors, the style's + standard palette is not used. In particular, the Windows XP, + Vista, and Mac styles do not use the standard palette, but make + use of native theme engines. With these styles, you should not set + the palette with QApplication::setStandardPalette(). + + */ +QPalette QStyle::standardPalette() const +{ +#ifdef Q_WS_X11 + QColor background; + if (QX11Info::appDepth() > 8) + background = QColor(0xd4, 0xd0, 0xc8); // win 2000 grey + else + background = QColor(192, 192, 192); +#else + QColor background(0xd4, 0xd0, 0xc8); // win 2000 grey +#endif + QColor light(background.lighter()); + QColor dark(background.darker()); + QColor mid(Qt::gray); + QPalette palette(Qt::black, background, light, dark, mid, Qt::black, Qt::white); + palette.setBrush(QPalette::Disabled, QPalette::WindowText, dark); + palette.setBrush(QPalette::Disabled, QPalette::Text, dark); + palette.setBrush(QPalette::Disabled, QPalette::ButtonText, dark); + palette.setBrush(QPalette::Disabled, QPalette::Base, background); + return palette; +} + +/*! + \since 4.1 + + Returns an icon for the given \a standardIcon. + + The \a standardIcon is a standard pixmap which can follow some + existing GUI style or guideline. The \a option argument can be + used to pass extra information required when defining the + appropriate icon. The \a widget argument is optional and can also + be used to aid the determination of the icon. + + \warning Because of binary compatibility constraints, this + function is not virtual. If you want to provide your own icons in + a QStyle subclass, reimplement the standardIconImplementation() + slot in your subclass instead. The standardIcon() function will + dynamically detect the slot and call it. + + \sa standardIconImplementation() +*/ +QIcon QStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget) const +{ + QIcon result; + // ### Qt 4.1: invokeMethod should accept const functions, to avoid this dirty cast + QMetaObject::invokeMethod(const_cast(this), + "standardIconImplementation", Qt::DirectConnection, + Q_RETURN_ARG(QIcon, result), + Q_ARG(StandardPixmap, standardIcon), + Q_ARG(const QStyleOption*, option), + Q_ARG(const QWidget*, widget)); + return result; +} + +/*! + \since 4.1 + + Returns an icon for the given \a standardIcon. + + Reimplement this slot to provide your own icons in a QStyle + subclass; because of binary compatibility constraints, the + standardIcon() function (introduced in Qt 4.1) is not + virtual. Instead, standardIcon() will dynamically detect and call + \e this slot. + + The \a standardIcon is a standard pixmap which can follow some + existing GUI style or guideline. The \a option argument can be + used to pass extra information required when defining the + appropriate icon. The \a widget argument is optional and can also + be used to aid the determination of the icon. + + \sa standardIcon() +*/ +QIcon QStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget) const +{ + return QIcon(standardPixmap(standardIcon, option, widget)); +} + +/*! + \since 4.3 + + Returns the spacing that should be used between \a control1 and + \a control2 in a layout. \a orientation specifies whether the + controls are laid out side by side or stacked vertically. The \a + option parameter can be used to pass extra information about the + parent widget. The \a widget parameter is optional and can also + be used if \a option is 0. + + This function is called by the layout system. It is used only if + PM_LayoutHorizontalSpacing or PM_LayoutVerticalSpacing returns a + negative value. + + For binary compatibility reasons, this function is not virtual. + If you want to specify custom layout spacings in a QStyle + subclass, implement a slot called layoutSpacingImplementation(). + QStyle will discover the slot at run-time (using Qt's + \l{meta-object system}) and direct all calls to layoutSpacing() + to layoutSpacingImplementation(). + + \sa combinedLayoutSpacing(), layoutSpacingImplementation() +*/ +int QStyle::layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, + Qt::Orientation orientation, const QStyleOption *option, + const QWidget *widget) const +{ + Q_D(const QStyle); + if (d->layoutSpacingIndex == -1) { + d->layoutSpacingIndex = metaObject()->indexOfMethod( + "layoutSpacingImplementation(QSizePolicy::ControlType,QSizePolicy::ControlType," + "Qt::Orientation,const QStyleOption*,const QWidget*)" + ); + } + if (d->layoutSpacingIndex < 0) + return -1; + int result = -1; + void *param[] = {&result, &control1, &control2, &orientation, &option, &widget}; + + const_cast(this)->qt_metacall(QMetaObject::InvokeMetaMethod, + d->layoutSpacingIndex, param); + return result; +} + +/*! + \since 4.3 + + Returns the spacing that should be used between \a controls1 and + \a controls2 in a layout. \a orientation specifies whether the + controls are laid out side by side or stacked vertically. The \a + option parameter can be used to pass extra information about the + parent widget. The \a widget parameter is optional and can also + be used if \a option is 0. + + \a controls1 and \a controls2 are OR-combination of zero or more + \l{QSizePolicy::ControlTypes}{control types}. + + This function is called by the layout system. It is used only if + PM_LayoutHorizontalSpacing or PM_LayoutVerticalSpacing returns a + negative value. + + \sa layoutSpacing(), layoutSpacingImplementation() +*/ +int QStyle::combinedLayoutSpacing(QSizePolicy::ControlTypes controls1, + QSizePolicy::ControlTypes controls2, Qt::Orientation orientation, + QStyleOption *option, QWidget *widget) const +{ + QSizePolicy::ControlType array1[MaxBits]; + QSizePolicy::ControlType array2[MaxBits]; + int count1 = unpackControlTypes(controls1, array1); + int count2 = unpackControlTypes(controls2, array2); + int result = -1; + + for (int i = 0; i < count1; ++i) { + for (int j = 0; j < count2; ++j) { + int spacing = layoutSpacing(array1[i], array2[j], orientation, option, widget); + result = qMax(spacing, result); + } + } + return result; +} + +/*! + \since 4.3 + + This slot is called by layoutSpacing() to determine the spacing + that should be used between \a control1 and \a control2 in a + layout. \a orientation specifies whether the controls are laid + out side by side or stacked vertically. The \a option parameter + can be used to pass extra information about the parent widget. + The \a widget parameter is optional and can also be used if \a + option is 0. + + If you want to provide custom layout spacings in a QStyle + subclass, implement a slot called layoutSpacingImplementation() + in your subclass. Be aware that this slot will only be called if + PM_LayoutHorizontalSpacing or PM_LayoutVerticalSpacing returns a + negative value. + + The default implementation returns -1. + + \sa layoutSpacing(), combinedLayoutSpacing() +*/ +int QStyle::layoutSpacingImplementation(QSizePolicy::ControlType /* control1 */, + QSizePolicy::ControlType /* control2 */, + Qt::Orientation /*orientation*/, + const QStyleOption * /* option */, + const QWidget * /* widget */) const +{ + return -1; +} + +QT_BEGIN_INCLUDE_NAMESPACE +#include +QT_END_INCLUDE_NAMESPACE + +#if !defined(QT_NO_DEBUG_STREAM) +QDebug operator<<(QDebug debug, QStyle::State state) +{ +#if !defined(QT_NO_DEBUG) + debug << "QStyle::State("; + + QStringList states; + if (state & QStyle::State_Active) states << QLatin1String("Active"); + if (state & QStyle::State_AutoRaise) states << QLatin1String("AutoRaise"); + if (state & QStyle::State_Bottom) states << QLatin1String("Bottom"); + if (state & QStyle::State_Children) states << QLatin1String("Children"); + if (state & QStyle::State_DownArrow) states << QLatin1String("DownArrow"); + if (state & QStyle::State_Editing) states << QLatin1String("Editing"); + if (state & QStyle::State_Enabled) states << QLatin1String("Enabled"); + if (state & QStyle::State_FocusAtBorder) states << QLatin1String("FocusAtBorder"); + if (state & QStyle::State_HasFocus) states << QLatin1String("HasFocus"); + if (state & QStyle::State_Horizontal) states << QLatin1String("Horizontal"); + if (state & QStyle::State_Item) states << QLatin1String("Item"); + if (state & QStyle::State_KeyboardFocusChange) states << QLatin1String("KeyboardFocusChange"); + if (state & QStyle::State_MouseOver) states << QLatin1String("MouseOver"); + if (state & QStyle::State_NoChange) states << QLatin1String("NoChange"); + if (state & QStyle::State_Off) states << QLatin1String("Off"); + if (state & QStyle::State_On) states << QLatin1String("On"); + if (state & QStyle::State_Open) states << QLatin1String("Open"); + if (state & QStyle::State_Raised) states << QLatin1String("Raised"); + if (state & QStyle::State_ReadOnly) states << QLatin1String("ReadOnly"); + if (state & QStyle::State_Selected) states << QLatin1String("Selected"); + if (state & QStyle::State_Sibling) states << QLatin1String("Sibling"); + if (state & QStyle::State_Sunken) states << QLatin1String("Sunken"); + if (state & QStyle::State_Top) states << QLatin1String("Top"); + if (state & QStyle::State_UpArrow) states << QLatin1String("UpArrow"); + + qSort(states); + debug << states.join(QLatin1String(" | ")); + debug << ')'; +#else + Q_UNUSED(state); +#endif + return debug; +} +#endif + +/*! + \since 4.6 + + \fn const QStyle *QStyle::proxy() const + + This function returns the current proxy for this style. + By default most styles will return themselves. However + when a proxy style is in use, it will allow the style to + call back into its proxy. +*/ +const QStyle * QStyle::proxy() const +{ + Q_D(const QStyle); + return d->proxyStyle; +} + +/* \internal + + This function sets the base style that style calls will be + redirected to. Note that ownership is not transferred. +*/ +void QStyle::setProxy(QStyle *style) +{ + Q_D(QStyle); + d->proxyStyle = style; +} + +QT_END_NAMESPACE diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h new file mode 100644 index 0000000000..94f2ce102f --- /dev/null +++ b/src/widgets/styles/qstyle.h @@ -0,0 +1,889 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLE_H +#define QSTYLE_H + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QAction; +class QDebug; +class QTab; +class QFontMetrics; +class QStyleHintReturn; +class QStyleOption; +class QStyleOptionComplex; +class QStylePrivate; + +class Q_GUI_EXPORT QStyle : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QStyle) + +protected: + QStyle(QStylePrivate &dd); + +public: + QStyle(); + virtual ~QStyle(); + + virtual void polish(QWidget *); + virtual void unpolish(QWidget *); + + virtual void polish(QApplication *); + virtual void unpolish(QApplication *); + + virtual void polish(QPalette &); + + virtual QRect itemTextRect(const QFontMetrics &fm, const QRect &r, + int flags, bool enabled, + const QString &text) const; + + virtual QRect itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const; + + virtual void drawItemText(QPainter *painter, const QRect &rect, + int flags, const QPalette &pal, bool enabled, + const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const; + + virtual void drawItemPixmap(QPainter *painter, const QRect &rect, + int alignment, const QPixmap &pixmap) const; + + virtual QPalette standardPalette() const; + + enum StateFlag { + State_None = 0x00000000, +#ifdef QT3_SUPPORT + State_Default = State_None, +#endif + State_Enabled = 0x00000001, + State_Raised = 0x00000002, + State_Sunken = 0x00000004, + State_Off = 0x00000008, + State_NoChange = 0x00000010, + State_On = 0x00000020, + State_DownArrow = 0x00000040, + State_Horizontal = 0x00000080, + State_HasFocus = 0x00000100, + State_Top = 0x00000200, + State_Bottom = 0x00000400, + State_FocusAtBorder = 0x00000800, + State_AutoRaise = 0x00001000, + State_MouseOver = 0x00002000, + State_UpArrow = 0x00004000, + State_Selected = 0x00008000, + State_Active = 0x00010000, + State_Window = 0x00020000, + State_Open = 0x00040000, + State_Children = 0x00080000, + State_Item = 0x00100000, + State_Sibling = 0x00200000, + State_Editing = 0x00400000, + State_KeyboardFocusChange = 0x00800000, +#ifdef QT_KEYPAD_NAVIGATION + State_HasEditFocus = 0x01000000, +#endif + State_ReadOnly = 0x02000000, + State_Small = 0x04000000, + State_Mini = 0x08000000 + }; + Q_DECLARE_FLAGS(State, StateFlag) + +#ifdef QT3_SUPPORT + typedef State SFlags; +#endif + + enum PrimitiveElement { + PE_Q3CheckListController, + PE_Q3CheckListExclusiveIndicator, + PE_Q3CheckListIndicator, + PE_Q3DockWindowSeparator, + PE_Q3Separator, + + PE_Frame, + PE_FrameDefaultButton, + PE_FrameDockWidget, + PE_FrameFocusRect, + PE_FrameGroupBox, + PE_FrameLineEdit, + PE_FrameMenu, + PE_FrameStatusBar, // obsolete + PE_FrameStatusBarItem = PE_FrameStatusBar, + PE_FrameTabWidget, + PE_FrameWindow, + PE_FrameButtonBevel, + PE_FrameButtonTool, + PE_FrameTabBarBase, + + PE_PanelButtonCommand, + PE_PanelButtonBevel, + PE_PanelButtonTool, + PE_PanelMenuBar, + PE_PanelToolBar, + PE_PanelLineEdit, + + PE_IndicatorArrowDown, + PE_IndicatorArrowLeft, + PE_IndicatorArrowRight, + PE_IndicatorArrowUp, + PE_IndicatorBranch, + PE_IndicatorButtonDropDown, + PE_IndicatorViewItemCheck, + PE_IndicatorItemViewItemCheck = PE_IndicatorViewItemCheck, + PE_IndicatorCheckBox, + PE_IndicatorDockWidgetResizeHandle, + PE_IndicatorHeaderArrow, + PE_IndicatorMenuCheckMark, + PE_IndicatorProgressChunk, + PE_IndicatorRadioButton, + PE_IndicatorSpinDown, + PE_IndicatorSpinMinus, + PE_IndicatorSpinPlus, + PE_IndicatorSpinUp, + PE_IndicatorToolBarHandle, + PE_IndicatorToolBarSeparator, + PE_PanelTipLabel, + PE_IndicatorTabTear, + PE_PanelScrollAreaCorner, + + PE_Widget, + + PE_IndicatorColumnViewArrow, + PE_IndicatorItemViewItemDrop, + + PE_PanelItemViewItem, + PE_PanelItemViewRow, // ### Qt 5: remove + + PE_PanelStatusBar, + + PE_IndicatorTabClose, + PE_PanelMenu, + + // do not add any values below/greater this + PE_CustomBase = 0xf000000 + }; + + virtual void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const = 0; + enum ControlElement { + CE_PushButton, + CE_PushButtonBevel, + CE_PushButtonLabel, + + CE_CheckBox, + CE_CheckBoxLabel, + + CE_RadioButton, + CE_RadioButtonLabel, + + CE_TabBarTab, + CE_TabBarTabShape, + CE_TabBarTabLabel, + + CE_ProgressBar, + CE_ProgressBarGroove, + CE_ProgressBarContents, + CE_ProgressBarLabel, + + CE_MenuItem, + CE_MenuScroller, + CE_MenuVMargin, + CE_MenuHMargin, + CE_MenuTearoff, + CE_MenuEmptyArea, + + CE_MenuBarItem, + CE_MenuBarEmptyArea, + + CE_ToolButtonLabel, + + CE_Header, + CE_HeaderSection, + CE_HeaderLabel, + + CE_Q3DockWindowEmptyArea, + CE_ToolBoxTab, + CE_SizeGrip, + CE_Splitter, + CE_RubberBand, + CE_DockWidgetTitle, + + CE_ScrollBarAddLine, + CE_ScrollBarSubLine, + CE_ScrollBarAddPage, + CE_ScrollBarSubPage, + CE_ScrollBarSlider, + CE_ScrollBarFirst, + CE_ScrollBarLast, + + CE_FocusFrame, + CE_ComboBoxLabel, + + CE_ToolBar, + CE_ToolBoxTabShape, + CE_ToolBoxTabLabel, + CE_HeaderEmptyArea, + + CE_ColumnViewGrip, + + CE_ItemViewItem, + + CE_ShapedFrame, + + // do not add any values below/greater than this + CE_CustomBase = 0xf0000000 + }; + + virtual void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const = 0; + + enum SubElement { + SE_PushButtonContents, + SE_PushButtonFocusRect, + + SE_CheckBoxIndicator, + SE_CheckBoxContents, + SE_CheckBoxFocusRect, + SE_CheckBoxClickRect, + + SE_RadioButtonIndicator, + SE_RadioButtonContents, + SE_RadioButtonFocusRect, + SE_RadioButtonClickRect, + + SE_ComboBoxFocusRect, + + SE_SliderFocusRect, + + SE_Q3DockWindowHandleRect, + + SE_ProgressBarGroove, + SE_ProgressBarContents, + SE_ProgressBarLabel, + + // ### Qt 5: These values are unused; eliminate them + SE_DialogButtonAccept, + SE_DialogButtonReject, + SE_DialogButtonApply, + SE_DialogButtonHelp, + SE_DialogButtonAll, + SE_DialogButtonAbort, + SE_DialogButtonIgnore, + SE_DialogButtonRetry, + SE_DialogButtonCustom, + + SE_ToolBoxTabContents, + + SE_HeaderLabel, + SE_HeaderArrow, + + SE_TabWidgetTabBar, + SE_TabWidgetTabPane, + SE_TabWidgetTabContents, + SE_TabWidgetLeftCorner, + SE_TabWidgetRightCorner, + + SE_ViewItemCheckIndicator, + SE_ItemViewItemCheckIndicator = SE_ViewItemCheckIndicator, + + SE_TabBarTearIndicator, + + SE_TreeViewDisclosureItem, + + SE_LineEditContents, + SE_FrameContents, + + SE_DockWidgetCloseButton, + SE_DockWidgetFloatButton, + SE_DockWidgetTitleBarText, + SE_DockWidgetIcon, + + SE_CheckBoxLayoutItem, + SE_ComboBoxLayoutItem, + SE_DateTimeEditLayoutItem, + SE_DialogButtonBoxLayoutItem, // ### remove + SE_LabelLayoutItem, + SE_ProgressBarLayoutItem, + SE_PushButtonLayoutItem, + SE_RadioButtonLayoutItem, + SE_SliderLayoutItem, + SE_SpinBoxLayoutItem, + SE_ToolButtonLayoutItem, + + SE_FrameLayoutItem, + SE_GroupBoxLayoutItem, + SE_TabWidgetLayoutItem, + + SE_ItemViewItemDecoration, + SE_ItemViewItemText, + SE_ItemViewItemFocusRect, + + SE_TabBarTabLeftButton, + SE_TabBarTabRightButton, + SE_TabBarTabText, + + SE_ShapedFrameContents, + + SE_ToolBarHandle, + + // do not add any values below/greater than this + SE_CustomBase = 0xf0000000 + }; + + virtual QRect subElementRect(SubElement subElement, const QStyleOption *option, + const QWidget *widget = 0) const = 0; + + + enum ComplexControl { + CC_SpinBox, + CC_ComboBox, + CC_ScrollBar, + CC_Slider, + CC_ToolButton, + CC_TitleBar, + CC_Q3ListView, + CC_Dial, + CC_GroupBox, + CC_MdiControls, + + // do not add any values below/greater than this + CC_CustomBase = 0xf0000000 + }; + + enum SubControl { + SC_None = 0x00000000, + + SC_ScrollBarAddLine = 0x00000001, + SC_ScrollBarSubLine = 0x00000002, + SC_ScrollBarAddPage = 0x00000004, + SC_ScrollBarSubPage = 0x00000008, + SC_ScrollBarFirst = 0x00000010, + SC_ScrollBarLast = 0x00000020, + SC_ScrollBarSlider = 0x00000040, + SC_ScrollBarGroove = 0x00000080, + + SC_SpinBoxUp = 0x00000001, + SC_SpinBoxDown = 0x00000002, + SC_SpinBoxFrame = 0x00000004, + SC_SpinBoxEditField = 0x00000008, + + SC_ComboBoxFrame = 0x00000001, + SC_ComboBoxEditField = 0x00000002, + SC_ComboBoxArrow = 0x00000004, + SC_ComboBoxListBoxPopup = 0x00000008, + + SC_SliderGroove = 0x00000001, + SC_SliderHandle = 0x00000002, + SC_SliderTickmarks = 0x00000004, + + SC_ToolButton = 0x00000001, + SC_ToolButtonMenu = 0x00000002, + + SC_TitleBarSysMenu = 0x00000001, + SC_TitleBarMinButton = 0x00000002, + SC_TitleBarMaxButton = 0x00000004, + SC_TitleBarCloseButton = 0x00000008, + SC_TitleBarNormalButton = 0x00000010, + SC_TitleBarShadeButton = 0x00000020, + SC_TitleBarUnshadeButton = 0x00000040, + SC_TitleBarContextHelpButton = 0x00000080, + SC_TitleBarLabel = 0x00000100, + + SC_Q3ListView = 0x00000001, + SC_Q3ListViewBranch = 0x00000002, + SC_Q3ListViewExpand = 0x00000004, + + SC_DialGroove = 0x00000001, + SC_DialHandle = 0x00000002, + SC_DialTickmarks = 0x00000004, + + SC_GroupBoxCheckBox = 0x00000001, + SC_GroupBoxLabel = 0x00000002, + SC_GroupBoxContents = 0x00000004, + SC_GroupBoxFrame = 0x00000008, + + SC_MdiMinButton = 0x00000001, + SC_MdiNormalButton = 0x00000002, + SC_MdiCloseButton = 0x00000004, + + SC_CustomBase = 0xf0000000, + SC_All = 0xffffffff + }; + Q_DECLARE_FLAGS(SubControls, SubControl) + +#ifdef QT3_SUPPORT + typedef SubControls SCFlags; +#endif + + virtual void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, + const QWidget *widget = 0) const = 0; + virtual SubControl hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *widget = 0) const = 0; + virtual QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, + SubControl sc, const QWidget *widget = 0) const = 0; + + enum PixelMetric { + PM_ButtonMargin, + PM_ButtonDefaultIndicator, + PM_MenuButtonIndicator, + PM_ButtonShiftHorizontal, + PM_ButtonShiftVertical, + + PM_DefaultFrameWidth, + PM_SpinBoxFrameWidth, + PM_ComboBoxFrameWidth, + + PM_MaximumDragDistance, + + PM_ScrollBarExtent, + PM_ScrollBarSliderMin, + + PM_SliderThickness, // total slider thickness + PM_SliderControlThickness, // thickness of the business part + PM_SliderLength, // total length of slider + PM_SliderTickmarkOffset, // + PM_SliderSpaceAvailable, // available space for slider to move + + PM_DockWidgetSeparatorExtent, + PM_DockWidgetHandleExtent, + PM_DockWidgetFrameWidth, + + PM_TabBarTabOverlap, + PM_TabBarTabHSpace, + PM_TabBarTabVSpace, + PM_TabBarBaseHeight, + PM_TabBarBaseOverlap, + + PM_ProgressBarChunkWidth, + + PM_SplitterWidth, + PM_TitleBarHeight, + + PM_MenuScrollerHeight, + PM_MenuHMargin, + PM_MenuVMargin, + PM_MenuPanelWidth, + PM_MenuTearoffHeight, + PM_MenuDesktopFrameWidth, + + PM_MenuBarPanelWidth, + PM_MenuBarItemSpacing, + PM_MenuBarVMargin, + PM_MenuBarHMargin, + + PM_IndicatorWidth, + PM_IndicatorHeight, + PM_ExclusiveIndicatorWidth, + PM_ExclusiveIndicatorHeight, + PM_CheckListButtonSize, + PM_CheckListControllerSize, + + PM_DialogButtonsSeparator, + PM_DialogButtonsButtonWidth, + PM_DialogButtonsButtonHeight, + + PM_MdiSubWindowFrameWidth, + PM_MDIFrameWidth = PM_MdiSubWindowFrameWidth, //obsolete + PM_MdiSubWindowMinimizedWidth, + PM_MDIMinimizedWidth = PM_MdiSubWindowMinimizedWidth, //obsolete + + PM_HeaderMargin, + PM_HeaderMarkSize, + PM_HeaderGripMargin, + PM_TabBarTabShiftHorizontal, + PM_TabBarTabShiftVertical, + PM_TabBarScrollButtonWidth, + + PM_ToolBarFrameWidth, + PM_ToolBarHandleExtent, + PM_ToolBarItemSpacing, + PM_ToolBarItemMargin, + PM_ToolBarSeparatorExtent, + PM_ToolBarExtensionExtent, + + PM_SpinBoxSliderHeight, + + PM_DefaultTopLevelMargin, + PM_DefaultChildMargin, + PM_DefaultLayoutSpacing, + + PM_ToolBarIconSize, + PM_ListViewIconSize, + PM_IconViewIconSize, + PM_SmallIconSize, + PM_LargeIconSize, + + PM_FocusFrameVMargin, + PM_FocusFrameHMargin, + + PM_ToolTipLabelFrameWidth, + PM_CheckBoxLabelSpacing, + PM_TabBarIconSize, + PM_SizeGripSize, + PM_DockWidgetTitleMargin, + PM_MessageBoxIconSize, + PM_ButtonIconSize, + + PM_DockWidgetTitleBarButtonMargin, + + PM_RadioButtonLabelSpacing, + PM_LayoutLeftMargin, + PM_LayoutTopMargin, + PM_LayoutRightMargin, + PM_LayoutBottomMargin, + PM_LayoutHorizontalSpacing, + PM_LayoutVerticalSpacing, + PM_TabBar_ScrollButtonOverlap, + + PM_TextCursorWidth, + + PM_TabCloseIndicatorWidth, + PM_TabCloseIndicatorHeight, + + PM_ScrollView_ScrollBarSpacing, + PM_SubMenuOverlap, + + // do not add any values below/greater than this + PM_CustomBase = 0xf0000000 + }; + + virtual int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, + const QWidget *widget = 0) const = 0; + + enum ContentsType { + CT_PushButton, + CT_CheckBox, + CT_RadioButton, + CT_ToolButton, + CT_ComboBox, + CT_Splitter, + CT_Q3DockWindow, + CT_ProgressBar, + CT_MenuItem, + CT_MenuBarItem, + CT_MenuBar, + CT_Menu, + CT_TabBarTab, + CT_Slider, + CT_ScrollBar, + CT_Q3Header, + CT_LineEdit, + CT_SpinBox, + CT_SizeGrip, + CT_TabWidget, + CT_DialogButtons, + CT_HeaderSection, + CT_GroupBox, + CT_MdiControls, + CT_ItemViewItem, + // do not add any values below/greater than this + CT_CustomBase = 0xf0000000 + }; + + virtual QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, + const QSize &contentsSize, const QWidget *w = 0) const = 0; + + enum RequestSoftwareInputPanel { + RSIP_OnMouseClickAndAlreadyFocused, + RSIP_OnMouseClick + }; + + enum StyleHint { + SH_EtchDisabledText, + SH_DitherDisabledText, + SH_ScrollBar_MiddleClickAbsolutePosition, + SH_ScrollBar_ScrollWhenPointerLeavesControl, + SH_TabBar_SelectMouseType, + SH_TabBar_Alignment, + SH_Header_ArrowAlignment, + SH_Slider_SnapToValue, + SH_Slider_SloppyKeyEvents, + SH_ProgressDialog_CenterCancelButton, + SH_ProgressDialog_TextLabelAlignment, + SH_PrintDialog_RightAlignButtons, + SH_MainWindow_SpaceBelowMenuBar, + SH_FontDialog_SelectAssociatedText, + SH_Menu_AllowActiveAndDisabled, + SH_Menu_SpaceActivatesItem, + SH_Menu_SubMenuPopupDelay, + SH_ScrollView_FrameOnlyAroundContents, + SH_MenuBar_AltKeyNavigation, + SH_ComboBox_ListMouseTracking, + SH_Menu_MouseTracking, + SH_MenuBar_MouseTracking, + SH_ItemView_ChangeHighlightOnFocus, + SH_Widget_ShareActivation, + SH_Workspace_FillSpaceOnMaximize, + SH_ComboBox_Popup, + SH_TitleBar_NoBorder, + SH_Slider_StopMouseOverSlider, + SH_ScrollBar_StopMouseOverSlider = SH_Slider_StopMouseOverSlider, // obsolete + SH_BlinkCursorWhenTextSelected, + SH_RichText_FullWidthSelection, + SH_Menu_Scrollable, + SH_GroupBox_TextLabelVerticalAlignment, + SH_GroupBox_TextLabelColor, + SH_Menu_SloppySubMenus, + SH_Table_GridLineColor, + SH_LineEdit_PasswordCharacter, + SH_DialogButtons_DefaultButton, + SH_ToolBox_SelectedPageTitleBold, + SH_TabBar_PreferNoArrows, + SH_ScrollBar_LeftClickAbsolutePosition, + SH_Q3ListViewExpand_SelectMouseType, + SH_UnderlineShortcut, + SH_SpinBox_AnimateButton, + SH_SpinBox_KeyPressAutoRepeatRate, + SH_SpinBox_ClickAutoRepeatRate, + SH_Menu_FillScreenWithScroll, + SH_ToolTipLabel_Opacity, + SH_DrawMenuBarSeparator, + SH_TitleBar_ModifyNotification, + SH_Button_FocusPolicy, + SH_MenuBar_DismissOnSecondClick, + SH_MessageBox_UseBorderForButtonSpacing, + SH_TitleBar_AutoRaise, + SH_ToolButton_PopupDelay, + SH_FocusFrame_Mask, + SH_RubberBand_Mask, + SH_WindowFrame_Mask, + SH_SpinControls_DisableOnBounds, + SH_Dial_BackgroundRole, + SH_ComboBox_LayoutDirection, + SH_ItemView_EllipsisLocation, + SH_ItemView_ShowDecorationSelected, + SH_ItemView_ActivateItemOnSingleClick, + SH_ScrollBar_ContextMenu, + SH_ScrollBar_RollBetweenButtons, + SH_Slider_AbsoluteSetButtons, + SH_Slider_PageSetButtons, + SH_Menu_KeyboardSearch, + SH_TabBar_ElideMode, + SH_DialogButtonLayout, + SH_ComboBox_PopupFrameStyle, + SH_MessageBox_TextInteractionFlags, + SH_DialogButtonBox_ButtonsHaveIcons, + SH_SpellCheckUnderlineStyle, + SH_MessageBox_CenterButtons, + SH_Menu_SelectionWrap, + SH_ItemView_MovementWithoutUpdatingSelection, + SH_ToolTip_Mask, + SH_FocusFrame_AboveWidget, + SH_TextControl_FocusIndicatorTextCharFormat, + SH_WizardStyle, + SH_ItemView_ArrowKeysNavigateIntoChildren, + SH_Menu_Mask, + SH_Menu_FlashTriggeredItem, + SH_Menu_FadeOutOnHide, + SH_SpinBox_ClickAutoRepeatThreshold, + SH_ItemView_PaintAlternatingRowColorsForEmptyArea, + SH_FormLayoutWrapPolicy, + SH_TabWidget_DefaultTabPosition, + SH_ToolBar_Movable, + SH_FormLayoutFieldGrowthPolicy, + SH_FormLayoutFormAlignment, + SH_FormLayoutLabelAlignment, + SH_ItemView_DrawDelegateFrame, + SH_TabBar_CloseButtonPosition, + SH_DockWidget_ButtonsHaveFrame, + SH_ToolButtonStyle, + SH_RequestSoftwareInputPanel, + // Add new style hint values here + +#ifdef QT3_SUPPORT + SH_GUIStyle = 0x00000100, + SH_ScrollBar_BackgroundMode, + // Add other compat values here + + SH_UnderlineAccelerator = SH_UnderlineShortcut, +#endif + SH_CustomBase = 0xf0000000 + }; + + virtual int styleHint(StyleHint stylehint, const QStyleOption *opt = 0, + const QWidget *widget = 0, QStyleHintReturn* returnData = 0) const = 0; + + enum StandardPixmap { + SP_TitleBarMenuButton, + SP_TitleBarMinButton, + SP_TitleBarMaxButton, + SP_TitleBarCloseButton, + SP_TitleBarNormalButton, + SP_TitleBarShadeButton, + SP_TitleBarUnshadeButton, + SP_TitleBarContextHelpButton, + SP_DockWidgetCloseButton, + SP_MessageBoxInformation, + SP_MessageBoxWarning, + SP_MessageBoxCritical, + SP_MessageBoxQuestion, + SP_DesktopIcon, + SP_TrashIcon, + SP_ComputerIcon, + SP_DriveFDIcon, + SP_DriveHDIcon, + SP_DriveCDIcon, + SP_DriveDVDIcon, + SP_DriveNetIcon, + SP_DirOpenIcon, + SP_DirClosedIcon, + SP_DirLinkIcon, + SP_FileIcon, + SP_FileLinkIcon, + SP_ToolBarHorizontalExtensionButton, + SP_ToolBarVerticalExtensionButton, + SP_FileDialogStart, + SP_FileDialogEnd, + SP_FileDialogToParent, + SP_FileDialogNewFolder, + SP_FileDialogDetailedView, + SP_FileDialogInfoView, + SP_FileDialogContentsView, + SP_FileDialogListView, + SP_FileDialogBack, + SP_DirIcon, + SP_DialogOkButton, + SP_DialogCancelButton, + SP_DialogHelpButton, + SP_DialogOpenButton, + SP_DialogSaveButton, + SP_DialogCloseButton, + SP_DialogApplyButton, + SP_DialogResetButton, + SP_DialogDiscardButton, + SP_DialogYesButton, + SP_DialogNoButton, + SP_ArrowUp, + SP_ArrowDown, + SP_ArrowLeft, + SP_ArrowRight, + SP_ArrowBack, + SP_ArrowForward, + SP_DirHomeIcon, + SP_CommandLink, + SP_VistaShield, + SP_BrowserReload, + SP_BrowserStop, + SP_MediaPlay, + SP_MediaStop, + SP_MediaPause, + SP_MediaSkipForward, + SP_MediaSkipBackward, + SP_MediaSeekForward, + SP_MediaSeekBackward, + SP_MediaVolume, + SP_MediaVolumeMuted, + // do not add any values below/greater than this + SP_CustomBase = 0xf0000000 + }; + + virtual QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt = 0, + const QWidget *widget = 0) const = 0; + + QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = 0, + const QWidget *widget = 0) const; + + virtual QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *opt) const = 0; + + static QRect visualRect(Qt::LayoutDirection direction, const QRect &boundingRect, + const QRect &logicalRect); + static QPoint visualPos(Qt::LayoutDirection direction, const QRect &boundingRect, + const QPoint &logicalPos); + static int sliderPositionFromValue(int min, int max, int val, int space, + bool upsideDown = false); + static int sliderValueFromPosition(int min, int max, int pos, int space, + bool upsideDown = false); + static Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment); + static QRect alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment, + const QSize &size, const QRect &rectangle); + + int layoutSpacing(QSizePolicy::ControlType control1, + QSizePolicy::ControlType control2, Qt::Orientation orientation, + const QStyleOption *option = 0, const QWidget *widget = 0) const; + int combinedLayoutSpacing(QSizePolicy::ControlTypes controls1, + QSizePolicy::ControlTypes controls2, Qt::Orientation orientation, + QStyleOption *option = 0, QWidget *widget = 0) const; + + const QStyle * proxy() const; + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt = 0, + const QWidget *widget = 0) const; + int layoutSpacingImplementation(QSizePolicy::ControlType control1, + QSizePolicy::ControlType control2, + Qt::Orientation orientation, + const QStyleOption *option = 0, + const QWidget *widget = 0) const; + +private: + Q_DISABLE_COPY(QStyle) + friend class QWidget; + friend class QWidgetPrivate; + friend class QApplication; + friend class QProxyStyle; + friend class QProxyStylePrivate; + void setProxy(QStyle *style); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QStyle::State) +Q_DECLARE_OPERATORS_FOR_FLAGS(QStyle::SubControls) + +#if !defined(QT_NO_DEBUG_STREAM) +Q_GUI_EXPORT QDebug operator<<(QDebug debug, QStyle::State state); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSTYLE_H diff --git a/src/widgets/styles/qstyle.qrc b/src/widgets/styles/qstyle.qrc new file mode 100644 index 0000000000..8654e66a37 --- /dev/null +++ b/src/widgets/styles/qstyle.qrc @@ -0,0 +1,135 @@ + + +images/filelink-16.png +images/filelink-32.png +images/filelink-128.png +images/file-16.png +images/file-32.png +images/file-128.png +images/newdirectory-16.png +images/newdirectory-32.png +images/newdirectory-128.png +images/parentdir-16.png +images/parentdir-32.png +images/parentdir-128.png +images/dvd-16.png +images/dvd-32.png +images/dvd-128.png +images/cdr-16.png +images/cdr-32.png +images/cdr-128.png +images/floppy-16.png +images/floppy-32.png +images/floppy-128.png +images/harddrive-16.png +images/harddrive-32.png +images/harddrive-128.png +images/trash-16.png +images/trash-32.png +images/trash-128.png +images/networkdrive-16.png +images/networkdrive-32.png +images/networkdrive-128.png +images/computer-16.png +images/computer-32.png +images/desktop-16.png +images/desktop-32.png +images/dirclosed-16.png +images/dirclosed-32.png +images/dirclosed-128.png +images/dirlink-16.png +images/dirlink-32.png +images/dirlink-128.png +images/diropen-16.png +images/diropen-32.png +images/diropen-128.png +images/left-16.png +images/left-32.png +images/left-128.png +images/right-16.png +images/right-32.png +images/right-128.png +images/up-16.png +images/up-32.png +images/up-128.png +images/down-16.png +images/down-32.png +images/down-128.png +images/filecontents-16.png +images/filecontents-32.png +images/filecontents-128.png +images/fileinfo-16.png +images/fileinfo-32.png +images/fileinfo-128.png +images/viewdetailed-16.png +images/viewdetailed-32.png +images/viewdetailed-128.png +images/viewlist-16.png +images/viewlist-32.png +images/viewlist-128.png +images/fontbitmap-16.png +images/fonttruetype-16.png +images/standardbutton-apply-128.png +images/standardbutton-apply-16.png +images/standardbutton-apply-32.png +images/standardbutton-cancel-128.png +images/standardbutton-cancel-16.png +images/standardbutton-cancel-32.png +images/standardbutton-clear-128.png +images/standardbutton-clear-16.png +images/standardbutton-clear-32.png +images/standardbutton-close-128.png +images/standardbutton-close-16.png +images/standardbutton-close-32.png +images/standardbutton-delete-128.png +images/standardbutton-delete-16.png +images/standardbutton-delete-32.png +images/standardbutton-help-128.png +images/standardbutton-help-16.png +images/standardbutton-help-32.png +images/standardbutton-no-128.png +images/standardbutton-no-16.png +images/standardbutton-no-32.png +images/standardbutton-ok-128.png +images/standardbutton-ok-16.png +images/standardbutton-ok-32.png +images/standardbutton-open-128.png +images/standardbutton-open-16.png +images/standardbutton-open-32.png +images/standardbutton-save-128.png +images/standardbutton-save-16.png +images/standardbutton-save-32.png +images/standardbutton-yes-128.png +images/standardbutton-yes-16.png +images/standardbutton-yes-32.png +images/standardbutton-closetab-16.png +images/standardbutton-closetab-down-16.png +images/standardbutton-closetab-hover-16.png +images/refresh-24.png +images/refresh-32.png +images/stop-24.png +images/stop-32.png +images/media-stop-16.png +images/media-stop-32.png +images/media-play-16.png +images/media-play-32.png +images/media-pause-16.png +images/media-pause-32.png +images/media-seek-forward-16.png +images/media-seek-forward-32.png +images/media-seek-backward-16.png +images/media-seek-backward-32.png +images/media-skip-forward-16.png +images/media-skip-forward-32.png +images/media-skip-backward-16.png +images/media-skip-backward-32.png +images/media-volume-16.png +images/media-volume-muted-16.png + + +images/closedock-16.png +images/closedock-down-16.png +images/dockdock-16.png +images/dockdock-down-16.png + + diff --git a/src/widgets/styles/qstyle_p.h b/src/widgets/styles/qstyle_p.h new file mode 100644 index 0000000000..1fcd2eaf2a --- /dev/null +++ b/src/widgets/styles/qstyle_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLE_P_H +#define QSTYLE_P_H + +#include "private/qobject_p.h" +#include + +QT_BEGIN_NAMESPACE + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qstyle_*.cpp. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +// Private class + +class QStyle; + +class QStylePrivate: public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QStyle) +public: + inline QStylePrivate() + : layoutSpacingIndex(-1), proxyStyle(0) {} + mutable int layoutSpacingIndex; + QStyle *proxyStyle; +}; + + +#define BEGIN_STYLE_PIXMAPCACHE(a) \ + QRect rect = option->rect; \ + QPixmap internalPixmapCache; \ + QImage imageCache; \ + QPainter *p = painter; \ + QString unique = QStyleHelper::uniqueName((a), option, option->rect.size()); \ + int txType = painter->deviceTransform().type() | painter->worldTransform().type(); \ + bool doPixmapCache = txType <= QTransform::TxTranslate; \ + if (doPixmapCache && QPixmapCache::find(unique, internalPixmapCache)) { \ + painter->drawPixmap(option->rect.topLeft(), internalPixmapCache); \ + } else { \ + if (doPixmapCache) { \ + rect.setRect(0, 0, option->rect.width(), option->rect.height()); \ + imageCache = QImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); \ + imageCache.fill(0); \ + p = new QPainter(&imageCache); \ + } + + + +#define END_STYLE_PIXMAPCACHE \ + if (doPixmapCache) { \ + p->end(); \ + delete p; \ + internalPixmapCache = QPixmap::fromImage(imageCache); \ + painter->drawPixmap(option->rect.topLeft(), internalPixmapCache); \ + QPixmapCache::insert(unique, internalPixmapCache); \ + } \ + } + +QT_END_NAMESPACE + +#endif //QSTYLE_P_H diff --git a/src/widgets/styles/qstyle_s60.qrc b/src/widgets/styles/qstyle_s60.qrc new file mode 100644 index 0000000000..dbee38b266 --- /dev/null +++ b/src/widgets/styles/qstyle_s60.qrc @@ -0,0 +1,137 @@ + + + +images/filelink-32.png + + +images/file-32.png + + +images/newdirectory-32.png + + +images/parentdir-32.png + + + + + + + + + + + +images/harddrive-32.png + + + + + + + + + + +images/desktop-32.png + +images/dirclosed-32.png + + +images/dirlink-32.png + + +images/diropen-32.png + + +images/left-32.png + + +images/right-32.png + + +images/up-32.png + + +images/down-32.png + + +images/filecontents-32.png + + +images/fileinfo-32.png + + +images/viewdetailed-32.png + + +images/viewlist-32.png + +images/fontbitmap-16.png +images/fonttruetype-16.png + + +images/standardbutton-apply-32.png + + +images/standardbutton-cancel-32.png + + +images/standardbutton-clear-32.png + + +images/standardbutton-close-32.png + + +images/standardbutton-delete-32.png + + +images/standardbutton-help-32.png + + +images/standardbutton-no-32.png + + +images/standardbutton-ok-32.png + + +images/standardbutton-open-32.png + + +images/standardbutton-save-32.png + + +images/standardbutton-yes-32.png +images/standardbutton-closetab-16.png +images/standardbutton-closetab-down-16.png +images/standardbutton-closetab-hover-16.png + +images/refresh-32.png + +images/stop-32.png + +images/media-stop-32.png + +images/media-play-32.png + +images/media-pause-32.png + +images/media-seek-forward-32.png + +images/media-seek-backward-32.png + +images/media-skip-forward-32.png + +images/media-skip-backward-32.png +images/media-volume-16.png +images/media-volume-muted-16.png + + + diff --git a/src/widgets/styles/qstyle_s60_simulated.qrc b/src/widgets/styles/qstyle_s60_simulated.qrc new file mode 100644 index 0000000000..969732e1e0 --- /dev/null +++ b/src/widgets/styles/qstyle_s60_simulated.qrc @@ -0,0 +1,6 @@ + + + + images/defaults60theme.blob + + diff --git a/src/widgets/styles/qstyle_wince.qrc b/src/widgets/styles/qstyle_wince.qrc new file mode 100644 index 0000000000..bdcf604625 --- /dev/null +++ b/src/widgets/styles/qstyle_wince.qrc @@ -0,0 +1,97 @@ + + +images/filelink-16.png +images/filelink-32.png +images/file-16.png +images/file-32.png +images/newdirectory-16.png +images/newdirectory-32.png +images/parentdir-16.png +images/parentdir-32.png +images/dvd-16.png +images/dvd-32.png +images/cdr-16.png +images/cdr-32.png +images/floppy-16.png +images/floppy-32.png +images/harddrive-16.png +images/harddrive-32.png +images/trash-16.png +images/trash-32.png +images/networkdrive-16.png +images/networkdrive-32.png +images/computer-16.png +images/computer-32.png +images/desktop-16.png +images/desktop-32.png +images/dirclosed-16.png +images/dirclosed-32.png +images/dirlink-16.png +images/dirlink-32.png +images/diropen-16.png +images/diropen-32.png +images/left-16.png +images/left-32.png +images/right-16.png +images/right-32.png +images/up-16.png +images/up-32.png +images/down-16.png +images/down-32.png +images/filecontents-16.png +images/filecontents-32.png +images/fileinfo-16.png +images/fileinfo-32.png +images/viewdetailed-16.png +images/viewdetailed-32.png +images/viewlist-16.png +images/viewlist-32.png +images/fontbitmap-16.png +images/fonttruetype-16.png +images/standardbutton-apply-16.png +images/standardbutton-apply-32.png +images/standardbutton-cancel-16.png +images/standardbutton-cancel-32.png +images/standardbutton-clear-16.png +images/standardbutton-clear-32.png +images/standardbutton-close-16.png +images/standardbutton-close-32.png +images/standardbutton-delete-16.png +images/standardbutton-delete-32.png +images/standardbutton-help-16.png +images/standardbutton-help-32.png +images/standardbutton-no-16.png +images/standardbutton-no-32.png +images/standardbutton-ok-16.png +images/standardbutton-ok-32.png +images/standardbutton-open-16.png +images/standardbutton-open-32.png +images/standardbutton-save-16.png +images/standardbutton-save-32.png +images/standardbutton-yes-16.png +images/standardbutton-yes-32.png +images/standardbutton-closetab-16.png +images/standardbutton-closetab-down-16.png +images/standardbutton-closetab-hover-16.png +images/refresh-24.png +images/refresh-32.png +images/stop-24.png +images/stop-32.png +images/media-stop-16.png +images/media-stop-32.png +images/media-play-16.png +images/media-play-32.png +images/media-pause-16.png +images/media-pause-32.png +images/media-seek-forward-16.png +images/media-seek-forward-32.png +images/media-seek-backward-16.png +images/media-seek-backward-32.png +images/media-skip-forward-16.png +images/media-skip-forward-32.png +images/media-skip-backward-16.png +images/media-skip-backward-32.png +images/media-volume-16.png +images/media-volume-muted-16.png + + diff --git a/src/widgets/styles/qstylefactory.cpp b/src/widgets/styles/qstylefactory.cpp new file mode 100644 index 0000000000..1a9682a831 --- /dev/null +++ b/src/widgets/styles/qstylefactory.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstylefactory.h" +#include "qstyleplugin.h" +#include "private/qfactoryloader_p.h" +#include "qmutex.h" + +#include "qapplication.h" +#include "qwindowsstyle.h" +#include "qmotifstyle.h" +#include "qcdestyle.h" +#ifndef QT_NO_STYLE_PLASTIQUE +#include "qplastiquestyle.h" +#endif +#ifndef QT_NO_STYLE_CLEANLOOKS +#include "qcleanlooksstyle.h" +#endif +#ifndef QT_NO_STYLE_GTK +#include "qgtkstyle.h" +#endif +#ifndef QT_NO_STYLE_WINDOWSXP +#include "qwindowsxpstyle.h" +#endif +#ifndef QT_NO_STYLE_WINDOWSVISTA +#include "qwindowsvistastyle.h" +#endif +#ifndef QT_NO_STYLE_WINDOWSCE +#include "qwindowscestyle.h" +#endif +#ifndef QT_NO_STYLE_WINDOWSMOBILE +#include "qwindowsmobilestyle.h" +#endif +#ifndef QT_NO_STYLE_S60 +#include "qs60style.h" +#endif + +QT_BEGIN_NAMESPACE + +#if !defined(QT_NO_STYLE_MAC) && defined(Q_WS_MAC) +QT_BEGIN_INCLUDE_NAMESPACE +# include "qmacstyle_mac.h" +QT_END_INCLUDE_NAMESPACE +#endif + +#ifndef QT_NO_LIBRARY +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QStyleFactoryInterface_iid, QLatin1String("/styles"), Qt::CaseInsensitive)) +#endif + +/*! + \class QStyleFactory + \brief The QStyleFactory class creates QStyle objects. + + \ingroup appearance + + The QStyle class is an abstract base class that encapsulates the + look and feel of a GUI. QStyleFactory creates a QStyle object + using the create() function and a key identifying the style. The + styles are either built-in or dynamically loaded from a style + plugin (see QStylePlugin). + + The valid keys can be retrieved using the keys() + function. Typically they include "windows", "motif", "cde", + "plastique" and "cleanlooks". Depending on the platform, + "windowsxp", "windowsvista" and "macintosh" may be available. + Note that keys are case insensitive. + + \sa QStyle +*/ + +/*! + Creates and returns a QStyle object that matches the given \a key, or + returns 0 if no matching style is found. + + Both built-in styles and styles from style plugins are queried for a + matching style. + + \note The keys used are case insensitive. + + \sa keys() +*/ +QStyle *QStyleFactory::create(const QString& key) +{ + QStyle *ret = 0; + QString style = key.toLower(); +#ifndef QT_NO_STYLE_WINDOWS + if (style == QLatin1String("windows")) + ret = new QWindowsStyle; + else +#endif +#ifndef QT_NO_STYLE_WINDOWSCE + if (style == QLatin1String("windowsce")) + ret = new QWindowsCEStyle; + else +#endif +#ifndef QT_NO_STYLE_WINDOWSMOBILE + if (style == QLatin1String("windowsmobile")) + ret = new QWindowsMobileStyle; + else +#endif +#ifndef QT_NO_STYLE_WINDOWSXP + if (style == QLatin1String("windowsxp")) + ret = new QWindowsXPStyle; + else +#endif +#ifndef QT_NO_STYLE_WINDOWSVISTA + if (style == QLatin1String("windowsvista")) + ret = new QWindowsVistaStyle; + else +#endif +#ifndef QT_NO_STYLE_MOTIF + if (style == QLatin1String("motif")) + ret = new QMotifStyle; + else +#endif +#ifndef QT_NO_STYLE_CDE + if (style == QLatin1String("cde")) + ret = new QCDEStyle; + else +#endif +#ifndef QT_NO_STYLE_S60 + if (style == QLatin1String("s60")) + ret = new QS60Style; + else +#endif +#ifndef QT_NO_STYLE_PLASTIQUE + if (style == QLatin1String("plastique")) + ret = new QPlastiqueStyle; + else +#endif +#ifndef QT_NO_STYLE_CLEANLOOKS + if (style == QLatin1String("cleanlooks")) + ret = new QCleanlooksStyle; + else +#endif +#ifndef QT_NO_STYLE_GTK + if (style == QLatin1String("gtk") || style == QLatin1String("gtk+")) + ret = new QGtkStyle; + else +#endif +#ifndef QT_NO_STYLE_MAC + if (style.startsWith(QLatin1String("macintosh"))) { + ret = new QMacStyle; +# ifdef Q_WS_MAC + if (style == QLatin1String("macintosh")) + style += QLatin1String(" (aqua)"); +# endif + } else +#endif + { } // Keep these here - they make the #ifdefery above work +#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) + if(!ret) { + if (QStyleFactoryInterface *factory = qobject_cast(loader()->instance(style))) + ret = factory->create(style); + } +#endif + if(ret) + ret->setObjectName(style); + return ret; +} + +/*! + Returns the list of valid keys, i.e. the keys this factory can + create styles for. + + \sa create() +*/ +QStringList QStyleFactory::keys() +{ +#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) + QStringList list = loader()->keys(); +#else + QStringList list; +#endif +#ifndef QT_NO_STYLE_WINDOWS + if (!list.contains(QLatin1String("Windows"))) + list << QLatin1String("Windows"); +#endif +#ifndef QT_NO_STYLE_WINDOWSCE + if (!list.contains(QLatin1String("WindowsCE"))) + list << QLatin1String("WindowsCE"); +#endif +#ifndef QT_NO_STYLE_WINDOWSMOBILE + if (!list.contains(QLatin1String("WindowsMobile"))) + list << QLatin1String("WindowsMobile"); +#endif +#ifndef QT_NO_STYLE_WINDOWSXP + if (!list.contains(QLatin1String("WindowsXP")) && + (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) + list << QLatin1String("WindowsXP"); +#endif +#ifndef QT_NO_STYLE_WINDOWSVISTA + if (!list.contains(QLatin1String("WindowsVista")) && + (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) + list << QLatin1String("WindowsVista"); +#endif +#ifndef QT_NO_STYLE_MOTIF + if (!list.contains(QLatin1String("Motif"))) + list << QLatin1String("Motif"); +#endif +#ifndef QT_NO_STYLE_CDE + if (!list.contains(QLatin1String("CDE"))) + list << QLatin1String("CDE"); +#endif +#ifndef QT_NO_STYLE_S60 + if (!list.contains(QLatin1String("S60"))) + list << QLatin1String("S60"); +#endif +#ifndef QT_NO_STYLE_PLASTIQUE + if (!list.contains(QLatin1String("Plastique"))) + list << QLatin1String("Plastique"); +#endif +#ifndef QT_NO_STYLE_GTK + if (!list.contains(QLatin1String("GTK+"))) + list << QLatin1String("GTK+"); +#endif +#ifndef QT_NO_STYLE_CLEANLOOKS + if (!list.contains(QLatin1String("Cleanlooks"))) + list << QLatin1String("Cleanlooks"); +#endif +#ifndef QT_NO_STYLE_MAC + QString mstyle = QLatin1String("Macintosh"); +# ifdef Q_WS_MAC + mstyle += QLatin1String(" (aqua)"); +# endif + if (!list.contains(mstyle)) + list << mstyle; +#endif + return list; +} + +QT_END_NAMESPACE diff --git a/src/widgets/styles/qstylefactory.h b/src/widgets/styles/qstylefactory.h new file mode 100644 index 0000000000..b665e5fce4 --- /dev/null +++ b/src/widgets/styles/qstylefactory.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLEFACTORY_H +#define QSTYLEFACTORY_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QStyle; + +class Q_GUI_EXPORT QStyleFactory +{ +public: + static QStringList keys(); + static QStyle *create(const QString&); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSTYLEFACTORY_H diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp new file mode 100644 index 0000000000..59766cae0f --- /dev/null +++ b/src/widgets/styles/qstylehelper.cpp @@ -0,0 +1,378 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#if defined(Q_WS_WIN) +#include "qt_windows.h" +#elif defined(Q_WS_MAC) +#include +#endif + +#include "qstylehelper_p.h" +#include + +QT_BEGIN_NAMESPACE + +namespace QStyleHelper { + +QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size) +{ + const QStyleOptionComplex *complexOption = qstyleoption_cast(option); + QString tmp = key % HexString(option->state) + % HexString(option->direction) + % HexString(complexOption ? uint(complexOption->activeSubControls) : 0u) + % HexString(option->palette.cacheKey()) + % HexString(size.width()) + % HexString(size.height()); + +#ifndef QT_NO_SPINBOX + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { + tmp = tmp % HexString(spinBox->buttonSymbols) + % HexString(spinBox->stepEnabled) + % QLatin1Char(spinBox->frame ? '1' : '0'); ; + } +#endif // QT_NO_SPINBOX + return tmp; +} + +qreal dpiScaled(qreal value) +{ + static qreal scale = -1; + if (scale < 0) { + scale = 1.0; +#if defined(Q_WS_WIN) + { + HDC hdcScreen = GetDC(0); + int dpi = GetDeviceCaps(hdcScreen, LOGPIXELSX); + ReleaseDC(0, hdcScreen); + scale = dpi/96.0; + } +#elif defined(Q_WS_MAC) + scale = qt_mac_get_scalefactor(); +#endif + } + return value * scale; +} + + +#ifndef QT_NO_DIAL + +int calcBigLineSize(int radius) +{ + int bigLineSize = radius / 6; + if (bigLineSize < 4) + bigLineSize = 4; + if (bigLineSize > radius / 2) + bigLineSize = radius / 2; + return bigLineSize; +} + +static QPointF calcRadialPos(const QStyleOptionSlider *dial, qreal offset) +{ + const int width = dial->rect.width(); + const int height = dial->rect.height(); + const int r = qMin(width, height) / 2; + const int currentSliderPosition = dial->upsideDown ? dial->sliderPosition : (dial->maximum - dial->sliderPosition); + qreal a = 0; + if (dial->maximum == dial->minimum) + a = Q_PI / 2; + else if (dial->dialWrapping) + a = Q_PI * 3 / 2 - (currentSliderPosition - dial->minimum) * 2 * Q_PI + / (dial->maximum - dial->minimum); + else + a = (Q_PI * 8 - (currentSliderPosition - dial->minimum) * 10 * Q_PI + / (dial->maximum - dial->minimum)) / 6; + qreal xc = width / 2.0; + qreal yc = height / 2.0; + qreal len = r - QStyleHelper::calcBigLineSize(r) - 3; + qreal back = offset * len; + QPointF pos(QPointF(xc + back * qCos(a), yc - back * qSin(a))); + return pos; +} + +qreal angle(const QPointF &p1, const QPointF &p2) +{ + static const qreal rad_factor = 180 / Q_PI; + qreal _angle = 0; + + if (p1.x() == p2.x()) { + if (p1.y() < p2.y()) + _angle = 270; + else + _angle = 90; + } else { + qreal x1, x2, y1, y2; + + if (p1.x() <= p2.x()) { + x1 = p1.x(); y1 = p1.y(); + x2 = p2.x(); y2 = p2.y(); + } else { + x2 = p1.x(); y2 = p1.y(); + x1 = p2.x(); y1 = p2.y(); + } + + qreal m = -(y2 - y1) / (x2 - x1); + _angle = qAtan(m) * rad_factor; + + if (p1.x() < p2.x()) + _angle = 180 - _angle; + else + _angle = -_angle; + } + return _angle; +} + +QPolygonF calcLines(const QStyleOptionSlider *dial) +{ + QPolygonF poly; + int width = dial->rect.width(); + int height = dial->rect.height(); + qreal r = qMin(width, height) / 2; + int bigLineSize = calcBigLineSize(int(r)); + + qreal xc = width / 2 + 0.5; + qreal yc = height / 2 + 0.5; + int ns = dial->tickInterval; + int notches = (dial->maximum + ns - 1 - dial->minimum) / ns; + if (notches <= 0) + return poly; + if (dial->maximum < dial->minimum || dial->maximum - dial->minimum > 1000) { + int maximum = dial->minimum + 1000; + notches = (maximum + ns - 1 - dial->minimum) / ns; + } + + poly.resize(2 + 2 * notches); + int smallLineSize = bigLineSize / 2; + for (int i = 0; i <= notches; ++i) { + qreal angle = dial->dialWrapping ? Q_PI * 3 / 2 - i * 2 * Q_PI / notches + : (Q_PI * 8 - i * 10 * Q_PI / notches) / 6; + qreal s = qSin(angle); + qreal c = qCos(angle); + if (i == 0 || (((ns * i) % (dial->pageStep ? dial->pageStep : 1)) == 0)) { + poly[2 * i] = QPointF(xc + (r - bigLineSize) * c, + yc - (r - bigLineSize) * s); + poly[2 * i + 1] = QPointF(xc + r * c, yc - r * s); + } else { + poly[2 * i] = QPointF(xc + (r - 1 - smallLineSize) * c, + yc - (r - 1 - smallLineSize) * s); + poly[2 * i + 1] = QPointF(xc + (r - 1) * c, yc -(r - 1) * s); + } + } + return poly; +} + +// This will draw a nice and shiny QDial for us. We don't want +// all the shinyness in QWindowsStyle, hence we place it here + +void drawDial(const QStyleOptionSlider *option, QPainter *painter) +{ + QPalette pal = option->palette; + QColor buttonColor = pal.button().color(); + const int width = option->rect.width(); + const int height = option->rect.height(); + const bool enabled = option->state & QStyle::State_Enabled; + qreal r = qMin(width, height) / 2; + r -= r/50; + const qreal penSize = r/20.0; + + painter->save(); + painter->setRenderHint(QPainter::Antialiasing); + + // Draw notches + if (option->subControls & QStyle::SC_DialTickmarks) { + painter->setPen(option->palette.dark().color().darker(120)); + painter->drawLines(QStyleHelper::calcLines(option)); + } + + // Cache dial background + BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("qdial")); + p->setRenderHint(QPainter::Antialiasing); + + const qreal d_ = r / 6; + const qreal dx = option->rect.x() + d_ + (width - 2 * r) / 2 + 1; + const qreal dy = option->rect.y() + d_ + (height - 2 * r) / 2 + 1; + + QRectF br = QRectF(dx + 0.5, dy + 0.5, + int(r * 2 - 2 * d_ - 2), + int(r * 2 - 2 * d_ - 2)); + buttonColor.setHsv(buttonColor .hue(), + qMin(140, buttonColor .saturation()), + qMax(180, buttonColor.value())); + QColor shadowColor(0, 0, 0, 20); + + if (enabled) { + // Drop shadow + qreal shadowSize = qMax(1.0, penSize/2.0); + QRectF shadowRect= br.adjusted(-2*shadowSize, -2*shadowSize, + 2*shadowSize, 2*shadowSize); + QRadialGradient shadowGradient(shadowRect.center().x(), + shadowRect.center().y(), shadowRect.width()/2.0, + shadowRect.center().x(), shadowRect.center().y()); + shadowGradient.setColorAt(qreal(0.91), QColor(0, 0, 0, 40)); + shadowGradient.setColorAt(qreal(1.0), Qt::transparent); + p->setBrush(shadowGradient); + p->setPen(Qt::NoPen); + p->translate(shadowSize, shadowSize); + p->drawEllipse(shadowRect); + p->translate(-shadowSize, -shadowSize); + + // Main gradient + QRadialGradient gradient(br.center().x() - br.width()/3, dy, + br.width()*1.3, br.center().x(), + br.center().y() - br.height()/2); + gradient.setColorAt(0, buttonColor.lighter(110)); + gradient.setColorAt(qreal(0.5), buttonColor); + gradient.setColorAt(qreal(0.501), buttonColor.darker(102)); + gradient.setColorAt(1, buttonColor.darker(115)); + p->setBrush(gradient); + } else { + p->setBrush(Qt::NoBrush); + } + + p->setPen(QPen(buttonColor.darker(280))); + p->drawEllipse(br); + p->setBrush(Qt::NoBrush); + p->setPen(buttonColor.lighter(110)); + p->drawEllipse(br.adjusted(1, 1, -1, -1)); + + if (option->state & QStyle::State_HasFocus) { + QColor highlight = pal.highlight().color(); + highlight.setHsv(highlight.hue(), + qMin(160, highlight.saturation()), + qMax(230, highlight.value())); + highlight.setAlpha(127); + p->setPen(QPen(highlight, 2.0)); + p->setBrush(Qt::NoBrush); + p->drawEllipse(br.adjusted(-1, -1, 1, 1)); + } + + END_STYLE_PIXMAPCACHE + + QPointF dp = calcRadialPos(option, qreal(0.70)); + buttonColor = buttonColor.lighter(104); + buttonColor.setAlphaF(qreal(0.8)); + const qreal ds = r/qreal(7.0); + QRectF dialRect(dp.x() - ds, dp.y() - ds, 2*ds, 2*ds); + QRadialGradient dialGradient(dialRect.center().x() + dialRect.width()/2, + dialRect.center().y() + dialRect.width(), + dialRect.width()*2, + dialRect.center().x(), dialRect.center().y()); + dialGradient.setColorAt(1, buttonColor.darker(140)); + dialGradient.setColorAt(qreal(0.4), buttonColor.darker(120)); + dialGradient.setColorAt(0, buttonColor.darker(110)); + if (penSize > 3.0) { + painter->setPen(QPen(QColor(0, 0, 0, 25), penSize)); + painter->drawLine(calcRadialPos(option, qreal(0.90)), calcRadialPos(option, qreal(0.96))); + } + + painter->setBrush(dialGradient); + painter->setPen(QColor(255, 255, 255, 150)); + painter->drawEllipse(dialRect.adjusted(-1, -1, 1, 1)); + painter->setPen(QColor(0, 0, 0, 80)); + painter->drawEllipse(dialRect); + painter->restore(); +} +#endif //QT_NO_DIAL + +void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rect, + int left, int top, int right, + int bottom) +{ + QSize size = pixmap.size(); + //painter->setRenderHint(QPainter::SmoothPixmapTransform); + + //top + if (top > 0) { + painter->drawPixmap(QRect(rect.left() + left, rect.top(), rect.width() -right - left, top), pixmap, + QRect(left, 0, size.width() -right - left, top)); + + //top-left + if(left > 0) + painter->drawPixmap(QRect(rect.left(), rect.top(), left, top), pixmap, + QRect(0, 0, left, top)); + + //top-right + if (right > 0) + painter->drawPixmap(QRect(rect.left() + rect.width() - right, rect.top(), right, top), pixmap, + QRect(size.width() - right, 0, right, top)); + } + + //left + if (left > 0) + painter->drawPixmap(QRect(rect.left(), rect.top()+top, left, rect.height() - top - bottom), pixmap, + QRect(0, top, left, size.height() - bottom - top)); + + //center + painter->drawPixmap(QRect(rect.left() + left, rect.top()+top, rect.width() -right - left, + rect.height() - bottom - top), pixmap, + QRect(left, top, size.width() -right -left, + size.height() - bottom - top)); + //right + if (right > 0) + painter->drawPixmap(QRect(rect.left() +rect.width() - right, rect.top()+top, right, rect.height() - top - bottom), pixmap, + QRect(size.width() - right, top, right, size.height() - bottom - top)); + + //bottom + if (bottom > 0) { + painter->drawPixmap(QRect(rect.left() +left, rect.top() + rect.height() - bottom, + rect.width() - right - left, bottom), pixmap, + QRect(left, size.height() - bottom, + size.width() - right - left, bottom)); + //bottom-left + if (left > 0) + painter->drawPixmap(QRect(rect.left(), rect.top() + rect.height() - bottom, left, bottom), pixmap, + QRect(0, size.height() - bottom, left, bottom)); + + //bottom-right + if (right > 0) + painter->drawPixmap(QRect(rect.left() + rect.width() - right, rect.top() + rect.height() - bottom, right, bottom), pixmap, + QRect(size.width() - right, size.height() - bottom, right, bottom)); + + } +} +} +QT_END_NAMESPACE diff --git a/src/widgets/styles/qstylehelper_p.h b/src/widgets/styles/qstylehelper_p.h new file mode 100644 index 0000000000..6aeb71c103 --- /dev/null +++ b/src/widgets/styles/qstylehelper_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +#ifndef QSTYLEHELPER_P_H +#define QSTYLEHELPER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_NAMESPACE + +class QPainter; +class QPixmap; +class QStyleOptionSlider; +class QStyleOption; + +namespace QStyleHelper +{ + QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size); + qreal dpiScaled(qreal value); +#ifndef QT_NO_DIAL + qreal angle(const QPointF &p1, const QPointF &p2); + QPolygonF calcLines(const QStyleOptionSlider *dial); + int calcBigLineSize(int radius); + void drawDial(const QStyleOptionSlider *dial, QPainter *painter); +#endif //QT_NO_DIAL + void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rect, + int left = 0, int top = 0, int right = 0, + int bottom = 0); +} + + +QT_END_NAMESPACE + +#endif // QSTYLEHELPER_P_H diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp new file mode 100644 index 0000000000..ee8e177546 --- /dev/null +++ b/src/widgets/styles/qstyleoption.cpp @@ -0,0 +1,5508 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstyleoption.h" +#include "qapplication.h" +#ifdef Q_WS_MAC +# include "private/qt_mac_p.h" +# include "qmacstyle_mac.h" +#endif +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QStyleOption + \brief The QStyleOption class stores the parameters used by QStyle functions. + + \ingroup appearance + + QStyleOption and its subclasses contain all the information that + QStyle functions need to draw a graphical element. + + For performance reasons, there are few member functions and the + access to the member variables is direct (i.e., using the \c . or + \c -> operator). This low-level feel makes the structures + straightforward to use and emphasizes that these are simply + parameters used by the style functions. + + The caller of a QStyle function usually creates QStyleOption + objects on the stack. This combined with Qt's extensive use of + \l{implicit sharing} for types such as QString, QPalette, and + QColor ensures that no memory allocation needlessly takes place. + + The following code snippet shows how to use a specific + QStyleOption subclass to paint a push button: + + \snippet doc/src/snippets/qstyleoption/main.cpp 0 + + In our example, the control is a QStyle::CE_PushButton, and + according to the QStyle::drawControl() documentation the + corresponding class is QStyleOptionButton. + + When reimplementing QStyle functions that take a QStyleOption + parameter, you often need to cast the QStyleOption to a subclass. + For safety, you can use qstyleoption_cast() to ensure that the + pointer type is correct. For example: + + \snippet doc/src/snippets/qstyleoption/main.cpp 4 + + The qstyleoption_cast() function will return 0 if the object to + which \c option points is not of the correct type. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyle, QStylePainter +*/ + +/*! + \enum QStyleOption::OptionType + + This enum is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \value SO_Button \l QStyleOptionButton + \value SO_ComboBox \l QStyleOptionComboBox + \value SO_Complex \l QStyleOptionComplex + \value SO_Default QStyleOption + \value SO_DockWidget \l QStyleOptionDockWidget + \value SO_FocusRect \l QStyleOptionFocusRect + \value SO_Frame \l QStyleOptionFrame \l QStyleOptionFrameV2 + \value SO_GraphicsItem \l QStyleOptionGraphicsItem + \value SO_GroupBox \l QStyleOptionGroupBox + \value SO_Header \l QStyleOptionHeader + \value SO_MenuItem \l QStyleOptionMenuItem + \value SO_ProgressBar \l QStyleOptionProgressBar \l QStyleOptionProgressBarV2 + \value SO_RubberBand \l QStyleOptionRubberBand + \value SO_SizeGrip \l QStyleOptionSizeGrip + \value SO_Slider \l QStyleOptionSlider + \value SO_SpinBox \l QStyleOptionSpinBox + \value SO_Tab \l QStyleOptionTab + \value SO_TabBarBase \l QStyleOptionTabBarBase + \value SO_TabWidgetFrame \l QStyleOptionTabWidgetFrame + \value SO_TitleBar \l QStyleOptionTitleBar + \value SO_ToolBar \l QStyleOptionToolBar + \value SO_ToolBox \l QStyleOptionToolBox + \value SO_ToolButton \l QStyleOptionToolButton + \value SO_ViewItem \l QStyleOptionViewItem (used in Interviews) + + The following values are used for custom controls: + + \value SO_CustomBase Reserved for custom QStyleOptions; + all custom controls values must be above this value + \value SO_ComplexCustomBase Reserved for custom QStyleOptions; + all custom complex controls values must be above this value + + Some style options are defined for various Qt3Support controls: + + \value SO_Q3DockWindow \l QStyleOptionQ3DockWindow + \value SO_Q3ListView \l QStyleOptionQ3ListView + \value SO_Q3ListViewItem \l QStyleOptionQ3ListViewItem + + \sa type +*/ + +/*! + Constructs a QStyleOption with the specified \a version and \a + type. + + The version has no special meaning for QStyleOption; it can be + used by subclasses to distinguish between different version of + the same option type. + + The \l state member variable is initialized to + QStyle::State_None. + + \sa version, type +*/ + +QStyleOption::QStyleOption(int version, int type) + : version(version), type(type), state(QStyle::State_None), + direction(QApplication::layoutDirection()), fontMetrics(QFont()) +{ +} + + +/*! + Destroys this style option object. +*/ +QStyleOption::~QStyleOption() +{ +} + +/*! + \fn void QStyleOption::initFrom(const QWidget *widget) + \since 4.1 + + Initializes the \l state, \l direction, \l rect, \l palette, and + \l fontMetrics member variables based on the specified \a widget. + + This is a convenience function; the member variables can also be + initialized manually. + + \sa QWidget::layoutDirection(), QWidget::rect(), + QWidget::palette(), QWidget::fontMetrics() +*/ + +/*! + \obsolete + + Use initFrom(\a widget) instead. +*/ +void QStyleOption::init(const QWidget *widget) +{ + QWidget *window = widget->window(); + state = QStyle::State_None; + if (widget->isEnabled()) + state |= QStyle::State_Enabled; + if (widget->hasFocus()) + state |= QStyle::State_HasFocus; + if (window->testAttribute(Qt::WA_KeyboardFocusChange)) + state |= QStyle::State_KeyboardFocusChange; + if (widget->underMouse()) + state |= QStyle::State_MouseOver; + if (window->isActiveWindow()) + state |= QStyle::State_Active; + if (widget->isWindow()) + state |= QStyle::State_Window; +#ifdef Q_WS_MAC + extern bool qt_mac_can_clickThrough(const QWidget *w); //qwidget_mac.cpp + if (!(state & QStyle::State_Active) && !qt_mac_can_clickThrough(widget)) + state &= ~QStyle::State_Enabled; + + switch (QMacStyle::widgetSizePolicy(widget)) { + case QMacStyle::SizeSmall: + state |= QStyle::State_Small; + break; + case QMacStyle::SizeMini: + state |= QStyle::State_Mini; + break; + default: + ; + } +#endif +#ifdef QT_KEYPAD_NAVIGATION + if (widget->hasEditFocus()) + state |= QStyle::State_HasEditFocus; +#endif + + direction = widget->layoutDirection(); + rect = widget->rect(); + palette = widget->palette(); + fontMetrics = widget->fontMetrics(); +} + +/*! + Constructs a copy of \a other. +*/ +QStyleOption::QStyleOption(const QStyleOption &other) + : version(Version), type(Type), state(other.state), + direction(other.direction), rect(other.rect), fontMetrics(other.fontMetrics), + palette(other.palette) +{ +} + +/*! + Assign \a other to this QStyleOption. +*/ +QStyleOption &QStyleOption::operator=(const QStyleOption &other) +{ + state = other.state; + direction = other.direction; + rect = other.rect; + fontMetrics = other.fontMetrics; + palette = other.palette; + return *this; +} + +/*! + \enum QStyleOption::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_Default} for + this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOption::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOption::palette + \brief the palette that should be used when painting the control + + By default, the application's default palette is used. + + \sa initFrom() +*/ + +/*! + \variable QStyleOption::direction + \brief the text layout direction that should be used when drawing text in the control + + By default, the layout direction is Qt::LeftToRight. + + \sa initFrom() +*/ + +/*! + \variable QStyleOption::fontMetrics + \brief the font metrics that should be used when drawing text in the control + + By default, the application's default font is used. + + \sa initFrom() +*/ + +/*! + \variable QStyleOption::rect + \brief the area that should be used for various calculations and painting + + This can have different meanings for different types of elements. + For example, for a \l QStyle::CE_PushButton element it would be + the rectangle for the entire button, while for a \l + QStyle::CE_PushButtonLabel element it would be just the area for + the push button label. + + The default value is a null rectangle, i.e. a rectangle with both + the width and the height set to 0. + + \sa initFrom() +*/ + +/*! + \variable QStyleOption::state + \brief the style flags that are used when drawing the control + + The default value is QStyle::State_None. + + \sa initFrom(), QStyle::drawPrimitive(), QStyle::drawControl(), + QStyle::drawComplexControl(), QStyle::State +*/ + +/*! + \variable QStyleOption::type + \brief the option type of the style option + + The default value is SO_Default. + + \sa OptionType +*/ + +/*! + \variable QStyleOption::version + \brief the version of the style option + + This value can be used by subclasses to implement extensions + without breaking compatibility. If you use the qstyleoption_cast() + function, you normally do not need to check it. + + The default value is 1. +*/ + +/*! + \class QStyleOptionFocusRect + \brief The QStyleOptionFocusRect class is used to describe the + parameters for drawing a focus rectangle with QStyle. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption +*/ + +/*! + Constructs a QStyleOptionFocusRect, initializing the members + variables to their default values. +*/ + +QStyleOptionFocusRect::QStyleOptionFocusRect() + : QStyleOption(Version, SO_FocusRect) +{ + state |= QStyle::State_KeyboardFocusChange; // assume we had one, will be corrected in initFrom() +} + +/*! + \internal +*/ +QStyleOptionFocusRect::QStyleOptionFocusRect(int version) + : QStyleOption(version, SO_FocusRect) +{ + state |= QStyle::State_KeyboardFocusChange; // assume we had one, will be corrected in initFrom() +} + +/*! + \enum QStyleOptionFocusRect::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_FocusRect} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionFocusRect::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \fn QStyleOptionFocusRect::QStyleOptionFocusRect(const QStyleOptionFocusRect &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \variable QStyleOptionFocusRect::backgroundColor + \brief the background color on which the focus rectangle is being drawn + + The default value is an invalid color with the RGB value (0, 0, + 0). An invalid color is a color that is not properly set up for + the underlying window system. +*/ + +/*! + \class QStyleOptionFrame + \brief The QStyleOptionFrame class is used to describe the + parameters for drawing a frame. + + QStyleOptionFrame is used for drawing several built-in Qt widgets, + including QFrame, QGroupBox, QLineEdit, and QMenu. Note that to + describe the parameters necessary for drawing a frame in Qt 4.1 or + above, you must use the QStyleOptionFrameV2 subclass. + + An instance of the QStyleOptionFrame class has + \l{QStyleOption::type} {type} SO_Frame and \l{QStyleOption::version} + {version} 1. + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. The + version is used by QStyleOption subclasses to implement extensions + without breaking compatibility. If you use qstyleoption_cast(), + you normally do not need to check it. + + If you create your own QStyle subclass, you should handle both + QStyleOptionFrame and QStyleOptionFrameV2. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOptionFrameV2, QStyleOption +*/ + +/*! + Constructs a QStyleOptionFrame, initializing the members + variables to their default values. +*/ + +QStyleOptionFrame::QStyleOptionFrame() + : QStyleOption(Version, SO_Frame), lineWidth(0), midLineWidth(0) +{ +} + +/*! + \internal +*/ +QStyleOptionFrame::QStyleOptionFrame(int version) + : QStyleOption(version, SO_Frame), lineWidth(0), midLineWidth(0) +{ +} + +/*! + \fn QStyleOptionFrame::QStyleOptionFrame(const QStyleOptionFrame &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionFrame::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_Frame} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionFrame::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionFrame::lineWidth + \brief the line width for drawing the frame + + The default value is 0. + + \sa QFrame::lineWidth +*/ + +/*! + \variable QStyleOptionFrame::midLineWidth + \brief the mid-line width for drawing the frame + + This is usually used in drawing sunken or raised frames. + + The default value is 0. + + \sa QFrame::midLineWidth +*/ + +/*! + \class QStyleOptionFrameV2 + \brief The QStyleOptionFrameV2 class is used to describe the + parameters necessary for drawing a frame in Qt 4.1 or above. + + \since 4.1 + + QStyleOptionFrameV2 inherits QStyleOptionFrame which is used for + drawing several built-in Qt widgets, including QFrame, QGroupBox, + QLineEdit, and QMenu. + + An instance of the QStyleOptionFrameV2 class has + \l{QStyleOption::type} {type} SO_Frame and + \l{QStyleOption::version} {version} 2. The type is used + internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. The + version is used by QStyleOption subclasses to implement extensions + without breaking compatibility. If you use qstyleoption_cast(), + you normally do not need to check it. + + If you create your own QStyle subclass, you should handle both + QStyleOptionFrame and QStyleOptionFrameV2. One way to achieve this + is to use the QStyleOptionFrameV2 copy constructor. For example: + + \snippet doc/src/snippets/qstyleoption/main.cpp 1 + + In the example above: If the \c frameOption's version is 1, \l + FrameFeature is set to \l None for \c frameOptionV2. If \c + frameOption's version is 2, the constructor will simply copy the + \c frameOption's \l FrameFeature value. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOptionFrame, QStyleOption +*/ + +/*! + Constructs a QStyleOptionFrameV2 object. +*/ +QStyleOptionFrameV2::QStyleOptionFrameV2() + : QStyleOptionFrame(Version), features(None) +{ +} + +/*! + \fn QStyleOptionFrameV2::QStyleOptionFrameV2(const QStyleOptionFrameV2 &other) + + Constructs a QStyleOptionFrameV2 copy of the \a other style option. +*/ + +/*! + \internal +*/ +QStyleOptionFrameV2::QStyleOptionFrameV2(int version) + : QStyleOptionFrame(version), features(None) +{ +} + +/*! + Constructs a QStyleOptionFrameV2 copy of the \a other style option + which can be either of the QStyleOptionFrameV2 or + QStyleOptionFrame types. + + If the \a other style option's version is 1, the new style option's \l + FrameFeature value is set to \l QStyleOptionFrameV2::None. If its + version is 2, its \l FrameFeature value is simply copied to the + new style option. + + \sa version +*/ +QStyleOptionFrameV2::QStyleOptionFrameV2(const QStyleOptionFrame &other) +{ + QStyleOptionFrame::operator=(other); + + const QStyleOptionFrameV2 *f2 = qstyleoption_cast(&other); + features = f2 ? f2->features : FrameFeatures(QStyleOptionFrameV2::None); + version = Version; +} + +/*! + Assigns the \a other style option to this style option. The \a + other style option can be either of the QStyleOptionFrameV2 or + QStyleOptionFrame types. + + If the \a{other} style option's version is 1, this style option's + \l FrameFeature value is set to \l QStyleOptionFrameV2::None. If + its version is 2, its \l FrameFeature value is simply copied to + this style option. +*/ +QStyleOptionFrameV2 &QStyleOptionFrameV2::operator=(const QStyleOptionFrame &other) +{ + QStyleOptionFrame::operator=(other); + + const QStyleOptionFrameV2 *f2 = qstyleoption_cast(&other); + features = f2 ? f2->features : FrameFeatures(QStyleOptionFrameV2::None); + version = Version; + return *this; +} + +/*! + \enum QStyleOptionFrameV2::FrameFeature + + This enum describes the different types of features a frame can have. + + \value None Indicates a normal frame. + \value Flat Indicates a flat frame. +*/ + +/*! + \variable QStyleOptionFrameV2::features + \brief a bitwise OR of the features that describe this frame. + + \sa FrameFeature +*/ + +/*! + \enum QStyleOptionFrameV2::StyleOptionVersion + + This enum is used to hold information about the version of the + style option, and is defined for each QStyleOption subclass. + + \value Version 2 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \class QStyleOptionFrameV3 + \brief The QStyleOptionFrameV3 class is used to describe the + parameters necessary for drawing a frame in Qt 4.1 or above. + + \since 4.5 + + QStyleOptionFrameV3 inherits QStyleOptionFrameV2 + + An instance of the QStyleOptionFrameV3 class has + \l{QStyleOption::type} {type} SO_Frame and + \l{QStyleOption::version} {version} 3. The type is used + internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. The + version is used by QStyleOption subclasses to implement extensions + without breaking compatibility. If you use qstyleoption_cast(), + you normally do not need to check it. + + \sa QStyleOptionFrameV2, QStyleOption +*/ + +/*! + Constructs a QStyleOptionFrameV3 object. +*/ +QStyleOptionFrameV3::QStyleOptionFrameV3() + : QStyleOptionFrameV2(Version), frameShape(QFrame::NoFrame), unused(0) +{ +} + +/*! + \fn QStyleOptionFrameV3::QStyleOptionFrameV3(const QStyleOptionFrameV3 &other) + + Constructs a QStyleOptionFrameV3 copy of the \a other style option. +*/ + +/*! + \internal +*/ +QStyleOptionFrameV3::QStyleOptionFrameV3(int version) + : QStyleOptionFrameV2(version), frameShape(QFrame::NoFrame), unused(0) +{ +} + +/*! + Constructs a QStyleOptionFrameV3 copy of the \a other style option + which can be either of the QStyleOptionFrameV3 or + QStyleOptionFrame types. + + If the \a other style option's version is 1, the new style + option's \l FrameFeature value is set to + \l{QStyleOptionFrameV2::None}. If its version is 2 or lower, + \l{QStyleOptionFrameV3::frameShape} value is QFrame::NoFrame + + \sa version +*/ +QStyleOptionFrameV3::QStyleOptionFrameV3(const QStyleOptionFrame &other) +{ + operator=(other); +} + +/*! + Assigns the \a other style option to this style option. The \a + other style option can be either of the QStyleOptionFrameV3, + QStyleOptionFrameV2 or QStyleOptionFrame types. + + If the \a other style option's version is 1, the new style + option's \l FrameFeature value is set to + \l{QStyleOptionFrameV2::None}. If its version is 2 or lower, + \l{QStyleOptionFrameV3::frameShape} value is QFrame::NoFrame +*/ +QStyleOptionFrameV3 &QStyleOptionFrameV3::operator=(const QStyleOptionFrame &other) +{ + QStyleOptionFrameV2::operator=(other); + + const QStyleOptionFrameV3 *f3 = qstyleoption_cast(&other); + frameShape = f3 ? f3->frameShape : QFrame::NoFrame; + version = Version; + return *this; +} + + +/*! + \variable QStyleOptionFrameV3::frameShape + \brief This property holds the frame shape value of the frame. + + \sa QFrame::frameShape +*/ + +/*! + \enum QStyleOptionFrameV3::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 3 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \class QStyleOptionViewItemV2 + \brief The QStyleOptionViewItemV2 class is used to describe the + parameters necessary for drawing a frame in Qt 4.2 or above. + \since 4.2 + + QStyleOptionViewItemV2 inherits QStyleOptionViewItem. + + An instance of the QStyleOptionViewItemV2 class has + \l{QStyleOption::type} {type} SO_ViewItem and + \l{QStyleOption::version} {version} 2. The type is used internally + by QStyleOption, its subclasses, and qstyleoption_cast() to + determine the type of style option. In general you do not need to + worry about this unless you want to create your own QStyleOption + subclass and your own styles. The version is used by QStyleOption + subclasses to implement extensions without breaking + compatibility. If you use qstyleoption_cast(), you normally do not + need to check it. + + See QStyleOptionFrameV2's detailed description for a discussion + of how to handle "V2" classes. + + \sa QStyleOptionViewItem, QStyleOption +*/ + +/*! + \enum QStyleOptionViewItemV2::StyleOptionVersion + + This enum is used to hold information about the version of the + style option, and is defined for each QStyleOption subclass. + + \value Version 2 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionViewItemV2::features + \brief a bitwise OR of the features that describe this view item + + \sa ViewItemFeature +*/ + +/*! + Constructs a QStyleOptionViewItemV2 object. +*/ +QStyleOptionViewItemV2::QStyleOptionViewItemV2() + : QStyleOptionViewItem(Version), features(None) +{ +} + +/*! + \fn QStyleOptionViewItemV2::QStyleOptionViewItemV2(const QStyleOptionViewItemV2 &other) + + Constructs a copy of \a other. +*/ + +/*! + Constructs a QStyleOptionViewItemV2 copy of the \a other style option + which can be either of the QStyleOptionViewItemV2 or + QStyleOptionViewItem types. + + If the \a other style option's version is 1, the new style option's \l + ViewItemFeature value is set to \l QStyleOptionViewItemV2::None. If its + version is 2, its \l ViewItemFeature value is simply copied to the + new style option. + + \sa version +*/ +QStyleOptionViewItemV2::QStyleOptionViewItemV2(const QStyleOptionViewItem &other) + : QStyleOptionViewItem(Version) +{ + (void)QStyleOptionViewItemV2::operator=(other); +} + +/*! + \internal +*/ +QStyleOptionViewItemV2::QStyleOptionViewItemV2(int version) + : QStyleOptionViewItem(version) +{ + +} + +/*! + Assigns the \a other style option to this style option. The \a + other style option can be either of the QStyleOptionViewItemV2 or + QStyleOptionViewItem types. + + If the \a{other} style option's version is 1, this style option's + \l ViewItemFeature value is set to \l QStyleOptionViewItemV2::None. + If its version is 2, its \l ViewItemFeature value is simply copied + to this style option. +*/ +QStyleOptionViewItemV2 &QStyleOptionViewItemV2::operator=(const QStyleOptionViewItem &other) +{ + QStyleOptionViewItem::operator=(other); + const QStyleOptionViewItemV2 *v2 = qstyleoption_cast(&other); + features = v2 ? v2->features : ViewItemFeatures(QStyleOptionViewItemV2::None); + return *this; +} + +/*! + \enum QStyleOptionViewItemV2::ViewItemFeature + + This enum describes the different types of features an item can have. + + \value None Indicates a normal item. + \value WrapText Indicates an item with wrapped text. + \value Alternate Indicates that the item's background is rendered using alternateBase. + \value HasCheckIndicator Indicates that the item has a check state indicator. + \value HasDisplay Indicates that the item has a display role. + \value HasDecoration Indicates that the item has a decoration role. +*/ + + + +/*! + \class QStyleOptionViewItemV3 + \brief The QStyleOptionViewItemV3 class is used to describe the + parameters necessary for drawing a frame in Qt 4.3 or above. + \since 4.3 + + QStyleOptionViewItemV3 inherits QStyleOptionViewItem. + + An instance of the QStyleOptionViewItemV3 class has + \l{QStyleOption::type} {type} SO_ViewItem and \l{QStyleOption::version} + {version} 3. The type is used internally by QStyleOption, its subclasses, + and qstyleoption_cast() to determine the type of style option. In general + you do not need to worry about this unless you want to create your own + QStyleOption subclass and your own styles. The version is used by + QStyleOption subclasses to implement extensions without breaking + compatibility. If you use qstyleoption_cast(), you normally do not need to + check it. + + See QStyleOptionFrameV2's detailed description for a discussion + of how to handle "V2" and other versioned classes. + + \sa QStyleOptionViewItem, QStyleOption +*/ + +/*! + \enum QStyleOptionViewItemV3::StyleOptionVersion + + This enum is used to hold information about the version of the + style option, and is defined for each QStyleOption subclass. + + \value Version 3 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + Constructs a QStyleOptionViewItemV3 object. +*/ +QStyleOptionViewItemV3::QStyleOptionViewItemV3() + : QStyleOptionViewItemV2(Version), widget(0) +{ +} + +/*! + Constructs a copy of \a other. +*/ +QStyleOptionViewItemV3::QStyleOptionViewItemV3(const QStyleOptionViewItem &other) + : QStyleOptionViewItemV2(Version), widget(0) +{ + (void)QStyleOptionViewItemV3::operator=(other); +} + +/*! + \fn QStyleOptionViewItemV3::QStyleOptionViewItemV3(const QStyleOptionViewItemV3 &other) + + Constructs a copy of \a other. +*/ + +/*! + Assigns the \a other style option to this style option. The \a + other style option can be an instance of the QStyleOptionViewItemV2, + QStyleOptionViewItemV3 or QStyleOptionViewItem types. +*/ +QStyleOptionViewItemV3 &QStyleOptionViewItemV3::operator = (const QStyleOptionViewItem &other) +{ + QStyleOptionViewItemV2::operator=(other); + const QStyleOptionViewItemV3 *v3 = qstyleoption_cast(&other); + locale = v3 ? v3->locale : QLocale(); + widget = v3 ? v3->widget : 0; + return *this; +} + +/*! + \internal +*/ +QStyleOptionViewItemV3::QStyleOptionViewItemV3(int version) + : QStyleOptionViewItemV2(version), widget(0) +{ +} + +#ifndef QT_NO_ITEMVIEWS + +/*! + \class QStyleOptionViewItemV4 + \brief The QStyleOptionViewItemV4 class is used to describe the + parameters necessary for drawing a frame in Qt 4.4 or above. + \since 4.4 + + QStyleOptionViewItemV4 inherits QStyleOptionViewItemV3. + + An instance of the QStyleOptionViewItemV4 class has + \l{QStyleOption::type} {type} SO_ViewItem and + \l{QStyleOption::version} {version} 4. The type is used internally + by QStyleOption, its subclasses, and qstyleoption_cast() to + determine the type of style option. In general you do not need to + worry about this unless you want to create your own QStyleOption + subclass and your own styles. The version is used by QStyleOption + subclasses to implement extensions without breaking + compatibility. If you use qstyleoption_cast(), you normally do not + need to check it. + + See QStyleOptionViewItemV3's detailed description for a discussion + of how to handle "V3" classes. + + \sa QStyleOptionViewItem, QStyleOption +*/ + +/*! + \variable QStyleOptionViewItemV4::index + + The model index that is to be drawn. +*/ + +/*! + \variable QStyleOptionViewItemV4::checkState + + If this view item is checkable, i.e., + ViewItemFeature::HasCheckIndicator is true, \c checkState is true + if the item is checked; otherwise, it is false. + +*/ + +/*! + \variable QStyleOptionViewItemV4::icon + + The icon (if any) to be drawn in the view item. +*/ + + +/*! + \variable QStyleOptionViewItemV4::text + + The text (if any) to be drawn in the view item. +*/ + +/*! + \variable QStyleOptionViewItemV4::backgroundBrush + + The QBrush that should be used to paint the view items + background. +*/ + +/*! + \variable QStyleOptionViewItemV4::viewItemPosition + + Gives the position of this view item relative to other items. See + the \l{QStyleOptionViewItemV4::}{ViewItemPosition} enum for the + details. +*/ + +/*! + \enum QStyleOptionViewItemV4::StyleOptionVersion + + This enum is used to hold information about the version of the + style option, and is defined for each QStyleOption subclass. + + \value Version 4 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \enum QStyleOptionViewItemV4::ViewItemPosition + + This enum is used to represent the placement of the item on + a row. This can be used to draw items differently depending + on their placement, for example by putting rounded edges at + the beginning and end, and straight edges in between. + + \value Invalid The ViewItemPosition is unknown and should be + disregarded. + \value Beginning The item appears at the beginning of the row. + \value Middle The item appears in the middle of the row. + \value End The item appears at the end of the row. + \value OnlyOne The item is the only one on the row, and is + therefore both at the beginning and the end. +*/ + + +/*! + Constructs a QStyleOptionViewItemV4 object. +*/ +QStyleOptionViewItemV4::QStyleOptionViewItemV4() +: QStyleOptionViewItemV3(Version), checkState(Qt::Unchecked), viewItemPosition(QStyleOptionViewItemV4::Invalid) +{ +} + +/*! + \fn QStyleOptionViewItemV4::QStyleOptionViewItemV4(const QStyleOptionViewItemV4 &other) + + Constructs a copy of \a other. +*/ + +/*! + Constructs a QStyleOptionViewItemV4 copy of the \a other style option + which can be either of the QStyleOptionViewItemV3 or + QStyleOptionViewItem types. + + \sa version +*/ +QStyleOptionViewItemV4::QStyleOptionViewItemV4(const QStyleOptionViewItem &other) + : QStyleOptionViewItemV3(Version) +{ + (void)QStyleOptionViewItemV4::operator=(other); +} + +/*! + Assigns the \a other style option to this style option. The \a + other style option can be either of the QStyleOptionViewItemV3 or + QStyleOptionViewItem types. +*/ +QStyleOptionViewItemV4 &QStyleOptionViewItemV4::operator = (const QStyleOptionViewItem &other) +{ + QStyleOptionViewItemV3::operator=(other); + if (const QStyleOptionViewItemV4 *v4 = qstyleoption_cast(&other)) { + index = v4->index; + checkState = v4->checkState; + text = v4->text; + viewItemPosition = v4->viewItemPosition; + backgroundBrush = v4->backgroundBrush; + icon = v4->icon; + } else { + viewItemPosition = QStyleOptionViewItemV4::Invalid; + checkState = Qt::Unchecked; + } + return *this; +} + +/*! + \internal +*/ +QStyleOptionViewItemV4::QStyleOptionViewItemV4(int version) + : QStyleOptionViewItemV3(version) +{ +} +#endif // QT_NO_ITEMVIEWS + +/*! + \class QStyleOptionGroupBox + \brief The QStyleOptionGroupBox class describes the parameters for + drawing a group box. + + \since 4.1 + + QStyleOptionButton contains all the information that QStyle + functions need the various graphical elements of a group box. + + It holds the lineWidth and the midLineWidth for drawing the panel, + the group box's \l {text}{title} and the title's \l + {textAlignment}{alignment} and \l {textColor}{color}. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QStyleOptionComplex, QGroupBox +*/ + +/*! + \enum QStyleOptionGroupBox::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_GroupBox} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionGroupBox::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionGroupBox::lineWidth + \brief the line width for drawing the panel + + The value of this variable is, currently, always 1. + + \sa QFrame::lineWidth +*/ + +/*! + \variable QStyleOptionGroupBox::midLineWidth + \brief the mid-line width for drawing the panel + + The mid-line width is usually used when drawing sunken or raised + group box frames. The value of this variable is, currently, always 0. + + \sa QFrame::midLineWidth +*/ + +/*! + \variable QStyleOptionGroupBox::text + \brief the text of the group box + + The default value is an empty string. + + \sa QGroupBox::title +*/ + +/*! + \variable QStyleOptionGroupBox::textAlignment + \brief the alignment of the group box title + + The default value is Qt::AlignLeft. + + \sa QGroupBox::alignment +*/ + +/*! + \variable QStyleOptionGroupBox::features + \brief the features of the group box frame + + The frame is flat by default. + + \sa QStyleOptionFrameV2::FrameFeature +*/ + +/*! + \variable QStyleOptionGroupBox::textColor + \brief the color of the group box title + + The default value is an invalid color with the RGB value (0, 0, + 0). An invalid color is a color that is not properly set up for + the underlying window system. +*/ + +/*! + Constructs a QStyleOptionGroupBox, initializing the members + variables to their default values. +*/ +QStyleOptionGroupBox::QStyleOptionGroupBox() + : QStyleOptionComplex(Version, Type), features(QStyleOptionFrameV2::None), + textAlignment(Qt::AlignLeft), lineWidth(0), midLineWidth(0) +{ +} + +/*! + \fn QStyleOptionGroupBox::QStyleOptionGroupBox(const QStyleOptionGroupBox &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \internal +*/ +QStyleOptionGroupBox::QStyleOptionGroupBox(int version) + : QStyleOptionComplex(version, Type), features(QStyleOptionFrameV2::None), + textAlignment(Qt::AlignLeft), lineWidth(0), midLineWidth(0) +{ +} + +/*! + \class QStyleOptionHeader + \brief The QStyleOptionHeader class is used to describe the + parameters for drawing a header. + + QStyleOptionHeader contains all the information that QStyle + functions need to draw the item views' header pane, header sort + arrow, and header label. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption +*/ + +/*! + Constructs a QStyleOptionHeader, initializing the members + variables to their default values. +*/ + +QStyleOptionHeader::QStyleOptionHeader() + : QStyleOption(QStyleOptionHeader::Version, SO_Header), + section(0), textAlignment(Qt::AlignLeft), iconAlignment(Qt::AlignLeft), + position(QStyleOptionHeader::Beginning), + selectedPosition(QStyleOptionHeader::NotAdjacent), sortIndicator(None), + orientation(Qt::Horizontal) +{ +} + +/*! + \internal +*/ +QStyleOptionHeader::QStyleOptionHeader(int version) + : QStyleOption(version, SO_Header), + section(0), textAlignment(Qt::AlignLeft), iconAlignment(Qt::AlignLeft), + position(QStyleOptionHeader::Beginning), + selectedPosition(QStyleOptionHeader::NotAdjacent), sortIndicator(None), + orientation(Qt::Horizontal) +{ +} + +/*! + \variable QStyleOptionHeader::orientation + \brief the header's orientation (horizontal or vertical) + + The default orientation is Qt::Horizontal +*/ + +/*! + \fn QStyleOptionHeader::QStyleOptionHeader(const QStyleOptionHeader &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionHeader::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_Header} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionHeader::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionHeader::section + \brief which section of the header is being painted + + The default value is 0. +*/ + +/*! + \variable QStyleOptionHeader::text + \brief the text of the header + + The default value is an empty string. +*/ + +/*! + \variable QStyleOptionHeader::textAlignment + \brief the alignment flags for the text of the header + + The default value is Qt::AlignLeft. +*/ + +/*! + \variable QStyleOptionHeader::icon + \brief the icon of the header + + The default value is an empty icon, i.e. an icon with neither a + pixmap nor a filename. +*/ + +/*! + \variable QStyleOptionHeader::iconAlignment + \brief the alignment flags for the icon of the header + + The default value is Qt::AlignLeft. +*/ + +/*! + \variable QStyleOptionHeader::position + \brief the section's position in relation to the other sections + + The default value is QStyleOptionHeader::Beginning. +*/ + +/*! + \variable QStyleOptionHeader::selectedPosition + \brief the section's position in relation to the selected section + + The default value is QStyleOptionHeader::NotAdjacent +*/ + +/*! + \variable QStyleOptionHeader::sortIndicator + \brief the direction the sort indicator should be drawn + + The default value is QStyleOptionHeader::None. +*/ + +/*! + \enum QStyleOptionHeader::SectionPosition + + This enum lets you know where the section's position is in relation to the other sections. + + \value Beginning At the beginining of the header + \value Middle In the middle of the header + \value End At the end of the header + \value OnlyOneSection Only one header section + + \sa position +*/ + +/*! + \enum QStyleOptionHeader::SelectedPosition + + This enum lets you know where the section's position is in relation to the selected section. + + \value NotAdjacent Not adjacent to the selected section + \value NextIsSelected The next section is selected + \value PreviousIsSelected The previous section is selected + \value NextAndPreviousAreSelected Both the next and previous section are selected + + \sa selectedPosition +*/ + +/*! + \enum QStyleOptionHeader::SortIndicator + + Indicates which direction the sort indicator should be drawn + + \value None No sort indicator is needed + \value SortUp Draw an up indicator + \value SortDown Draw a down indicator + + \sa sortIndicator +*/ + +/*! + \class QStyleOptionButton + \brief The QStyleOptionButton class is used to describe the + parameters for drawing buttons. + + QStyleOptionButton contains all the information that QStyle + functions need to draw graphical elements like QPushButton, + QCheckBox, and QRadioButton. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QStyleOptionToolButton +*/ + +/*! + \enum QStyleOptionButton::ButtonFeature + + This enum describes the different types of features a push button can have. + + \value None Indicates a normal push button. + \value Flat Indicates a flat push button. + \value HasMenu Indicates that the button has a drop down menu. + \value DefaultButton Indicates that the button is a default button. + \value AutoDefaultButton Indicates that the button is an auto default button. + \value CommandLinkButton Indicates that the button is a Windows Vista type command link. + + \sa features +*/ + +/*! + Constructs a QStyleOptionButton, initializing the members + variables to their default values. +*/ + +QStyleOptionButton::QStyleOptionButton() + : QStyleOption(QStyleOptionButton::Version, SO_Button), features(None) +{ +} + +/*! + \internal +*/ +QStyleOptionButton::QStyleOptionButton(int version) + : QStyleOption(version, SO_Button), features(None) +{ +} + +/*! + \fn QStyleOptionButton::QStyleOptionButton(const QStyleOptionButton &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionButton::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_Button} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionButton::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionButton::features + \brief a bitwise OR of the features that describe this button + + \sa ButtonFeature +*/ + +/*! + \variable QStyleOptionButton::text + \brief the text of the button + + The default value is an empty string. +*/ + +/*! + \variable QStyleOptionButton::icon + \brief the icon of the button + + The default value is an empty icon, i.e. an icon with neither a + pixmap nor a filename. + + \sa iconSize +*/ + +/*! + \variable QStyleOptionButton::iconSize + \brief the size of the icon for the button + + The default value is QSize(-1, -1), i.e. an invalid size. +*/ + + +#ifndef QT_NO_TOOLBAR +/*! + \class QStyleOptionToolBar + \brief The QStyleOptionToolBar class is used to describe the + parameters for drawing a toolbar. + + \since 4.1 + + QStyleOptionToolBar contains all the information that QStyle + functions need to draw QToolBar. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + The QStyleOptionToolBar class holds the lineWidth and the + midLineWidth for drawing the widget. It also stores information + about which \l {toolBarArea}{area} the toolbar should be located + in, whether it is movable or not, which position the toolbar line + should have (positionOfLine), and the toolbar's position within + the line (positionWithinLine). + + In addition, the class provides a couple of enums: The + ToolBarFeature enum is used to describe whether a toolbar is + movable or not, and the ToolBarPosition enum is used to describe + the position of a toolbar line, as well as the toolbar's position + within the line. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption +*/ + +/*! + Constructs a QStyleOptionToolBar, initializing the members + variables to their default values. +*/ + +QStyleOptionToolBar::QStyleOptionToolBar() + : QStyleOption(Version, SO_ToolBar), positionOfLine(OnlyOne), positionWithinLine(OnlyOne), + toolBarArea(Qt::TopToolBarArea), features(None), lineWidth(0), midLineWidth(0) +{ +} + +/*! + \fn QStyleOptionToolBar::QStyleOptionToolBar(const QStyleOptionToolBar &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \internal +*/ +QStyleOptionToolBar::QStyleOptionToolBar(int version) +: QStyleOption(version, SO_ToolBar), positionOfLine(OnlyOne), positionWithinLine(OnlyOne), + toolBarArea(Qt::TopToolBarArea), features(None), lineWidth(0), midLineWidth(0) +{ + +} + +/*! + \enum QStyleOptionToolBar::ToolBarPosition + + \image qstyleoptiontoolbar-position.png + + This enum is used to describe the position of a toolbar line, as + well as the toolbar's position within the line. + + The order of the positions within a line starts at the top of a + vertical line, and from the left within a horizontal line. The + order of the positions for the lines is always from the the + parent widget's boundary edges. + + \value Beginning The toolbar is located at the beginning of the line, + or the toolbar line is the first of several lines. There can + only be one toolbar (and only one line) with this position. + \value Middle The toolbar is located in the middle of the line, + or the toolbar line is in the middle of several lines. There can + several toolbars (and lines) with this position. + \value End The toolbar is located at the end of the line, + or the toolbar line is the last of several lines. There can + only be one toolbar (and only one line) with this position. + \value OnlyOne There is only one toolbar or line. This is the default value + of the positionOfLine and positionWithinLine variables. + + \sa positionWithinLine, positionOfLine +*/ + +/*! + \enum QStyleOptionToolBar::ToolBarFeature + + This enum is used to describe whether a toolbar is movable or not. + + \value None The toolbar cannot be moved. The default value. + \value Movable The toolbar is movable, and a handle will appear when + holding the cursor over the toolbar's boundary. + + \sa features, QToolBar::isMovable() +*/ + +/*! + \variable QStyleOptionToolBar::positionOfLine + + This variable holds the position of the toolbar line. + + The default value is QStyleOptionToolBar::OnlyOne. +*/ + +/*! + \variable QStyleOptionToolBar::positionWithinLine + + This variable holds the position of the toolbar within a line. + + The default value is QStyleOptionToolBar::OnlyOne. +*/ + +/*! + \variable QStyleOptionToolBar::toolBarArea + + This variable holds the location for drawing the toolbar. + + The default value is Qt::TopToolBarArea. + + \sa Qt::ToolBarArea +*/ + +/*! + \variable QStyleOptionToolBar::features + + This variable holds whether the toolbar is movable or not. + + The default value is \l None. +*/ + +/*! + \variable QStyleOptionToolBar::lineWidth + + This variable holds the line width for drawing the toolbar. + + The default value is 0. +*/ + +/*! + \variable QStyleOptionToolBar::midLineWidth + + This variable holds the mid-line width for drawing the toolbar. + + The default value is 0. +*/ + +/*! + \enum QStyleOptionToolBar::StyleOptionType + + This enum is used to hold information about the type of the style + option, and is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_ToolBar} for + this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionToolBar::StyleOptionVersion + + This enum is used to hold information about the version of the + style option, and is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +#endif + +#ifndef QT_NO_TABBAR +/*! + \class QStyleOptionTab + \brief The QStyleOptionTab class is used to describe the + parameters for drawing a tab bar. + + The QStyleOptionTab class is used for drawing several built-in Qt + widgets including \l QTabBar and the panel for \l QTabWidget. Note + that to describe the parameters necessary for drawing a frame in + Qt 4.1 or above, you must use the QStyleOptionFrameV2 subclass. + + An instance of the QStyleOptiontabV2 class has + \l{QStyleOption::type} {type} \l SO_Tab and + \l{QStyleOption::version} {version} 1. The type is used internally + by QStyleOption, its subclasses, and qstyleoption_cast() to + determine the type of style option. In general you do not need to + worry about this unless you want to create your own QStyleOption + subclass and your own styles. The version is used by QStyleOption + subclasses to implement extensions without breaking + compatibility. If you use qstyleoption_cast(), you normally do not + need to check it. + + If you create your own QStyle subclass, you should handle both + QStyleOptionTab and QStyleOptionTabV2. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOptionTabV2, QStyleOption +*/ + +/*! + Constructs a QStyleOptionTab object, initializing the members + variables to their default values. +*/ + +QStyleOptionTab::QStyleOptionTab() + : QStyleOption(QStyleOptionTab::Version, SO_Tab), + shape(QTabBar::RoundedNorth), + row(0), + position(Beginning), + selectedPosition(NotAdjacent), cornerWidgets(QStyleOptionTab::NoCornerWidgets) +{ +} + +/*! + \internal +*/ +QStyleOptionTab::QStyleOptionTab(int version) + : QStyleOption(version, SO_Tab), + shape(QTabBar::RoundedNorth), + row(0), + position(Beginning), + selectedPosition(NotAdjacent), cornerWidgets(QStyleOptionTab::NoCornerWidgets) +{ +} + +/*! + \fn QStyleOptionTab::QStyleOptionTab(const QStyleOptionTab &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionTab::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_Tab} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionTab::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \enum QStyleOptionTab::TabPosition + + This enum describes the position of the tab. + + \value Beginning The tab is the first tab in the tab bar. + \value Middle The tab is neither the first nor the last tab in the tab bar. + \value End The tab is the last tab in the tab bar. + \value OnlyOneTab The tab is both the first and the last tab in the tab bar. + + \sa position +*/ + +/*! + \enum QStyleOptionTab::CornerWidget + + These flags indicate the corner widgets in a tab. + + \value NoCornerWidgets There are no corner widgets + \value LeftCornerWidget Left corner widget + \value RightCornerWidget Right corner widget + + \sa cornerWidgets +*/ + +/*! \enum QStyleOptionTab::SelectedPosition + + This enum describes the position of the selected tab. Some styles + need to draw a tab differently depending on whether or not it is + adjacent to the selected tab. + + \value NotAdjacent The tab is not adjacent to a selected tab (or is the selected tab). + \value NextIsSelected The next tab (typically the tab on the right) is selected. + \value PreviousIsSelected The previous tab (typically the tab on the left) is selected. + + \sa selectedPosition +*/ + +/*! + \variable QStyleOptionTab::selectedPosition + \brief the position of the selected tab in relation to this tab + + The default value is NotAdjacent, i.e. the tab is not adjacent to + a selected tab nor is it the selected tab. +*/ + +/*! + \variable QStyleOptionTab::cornerWidgets + \brief an OR combination of CornerWidget values indicating the + corner widgets of the tab bar + + The default value is NoCornerWidgets. + + \sa CornerWidget +*/ + + +/*! + \variable QStyleOptionTab::shape + \brief the tab shape used to draw the tab; by default + QTabBar::RoundedNorth + + \sa QTabBar::Shape +*/ + +/*! + \variable QStyleOptionTab::text + \brief the text of the tab + + The default value is an empty string. +*/ + +/*! + \variable QStyleOptionTab::icon + \brief the icon for the tab + + The default value is an empty icon, i.e. an icon with neither a + pixmap nor a filename. +*/ + +/*! + \variable QStyleOptionTab::row + \brief which row the tab is currently in + + The default value is 0, indicating the front row. Currently this + property can only be 0. +*/ + +/*! + \variable QStyleOptionTab::position + \brief the position of the tab in the tab bar + + The default value is \l Beginning, i.e. the tab is the first tab + in the tab bar. +*/ + +/*! + \class QStyleOptionTabV2 + \brief The QStyleOptionTabV2 class is used to describe the + parameters necessary for drawing a tabs in Qt 4.1 or above. + + \since 4.1 + + An instance of the QStyleOptionTabV2 class has + \l{QStyleOption::type} {type} \l SO_Tab and + \l{QStyleOption::version} {version} 2. The type is used internally + by QStyleOption, its subclasses, and qstyleoption_cast() to + determine the type of style option. In general you do not need to + worry about this unless you want to create your own QStyleOption + subclass and your own styles. The version is used by QStyleOption + subclasses to implement extensions without breaking + compatibility. If you use qstyleoption_cast(), you normally do not + need to check it. + + If you create your own QStyle subclass, you should handle both + QStyleOptionTab and QStyleOptionTabV2. One way to achieve this is + to use the QStyleOptionTabV2 copy constructor. For example: + + \snippet doc/src/snippets/qstyleoption/main.cpp 3 + + In the example above: If \c tabOption's version is 1, the extra + member (\l iconSize) will be set to an invalid size for \c tabV2. + If \c tabOption's version is 2, the constructor will simply copy + the \c tab's iconSize. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOptionTab, QStyleOption +*/ + +/*! + \enum QStyleOptionTabV2::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 2 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionTabV2::iconSize + \brief the size for the icons + + The default value is QSize(-1, -1), i.e. an invalid size; use + QStyle::pixelMetric() to find the default icon size for tab bars. + + \sa QTabBar::iconSize() +*/ + +/*! + Constructs a QStyleOptionTabV2. +*/ +QStyleOptionTabV2::QStyleOptionTabV2() + : QStyleOptionTab(Version) +{ +} + +/*! + \internal +*/ +QStyleOptionTabV2::QStyleOptionTabV2(int version) + : QStyleOptionTab(version) +{ +} + +/*! + \fn QStyleOptionTabV2::QStyleOptionTabV2(const QStyleOptionTabV2 &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + Constructs a QStyleOptionTabV2 copy of the \a other style option + which can be either of the QStyleOptionTabV2 or QStyleOptionTab + types. + + If the other style option's version is 1, the new style option's + \c iconSize is set to an invalid value. If its version is 2, its + \c iconSize value is simply copied to the new style option. +*/ +QStyleOptionTabV2::QStyleOptionTabV2(const QStyleOptionTab &other) + : QStyleOptionTab(Version) +{ + if (const QStyleOptionTabV2 *tab = qstyleoption_cast(&other)) { + *this = *tab; + } else { + *((QStyleOptionTab *)this) = other; + version = Version; + } +} + +/*! + Assigns the \a other style option to this QStyleOptionTabV2. The + \a other style option can be either of the QStyleOptionTabV2 or + QStyleOptionTab types. + + If the other style option's version is 1, this style option's \c + iconSize is set to an invalid size. If its version is 2, its \c + iconSize value is simply copied to this style option. +*/ +QStyleOptionTabV2 &QStyleOptionTabV2::operator=(const QStyleOptionTab &other) +{ + QStyleOptionTab::operator=(other); + + if (const QStyleOptionTabV2 *tab = qstyleoption_cast(&other)) + iconSize = tab->iconSize; + else + iconSize = QSize(); + return *this; +} + +/*! + \class QStyleOptionTabV3 + \brief The QStyleOptionTabV3 class is used to describe the + parameters necessary for drawing a tabs in Qt 4.5 or above. + + \since 4.5 + + An instance of the QStyleOptionTabV3 class has + \l{QStyleOption::type} {type} \l SO_Tab and + \l{QStyleOption::version} {version} 3. The type is used internally + by QStyleOption, its subclasses, and qstyleoption_cast() to + determine the type of style option. In general you do not need to + worry about this unless you want to create your own QStyleOption + subclass and your own styles. The version is used by QStyleOption + subclasses to implement extensions without breaking + compatibility. If you use qstyleoption_cast(), you normally do not + need to check it. + + If you create your own QStyle subclass, you should handle both + QStyleOptionTab, QStyleOptionTabV2 and QStyleOptionTabV3. + One way to achieve this is to use the QStyleOptionTabV3 copy + constructor. For example: + + \snippet doc/src/snippets/qstyleoption/main.cpp 3 + + In the example above: If \c tabOption's version is 1, the extra + member (\l{QStyleOptionTabV2::iconSize}{iconSize}) will be set to + an invalid size for \c tabV2. If \c tabOption's version is 2, the + constructor will simply copy the \c tab's iconSize. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOptionTab, QStyleOption +*/ + +/*! + \enum QStyleOptionTabV3::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 3 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionTabV3::documentMode + \brief whether the tabbar is in document mode. + + The default value is false; +*/ + +/*! + \variable QStyleOptionTabV3::leftButtonSize + \brief the size for the left widget on the tab. + + The default value is QSize(-1, -1), i.e. an invalid size; +*/ + +/*! + \variable QStyleOptionTabV3::rightButtonSize + \brief the size for the right widget on the tab. + + The default value is QSize(-1, -1), i.e. an invalid size; +*/ + +/*! + Constructs a QStyleOptionTabV3. +*/ + +QStyleOptionTabV3::QStyleOptionTabV3() + : QStyleOptionTabV2(Version) + , documentMode(false) +{ +} + +/*! + \internal +*/ +QStyleOptionTabV3::QStyleOptionTabV3(int version) + : QStyleOptionTabV2(version) +{ +} + +/*! + \fn QStyleOptionTabV3::QStyleOptionTabV3(const QStyleOptionTabV3 &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \fn QStyleOptionTabV3::QStyleOptionTabV3(const QStyleOptionTabV2 &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + Constructs a QStyleOptionTabV3 copy of the \a other style option + which can be either of the QStyleOptionTabV3, QStyleOptionTabV2 + or QStyleOptionTab types. + + If the other style option's version is 1 or 2, the new style option's + \c leftButtonSize and \c rightButtonSize is set to an invalid value. If + its version is 3, its \c leftButtonSize and \c rightButtonSize values + are simply copied to the new style option. +*/ +QStyleOptionTabV3::QStyleOptionTabV3(const QStyleOptionTab &other) + : QStyleOptionTabV2(Version) +{ + if (const QStyleOptionTabV3 *tab = qstyleoption_cast(&other)) { + *this = *tab; + } else { + *((QStyleOptionTabV2 *)this) = other; + version = Version; + } +} + +/*! + Assigns the \a other style option to this QStyleOptionTabV3. The + \a other style option can be either of the QStyleOptionTabV3, + QStyleOptionTabV2 or QStyleOptionTab types. + + If the other style option's version is 1 or 2, the new style option's + \c leftButtonSize and \c rightButtonSize is set to an invalid value. If + its version is 3, its \c leftButtonSize and \c rightButtonSize values + are simply copied to the new style option. +*/ +QStyleOptionTabV3 &QStyleOptionTabV3::operator=(const QStyleOptionTab &other) +{ + QStyleOptionTabV2::operator=(other); + + if (const QStyleOptionTabV3 *tab = qstyleoption_cast(&other)) { + leftButtonSize = tab->leftButtonSize; + rightButtonSize = tab->rightButtonSize; + } else { + leftButtonSize = QSize(); + rightButtonSize = QSize(); + documentMode = false; + } + return *this; +} + +#endif // QT_NO_TABBAR + +/*! + \class QStyleOptionProgressBar + \brief The QStyleOptionProgressBar class is used to describe the + parameters necessary for drawing a progress bar. + + Since Qt 4.1, Qt uses the QStyleOptionProgressBarV2 subclass for + drawing QProgressBar. + + An instance of the QStyleOptionProgressBar class has type + SO_ProgressBar and version 1. + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. The + version is used by QStyleOption subclasses to implement extensions + without breaking compatibility. If you use qstyleoption_cast(), + you normally do not need to check it. + + If you create your own QStyle subclass, you should handle both + QStyleOptionProgressBar and QStyleOptionProgressBarV2. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOptionProgressBarV2, QStyleOption +*/ + +/*! + Constructs a QStyleOptionProgressBar, initializing the members + variables to their default values. +*/ + +QStyleOptionProgressBar::QStyleOptionProgressBar() + : QStyleOption(QStyleOptionProgressBar::Version, SO_ProgressBar), + minimum(0), maximum(0), progress(0), textAlignment(Qt::AlignLeft), textVisible(false) +{ +} + +/*! + \internal +*/ +QStyleOptionProgressBar::QStyleOptionProgressBar(int version) + : QStyleOption(version, SO_ProgressBar), + minimum(0), maximum(0), progress(0), textAlignment(Qt::AlignLeft), textVisible(false) +{ +} + +/*! + \fn QStyleOptionProgressBar::QStyleOptionProgressBar(const QStyleOptionProgressBar &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionProgressBar::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_ProgressBar} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionProgressBar::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionProgressBar::minimum + \brief the minimum value for the progress bar + + This is the minimum value in the progress bar. The default value + is 0. + + \sa QProgressBar::minimum +*/ + +/*! + \variable QStyleOptionProgressBar::maximum + \brief the maximum value for the progress bar + + This is the maximum value in the progress bar. The default value + is 0. + + \sa QProgressBar::maximum +*/ + +/*! + \variable QStyleOptionProgressBar::text + \brief the text for the progress bar + + The progress bar text is usually just the progress expressed as a + string. An empty string indicates that the progress bar has not + started yet. The default value is an empty string. + + \sa QProgressBar::text +*/ + +/*! + \variable QStyleOptionProgressBar::textVisible + \brief a flag indicating whether or not text is visible + + If this flag is true then the text is visible. Otherwise, the text + is not visible. The default value is false. + + \sa QProgressBar::textVisible +*/ + + +/*! + \variable QStyleOptionProgressBar::textAlignment + \brief the text alignment for the text in the QProgressBar + + This can be used as a guide on where the text should be in the + progress bar. The default value is Qt::AlignLeft. +*/ + +/*! + \variable QStyleOptionProgressBar::progress + \brief the current progress for the progress bar + + The current progress. A value of QStyleOptionProgressBar::minimum + - 1 indicates that the progress hasn't started yet. The default + value is 0. + + \sa QProgressBar::value +*/ + +/*! + \class QStyleOptionProgressBarV2 + \brief The QStyleOptionProgressBarV2 class is used to describe the + parameters necessary for drawing a progress bar in Qt 4.1 or above. + + \since 4.1 + + An instance of this class has \l{QStyleOption::type} {type} + SO_ProgressBar and \l{QStyleOption::version} {version} 2. + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. The + version is used by QStyleOption subclasses to implement extensions + without breaking compatibility. If you use qstyleoption_cast(), + you normally do not need to check it. + + If you create your own QStyle subclass, you should handle both + QStyleOptionProgressBar and QStyleOptionProgressBarV2. One way + to achieve this is to use the QStyleOptionProgressBarV2 copy + constructor. For example: + + \snippet doc/src/snippets/qstyleoption/main.cpp 2 + + In the example above: If the \c progressBarOption's version is 1, + the extra members (\l orientation, \l invertedAppearance, and \l + bottomToTop) are set to default values for \c progressBarV2. If + the \c progressBarOption's version is 2, the constructor will + simply copy the extra members to progressBarV2. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOptionProgressBar, QStyleOption +*/ + +/*! + Constructs a QStyleOptionProgressBarV2, initializing he members + variables to their default values. +*/ + +QStyleOptionProgressBarV2::QStyleOptionProgressBarV2() + : QStyleOptionProgressBar(2), + orientation(Qt::Horizontal), invertedAppearance(false), bottomToTop(false) +{ +} + +/*! + \internal +*/ +QStyleOptionProgressBarV2::QStyleOptionProgressBarV2(int version) + : QStyleOptionProgressBar(version), + orientation(Qt::Horizontal), invertedAppearance(false), bottomToTop(false) +{ +} + +/*! + Constructs a copy of the \a other style option which can be either + of the QStyleOptionProgressBar and QStyleOptionProgressBarV2 + types. + + If the \a{other} style option's version is 1, the extra members (\l + orientation, \l invertedAppearance, and \l bottomToTop) are set + to default values for the new style option. If \a{other}'s version + is 2, the extra members are simply copied. + + \sa version +*/ +QStyleOptionProgressBarV2::QStyleOptionProgressBarV2(const QStyleOptionProgressBar &other) + : QStyleOptionProgressBar(2), orientation(Qt::Horizontal), invertedAppearance(false), bottomToTop(false) +{ + const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(&other); + if (pb2) + *this = *pb2; + else + *((QStyleOptionProgressBar *)this) = other; +} + +/*! + Constructs a copy of the \a other style option. +*/ +QStyleOptionProgressBarV2::QStyleOptionProgressBarV2(const QStyleOptionProgressBarV2 &other) + : QStyleOptionProgressBar(2), orientation(Qt::Horizontal), invertedAppearance(false), bottomToTop(false) +{ + *this = other; +} + +/*! + Assigns the \a other style option to this style option. The \a + other style option can be either of the QStyleOptionProgressBarV2 + or QStyleOptionProgressBar types. + + If the \a{other} style option's version is 1, the extra members + (\l orientation, \l invertedAppearance, and \l bottomToTop) are + set to default values for this style option. If \a{other}'s + version is 2, the extra members are simply copied to this style + option. +*/ +QStyleOptionProgressBarV2 &QStyleOptionProgressBarV2::operator=(const QStyleOptionProgressBar &other) +{ + QStyleOptionProgressBar::operator=(other); + + const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(&other); + orientation = pb2 ? pb2->orientation : Qt::Horizontal; + invertedAppearance = pb2 ? pb2->invertedAppearance : false; + bottomToTop = pb2 ? pb2->bottomToTop : false; + return *this; +} + +/*! + \variable QStyleOptionProgressBarV2::orientation + \brief the progress bar's orientation (horizontal or vertical); + the default orentation is Qt::Horizontal + + \sa QProgressBar::orientation +*/ + +/*! + \variable QStyleOptionProgressBarV2::invertedAppearance + \brief whether the progress bar's appearance is inverted + + The default value is false. + + \sa QProgressBar::invertedAppearance +*/ + +/*! + \variable QStyleOptionProgressBarV2::bottomToTop + \brief whether the text reads from bottom to top when the progress + bar is vertical + + The default value is false. + + \sa QProgressBar::textDirection +*/ + +/*! + \enum QStyleOptionProgressBarV2::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_ProgressBar} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionProgressBarV2::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 2 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + + +/*! + \class QStyleOptionMenuItem + \brief The QStyleOptionMenuItem class is used to describe the + parameter necessary for drawing a menu item. + + QStyleOptionMenuItem contains all the information that QStyle + functions need to draw the menu items from \l QMenu. It is also + used for drawing other menu-related widgets. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption +*/ + +/*! + Constructs a QStyleOptionMenuItem, initializing the members + variables to their default values. +*/ + +QStyleOptionMenuItem::QStyleOptionMenuItem() + : QStyleOption(QStyleOptionMenuItem::Version, SO_MenuItem), menuItemType(Normal), + checkType(NotCheckable), checked(false), menuHasCheckableItems(true), maxIconWidth(0), tabWidth(0) +{ +} + +/*! + \internal +*/ +QStyleOptionMenuItem::QStyleOptionMenuItem(int version) + : QStyleOption(version, SO_MenuItem), menuItemType(Normal), + checkType(NotCheckable), checked(false), menuHasCheckableItems(true), maxIconWidth(0), tabWidth(0) +{ +} + +/*! + \fn QStyleOptionMenuItem::QStyleOptionMenuItem(const QStyleOptionMenuItem &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionMenuItem::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_MenuItem} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionMenuItem::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \enum QStyleOptionMenuItem::MenuItemType + + This enum indicates the type of menu item that the structure describes. + + \value Normal A normal menu item. + \value DefaultItem A menu item that is the default action as specified with \l QMenu::defaultAction(). + \value Separator A menu separator. + \value SubMenu Indicates the menu item points to a sub-menu. + \value Scroller A popup menu scroller (currently only used on Mac OS X). + \value TearOff A tear-off handle for the menu. + \value Margin The margin of the menu. + \value EmptyArea The empty area of the menu. + + \sa menuItemType +*/ + +/*! + \enum QStyleOptionMenuItem::CheckType + + This enum is used to indicate whether or not a check mark should be + drawn for the item, or even if it should be drawn at all. + + \value NotCheckable The item is not checkable. + \value Exclusive The item is an exclusive check item (like a radio button). + \value NonExclusive The item is a non-exclusive check item (like a check box). + + \sa checkType, QAction::checkable, QAction::checked, QActionGroup::exclusive +*/ + +/*! + \variable QStyleOptionMenuItem::menuItemType + \brief the type of menu item + + The default value is \l Normal. + + \sa MenuItemType +*/ + +/*! + \variable QStyleOptionMenuItem::checkType + \brief the type of checkmark of the menu item + + The default value is \l NotCheckable. + + \sa CheckType +*/ + +/*! + \variable QStyleOptionMenuItem::checked + \brief whether the menu item is checked or not + + The default value is false. +*/ + +/*! + \variable QStyleOptionMenuItem::menuHasCheckableItems + \brief whether the menu as a whole has checkable items or not + + The default value is true. + + If this option is set to false, then the menu has no checkable + items. This makes it possible for GUI styles to save some + horizontal space that would normally be used for the check column. +*/ + +/*! + \variable QStyleOptionMenuItem::menuRect + \brief the rectangle for the entire menu + + The default value is a null rectangle, i.e. a rectangle with both + the width and the height set to 0. +*/ + +/*! + \variable QStyleOptionMenuItem::text + \brief the text for the menu item + + Note that the text format is something like this "Menu + text\bold{\\t}Shortcut". + + If the menu item doesn't have a shortcut, it will just contain the + menu item's text. The default value is an empty string. +*/ + +/*! + \variable QStyleOptionMenuItem::icon + \brief the icon for the menu item + + The default value is an empty icon, i.e. an icon with neither a + pixmap nor a filename. +*/ + +/*! + \variable QStyleOptionMenuItem::maxIconWidth + \brief the maximum icon width for the icon in the menu item + + This can be used for drawing the icon into the correct place or + properly aligning items. The variable must be set regardless of + whether or not the menu item has an icon. The default value is 0. +*/ + +/*! + \variable QStyleOptionMenuItem::tabWidth + \brief the tab width for the menu item + + The tab width is the distance between the text of the menu item + and the shortcut. The default value is 0. +*/ + + +/*! + \variable QStyleOptionMenuItem::font + \brief the font used for the menu item text + + This is the font that should be used for drawing the menu text + minus the shortcut. The shortcut is usually drawn using the + painter's font. By default, the application's default font is + used. +*/ + +/*! + \class QStyleOptionComplex + \brief The QStyleOptionComplex class is used to hold parameters that are + common to all complex controls. + + This class is not used on its own. Instead it is used to derive + other complex control options, for example QStyleOptionSlider and + QStyleOptionSpinBox. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption +*/ + +/*! + Constructs a QStyleOptionComplex of the specified \a type and \a + version, initializing the member variables to their default + values. This constructor is usually called by subclasses. +*/ + +QStyleOptionComplex::QStyleOptionComplex(int version, int type) + : QStyleOption(version, type), subControls(QStyle::SC_All), activeSubControls(QStyle::SC_None) +{ +} + +/*! + \fn QStyleOptionComplex::QStyleOptionComplex(const QStyleOptionComplex &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionComplex::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_Complex} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionComplex::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionComplex::subControls + + This variable holds a bitwise OR of the \l{QStyle::SubControl} + {sub-controls} to be drawn for the complex control. + + The default value is QStyle::SC_All. + + \sa QStyle::SubControl +*/ + +/*! + \variable QStyleOptionComplex::activeSubControls + + This variable holds a bitwise OR of the \l{QStyle::SubControl} + {sub-controls} that are active for the complex control. + + The default value is QStyle::SC_None. + + \sa QStyle::SubControl +*/ + +#ifndef QT_NO_SLIDER +/*! + \class QStyleOptionSlider + \brief The QStyleOptionSlider class is used to describe the + parameters needed for drawing a slider. + + QStyleOptionSlider contains all the information that QStyle + functions need to draw QSlider and QScrollBar. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOptionComplex, QSlider, QScrollBar +*/ + +/*! + Constructs a QStyleOptionSlider, initializing the members + variables to their default values. +*/ + +QStyleOptionSlider::QStyleOptionSlider() + : QStyleOptionComplex(Version, SO_Slider), orientation(Qt::Horizontal), minimum(0), maximum(0), + tickPosition(QSlider::NoTicks), tickInterval(0), upsideDown(false), + sliderPosition(0), sliderValue(0), singleStep(0), pageStep(0), notchTarget(0.0), + dialWrapping(false) +{ +} + +/*! + \internal +*/ +QStyleOptionSlider::QStyleOptionSlider(int version) + : QStyleOptionComplex(version, SO_Slider), orientation(Qt::Horizontal), minimum(0), maximum(0), + tickPosition(QSlider::NoTicks), tickInterval(0), upsideDown(false), + sliderPosition(0), sliderValue(0), singleStep(0), pageStep(0), notchTarget(0.0), + dialWrapping(false) +{ +} + +/*! + \fn QStyleOptionSlider::QStyleOptionSlider(const QStyleOptionSlider &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionSlider::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_Slider} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionSlider::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionSlider::orientation + \brief the slider's orientation (horizontal or vertical) + + The default orientation is Qt::Horizontal. + + \sa Qt::Orientation +*/ + +/*! + \variable QStyleOptionSlider::minimum + \brief the minimum value for the slider + + The default value is 0. +*/ + +/*! + \variable QStyleOptionSlider::maximum + \brief the maximum value for the slider + + The default value is 0. +*/ + +/*! + \variable QStyleOptionSlider::tickPosition + \brief the position of the slider's tick marks, if any + + The default value is QSlider::NoTicks. + + \sa QSlider::TickPosition +*/ + +/*! + \variable QStyleOptionSlider::tickInterval + \brief the interval that should be drawn between tick marks + + The default value is 0. +*/ + +/*! + \variable QStyleOptionSlider::notchTarget + \brief the number of pixel between notches + + The default value is 0.0. + + \sa QDial::notchTarget() +*/ + +/*! + \variable QStyleOptionSlider::dialWrapping + \brief whether the dial should wrap or not + + The default value is false, i.e. the dial is not wrapped. + + \sa QDial::wrapping() +*/ + +/*! + \variable QStyleOptionSlider::upsideDown + \brief the slider control orientation + + Normally a slider increases as it moves up or to the right; + upsideDown indicates that it should do the opposite (increase as + it moves down or to the left). The default value is false, + i.e. the slider increases as it moves up or to the right. + + \sa QStyle::sliderPositionFromValue(), + QStyle::sliderValueFromPosition(), + QAbstractSlider::invertedAppearance +*/ + +/*! + \variable QStyleOptionSlider::sliderPosition + \brief the position of the slider handle + + If the slider has active feedback (i.e., + QAbstractSlider::tracking is true), this value will be the same as + \l sliderValue. Otherwise, it will have the current position of + the handle. The default value is 0. + + \sa QAbstractSlider::tracking, sliderValue +*/ + +/*! + \variable QStyleOptionSlider::sliderValue + \brief the value of the slider + + If the slider has active feedback (i.e., + QAbstractSlider::tracking is true), this value will be the same + as \l sliderPosition. Otherwise, it will have the value the + slider had before the mouse was pressed. + + The default value is 0. + + \sa QAbstractSlider::tracking sliderPosition +*/ + +/*! + \variable QStyleOptionSlider::singleStep + \brief the size of the single step of the slider + + The default value is 0. + + \sa QAbstractSlider::singleStep +*/ + +/*! + \variable QStyleOptionSlider::pageStep + \brief the size of the page step of the slider + + The default value is 0. + + \sa QAbstractSlider::pageStep +*/ +#endif // QT_NO_SLIDER + +#ifndef QT_NO_SPINBOX +/*! + \class QStyleOptionSpinBox + \brief The QStyleOptionSpinBox class is used to describe the + parameters necessary for drawing a spin box. + + QStyleOptionSpinBox contains all the information that QStyle + functions need to draw QSpinBox and QDateTimeEdit. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QStyleOptionComplex +*/ + +/*! + Constructs a QStyleOptionSpinBox, initializing the members + variables to their default values. +*/ + +QStyleOptionSpinBox::QStyleOptionSpinBox() + : QStyleOptionComplex(Version, SO_SpinBox), buttonSymbols(QAbstractSpinBox::UpDownArrows), + stepEnabled(QAbstractSpinBox::StepNone), frame(false) +{ +} + +/*! + \internal +*/ +QStyleOptionSpinBox::QStyleOptionSpinBox(int version) + : QStyleOptionComplex(version, SO_SpinBox), buttonSymbols(QAbstractSpinBox::UpDownArrows), + stepEnabled(QAbstractSpinBox::StepNone), frame(false) +{ +} + +/*! + \fn QStyleOptionSpinBox::QStyleOptionSpinBox(const QStyleOptionSpinBox &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionSpinBox::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_SpinBox} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionSpinBox::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionSpinBox::buttonSymbols + \brief the type of button symbols to draw for the spin box + + The default value is QAbstractSpinBox::UpDownArrows specufying + little arrows in the classic style. + + \sa QAbstractSpinBox::ButtonSymbols +*/ + +/*! + \variable QStyleOptionSpinBox::stepEnabled + \brief which buttons of the spin box that are enabled + + The default value is QAbstractSpinBox::StepNone. + + \sa QAbstractSpinBox::StepEnabled +*/ + +/*! + \variable QStyleOptionSpinBox::frame + \brief whether the spin box has a frame + + The default value is false, i.e. the spin box has no frame. +*/ +#endif // QT_NO_SPINBOX + +/*! + \class QStyleOptionQ3ListViewItem + \brief The QStyleOptionQ3ListViewItem class is used to describe an + item drawn in a Q3ListView. + + This class is used for drawing the compatibility Q3ListView's + items. \bold {It is not recommended for new classes}. + + QStyleOptionQ3ListViewItem contains all the information that + QStyle functions need to draw the Q3ListView items. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QStyleOptionQ3ListView, Q3ListViewItem +*/ + +/*! + \enum QStyleOptionQ3ListViewItem::Q3ListViewItemFeature + + This enum describes the features a list view item can have. + + \value None A standard item. + \value Expandable The item has children that can be shown. + \value MultiLine The item is more than one line tall. + \value Visible The item is visible. + \value ParentControl The item's parent is a type of item control (Q3CheckListItem::Controller). + + \sa features, Q3ListViewItem::isVisible(), Q3ListViewItem::multiLinesEnabled(), + Q3ListViewItem::isExpandable() +*/ + +/*! + Constructs a QStyleOptionQ3ListViewItem, initializing the members + variables to their default values. +*/ + +QStyleOptionQ3ListViewItem::QStyleOptionQ3ListViewItem() + : QStyleOption(Version, SO_Q3ListViewItem), features(None), height(0), totalHeight(0), + itemY(0), childCount(0) +{ +} + +/*! + \internal +*/ +QStyleOptionQ3ListViewItem::QStyleOptionQ3ListViewItem(int version) + : QStyleOption(version, SO_Q3ListViewItem), features(None), height(0), totalHeight(0), + itemY(0), childCount(0) +{ +} + +/*! + \fn QStyleOptionQ3ListViewItem::QStyleOptionQ3ListViewItem(const QStyleOptionQ3ListViewItem &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionQ3ListViewItem::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_Q3ListViewItem} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionQ3ListViewItem::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionQ3ListViewItem::features + \brief the features for this item + + This variable is a bitwise OR of the features of the item. The deafult value is \l None. + + \sa Q3ListViewItemFeature +*/ + +/*! + \variable QStyleOptionQ3ListViewItem::height + \brief the height of the item + + This doesn't include the height of the item's children. The default height is 0. + + \sa Q3ListViewItem::height() +*/ + +/*! + \variable QStyleOptionQ3ListViewItem::totalHeight + \brief the total height of the item, including its children + + The default total height is 0. + + \sa Q3ListViewItem::totalHeight() +*/ + +/*! + \variable QStyleOptionQ3ListViewItem::itemY + \brief the Y-coordinate for the item + + The default value is 0. + + \sa Q3ListViewItem::itemPos() +*/ + +/*! + \variable QStyleOptionQ3ListViewItem::childCount + \brief the number of children the item has +*/ + +/*! + \class QStyleOptionQ3ListView + \brief The QStyleOptionQ3ListView class is used to describe the + parameters for drawing a Q3ListView. + + This class is used for drawing the compatibility Q3ListView. \bold + {It is not recommended for new classes}. + + QStyleOptionQ3ListView contains all the information that QStyle + functions need to draw Q3ListView. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOptionComplex, Q3ListView, QStyleOptionQ3ListViewItem +*/ + +/*! + Creates a QStyleOptionQ3ListView, initializing the members + variables to their default values. +*/ + +QStyleOptionQ3ListView::QStyleOptionQ3ListView() + : QStyleOptionComplex(Version, SO_Q3ListView), viewportBGRole(QPalette::Base), + sortColumn(0), itemMargin(0), treeStepSize(0), rootIsDecorated(false) +{ +} + +/*! + \internal +*/ +QStyleOptionQ3ListView::QStyleOptionQ3ListView(int version) + : QStyleOptionComplex(version, SO_Q3ListView), viewportBGRole(QPalette::Base), + sortColumn(0), itemMargin(0), treeStepSize(0), rootIsDecorated(false) +{ +} + +/*! + \fn QStyleOptionQ3ListView::QStyleOptionQ3ListView(const QStyleOptionQ3ListView &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionQ3ListView::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_Q3ListView} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionQ3ListView::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionQ3ListView::items + \brief a list of items in the Q3ListView + + This is a list of \l {QStyleOptionQ3ListViewItem}s. The first item + can be used for most of the calculation that are needed for + drawing a list view. Any additional items are the children of + this first item, which may be used for additional information. + + \sa QStyleOptionQ3ListViewItem +*/ + +/*! + \variable QStyleOptionQ3ListView::viewportPalette + \brief the palette of Q3ListView's viewport + + By default, the application's default palette is used. +*/ + +/*! + \variable QStyleOptionQ3ListView::viewportBGRole + \brief the background role of Q3ListView's viewport + + The default value is QPalette::Base. + + \sa QWidget::backgroundRole() +*/ + +/*! + \variable QStyleOptionQ3ListView::sortColumn + \brief the sort column of the list view + + The default value is 0. + + \sa Q3ListView::sortColumn() +*/ + +/*! + \variable QStyleOptionQ3ListView::itemMargin + \brief the margin for items in the list view + + The default value is 0. + + \sa Q3ListView::itemMargin() +*/ + +/*! + \variable QStyleOptionQ3ListView::treeStepSize + \brief the number of pixel to offset children items from their + parents + + The default value is 0. + + \sa Q3ListView::treeStepSize() +*/ + +/*! + \variable QStyleOptionQ3ListView::rootIsDecorated + \brief whether root items are decorated + + The default value is false. + + \sa Q3ListView::rootIsDecorated() +*/ + +/*! + \class QStyleOptionQ3DockWindow + \brief The QStyleOptionQ3DockWindow class is used to describe the + parameters for drawing various parts of a Q3DockWindow. + + This class is used for drawing the old Q3DockWindow and its + parts. \bold {It is not recommended for new classes}. + + QStyleOptionQ3DockWindow contains all the information that QStyle + functions need to draw Q3DockWindow and its parts. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, Q3DockWindow +*/ + +/*! + Constructs a QStyleOptionQ3DockWindow, initializing the member + variables to their default values. +*/ + +QStyleOptionQ3DockWindow::QStyleOptionQ3DockWindow() + : QStyleOption(Version, SO_Q3DockWindow), docked(false), closeEnabled(false) +{ +} + +/*! + \internal +*/ +QStyleOptionQ3DockWindow::QStyleOptionQ3DockWindow(int version) + : QStyleOption(version, SO_Q3DockWindow), docked(false), closeEnabled(false) +{ +} + +/*! + \fn QStyleOptionQ3DockWindow::QStyleOptionQ3DockWindow(const QStyleOptionQ3DockWindow &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionQ3DockWindow::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_Q3DockWindow} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionQ3DockWindow::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionQ3DockWindow::docked + \brief whether the dock window is currently docked + + The default value is false. +*/ + +/*! + \variable QStyleOptionQ3DockWindow::closeEnabled + \brief whether the dock window has a close button + + The default value is false. +*/ + +/*! + \class QStyleOptionDockWidget + \brief The QStyleOptionDockWidget class is used to describe the + parameters for drawing a dock widget. + + QStyleOptionDockWidget contains all the information that QStyle + functions need to draw graphical elements like QDockWidget. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption +*/ + +/*! + Constructs a QStyleOptionDockWidget, initializing the member + variables to their default values. +*/ + +QStyleOptionDockWidget::QStyleOptionDockWidget() + : QStyleOption(Version, SO_DockWidget), closable(false), + movable(false), floatable(false) +{ +} + +/*! + \internal +*/ +QStyleOptionDockWidget::QStyleOptionDockWidget(int version) + : QStyleOption(version, SO_DockWidget), closable(false), + movable(false), floatable(false) +{ +} + +QStyleOptionDockWidgetV2::QStyleOptionDockWidgetV2() + : QStyleOptionDockWidget(Version), verticalTitleBar(false) +{ +} + +QStyleOptionDockWidgetV2::QStyleOptionDockWidgetV2( + const QStyleOptionDockWidget &other) + : QStyleOptionDockWidget(Version) +{ + (void)QStyleOptionDockWidgetV2::operator=(other); +} + +QStyleOptionDockWidgetV2 &QStyleOptionDockWidgetV2::operator = ( + const QStyleOptionDockWidget &other) +{ + QStyleOptionDockWidget::operator=(other); + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(&other); + verticalTitleBar = v2 ? v2->verticalTitleBar : false; + return *this; +} + +QStyleOptionDockWidgetV2::QStyleOptionDockWidgetV2(int version) + : QStyleOptionDockWidget(version), verticalTitleBar(false) +{ +} + +/*! + \fn QStyleOptionDockWidget::QStyleOptionDockWidget(const QStyleOptionDockWidget &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionDockWidget::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_DockWidget} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionDockWidget::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionDockWidget::title + \brief the title of the dock window + + The default value is an empty string. +*/ + +/*! + \variable QStyleOptionDockWidget::closable + \brief whether the dock window is closable + + The default value is true. +*/ + +/*! + \variable QStyleOptionDockWidget::movable + \brief whether the dock window is movable + + The default value is false. +*/ + +/*! + \variable QStyleOptionDockWidget::floatable + \brief whether the dock window is floatable + + The default value is true. +*/ + +/*! + \class QStyleOptionToolButton + \brief The QStyleOptionToolButton class is used to describe the + parameters for drawing a tool button. + + QStyleOptionToolButton contains all the information that QStyle + functions need to draw QToolButton. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QStyleOptionComplex, QStyleOptionButton +*/ + +/*! + \enum QStyleOptionToolButton::ToolButtonFeature + Describes the various features that a tool button can have. + + \value None A normal tool button. + \value Arrow The tool button is an arrow. + \value Menu The tool button has a menu. + \value PopupDelay There is a delay to showing the menu. + \value HasMenu The button has a popup menu. + \value MenuButtonPopup The button should display an arrow to + indicate that a menu is present. + + \sa features, QToolButton::toolButtonStyle(), QToolButton::popupMode() +*/ + +/*! + Constructs a QStyleOptionToolButton, initializing the members + variables to their default values. +*/ + +QStyleOptionToolButton::QStyleOptionToolButton() + : QStyleOptionComplex(Version, SO_ToolButton), features(None), arrowType(Qt::DownArrow) + , toolButtonStyle(Qt::ToolButtonIconOnly) +{ +} + +/*! + \internal +*/ +QStyleOptionToolButton::QStyleOptionToolButton(int version) + : QStyleOptionComplex(version, SO_ToolButton), features(None), arrowType(Qt::DownArrow) + , toolButtonStyle(Qt::ToolButtonIconOnly) + +{ +} + +/*! + \fn QStyleOptionToolButton::QStyleOptionToolButton(const QStyleOptionToolButton &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionToolButton::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_ToolButton} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionToolButton::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionToolButton::features + \brief an OR combination of the tool button's features + + The default value is \l None. + + \sa ToolButtonFeature +*/ + +/*! + \variable QStyleOptionToolButton::icon + \brief the icon for the tool button + + The default value is an empty icon, i.e. an icon with neither a + pixmap nor a filename. + + \sa iconSize +*/ + +/*! + \variable QStyleOptionToolButton::iconSize + \brief the size of the icon for the tool button + + The default value is QSize(-1, -1), i.e. an invalid size. +*/ + +/*! + \variable QStyleOptionToolButton::text + \brief the text of the tool button + + This value is only used if toolButtonStyle is + Qt::ToolButtonTextUnderIcon, Qt::ToolButtonTextBesideIcon, or + Qt::ToolButtonTextOnly. The default value is an empty string. +*/ + +/*! + \variable QStyleOptionToolButton::arrowType + \brief the direction of the arrow for the tool button + + This value is only used if \l features includes \l Arrow. The + default value is Qt::DownArrow. +*/ + +/*! + \variable QStyleOptionToolButton::toolButtonStyle + \brief a Qt::ToolButtonStyle value describing the appearance of + the tool button + + The default value is Qt::ToolButtonIconOnly. + + \sa QToolButton::toolButtonStyle() +*/ + +/*! + \variable QStyleOptionToolButton::pos + \brief the position of the tool button + + The default value is a null point, i.e. (0, 0) +*/ + +/*! + \variable QStyleOptionToolButton::font + \brief the font that is used for the text + + This value is only used if toolButtonStyle is + Qt::ToolButtonTextUnderIcon, Qt::ToolButtonTextBesideIcon, or + Qt::ToolButtonTextOnly. By default, the application's default font + is used. +*/ + +/*! + \class QStyleOptionComboBox + \brief The QStyleOptionComboBox class is used to describe the + parameter for drawing a combobox. + + QStyleOptionButton contains all the information that QStyle + functions need to draw QComboBox. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QStyleOptionComplex, QComboBox +*/ + +/*! + Creates a QStyleOptionComboBox, initializing the members variables + to their default values. +*/ + +QStyleOptionComboBox::QStyleOptionComboBox() + : QStyleOptionComplex(Version, SO_ComboBox), editable(false), frame(true) +{ +} + +/*! + \internal +*/ +QStyleOptionComboBox::QStyleOptionComboBox(int version) + : QStyleOptionComplex(version, SO_ComboBox), editable(false), frame(true) +{ +} + +/*! + \fn QStyleOptionComboBox::QStyleOptionComboBox(const QStyleOptionComboBox &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionComboBox::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_ComboBox} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionComboBox::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionComboBox::editable + \brief whether or not the combobox is editable or not + + the default + value is false + + \sa QComboBox::isEditable() +*/ + + +/*! + \variable QStyleOptionComboBox::frame + \brief whether the combo box has a frame + + The default value is true. +*/ + +/*! + \variable QStyleOptionComboBox::currentText + \brief the text for the current item of the combo box + + The default value is an empty string. +*/ + +/*! + \variable QStyleOptionComboBox::currentIcon + \brief the icon for the current item of the combo box + + The default value is an empty icon, i.e. an icon with neither a + pixmap nor a filename. +*/ + +/*! + \variable QStyleOptionComboBox::iconSize + \brief the icon size for the current item of the combo box + + The default value is QSize(-1, -1), i.e. an invalid size. +*/ + +/*! + \variable QStyleOptionComboBox::popupRect + \brief the popup rectangle for the combobox + + The default value is a null rectangle, i.e. a rectangle with both + the width and the height set to 0. + + This variable is currently unused. You can safely ignore it. + + \sa QStyle::SC_ComboBoxListBoxPopup +*/ + +/*! + \class QStyleOptionToolBox + \brief The QStyleOptionToolBox class is used to describe the + parameters needed for drawing a tool box. + + QStyleOptionToolBox contains all the information that QStyle + functions need to draw QToolBox. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QToolBox +*/ + +/*! + Creates a QStyleOptionToolBox, initializing the members variables + to their default values. +*/ + +QStyleOptionToolBox::QStyleOptionToolBox() + : QStyleOption(Version, SO_ToolBox) +{ +} + +/*! + \internal +*/ +QStyleOptionToolBox::QStyleOptionToolBox(int version) + : QStyleOption(version, SO_ToolBox) +{ +} + +/*! + \fn QStyleOptionToolBox::QStyleOptionToolBox(const QStyleOptionToolBox &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionToolBox::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_ToolBox} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionToolBox::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionToolBox::icon + \brief the icon for the tool box tab + + The default value is an empty icon, i.e. an icon with neither a + pixmap nor a filename. +*/ + +/*! + \variable QStyleOptionToolBox::text + \brief the text for the tool box tab + + The default value is an empty string. +*/ + +/*! + \class QStyleOptionToolBoxV2 + \brief The QStyleOptionToolBoxV2 class is used to describe the parameters necessary for drawing a frame in Qt 4.3 or above. + + \since 4.3 + QStyleOptionToolBoxV2 inherits QStyleOptionToolBox which is used for + drawing the tabs in a QToolBox. + + An instance of the QStyleOptionToolBoxV2 class has + \l{QStyleOption::type} {type} SO_ToolBox and + \l{QStyleOption::version} {version} 2. The type is used + internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. The + version is used by QStyleOption subclasses to implement extensions + without breaking compatibility. If you use qstyleoption_cast(), + you normally do not need to check it. + + If you create your own QStyle subclass, you should handle both + QStyleOptionToolBox and QStyleOptionToolBoxV2. + + \sa QStyleOptionToolBox, QStyleOption +*/ + +/*! + Contsructs a QStyleOptionToolBoxV2 object. +*/ +QStyleOptionToolBoxV2::QStyleOptionToolBoxV2() + : QStyleOptionToolBox(Version), position(Beginning), selectedPosition(NotAdjacent) +{ +} + +/*! + \fn QStyleOptionToolBoxV2::QStyleOptionToolBoxV2(const QStyleOptionToolBoxV2 &other) + + Constructs a QStyleOptionToolBoxV2 copy of the \a other style option. +*/ + +/*! + \internal +*/ +QStyleOptionToolBoxV2::QStyleOptionToolBoxV2(int version) + : QStyleOptionToolBox(version), position(Beginning), selectedPosition(NotAdjacent) +{ +} + +/*! + Constructs a QStyleOptionToolBoxV2 copy of the \a other style option + which can be either of the QStyleOptionToolBoxV2 or + QStyleOptionToolBox types. + + If the \a other style option's version is 1, the new style + option's \l{QStyleOptionTab::position} {position} value is set to + \l QStyleOptionToolBoxV2::Beginning and \l selectedPosition is set + to \l QStyleOptionToolBoxV2::NotAdjacent. If its version is 2, the + \l{QStyleOptionTab::position} {position} selectedPosition values + are simply copied to the new style option. + + \sa version +*/ +QStyleOptionToolBoxV2::QStyleOptionToolBoxV2(const QStyleOptionToolBox &other) +{ + QStyleOptionToolBox::operator=(other); + + const QStyleOptionToolBoxV2 *f2 = qstyleoption_cast(&other); + position = f2 ? f2->position : Beginning; + selectedPosition = f2 ? f2->selectedPosition : NotAdjacent; + version = Version; +} + +/*! + Assigns the \a other style option to this style option. The \a + other style option can be either of the QStyleOptionToolBoxV2 or + QStyleOptionToolBox types. + + If the \a{other} style option's version is 1, this style option's + \l{QStyleOptionTab::position} {position} and \l selectedPosition + values are set to \l QStyleOptionToolBoxV2::Beginning and \l + QStyleOptionToolBoxV2::NotAdjacent respectively. If its + \l{QStyleOption::version} {version} is 2, these values are simply + copied to this style option. +*/ +QStyleOptionToolBoxV2 &QStyleOptionToolBoxV2::operator=(const QStyleOptionToolBox &other) +{ + QStyleOptionToolBox::operator=(other); + + const QStyleOptionToolBoxV2 *f2 = qstyleoption_cast(&other); + position = f2 ? f2->position : Beginning; + selectedPosition = f2 ? f2->selectedPosition : NotAdjacent; + version = Version; + return *this; +} + + +/*! + \enum QStyleOptionToolBoxV2::SelectedPosition + + This enum describes the position of the selected tab. Some styles + need to draw a tab differently depending on whether or not it is + adjacent to the selected tab. + + \value NotAdjacent The tab is not adjacent to a selected tab (or is the selected tab). + \value NextIsSelected The next tab (typically the tab on the right) is selected. + \value PreviousIsSelected The previous tab (typically the tab on the left) is selected. + + \sa selectedPosition +*/ + +/*! + \enum QStyleOptionToolBoxV2::StyleOptionVersion + + This enum holds the version of this style option + + \value Version 2 +*/ + +/*! + \enum QStyleOptionToolBoxV2::TabPosition + + This enum describes tab positions relative to other tabs. + + \value Beginning The tab is the first (i.e., top-most) tab in + the toolbox. + \value Middle The tab is placed in the middle of the toolbox. + \value End The tab is placed at the bottom of the toolbox. + \value OnlyOneTab There is only one tab in the toolbox. +*/ + +/*! + \variable QStyleOptionToolBoxV2::selectedPosition + \brief the position of the selected tab in relation to this tab + + The default value is NotAdjacent, i.e. the tab is not adjacent to + a selected tab nor is it the selected tab. +*/ + +#ifndef QT_NO_RUBBERBAND +/*! + \class QStyleOptionRubberBand + \brief The QStyleOptionRubberBand class is used to describe the + parameters needed for drawing a rubber band. + + QStyleOptionRubberBand contains all the information that + QStyle functions need to draw QRubberBand. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QRubberBand +*/ + +/*! + Creates a QStyleOptionRubberBand, initializing the members + variables to their default values. +*/ + +QStyleOptionRubberBand::QStyleOptionRubberBand() + : QStyleOption(Version, SO_RubberBand), shape(QRubberBand::Line), opaque(false) +{ +} + +/*! + \internal +*/ +QStyleOptionRubberBand::QStyleOptionRubberBand(int version) + : QStyleOption(version, SO_RubberBand), shape(QRubberBand::Line), opaque(false) +{ +} + +/*! + \fn QStyleOptionRubberBand::QStyleOptionRubberBand(const QStyleOptionRubberBand &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionRubberBand::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_RubberBand} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionRubberBand::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionRubberBand::shape + \brief the shape of the rubber band + + The default shape is QRubberBand::Line. +*/ + +/*! + \variable QStyleOptionRubberBand::opaque + \brief whether the rubber band is required to be drawn in an opaque style + + The default value is true. +*/ +#endif // QT_NO_RUBBERBAND + +/*! + \class QStyleOptionTitleBar + \brief The QStyleOptionTitleBar class is used to describe the + parameters for drawing a title bar. + + QStyleOptionTitleBar contains all the information that QStyle + functions need to draw the title bar of a QMdiSubWindow. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QStyleOptionComplex, QMdiSubWindow +*/ + +/*! + Constructs a QStyleOptionTitleBar, initializing the members + variables to their default values. +*/ + +QStyleOptionTitleBar::QStyleOptionTitleBar() + : QStyleOptionComplex(Version, SO_TitleBar), titleBarState(0), titleBarFlags(0) +{ +} + +/*! + \fn QStyleOptionTitleBar::QStyleOptionTitleBar(const QStyleOptionTitleBar &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionTitleBar::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_TitleBar} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionTitleBar::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \internal +*/ +QStyleOptionTitleBar::QStyleOptionTitleBar(int version) + : QStyleOptionComplex(version, SO_TitleBar), titleBarState(0), titleBarFlags(0) +{ +} + + +/*! + \variable QStyleOptionTitleBar::text + \brief the text of the title bar + + The default value is an empty string. +*/ + +/*! + \variable QStyleOptionTitleBar::icon + \brief the icon for the title bar + + The default value is an empty icon, i.e. an icon with neither a + pixmap nor a filename. +*/ + +/*! + \variable QStyleOptionTitleBar::titleBarState + \brief the state of the title bar + + This is basically the window state of the underlying widget. The + default value is 0. + + \sa QWidget::windowState() +*/ + +/*! + \variable QStyleOptionTitleBar::titleBarFlags + \brief the widget flags for the title bar + + The default value is Qt::Widget. + + \sa Qt::WindowFlags +*/ + +/*! + \class QStyleOptionViewItem + \brief The QStyleOptionViewItem class is used to describe the + parameters used to draw an item in a view widget. + + QStyleOptionViewItem contains all the information that QStyle + functions need to draw the items for Qt's model/view classes. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, {model-view-programming.html}{Model/View + Programming} +*/ + +/*! + \enum QStyleOptionViewItem::Position + + This enum describes the position of the item's decoration. + + \value Left On the left of the text. + \value Right On the right of the text. + \value Top Above the text. + \value Bottom Below the text. + + \sa decorationPosition +*/ + +/*! + \variable QStyleOptionViewItem::showDecorationSelected + \brief whether the decoration should be highlighted on selected + items + + If this option is true, the branch and any decorations on selected items + should be highlighted, indicating that the item is selected; otherwise, no + highlighting is required. The default value is false. + + \sa QStyle::SH_ItemView_ShowDecorationSelected, QAbstractItemView +*/ + +/*! + \variable QStyleOptionViewItem::textElideMode + \brief where ellipsis should be added for text that is too long to fit + into an item + + The default value is Qt::ElideMiddle, i.e. the ellipsis appears in + the middle of the text. + + \sa Qt::TextElideMode, QStyle::SH_ItemView_EllipsisLocation +*/ + +/*! + Constructs a QStyleOptionViewItem, initializing the members + variables to their default values. +*/ + +QStyleOptionViewItem::QStyleOptionViewItem() + : QStyleOption(Version, SO_ViewItem), + displayAlignment(Qt::AlignLeft), decorationAlignment(Qt::AlignLeft), + textElideMode(Qt::ElideMiddle), decorationPosition(Left), + showDecorationSelected(false) +{ +} + +/*! + \internal +*/ +QStyleOptionViewItem::QStyleOptionViewItem(int version) + : QStyleOption(version, SO_ViewItem), + displayAlignment(Qt::AlignLeft), decorationAlignment(Qt::AlignLeft), + textElideMode(Qt::ElideMiddle), decorationPosition(Left), + showDecorationSelected(false) +{ +} + +/*! + \fn QStyleOptionViewItem::QStyleOptionViewItem(const QStyleOptionViewItem &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \enum QStyleOptionViewItem::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_ViewItem} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionViewItem::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionViewItem::displayAlignment + \brief the alignment of the display value for the item + + The default value is Qt::AlignLeft. +*/ + +/*! + \variable QStyleOptionViewItem::decorationAlignment + \brief the alignment of the decoration for the item + + The default value is Qt::AlignLeft. +*/ + +/*! + \variable QStyleOptionViewItem::decorationPosition + \brief the position of the decoration for the item + + The default value is \l Left. + + \sa Position +*/ + +/*! + \variable QStyleOptionViewItem::decorationSize + \brief the size of the decoration for the item + + The default value is QSize(-1, -1), i.e. an invalid size. + + \sa decorationAlignment, decorationPosition +*/ + +/*! + \variable QStyleOptionViewItem::font + \brief the font used for the item + + By default, the application's default font is used. + + \sa QFont +*/ + +/*! + \fn T qstyleoption_cast(const QStyleOption *option) + \relates QStyleOption + + Returns a T or 0 depending on the \l{QStyleOption::type}{type} and + \l{QStyleOption::version}{version} of the given \a option. + + Example: + + \snippet doc/src/snippets/qstyleoption/main.cpp 4 + + \sa QStyleOption::type, QStyleOption::version +*/ + +/*! + \fn T qstyleoption_cast(QStyleOption *option) + \overload + \relates QStyleOption + + Returns a T or 0 depending on the type of the given \a option. +*/ + +#ifndef QT_NO_TABWIDGET +/*! + \class QStyleOptionTabWidgetFrame + \brief The QStyleOptionTabWidgetFrame class is used to describe the + parameters for drawing the frame around a tab widget. + + QStyleOptionTabWidgetFrame contains all the information that + QStyle functions need to draw the frame around QTabWidget. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QTabWidget +*/ + +/*! + Constructs a QStyleOptionTabWidgetFrame, initializing the members + variables to their default values. +*/ +QStyleOptionTabWidgetFrame::QStyleOptionTabWidgetFrame() + : QStyleOption(Version, SO_TabWidgetFrame), lineWidth(0), midLineWidth(0), + shape(QTabBar::RoundedNorth) +{ +} + +/*! + \fn QStyleOptionTabWidgetFrame::QStyleOptionTabWidgetFrame(const QStyleOptionTabWidgetFrame &other) + + Constructs a copy of \a other. +*/ + +/*! \internal */ +QStyleOptionTabWidgetFrame::QStyleOptionTabWidgetFrame(int version) + : QStyleOption(version, SO_TabWidgetFrame), lineWidth(0), midLineWidth(0), + shape(QTabBar::RoundedNorth) +{ +} + +/*! + \enum QStyleOptionTabWidgetFrame::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_TabWidgetFrame} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionTabWidgetFrame::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionTabWidgetFrame::lineWidth + \brief the line width for drawing the panel + + The default value is 0. +*/ + +/*! + \variable QStyleOptionTabWidgetFrame::midLineWidth + \brief the mid-line width for drawing the panel + + The mid line width is usually used in drawing sunken or raised + frames. The default value is 0. +*/ + +/*! + \variable QStyleOptionTabWidgetFrame::shape + \brief the tab shape used to draw the tabs + + The default value is QTabBar::RoundedNorth. +*/ + +/*! + \variable QStyleOptionTabWidgetFrame::tabBarSize + \brief the size of the tab bar + + The default value is QSize(-1, -1), i.e. an invalid size. +*/ + +/*! + \variable QStyleOptionTabWidgetFrame::rightCornerWidgetSize + \brief the size of the right-corner widget + + The default value is QSize(-1, -1), i.e. an invalid size. +*/ + +/*! \variable QStyleOptionTabWidgetFrame::leftCornerWidgetSize + \brief the size of the left-corner widget + + The default value is QSize(-1, -1), i.e. an invalid size. +*/ + + +/*! + + \class QStyleOptionTabWidgetFrameV2 + \brief The QStyleOptionTabWidgetFrameV2 class is used to describe the + parameters for drawing the frame around a tab widget. + + QStyleOptionTabWidgetFrameV2 contains all the information that + QStyle functions need to draw the frame around QTabWidget. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QTabWidget +*/ + + +/*! + \variable QStyleOptionTabWidgetFrameV2::tabBarRect + \brief the rectangle containing all the tabs + + The default value is a null rectangle, i.e. a rectangle with both + the width and the height set to 0. +*/ + +/*! + \variable QStyleOptionTabWidgetFrameV2::selectedTabRect + \brief the rectangle containing the selected tab + + This rectangle is contained within the tabBarRect. The default + value is a null rectangle, i.e. a rectangle with both the width + and the height set to 0. +*/ + + +/*! + Constructs a QStyleOptionTabWidgetFrameV2, initializing the members + variables to their default values. +*/ + +QStyleOptionTabWidgetFrameV2::QStyleOptionTabWidgetFrameV2() + : QStyleOptionTabWidgetFrame(Version) +{ +} + + +/*! \internal */ +QStyleOptionTabWidgetFrameV2::QStyleOptionTabWidgetFrameV2(int version) + : QStyleOptionTabWidgetFrame(version) +{ +} + + +/*! \fn QStyleOptionTabWidgetFrameV2::QStyleOptionTabWidgetFrameV2(const QStyleOptionTabWidgetFrameV2 &other) + Constructs a QStyleOptionTabWidgetFrameV2 copy of the \a other style option. + + If the \a other style option's version is 1, the new style option's \l + selectedTabRect and tabBarRect will contain null rects + + \sa version +*/ + +/*! + Constructs a QStyleOptionTabWidgetFrameV2 copy of the \a other style option. + + If the \a other style option's version is 1, the new style option's \l + selectedTabRect and tabBarRect will contain null rects + + \sa version +*/ +QStyleOptionTabWidgetFrameV2::QStyleOptionTabWidgetFrameV2(const QStyleOptionTabWidgetFrame &other) +{ + QStyleOptionTabWidgetFrameV2::operator=(other); + +} + + +/*! + Assigns the \a other style option to this style option. The \a + other style option can be either of the QStyleOptionFrameV2 or + QStyleOptionFrame types. + + If the \a{other} style option's version is 1, this style option's + QStyleOptionFrameV2::FrameFeature value is set to + QStyleOptionFrameV2::None. If its version is 2, its + \l{QStyleOptionFrameV2::}{FrameFeature} value is simply copied to + this style option. +*/ +QStyleOptionTabWidgetFrameV2 &QStyleOptionTabWidgetFrameV2::operator=(const QStyleOptionTabWidgetFrame &other) +{ + QStyleOptionTabWidgetFrame::operator=(other); + if (const QStyleOptionTabWidgetFrameV2 *f2 = qstyleoption_cast(&other)) { + selectedTabRect = f2->selectedTabRect; + tabBarRect = f2->tabBarRect; + } + return *this; +} + + +/*! + \enum QStyleOptionTabWidgetFrameV2::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 2 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + + +#endif // QT_NO_TABWIDGET + +#ifndef QT_NO_TABBAR + +/*! + \class QStyleOptionTabBarBase + \brief The QStyleOptionTabBarBase class is used to describe + the base of a tab bar, i.e. the part that the tab bar usually + overlaps with. + + QStyleOptionTabBarBase contains all the information that QStyle + functions need to draw the tab bar base. Note that this is only + drawn for a standalone QTabBar (one that isn't part of a + QTabWidget). + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QTabBar::drawBase() +*/ + +/*! + Construct a QStyleOptionTabBarBase, initializing the members + vaiables to their default values. +*/ +QStyleOptionTabBarBase::QStyleOptionTabBarBase() + : QStyleOption(Version, SO_TabBarBase), shape(QTabBar::RoundedNorth) +{ +} + +/*! \internal */ +QStyleOptionTabBarBase::QStyleOptionTabBarBase(int version) + : QStyleOption(version, SO_TabBarBase), shape(QTabBar::RoundedNorth) +{ +} + +/*! + \fn QStyleOptionTabBarBase::QStyleOptionTabBarBase(const QStyleOptionTabBarBase &other) + + Constructs a copy of \a other. +*/ + +/*! + \enum QStyleOptionTabBarBase::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_TabBarBase} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionTabBarBase::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionTabBarBase::shape + \brief the shape of the tab bar + + The default value is QTabBar::RoundedNorth. +*/ + +/*! + \variable QStyleOptionTabBarBase::tabBarRect + \brief the rectangle containing all the tabs + + The default value is a null rectangle, i.e. a rectangle with both + the width and the height set to 0. +*/ + +/*! + \variable QStyleOptionTabBarBase::selectedTabRect + \brief the rectangle containing the selected tab + + This rectangle is contained within the tabBarRect. The default + value is a null rectangle, i.e. a rectangle with both the width + and the height set to 0. +*/ + + +/*! + \class QStyleOptionTabBarBaseV2 + \brief The QStyleOptionTabBarBaseV2 class is used to describe + the base of a tab bar, i.e. the part that the tab bar usually + overlaps with. + \since 4.5 + + QStyleOptionTabBarBase contains all the information that QStyle + functions need to draw the tab bar base. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QTabBar::drawBase() +*/ + +/*! + \enum QStyleOptionTabBarBaseV2::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 2 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleOptionTabBarBaseV2::documentMode + \brief whether the tabbar is in document mode. + + The default value is false; +*/ + +/*! + Construct a QStyleOptionTabBarBaseV2, initializing the members + vaiables to their default values. +*/ +QStyleOptionTabBarBaseV2::QStyleOptionTabBarBaseV2() + : QStyleOptionTabBarBase(Version) + , documentMode(false) +{ +} + +/*! + \fn QStyleOptionTabBarBaseV2::QStyleOptionTabBarBaseV2(const QStyleOptionTabBarBaseV2 &other) + + Constructs a copy of \a other. +*/ + +/*! + Constructs a copy of \a other. +*/ +QStyleOptionTabBarBaseV2::QStyleOptionTabBarBaseV2(const QStyleOptionTabBarBase &other) + : QStyleOptionTabBarBase(Version) +{ + (void)QStyleOptionTabBarBaseV2::operator=(other); +} + +/*! + Constructs a QStyleOptionTabBarBaseV2 copy of the \a other style option + which can be either of the QStyleOptionTabBarBaseV2, or QStyleOptionTabBarBase types. + + If the other style option's version is not 1, the new style option's + \c documentMode is set to false. If its version is 2, its \c documentMode value + is simply copied to the new style option. +*/ +QStyleOptionTabBarBaseV2 &QStyleOptionTabBarBaseV2::operator = (const QStyleOptionTabBarBase &other) +{ + QStyleOptionTabBarBase::operator=(other); + const QStyleOptionTabBarBaseV2 *v2 = qstyleoption_cast(&other); + documentMode = v2 ? v2->documentMode : false; + return *this; +} + +/*! \internal */ +QStyleOptionTabBarBaseV2::QStyleOptionTabBarBaseV2(int version) + : QStyleOptionTabBarBase(version), documentMode(false) +{ +} + +#endif // QT_NO_TABBAR + +#ifndef QT_NO_SIZEGRIP +/*! + \class QStyleOptionSizeGrip + \brief The QStyleOptionSizeGrip class is used to describe the + parameter for drawing a size grip. + \since 4.2 + + QStyleOptionButton contains all the information that QStyle + functions need to draw QSizeGrip. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QStyleOptionComplex, QSizeGrip +*/ + +/*! + Constructs a QStyleOptionSizeGrip. +*/ +QStyleOptionSizeGrip::QStyleOptionSizeGrip() + : QStyleOptionComplex(Version, Type), corner(Qt::BottomRightCorner) +{ +} + +/*! + \fn QStyleOptionSizeGrip::QStyleOptionSizeGrip(const QStyleOptionSizeGrip &other) + + Constructs a copy of the \a other style option. +*/ + +/*! + \internal +*/ +QStyleOptionSizeGrip::QStyleOptionSizeGrip(int version) + : QStyleOptionComplex(version, Type), corner(Qt::BottomRightCorner) +{ +} + +/*! + \variable QStyleOptionSizeGrip::corner + + The corner in which the size grip is located. +*/ + +/*! + \enum QStyleOptionSizeGrip::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l{SO_TabBarBase} for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionSizeGrip::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ +#endif // QT_NO_SIZEGRIP + +/*! + \class QStyleOptionGraphicsItem + \brief The QStyleOptionGraphicsItem class is used to describe + the parameters needed to draw a QGraphicsItem. + \since 4.2 + \ingroup graphicsview-api + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QGraphicsItem::paint() +*/ + +/*! + \enum QStyleOptionGraphicsItem::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleOption subclass. + + \value Type The type of style option provided (\l SO_GraphicsItem for this class). + + The type is used internally by QStyleOption, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleOption subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleOptionGraphicsItem::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 1 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + Constructs a QStyleOptionGraphicsItem. +*/ +QStyleOptionGraphicsItem::QStyleOptionGraphicsItem() + : QStyleOption(Version, Type), levelOfDetail(1) +{ +} + +/*! + \internal +*/ +QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(int version) + : QStyleOption(version, Type), levelOfDetail(1) +{ +} + +/*! + \since 4.6 + + Returns the level of detail from the \a worldTransform. + + Its value represents the maximum value of the height and + width of a unity rectangle, mapped using the \a worldTransform + of the painter used to draw the item. By default, if no + transformations are applied, its value is 1. If zoomed out 1:2, the level + of detail will be 0.5, and if zoomed in 2:1, its value is 2. +*/ +qreal QStyleOptionGraphicsItem::levelOfDetailFromTransform(const QTransform &worldTransform) +{ + if (worldTransform.type() <= QTransform::TxTranslate) + return 1; // Translation only? The LOD is 1. + + // Two unit vectors. + QLineF v1(0, 0, 1, 0); + QLineF v2(0, 0, 0, 1); + // LOD is the transformed area of a 1x1 rectangle. + return qSqrt(worldTransform.map(v1).length() * worldTransform.map(v2).length()); +} + +/*! + \fn QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(const QStyleOptionGraphicsItem &other) + + Constructs a copy of \a other. +*/ + +/*! + \variable QStyleOptionGraphicsItem::exposedRect + \brief the exposed rectangle, in item coordinates + + Make use of this rectangle to speed up item drawing when only parts of the + item are exposed. If the whole item is exposed, this rectangle will be the + same as QGraphicsItem::boundingRect(). + + This member is only initialized for items that have the + QGraphicsItem::ItemUsesExtendedStyleOption flag set. +*/ + +/*! + \variable QStyleOptionGraphicsItem::matrix + \brief the complete transformation matrix for the item + \obsolete + + The QMatrix provided through this member does include information about + any perspective transformations applied to the view or item. To get the + correct transformation matrix, use QPainter::transform() on the painter + passed into the QGraphicsItem::paint() implementation. + + This matrix is the combination of the item's scene matrix and the matrix + of the painter used for drawing the item. It is provided for convenience, + allowing anvanced level-of-detail metrics that can be used to speed up + item drawing. + + To find the dimensions of an item in screen coordinates (i.e., pixels), + you can use the mapping functions of QMatrix, such as QMatrix::map(). + + This member is only initialized for items that have the + QGraphicsItem::ItemUsesExtendedStyleOption flag set. + + \sa QStyleOptionGraphicsItem::levelOfDetailFromTransform() +*/ + +/*! + \variable QStyleOptionGraphicsItem::levelOfDetail + \obsolete + + Use QStyleOptionGraphicsItem::levelOfDetailFromTransform() + together with QPainter::worldTransform() instead. +*/ + +/*! + \class QStyleHintReturn + \brief The QStyleHintReturn class provides style hints that return more + than basic data types. + + \ingroup appearance + + QStyleHintReturn and its subclasses are used to pass information + from a style back to the querying widget. This is most useful + when the return value from QStyle::styleHint() does not provide enough + detail; for example, when a mask is to be returned. + + \omit + ### --Sam + \endomit +*/ + +/*! + \enum QStyleHintReturn::HintReturnType + + \value SH_Default QStyleHintReturn + \value SH_Mask \l QStyle::SH_RubberBand_Mask QStyle::SH_FocusFrame_Mask + \value SH_Variant \l QStyle::SH_TextControl_FocusIndicatorTextCharFormat +*/ + +/*! + \enum QStyleHintReturn::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleHintReturn subclass. + + \value Type The type of style option provided (\l SH_Default for + this class). + + The type is used internally by QStyleHintReturn, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleHintReturn subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleHintReturn::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleHintReturn subclass. + + \value Version 1 + + The version is used by QStyleHintReturn subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \variable QStyleHintReturn::type + \brief the type of the style hint container + + \sa HintReturnType +*/ + +/*! + \variable QStyleHintReturn::version + \brief the version of the style hint return container + + This value can be used by subclasses to implement extensions + without breaking compatibility. If you use qstyleoption_cast(), you + normally do not need to check it. +*/ + +/*! + Constructs a QStyleHintReturn with version \a version and type \a + type. + + The version has no special meaning for QStyleHintReturn; it can be + used by subclasses to distinguish between different version of + the same hint type. + + \sa QStyleOption::version, QStyleOption::type +*/ + +QStyleHintReturn::QStyleHintReturn(int version, int type) + : version(version), type(type) +{ +} + +/*! + \internal +*/ + +QStyleHintReturn::~QStyleHintReturn() +{ + +} + +/*! + \class QStyleHintReturnMask + \brief The QStyleHintReturnMask class provides style hints that return a QRegion. + + \ingroup appearance + + \omit + ### --Sam + \endomit +*/ + +/*! + \variable QStyleHintReturnMask::region + \brief the region for style hints that return a QRegion +*/ + +/*! + Constructs a QStyleHintReturnMask. The member variables are + initialized to default values. +*/ +QStyleHintReturnMask::QStyleHintReturnMask() : QStyleHintReturn(Version, Type) +{ +} + +/*! + \enum QStyleHintReturnMask::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleHintReturn subclass. + + \value Type The type of style option provided (\l{SH_Mask} for + this class). + + The type is used internally by QStyleHintReturn, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleHintReturn subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleHintReturnMask::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleHintReturn subclass. + + \value Version 1 + + The version is used by QStyleHintReturn subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \class QStyleHintReturnVariant + \brief The QStyleHintReturnVariant class provides style hints that return a QVariant. + \since 4.3 + \ingroup appearance +*/ + +/*! + \variable QStyleHintReturnVariant::variant + \brief the variant for style hints that return a QVariant +*/ + +/*! + Constructs a QStyleHintReturnVariant. The member variables are + initialized to default values. +*/ +QStyleHintReturnVariant::QStyleHintReturnVariant() : QStyleHintReturn(Version, Type) +{ +} + +/*! + \enum QStyleHintReturnVariant::StyleOptionType + + This enum is used to hold information about the type of the style option, and + is defined for each QStyleHintReturn subclass. + + \value Type The type of style option provided (\l{SH_Variant} for + this class). + + The type is used internally by QStyleHintReturn, its subclasses, and + qstyleoption_cast() to determine the type of style option. In + general you do not need to worry about this unless you want to + create your own QStyleHintReturn subclass and your own styles. + + \sa StyleOptionVersion +*/ + +/*! + \enum QStyleHintReturnVariant::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleHintReturn subclass. + + \value Version 1 + + The version is used by QStyleHintReturn subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + +/*! + \fn T qstyleoption_cast(const QStyleHintReturn *hint) + \relates QStyleHintReturn + + Returns a T or 0 depending on the \l{QStyleHintReturn::type}{type} + and \l{QStyleHintReturn::version}{version} of \a hint. + + Example: + + \snippet doc/src/snippets/code/src_gui_styles_qstyleoption.cpp 0 + + \sa QStyleHintReturn::type, QStyleHintReturn::version +*/ + +/*! + \fn T qstyleoption_cast(QStyleHintReturn *hint) + \overload + \relates QStyleHintReturn + + Returns a T or 0 depending on the type of \a hint. +*/ + +#if !defined(QT_NO_DEBUG_STREAM) +QDebug operator<<(QDebug debug, const QStyleOption::OptionType &optionType) +{ +#if !defined(QT_NO_DEBUG) + switch (optionType) { + case QStyleOption::SO_Default: + debug << "SO_Default"; break; + case QStyleOption::SO_FocusRect: + debug << "SO_FocusRect"; break; + case QStyleOption::SO_Button: + debug << "SO_Button"; break; + case QStyleOption::SO_Tab: + debug << "SO_Tab"; break; + case QStyleOption::SO_MenuItem: + debug << "SO_MenuItem"; break; + case QStyleOption::SO_Frame: + debug << "SO_Frame"; break; + case QStyleOption::SO_ProgressBar: + debug << "SO_ProgressBar"; break; + case QStyleOption::SO_ToolBox: + debug << "SO_ToolBox"; break; + case QStyleOption::SO_Header: + debug << "SO_Header"; break; + case QStyleOption::SO_Q3DockWindow: + debug << "SO_Q3DockWindow"; break; + case QStyleOption::SO_DockWidget: + debug << "SO_DockWidget"; break; + case QStyleOption::SO_Q3ListViewItem: + debug << "SO_Q3ListViewItem"; break; + case QStyleOption::SO_ViewItem: + debug << "SO_ViewItem"; break; + case QStyleOption::SO_TabWidgetFrame: + debug << "SO_TabWidgetFrame"; break; + case QStyleOption::SO_TabBarBase: + debug << "SO_TabBarBase"; break; + case QStyleOption::SO_RubberBand: + debug << "SO_RubberBand"; break; + case QStyleOption::SO_Complex: + debug << "SO_Complex"; break; + case QStyleOption::SO_Slider: + debug << "SO_Slider"; break; + case QStyleOption::SO_SpinBox: + debug << "SO_SpinBox"; break; + case QStyleOption::SO_ToolButton: + debug << "SO_ToolButton"; break; + case QStyleOption::SO_ComboBox: + debug << "SO_ComboBox"; break; + case QStyleOption::SO_Q3ListView: + debug << "SO_Q3ListView"; break; + case QStyleOption::SO_TitleBar: + debug << "SO_TitleBar"; break; + case QStyleOption::SO_CustomBase: + debug << "SO_CustomBase"; break; + case QStyleOption::SO_GroupBox: + debug << "SO_GroupBox"; break; + case QStyleOption::SO_ToolBar: + debug << "SO_ToolBar"; break; + case QStyleOption::SO_ComplexCustomBase: + debug << "SO_ComplexCustomBase"; break; + case QStyleOption::SO_SizeGrip: + debug << "SO_SizeGrip"; break; + case QStyleOption::SO_GraphicsItem: + debug << "SO_GraphicsItem"; break; + } +#else + Q_UNUSED(optionType); +#endif + return debug; +} + +QDebug operator<<(QDebug debug, const QStyleOption &option) +{ +#if !defined(QT_NO_DEBUG) + debug << "QStyleOption("; + debug << QStyleOption::OptionType(option.type); + debug << ',' << (option.direction == Qt::RightToLeft ? "RightToLeft" : "LeftToRight"); + debug << ',' << option.state; + debug << ',' << option.rect; + debug << ')'; +#else + Q_UNUSED(option); +#endif + return debug; +} +#endif + +QT_END_NAMESPACE diff --git a/src/widgets/styles/qstyleoption.h b/src/widgets/styles/qstyleoption.h new file mode 100644 index 0000000000..1b1de9cdf2 --- /dev/null +++ b/src/widgets/styles/qstyleoption.h @@ -0,0 +1,970 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLEOPTION_H +#define QSTYLEOPTION_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef QT_NO_ITEMVIEWS +# include +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QDebug; + +class Q_GUI_EXPORT QStyleOption +{ +public: + enum OptionType { + SO_Default, SO_FocusRect, SO_Button, SO_Tab, SO_MenuItem, + SO_Frame, SO_ProgressBar, SO_ToolBox, SO_Header, SO_Q3DockWindow, + SO_DockWidget, SO_Q3ListViewItem, SO_ViewItem, SO_TabWidgetFrame, + SO_TabBarBase, SO_RubberBand, SO_ToolBar, SO_GraphicsItem, + + SO_Complex = 0xf0000, SO_Slider, SO_SpinBox, SO_ToolButton, SO_ComboBox, + SO_Q3ListView, SO_TitleBar, SO_GroupBox, SO_SizeGrip, + + SO_CustomBase = 0xf00, + SO_ComplexCustomBase = 0xf000000 + }; + + enum StyleOptionType { Type = SO_Default }; + enum StyleOptionVersion { Version = 1 }; + + int version; + int type; + QStyle::State state; + Qt::LayoutDirection direction; + QRect rect; + QFontMetrics fontMetrics; + QPalette palette; + + QStyleOption(int version = QStyleOption::Version, int type = SO_Default); + QStyleOption(const QStyleOption &other); + ~QStyleOption(); + + void init(const QWidget *w); + inline void initFrom(const QWidget *w) { init(w); } + QStyleOption &operator=(const QStyleOption &other); +}; + +class Q_GUI_EXPORT QStyleOptionFocusRect : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_FocusRect }; + enum StyleOptionVersion { Version = 1 }; + + QColor backgroundColor; + + QStyleOptionFocusRect(); + QStyleOptionFocusRect(const QStyleOptionFocusRect &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionFocusRect(int version); +}; + +class Q_GUI_EXPORT QStyleOptionFrame : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_Frame }; + enum StyleOptionVersion { Version = 1 }; + + int lineWidth; + int midLineWidth; + + QStyleOptionFrame(); + QStyleOptionFrame(const QStyleOptionFrame &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionFrame(int version); +}; + +class Q_GUI_EXPORT QStyleOptionFrameV2 : public QStyleOptionFrame +{ +public: + enum StyleOptionVersion { Version = 2 }; + enum FrameFeature { + None = 0x00, + Flat = 0x01 + }; + Q_DECLARE_FLAGS(FrameFeatures, FrameFeature) + FrameFeatures features; + + QStyleOptionFrameV2(); + QStyleOptionFrameV2(const QStyleOptionFrameV2 &other) : QStyleOptionFrame(Version) { *this = other; } + QStyleOptionFrameV2(const QStyleOptionFrame &other); + QStyleOptionFrameV2 &operator=(const QStyleOptionFrame &other); + +protected: + QStyleOptionFrameV2(int version); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionFrameV2::FrameFeatures) + + +class Q_GUI_EXPORT QStyleOptionFrameV3 : public QStyleOptionFrameV2 +{ +public: + enum StyleOptionVersion { Version = 3 }; + QFrame::Shape frameShape : 4; + uint unused : 28; + + QStyleOptionFrameV3(); + QStyleOptionFrameV3(const QStyleOptionFrameV3 &other) : QStyleOptionFrameV2(Version) { *this = other; } + QStyleOptionFrameV3(const QStyleOptionFrame &other); + QStyleOptionFrameV3 &operator=(const QStyleOptionFrame &other); + +protected: + QStyleOptionFrameV3(int version); +}; + + +#ifndef QT_NO_TABWIDGET +class Q_GUI_EXPORT QStyleOptionTabWidgetFrame : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_TabWidgetFrame }; + enum StyleOptionVersion { Version = 1 }; + + int lineWidth; + int midLineWidth; + QTabBar::Shape shape; + QSize tabBarSize; + QSize rightCornerWidgetSize; + QSize leftCornerWidgetSize; + + QStyleOptionTabWidgetFrame(); + inline QStyleOptionTabWidgetFrame(const QStyleOptionTabWidgetFrame &other) + : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionTabWidgetFrame(int version); +}; + +class Q_GUI_EXPORT QStyleOptionTabWidgetFrameV2 : public QStyleOptionTabWidgetFrame +{ +public: + enum StyleOptionVersion { Version = 2 }; + + QRect tabBarRect; + QRect selectedTabRect; + + QStyleOptionTabWidgetFrameV2(); + QStyleOptionTabWidgetFrameV2(const QStyleOptionTabWidgetFrameV2 &other) : + QStyleOptionTabWidgetFrame(Version) { *this = other; } + QStyleOptionTabWidgetFrameV2(const QStyleOptionTabWidgetFrame &other); + QStyleOptionTabWidgetFrameV2 &operator=(const QStyleOptionTabWidgetFrame &other); + +protected: + QStyleOptionTabWidgetFrameV2(int version); +}; + +#endif + + +#ifndef QT_NO_TABBAR +class Q_GUI_EXPORT QStyleOptionTabBarBase : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_TabBarBase }; + enum StyleOptionVersion { Version = 1 }; + + QTabBar::Shape shape; + QRect tabBarRect; + QRect selectedTabRect; + + QStyleOptionTabBarBase(); + QStyleOptionTabBarBase(const QStyleOptionTabBarBase &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionTabBarBase(int version); +}; + +class Q_GUI_EXPORT QStyleOptionTabBarBaseV2 : public QStyleOptionTabBarBase +{ +public: + enum StyleOptionVersion { Version = 2 }; + bool documentMode; + QStyleOptionTabBarBaseV2(); + QStyleOptionTabBarBaseV2(const QStyleOptionTabBarBaseV2 &other) : QStyleOptionTabBarBase(Version) { *this = other; } + QStyleOptionTabBarBaseV2(const QStyleOptionTabBarBase &other); + QStyleOptionTabBarBaseV2 &operator=(const QStyleOptionTabBarBase &other); + +protected: + QStyleOptionTabBarBaseV2(int version); +}; + +#endif + +class Q_GUI_EXPORT QStyleOptionHeader : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_Header }; + enum StyleOptionVersion { Version = 1 }; + + enum SectionPosition { Beginning, Middle, End, OnlyOneSection }; + enum SelectedPosition { NotAdjacent, NextIsSelected, PreviousIsSelected, + NextAndPreviousAreSelected }; + enum SortIndicator { None, SortUp, SortDown }; + + int section; + QString text; + Qt::Alignment textAlignment; + QIcon icon; + Qt::Alignment iconAlignment; + SectionPosition position; + SelectedPosition selectedPosition; + SortIndicator sortIndicator; + Qt::Orientation orientation; + + QStyleOptionHeader(); + QStyleOptionHeader(const QStyleOptionHeader &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionHeader(int version); +}; + +class Q_GUI_EXPORT QStyleOptionButton : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_Button }; + enum StyleOptionVersion { Version = 1 }; + + enum ButtonFeature { None = 0x00, Flat = 0x01, HasMenu = 0x02, DefaultButton = 0x04, + AutoDefaultButton = 0x08, CommandLinkButton = 0x10 }; + Q_DECLARE_FLAGS(ButtonFeatures, ButtonFeature) + + ButtonFeatures features; + QString text; + QIcon icon; + QSize iconSize; + + QStyleOptionButton(); + QStyleOptionButton(const QStyleOptionButton &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionButton(int version); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionButton::ButtonFeatures) + +#ifndef QT_NO_TABBAR +class Q_GUI_EXPORT QStyleOptionTab : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_Tab }; + enum StyleOptionVersion { Version = 1 }; + + enum TabPosition { Beginning, Middle, End, OnlyOneTab }; + enum SelectedPosition { NotAdjacent, NextIsSelected, PreviousIsSelected }; + enum CornerWidget { NoCornerWidgets = 0x00, LeftCornerWidget = 0x01, + RightCornerWidget = 0x02 }; + Q_DECLARE_FLAGS(CornerWidgets, CornerWidget) + + QTabBar::Shape shape; + QString text; + QIcon icon; + int row; + TabPosition position; + SelectedPosition selectedPosition; + CornerWidgets cornerWidgets; + + QStyleOptionTab(); + QStyleOptionTab(const QStyleOptionTab &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionTab(int version); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionTab::CornerWidgets) + +class Q_GUI_EXPORT QStyleOptionTabV2 : public QStyleOptionTab +{ +public: + enum StyleOptionVersion { Version = 2 }; + QSize iconSize; + QStyleOptionTabV2(); + QStyleOptionTabV2(const QStyleOptionTabV2 &other) : QStyleOptionTab(Version) { *this = other; } + QStyleOptionTabV2(const QStyleOptionTab &other); + QStyleOptionTabV2 &operator=(const QStyleOptionTab &other); + +protected: + QStyleOptionTabV2(int version); +}; + +class Q_GUI_EXPORT QStyleOptionTabV3 : public QStyleOptionTabV2 +{ +public: + enum StyleOptionVersion { Version = 3 }; + bool documentMode; + QSize leftButtonSize; + QSize rightButtonSize; + QStyleOptionTabV3(); + QStyleOptionTabV3(const QStyleOptionTabV3 &other) : QStyleOptionTabV2(Version) { *this = other; } + QStyleOptionTabV3(const QStyleOptionTabV2 &other) : QStyleOptionTabV2(Version) { *this = other; } + QStyleOptionTabV3(const QStyleOptionTab &other); + QStyleOptionTabV3 &operator=(const QStyleOptionTab &other); + +protected: + QStyleOptionTabV3(int version); +}; + +#endif + + +#ifndef QT_NO_TOOLBAR + +class Q_GUI_EXPORT QStyleOptionToolBar : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_ToolBar }; + enum StyleOptionVersion { Version = 1 }; + enum ToolBarPosition { Beginning, Middle, End, OnlyOne }; + enum ToolBarFeature { None = 0x0, Movable = 0x1 }; + Q_DECLARE_FLAGS(ToolBarFeatures, ToolBarFeature) + ToolBarPosition positionOfLine; // The toolbar line position + ToolBarPosition positionWithinLine; // The position within a toolbar + Qt::ToolBarArea toolBarArea; // The toolbar docking area + ToolBarFeatures features; + int lineWidth; + int midLineWidth; + QStyleOptionToolBar(); + QStyleOptionToolBar(const QStyleOptionToolBar &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionToolBar(int version); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionToolBar::ToolBarFeatures) + +#endif + + + +class Q_GUI_EXPORT QStyleOptionProgressBar : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_ProgressBar }; + enum StyleOptionVersion { Version = 1 }; + + int minimum; + int maximum; + int progress; + QString text; + Qt::Alignment textAlignment; + bool textVisible; + + QStyleOptionProgressBar(); + QStyleOptionProgressBar(const QStyleOptionProgressBar &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionProgressBar(int version); +}; + +// Adds style info for vertical progress bars +class Q_GUI_EXPORT QStyleOptionProgressBarV2 : public QStyleOptionProgressBar +{ +public: + enum StyleOptionType { Type = SO_ProgressBar }; + enum StyleOptionVersion { Version = 2 }; + Qt::Orientation orientation; + bool invertedAppearance; + bool bottomToTop; + + QStyleOptionProgressBarV2(); + QStyleOptionProgressBarV2(const QStyleOptionProgressBar &other); + QStyleOptionProgressBarV2(const QStyleOptionProgressBarV2 &other); + QStyleOptionProgressBarV2 &operator=(const QStyleOptionProgressBar &other); + +protected: + QStyleOptionProgressBarV2(int version); +}; + +class Q_GUI_EXPORT QStyleOptionMenuItem : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_MenuItem }; + enum StyleOptionVersion { Version = 1 }; + + enum MenuItemType { Normal, DefaultItem, Separator, SubMenu, Scroller, TearOff, Margin, + EmptyArea }; + enum CheckType { NotCheckable, Exclusive, NonExclusive }; + + MenuItemType menuItemType; + CheckType checkType; + bool checked; + bool menuHasCheckableItems; + QRect menuRect; + QString text; + QIcon icon; + int maxIconWidth; + int tabWidth; + QFont font; + + QStyleOptionMenuItem(); + QStyleOptionMenuItem(const QStyleOptionMenuItem &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionMenuItem(int version); +}; + +class Q_GUI_EXPORT QStyleOptionQ3ListViewItem : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_Q3ListViewItem }; + enum StyleOptionVersion { Version = 1 }; + + enum Q3ListViewItemFeature { None = 0x00, Expandable = 0x01, MultiLine = 0x02, Visible = 0x04, + ParentControl = 0x08 }; + Q_DECLARE_FLAGS(Q3ListViewItemFeatures, Q3ListViewItemFeature) + + Q3ListViewItemFeatures features; + int height; + int totalHeight; + int itemY; + int childCount; + + QStyleOptionQ3ListViewItem(); + QStyleOptionQ3ListViewItem(const QStyleOptionQ3ListViewItem &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionQ3ListViewItem(int version); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionQ3ListViewItem::Q3ListViewItemFeatures) + +class Q_GUI_EXPORT QStyleOptionQ3DockWindow : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_Q3DockWindow }; + enum StyleOptionVersion { Version = 1 }; + + bool docked; + bool closeEnabled; + + QStyleOptionQ3DockWindow(); + QStyleOptionQ3DockWindow(const QStyleOptionQ3DockWindow &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionQ3DockWindow(int version); +}; + +class Q_GUI_EXPORT QStyleOptionDockWidget : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_DockWidget }; + enum StyleOptionVersion { Version = 1 }; + + QString title; + bool closable; + bool movable; + bool floatable; + + QStyleOptionDockWidget(); + QStyleOptionDockWidget(const QStyleOptionDockWidget &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionDockWidget(int version); +}; + +class Q_GUI_EXPORT QStyleOptionDockWidgetV2 : public QStyleOptionDockWidget +{ +public: + enum StyleOptionVersion { Version = 2 }; + + bool verticalTitleBar; + + QStyleOptionDockWidgetV2(); + QStyleOptionDockWidgetV2(const QStyleOptionDockWidgetV2 &other) + : QStyleOptionDockWidget(Version) { *this = other; } + QStyleOptionDockWidgetV2(const QStyleOptionDockWidget &other); + QStyleOptionDockWidgetV2 &operator = (const QStyleOptionDockWidget &other); + +protected: + QStyleOptionDockWidgetV2(int version); +}; + +class Q_GUI_EXPORT QStyleOptionViewItem : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_ViewItem }; + enum StyleOptionVersion { Version = 1 }; + + enum Position { Left, Right, Top, Bottom }; + + Qt::Alignment displayAlignment; + Qt::Alignment decorationAlignment; + Qt::TextElideMode textElideMode; + Position decorationPosition; + QSize decorationSize; + QFont font; + bool showDecorationSelected; + + QStyleOptionViewItem(); + QStyleOptionViewItem(const QStyleOptionViewItem &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionViewItem(int version); +}; + +class Q_GUI_EXPORT QStyleOptionViewItemV2 : public QStyleOptionViewItem +{ +public: + enum StyleOptionVersion { Version = 2 }; + + enum ViewItemFeature { + None = 0x00, + WrapText = 0x01, + Alternate = 0x02, + HasCheckIndicator = 0x04, + HasDisplay = 0x08, + HasDecoration = 0x10 + }; + Q_DECLARE_FLAGS(ViewItemFeatures, ViewItemFeature) + + ViewItemFeatures features; + + QStyleOptionViewItemV2(); + QStyleOptionViewItemV2(const QStyleOptionViewItemV2 &other) : QStyleOptionViewItem(Version) { *this = other; } + QStyleOptionViewItemV2(const QStyleOptionViewItem &other); + QStyleOptionViewItemV2 &operator=(const QStyleOptionViewItem &other); + +protected: + QStyleOptionViewItemV2(int version); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionViewItemV2::ViewItemFeatures) + +class Q_GUI_EXPORT QStyleOptionViewItemV3 : public QStyleOptionViewItemV2 +{ +public: + enum StyleOptionVersion { Version = 3 }; + + QLocale locale; + const QWidget *widget; + + QStyleOptionViewItemV3(); + QStyleOptionViewItemV3(const QStyleOptionViewItemV3 &other) + : QStyleOptionViewItemV2(Version) { *this = other; } + QStyleOptionViewItemV3(const QStyleOptionViewItem &other); + QStyleOptionViewItemV3 &operator = (const QStyleOptionViewItem &other); + +protected: + QStyleOptionViewItemV3(int version); +}; + +#ifndef QT_NO_ITEMVIEWS +class Q_GUI_EXPORT QStyleOptionViewItemV4 : public QStyleOptionViewItemV3 +{ +public: + enum StyleOptionVersion { Version = 4 }; + enum ViewItemPosition { Invalid, Beginning, Middle, End, OnlyOne }; + + QModelIndex index; + Qt::CheckState checkState; + QIcon icon; + QString text; + ViewItemPosition viewItemPosition; + QBrush backgroundBrush; + + QStyleOptionViewItemV4(); + QStyleOptionViewItemV4(const QStyleOptionViewItemV4 &other) + : QStyleOptionViewItemV3(Version) { *this = other; } + QStyleOptionViewItemV4(const QStyleOptionViewItem &other); + QStyleOptionViewItemV4 &operator = (const QStyleOptionViewItem &other); + +protected: + QStyleOptionViewItemV4(int version); +}; +#endif + +class Q_GUI_EXPORT QStyleOptionToolBox : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_ToolBox }; + enum StyleOptionVersion { Version = 1 }; + + QString text; + QIcon icon; + + QStyleOptionToolBox(); + QStyleOptionToolBox(const QStyleOptionToolBox &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionToolBox(int version); +}; + +class Q_GUI_EXPORT QStyleOptionToolBoxV2 : public QStyleOptionToolBox +{ +public: + enum StyleOptionVersion { Version = 2 }; + enum TabPosition { Beginning, Middle, End, OnlyOneTab }; + enum SelectedPosition { NotAdjacent, NextIsSelected, PreviousIsSelected }; + + TabPosition position; + SelectedPosition selectedPosition; + + QStyleOptionToolBoxV2(); + QStyleOptionToolBoxV2(const QStyleOptionToolBoxV2 &other) : QStyleOptionToolBox(Version) { *this = other; } + QStyleOptionToolBoxV2(const QStyleOptionToolBox &other); + QStyleOptionToolBoxV2 &operator=(const QStyleOptionToolBox &other); + +protected: + QStyleOptionToolBoxV2(int version); +}; + +#ifndef QT_NO_RUBBERBAND +class Q_GUI_EXPORT QStyleOptionRubberBand : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_RubberBand }; + enum StyleOptionVersion { Version = 1 }; + + QRubberBand::Shape shape; + bool opaque; + + QStyleOptionRubberBand(); + QStyleOptionRubberBand(const QStyleOptionRubberBand &other) : QStyleOption(Version, Type) { *this = other; } + +protected: + QStyleOptionRubberBand(int version); +}; +#endif // QT_NO_RUBBERBAND + +// -------------------------- Complex style options ------------------------------- +class Q_GUI_EXPORT QStyleOptionComplex : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_Complex }; + enum StyleOptionVersion { Version = 1 }; + + QStyle::SubControls subControls; + QStyle::SubControls activeSubControls; + + QStyleOptionComplex(int version = QStyleOptionComplex::Version, int type = SO_Complex); + QStyleOptionComplex(const QStyleOptionComplex &other) : QStyleOption(Version, Type) { *this = other; } +}; + +#ifndef QT_NO_SLIDER +class Q_GUI_EXPORT QStyleOptionSlider : public QStyleOptionComplex +{ +public: + enum StyleOptionType { Type = SO_Slider }; + enum StyleOptionVersion { Version = 1 }; + + Qt::Orientation orientation; + int minimum; + int maximum; + QSlider::TickPosition tickPosition; + int tickInterval; + bool upsideDown; + int sliderPosition; + int sliderValue; + int singleStep; + int pageStep; + qreal notchTarget; + bool dialWrapping; + + QStyleOptionSlider(); + QStyleOptionSlider(const QStyleOptionSlider &other) : QStyleOptionComplex(Version, Type) { *this = other; } + +protected: + QStyleOptionSlider(int version); +}; +#endif // QT_NO_SLIDER + +#ifndef QT_NO_SPINBOX +class Q_GUI_EXPORT QStyleOptionSpinBox : public QStyleOptionComplex +{ +public: + enum StyleOptionType { Type = SO_SpinBox }; + enum StyleOptionVersion { Version = 1 }; + + QAbstractSpinBox::ButtonSymbols buttonSymbols; + QAbstractSpinBox::StepEnabled stepEnabled; + bool frame; + + QStyleOptionSpinBox(); + QStyleOptionSpinBox(const QStyleOptionSpinBox &other) : QStyleOptionComplex(Version, Type) { *this = other; } + +protected: + QStyleOptionSpinBox(int version); +}; +#endif // QT_NO_SPINBOX + +class Q_GUI_EXPORT QStyleOptionQ3ListView : public QStyleOptionComplex +{ +public: + enum StyleOptionType { Type = SO_Q3ListView }; + enum StyleOptionVersion { Version = 1 }; + + QList items; + QPalette viewportPalette; + QPalette::ColorRole viewportBGRole; + int sortColumn; + int itemMargin; + int treeStepSize; + bool rootIsDecorated; + + QStyleOptionQ3ListView(); + QStyleOptionQ3ListView(const QStyleOptionQ3ListView &other) : QStyleOptionComplex(Version, Type) { *this = other; } + +protected: + QStyleOptionQ3ListView(int version); +}; + +class Q_GUI_EXPORT QStyleOptionToolButton : public QStyleOptionComplex +{ +public: + enum StyleOptionType { Type = SO_ToolButton }; + enum StyleOptionVersion { Version = 1 }; + + enum ToolButtonFeature { None = 0x00, Arrow = 0x01, Menu = 0x04, MenuButtonPopup = Menu, PopupDelay = 0x08, + HasMenu = 0x10 }; + Q_DECLARE_FLAGS(ToolButtonFeatures, ToolButtonFeature) + + ToolButtonFeatures features; + QIcon icon; + QSize iconSize; + QString text; + Qt::ArrowType arrowType; + Qt::ToolButtonStyle toolButtonStyle; + QPoint pos; + QFont font; + + QStyleOptionToolButton(); + QStyleOptionToolButton(const QStyleOptionToolButton &other) : QStyleOptionComplex(Version, Type) { *this = other; } + +protected: + QStyleOptionToolButton(int version); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionToolButton::ToolButtonFeatures) + +class Q_GUI_EXPORT QStyleOptionComboBox : public QStyleOptionComplex +{ +public: + enum StyleOptionType { Type = SO_ComboBox }; + enum StyleOptionVersion { Version = 1 }; + + bool editable; + QRect popupRect; + bool frame; + QString currentText; + QIcon currentIcon; + QSize iconSize; + + QStyleOptionComboBox(); + QStyleOptionComboBox(const QStyleOptionComboBox &other) : QStyleOptionComplex(Version, Type) { *this = other; } + +protected: + QStyleOptionComboBox(int version); +}; + +class Q_GUI_EXPORT QStyleOptionTitleBar : public QStyleOptionComplex +{ +public: + enum StyleOptionType { Type = SO_TitleBar }; + enum StyleOptionVersion { Version = 1 }; + + QString text; + QIcon icon; + int titleBarState; + Qt::WindowFlags titleBarFlags; + + QStyleOptionTitleBar(); + QStyleOptionTitleBar(const QStyleOptionTitleBar &other) : QStyleOptionComplex(Version, Type) { *this = other; } + +protected: + QStyleOptionTitleBar(int version); +}; + +class Q_GUI_EXPORT QStyleOptionGroupBox : public QStyleOptionComplex +{ +public: + enum StyleOptionType { Type = SO_GroupBox }; + enum StyleOptionVersion { Version = 1 }; + + QStyleOptionFrameV2::FrameFeatures features; + QString text; + Qt::Alignment textAlignment; + QColor textColor; + int lineWidth; + int midLineWidth; + + QStyleOptionGroupBox(); + QStyleOptionGroupBox(const QStyleOptionGroupBox &other) : QStyleOptionComplex(Version, Type) { *this = other; } +protected: + QStyleOptionGroupBox(int version); +}; + +class Q_GUI_EXPORT QStyleOptionSizeGrip : public QStyleOptionComplex +{ +public: + enum StyleOptionType { Type = SO_SizeGrip }; + enum StyleOptionVersion { Version = 1 }; + + Qt::Corner corner; + + QStyleOptionSizeGrip(); + QStyleOptionSizeGrip(const QStyleOptionSizeGrip &other) : QStyleOptionComplex(Version, Type) { *this = other; } +protected: + QStyleOptionSizeGrip(int version); +}; + +class Q_GUI_EXPORT QStyleOptionGraphicsItem : public QStyleOption +{ +public: + enum StyleOptionType { Type = SO_GraphicsItem }; + enum StyleOptionVersion { Version = 1 }; + + QRectF exposedRect; + QMatrix matrix; + qreal levelOfDetail; + + QStyleOptionGraphicsItem(); + QStyleOptionGraphicsItem(const QStyleOptionGraphicsItem &other) : QStyleOption(Version, Type) { *this = other; } + static qreal levelOfDetailFromTransform(const QTransform &worldTransform); +protected: + QStyleOptionGraphicsItem(int version); +}; + +template +T qstyleoption_cast(const QStyleOption *opt) +{ + if (opt && opt->version >= static_cast(0)->Version && (opt->type == static_cast(0)->Type + || int(static_cast(0)->Type) == QStyleOption::SO_Default + || (int(static_cast(0)->Type) == QStyleOption::SO_Complex + && opt->type > QStyleOption::SO_Complex))) + return static_cast(opt); + return 0; +} + +template +T qstyleoption_cast(QStyleOption *opt) +{ + if (opt && opt->version >= static_cast(0)->Version && (opt->type == static_cast(0)->Type + || int(static_cast(0)->Type) == QStyleOption::SO_Default + || (int(static_cast(0)->Type) == QStyleOption::SO_Complex + && opt->type > QStyleOption::SO_Complex))) + return static_cast(opt); + return 0; +} + +// -------------------------- QStyleHintReturn ------------------------------- +class Q_GUI_EXPORT QStyleHintReturn { +public: + enum HintReturnType { + SH_Default=0xf000, SH_Mask, SH_Variant + }; + + enum StyleOptionType { Type = SH_Default }; + enum StyleOptionVersion { Version = 1 }; + + QStyleHintReturn(int version = QStyleOption::Version, int type = SH_Default); + ~QStyleHintReturn(); + + int version; + int type; +}; + +class Q_GUI_EXPORT QStyleHintReturnMask : public QStyleHintReturn { +public: + enum StyleOptionType { Type = SH_Mask }; + enum StyleOptionVersion { Version = 1 }; + + QStyleHintReturnMask(); + + QRegion region; +}; + +class Q_GUI_EXPORT QStyleHintReturnVariant : public QStyleHintReturn { +public: + enum StyleOptionType { Type = SH_Variant }; + enum StyleOptionVersion { Version = 1 }; + + QStyleHintReturnVariant(); + + QVariant variant; +}; + +template +T qstyleoption_cast(const QStyleHintReturn *hint) +{ + if (hint && hint->version <= static_cast(0)->Version && + (hint->type == static_cast(0)->Type || int(static_cast(0)->Type) == QStyleHintReturn::SH_Default)) + return static_cast(hint); + return 0; +} + +template +T qstyleoption_cast(QStyleHintReturn *hint) +{ + if (hint && hint->version <= static_cast(0)->Version && + (hint->type == static_cast(0)->Type || int(static_cast(0)->Type) == QStyleHintReturn::SH_Default)) + return static_cast(hint); + return 0; +} + +#if !defined(QT_NO_DEBUG_STREAM) +Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QStyleOption::OptionType &optionType); +Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QStyleOption &option); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSTYLEOPTION_H diff --git a/src/widgets/styles/qstylepainter.cpp b/src/widgets/styles/qstylepainter.cpp new file mode 100644 index 0000000000..c8f9d05315 --- /dev/null +++ b/src/widgets/styles/qstylepainter.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstylepainter.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QStylePainter + + \brief The QStylePainter class is a convenience class for drawing QStyle + elements inside a widget. + + \ingroup appearance + \ingroup painting + + QStylePainter extends QPainter with a set of high-level \c + draw...() functions implemented on top of QStyle's API. The + advantage of using QStylePainter is that the parameter lists get + considerably shorter. Whereas a QStyle object must be able to + draw on any widget using any painter (because the application + normally has one QStyle object shared by all widget), a + QStylePainter is initialized with a widget, eliminating the need + to specify the QWidget, the QPainter, and the QStyle for every + function call. + + Example using QStyle directly: + + \snippet doc/src/snippets/styles/styles.cpp 1 + + Example using QStylePainter: + + \snippet doc/src/snippets/styles/styles.cpp 0 + \snippet doc/src/snippets/styles/styles.cpp 4 + \snippet doc/src/snippets/styles/styles.cpp 6 + + \sa QStyle, QStyleOption +*/ + +/*! + \fn QStylePainter::QStylePainter() + + Constructs a QStylePainter. +*/ + +/*! + \fn QStylePainter::QStylePainter(QWidget *widget) + + Construct a QStylePainter using widget \a widget for its paint device. +*/ + +/*! + \fn QStylePainter::QStylePainter(QPaintDevice *pd, QWidget *widget) + + Construct a QStylePainter using \a pd for its paint device, and + attributes from \a widget. +*/ + + +/*! + \fn bool QStylePainter::begin(QWidget *widget) + + Begin painting operations on the specified \a widget. + Returns true if the painter is ready to use; otherwise returns false. + + This is automatically called by the constructor that takes a QWidget. +*/ + +/*! + \fn bool QStylePainter::begin(QPaintDevice *pd, QWidget *widget) + \overload + + Begin painting operations on paint device \a pd as if it was \a + widget. + + This is automatically called by the constructor that + takes a QPaintDevice and a QWidget. +*/ + + +/*! + \fn void QStylePainter::drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption &option) + + Use the widget's style to draw a primitive element \a pe specified by QStyleOption \a option. + + \sa QStyle::drawPrimitive() +*/ + +/*! + \fn void QStylePainter::drawControl(QStyle::ControlElement ce, const QStyleOption &option) + + Use the widget's style to draw a control element \a ce specified by QStyleOption \a option. + + \sa QStyle::drawControl() +*/ + +/*! + \fn void QStylePainter::drawComplexControl(QStyle::ComplexControl cc, + const QStyleOptionComplex &option) + + Use the widget's style to draw a complex control \a cc specified by the + QStyleOptionComplex \a option. + + \sa QStyle::drawComplexControl() +*/ + +/*! + \fn void QStylePainter::drawItemText(const QRect &rect, int flags, const QPalette &pal, + bool enabled, const QString &text, + QPalette::ColorRole textRole = QPalette::NoRole) + + Draws the \a text in rectangle \a rect and palette \a pal. + The text is aligned and wrapped according to \a + flags. + + The pen color is specified with \a textRole. The \a enabled bool + indicates whether or not the item is enabled; when reimplementing + this bool should influence how the item is drawn. + + \sa QStyle::drawItemText(), Qt::Alignment +*/ + +/*! + \fn void QStylePainter::drawItemPixmap(const QRect &rect, int flags, const QPixmap &pixmap) + + Draws the \a pixmap in rectangle \a rect. + The pixmap is aligned according to \a flags. + + \sa QStyle::drawItemPixmap(), Qt::Alignment +*/ + +/*! + \fn QStyle *QStylePainter::style() const + + Return the current style used by the QStylePainter. +*/ + +QT_END_NAMESPACE diff --git a/src/widgets/styles/qstylepainter.h b/src/widgets/styles/qstylepainter.h new file mode 100644 index 0000000000..0fc3f2b4b9 --- /dev/null +++ b/src/widgets/styles/qstylepainter.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLEPAINTER_H +#define QSTYLEPAINTER_H + +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QStylePainter : public QPainter +{ +public: + inline QStylePainter() : QPainter(), widget(0), wstyle(0) {} + inline explicit QStylePainter(QWidget *w) { begin(w, w); } + inline QStylePainter(QPaintDevice *pd, QWidget *w) { begin(pd, w); } + inline bool begin(QWidget *w) { return begin(w, w); } + inline bool begin(QPaintDevice *pd, QWidget *w) { + Q_ASSERT_X(w, "QStylePainter::QStylePainter", "Widget must be non-zero"); + widget = w; + wstyle = w->style(); + return QPainter::begin(pd); + }; + inline void drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption &opt); + inline void drawControl(QStyle::ControlElement ce, const QStyleOption &opt); + inline void drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex &opt); + inline void drawItemText(const QRect &r, int flags, const QPalette &pal, bool enabled, + const QString &text, QPalette::ColorRole textRole = QPalette::NoRole); + inline void drawItemPixmap(const QRect &r, int flags, const QPixmap &pixmap); + inline QStyle *style() const { return wstyle; } + +private: + QWidget *widget; + QStyle *wstyle; + Q_DISABLE_COPY(QStylePainter) +}; + +void QStylePainter::drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption &opt) +{ + wstyle->drawPrimitive(pe, &opt, this, widget); +} + +void QStylePainter::drawControl(QStyle::ControlElement ce, const QStyleOption &opt) +{ + wstyle->drawControl(ce, &opt, this, widget); +} + +void QStylePainter::drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex &opt) +{ + wstyle->drawComplexControl(cc, &opt, this, widget); +} + +void QStylePainter::drawItemText(const QRect &r, int flags, const QPalette &pal, bool enabled, + const QString &text, QPalette::ColorRole textRole) +{ + wstyle->drawItemText(this, r, flags, pal, enabled, text, textRole); +} + +void QStylePainter::drawItemPixmap(const QRect &r, int flags, const QPixmap &pixmap) +{ + wstyle->drawItemPixmap(this, r, flags, pixmap); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSTYLEPAINTER_H diff --git a/src/widgets/styles/qstyleplugin.cpp b/src/widgets/styles/qstyleplugin.cpp new file mode 100644 index 0000000000..f2143e307a --- /dev/null +++ b/src/widgets/styles/qstyleplugin.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstyleplugin.h" +#include "qstyle.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QStylePlugin + \brief The QStylePlugin class provides an abstract base for custom QStyle plugins. + + \ingroup plugins + + QStylePlugin is a simple plugin interface that makes it easy + to create custom styles that can be loaded dynamically into + applications using the QStyleFactory class. + + Writing a style plugin is achieved by subclassing this base class, + reimplementing the pure virtual keys() and create() functions, and + exporting the class using the Q_EXPORT_PLUGIN2() macro. See \l + {How to Create Qt Plugins} for details. + + \sa QStyleFactory, QStyle +*/ + +/*! + \fn QStringList QStylePlugin::keys() const + + Returns the list of style keys this plugin supports. + + These keys are usually the class names of the custom styles that + are implemented in the plugin. + + \sa create() +*/ + +/*! + \fn QStyle *QStylePlugin::create(const QString& key) + + Creates and returns a QStyle object for the given style \a key. + If a plugin cannot create a style, it should return 0 instead. + + The style key is usually the class name of the required + style. Note that the keys are case insensitive. For example: + + \snippet doc/src/snippets/qstyleplugin/main.cpp 0 + \codeline + \snippet doc/src/snippets/qstyleplugin/main.cpp 1 + \snippet doc/src/snippets/qstyleplugin/main.cpp 2 + + \sa keys() +*/ + +/*! + Constructs a style plugin with the given \a parent. + + Note that this constructor is invoked automatically by the + Q_EXPORT_PLUGIN2() macro, so there is no need for calling it + explicitly. +*/ +QStylePlugin::QStylePlugin(QObject *parent) + : QObject(parent) +{ +} + +/*! + Destroys the style plugin. + + Note that Qt destroys a plugin automatically when it is no longer + used, so there is no need for calling the destructor explicitly. +*/ +QStylePlugin::~QStylePlugin() +{ +} + +QT_END_NAMESPACE diff --git a/src/widgets/styles/qstyleplugin.h b/src/widgets/styles/qstyleplugin.h new file mode 100644 index 0000000000..56d690f6ff --- /dev/null +++ b/src/widgets/styles/qstyleplugin.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLEPLUGIN_H +#define QSTYLEPLUGIN_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QStyle; + +struct Q_GUI_EXPORT QStyleFactoryInterface : public QFactoryInterface +{ + virtual QStyle *create(const QString &key) = 0; +}; + +#define QStyleFactoryInterface_iid "com.trolltech.Qt.QStyleFactoryInterface" + +Q_DECLARE_INTERFACE(QStyleFactoryInterface, QStyleFactoryInterface_iid) + +class Q_GUI_EXPORT QStylePlugin : public QObject, public QStyleFactoryInterface +{ + Q_OBJECT + Q_INTERFACES(QStyleFactoryInterface:QFactoryInterface) +public: + explicit QStylePlugin(QObject *parent = 0); + ~QStylePlugin(); + + virtual QStringList keys() const = 0; + virtual QStyle *create(const QString &key) = 0; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSTYLEPLUGIN_H diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp new file mode 100644 index 0000000000..faa929ebea --- /dev/null +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -0,0 +1,5898 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#ifndef QT_NO_STYLE_STYLESHEET + +#include "qstylesheetstyle_p.h" +#include "private/qcssutil_p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "private/qcssparser_p.h" +#include "private/qmath_p.h" +#include +#include "private/qabstractscrollarea_p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qdrawutil.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QCss; + + +class QStyleSheetStylePrivate : public QWindowsStylePrivate +{ + Q_DECLARE_PUBLIC(QStyleSheetStyle) +public: + QStyleSheetStylePrivate() { } +}; + + +static QStyleSheetStyleCaches *styleSheetCaches = 0; + +/* RECURSION_GUARD: + * the QStyleSheetStyle is a proxy. If used with others proxy style, we may end up with something like: + * QStyleSheetStyle -> ProxyStyle -> QStyleSheetStyle -> OriginalStyle + * Recursion may happen if the style call the widget()->style() again. + * Not to mention the performence penalty of having two lookup of rules. + * + * The first instance of QStyleSheetStyle will set globalStyleSheetStyle to itself. The second one + * will notice the globalStyleSheetStyle is not istelf and call its base style directly. + */ +static const QStyleSheetStyle *globalStyleSheetStyle = 0; +class QStyleSheetStyleRecursionGuard +{ + public: + QStyleSheetStyleRecursionGuard(const QStyleSheetStyle *that) + : guarded(globalStyleSheetStyle == 0) + { + if (guarded) globalStyleSheetStyle = that; + } + ~QStyleSheetStyleRecursionGuard() { if (guarded) globalStyleSheetStyle = 0; } + bool guarded; +}; +#define RECURSION_GUARD(RETURN) \ + if (globalStyleSheetStyle != 0 && globalStyleSheetStyle != this) { RETURN; } \ + QStyleSheetStyleRecursionGuard recursion_guard(this); + +#define ceil(x) ((int)(x) + ((x) > 0 && (x) != (int)(x))) + +enum PseudoElement { + PseudoElement_None, + PseudoElement_DownArrow, + PseudoElement_UpArrow, + PseudoElement_LeftArrow, + PseudoElement_RightArrow, + PseudoElement_Indicator, + PseudoElement_ExclusiveIndicator, + PseudoElement_PushButtonMenuIndicator, + PseudoElement_ComboBoxDropDown, + PseudoElement_ComboBoxArrow, + PseudoElement_Item, + PseudoElement_SpinBoxUpButton, + PseudoElement_SpinBoxUpArrow, + PseudoElement_SpinBoxDownButton, + PseudoElement_SpinBoxDownArrow, + PseudoElement_GroupBoxTitle, + PseudoElement_GroupBoxIndicator, + PseudoElement_ToolButtonMenu, + PseudoElement_ToolButtonMenuArrow, + PseudoElement_ToolButtonDownArrow, + PseudoElement_ToolBoxTab, + PseudoElement_ScrollBarSlider, + PseudoElement_ScrollBarAddPage, + PseudoElement_ScrollBarSubPage, + PseudoElement_ScrollBarAddLine, + PseudoElement_ScrollBarSubLine, + PseudoElement_ScrollBarFirst, + PseudoElement_ScrollBarLast, + PseudoElement_ScrollBarUpArrow, + PseudoElement_ScrollBarDownArrow, + PseudoElement_ScrollBarLeftArrow, + PseudoElement_ScrollBarRightArrow, + PseudoElement_SplitterHandle, + PseudoElement_ToolBarHandle, + PseudoElement_ToolBarSeparator, + PseudoElement_MenuScroller, + PseudoElement_MenuTearoff, + PseudoElement_MenuCheckMark, + PseudoElement_MenuSeparator, + PseudoElement_MenuIcon, + PseudoElement_MenuRightArrow, + PseudoElement_TreeViewBranch, + PseudoElement_HeaderViewSection, + PseudoElement_HeaderViewUpArrow, + PseudoElement_HeaderViewDownArrow, + PseudoElement_ProgressBarChunk, + PseudoElement_TabBarTab, + PseudoElement_TabBarScroller, + PseudoElement_TabBarTear, + PseudoElement_SliderGroove, + PseudoElement_SliderHandle, + PseudoElement_SliderAddPage, + PseudoElement_SliderSubPage, + PseudoElement_SliderTickmark, + PseudoElement_TabWidgetPane, + PseudoElement_TabWidgetTabBar, + PseudoElement_TabWidgetLeftCorner, + PseudoElement_TabWidgetRightCorner, + PseudoElement_DockWidgetTitle, + PseudoElement_DockWidgetCloseButton, + PseudoElement_DockWidgetFloatButton, + PseudoElement_DockWidgetSeparator, + PseudoElement_MdiCloseButton, + PseudoElement_MdiMinButton, + PseudoElement_MdiNormalButton, + PseudoElement_TitleBar, + PseudoElement_TitleBarCloseButton, + PseudoElement_TitleBarMinButton, + PseudoElement_TitleBarMaxButton, + PseudoElement_TitleBarShadeButton, + PseudoElement_TitleBarUnshadeButton, + PseudoElement_TitleBarNormalButton, + PseudoElement_TitleBarContextHelpButton, + PseudoElement_TitleBarSysMenu, + PseudoElement_ViewItem, + PseudoElement_ViewItemIcon, + PseudoElement_ViewItemText, + PseudoElement_ViewItemIndicator, + PseudoElement_ScrollAreaCorner, + PseudoElement_TabBarTabCloseButton, + NumPseudoElements +}; + +struct PseudoElementInfo { + QStyle::SubControl subControl; + const char *name; +}; + +static const PseudoElementInfo knownPseudoElements[NumPseudoElements] = { + { QStyle::SC_None, "" }, + { QStyle::SC_None, "down-arrow" }, + { QStyle::SC_None, "up-arrow" }, + { QStyle::SC_None, "left-arrow" }, + { QStyle::SC_None, "right-arrow" }, + { QStyle::SC_None, "indicator" }, + { QStyle::SC_None, "indicator" }, + { QStyle::SC_None, "menu-indicator" }, + { QStyle::SC_ComboBoxArrow, "drop-down" }, + { QStyle::SC_ComboBoxArrow, "down-arrow" }, + { QStyle::SC_None, "item" }, + { QStyle::SC_SpinBoxUp, "up-button" }, + { QStyle::SC_SpinBoxUp, "up-arrow" }, + { QStyle::SC_SpinBoxDown, "down-button" }, + { QStyle::SC_SpinBoxDown, "down-arrow" }, + { QStyle::SC_GroupBoxLabel, "title" }, + { QStyle::SC_GroupBoxCheckBox, "indicator" }, + { QStyle::SC_ToolButtonMenu, "menu-button" }, + { QStyle::SC_ToolButtonMenu, "menu-arrow" }, + { QStyle::SC_None, "menu-indicator" }, + { QStyle::SC_None, "tab" }, + { QStyle::SC_ScrollBarSlider, "handle" }, + { QStyle::SC_ScrollBarAddPage, "add-page" }, + { QStyle::SC_ScrollBarSubPage, "sub-page" }, + { QStyle::SC_ScrollBarAddLine, "add-line" }, + { QStyle::SC_ScrollBarSubLine, "sub-line" }, + { QStyle::SC_ScrollBarFirst, "first" }, + { QStyle::SC_ScrollBarLast, "last" }, + { QStyle::SC_ScrollBarSubLine, "up-arrow" }, + { QStyle::SC_ScrollBarAddLine, "down-arrow" }, + { QStyle::SC_ScrollBarSubLine, "left-arrow" }, + { QStyle::SC_ScrollBarAddLine, "right-arrow" }, + { QStyle::SC_None, "handle" }, + { QStyle::SC_None, "handle" }, + { QStyle::SC_None, "separator" }, + { QStyle::SC_None, "scroller" }, + { QStyle::SC_None, "tearoff" }, + { QStyle::SC_None, "indicator" }, + { QStyle::SC_None, "separator" }, + { QStyle::SC_None, "icon" }, + { QStyle::SC_None, "right-arrow" }, + { QStyle::SC_None, "branch" }, + { QStyle::SC_None, "section" }, + { QStyle::SC_None, "down-arrow" }, + { QStyle::SC_None, "up-arrow" }, + { QStyle::SC_None, "chunk" }, + { QStyle::SC_None, "tab" }, + { QStyle::SC_None, "scroller" }, + { QStyle::SC_None, "tear" }, + { QStyle::SC_SliderGroove, "groove" }, + { QStyle::SC_SliderHandle, "handle" }, + { QStyle::SC_None, "add-page" }, + { QStyle::SC_None, "sub-page"}, + { QStyle::SC_SliderTickmarks, "tick-mark" }, + { QStyle::SC_None, "pane" }, + { QStyle::SC_None, "tab-bar" }, + { QStyle::SC_None, "left-corner" }, + { QStyle::SC_None, "right-corner" }, + { QStyle::SC_None, "title" }, + { QStyle::SC_None, "close-button" }, + { QStyle::SC_None, "float-button" }, + { QStyle::SC_None, "separator" }, + { QStyle::SC_MdiCloseButton, "close-button" }, + { QStyle::SC_MdiMinButton, "minimize-button" }, + { QStyle::SC_MdiNormalButton, "normal-button" }, + { QStyle::SC_TitleBarLabel, "title" }, + { QStyle::SC_TitleBarCloseButton, "close-button" }, + { QStyle::SC_TitleBarMinButton, "minimize-button" }, + { QStyle::SC_TitleBarMaxButton, "maximize-button" }, + { QStyle::SC_TitleBarShadeButton, "shade-button" }, + { QStyle::SC_TitleBarUnshadeButton, "unshade-button" }, + { QStyle::SC_TitleBarNormalButton, "normal-button" }, + { QStyle::SC_TitleBarContextHelpButton, "contexthelp-button" }, + { QStyle::SC_TitleBarSysMenu, "sys-menu" }, + { QStyle::SC_None, "item" }, + { QStyle::SC_None, "icon" }, + { QStyle::SC_None, "text" }, + { QStyle::SC_None, "indicator" }, + { QStyle::SC_None, "corner" }, + { QStyle::SC_None, "close-button" }, +}; + + +struct QStyleSheetBorderImageData : public QSharedData +{ + QStyleSheetBorderImageData() + : horizStretch(QCss::TileMode_Unknown), vertStretch(QCss::TileMode_Unknown) + { + for (int i = 0; i < 4; i++) + cuts[i] = -1; + } + int cuts[4]; + QPixmap pixmap; + QImage image; + QCss::TileMode horizStretch, vertStretch; +}; + +struct QStyleSheetBackgroundData : public QSharedData +{ + QStyleSheetBackgroundData(const QBrush& b, const QPixmap& p, QCss::Repeat r, + Qt::Alignment a, QCss::Origin o, Attachment t, QCss::Origin c) + : brush(b), pixmap(p), repeat(r), position(a), origin(o), attachment(t), clip(c) { } + + bool isTransparent() const { + if (brush.style() != Qt::NoBrush) + return !brush.isOpaque(); + return pixmap.isNull() ? false : pixmap.hasAlpha(); + } + QBrush brush; + QPixmap pixmap; + QCss::Repeat repeat; + Qt::Alignment position; + QCss::Origin origin; + QCss::Attachment attachment; + QCss::Origin clip; +}; + +struct QStyleSheetBorderData : public QSharedData +{ + QStyleSheetBorderData() : bi(0) + { + for (int i = 0; i < 4; i++) { + borders[i] = 0; + styles[i] = QCss::BorderStyle_None; + } + } + + QStyleSheetBorderData(int *b, QBrush *c, QCss::BorderStyle *s, QSize *r) : bi(0) + { + for (int i = 0; i < 4; i++) { + borders[i] = b[i]; + styles[i] = s[i]; + colors[i] = c[i]; + radii[i] = r[i]; + } + } + + int borders[4]; + QBrush colors[4]; + QCss::BorderStyle styles[4]; + QSize radii[4]; // topleft, topright, bottomleft, bottomright + + const QStyleSheetBorderImageData *borderImage() const + { return bi; } + bool hasBorderImage() const { return bi!=0; } + + QSharedDataPointer bi; + + bool isOpaque() const + { + for (int i = 0; i < 4; i++) { + if (styles[i] == QCss::BorderStyle_Native || styles[i] == QCss::BorderStyle_None) + continue; + if (styles[i] >= QCss::BorderStyle_Dotted && styles[i] <= QCss::BorderStyle_DotDotDash + && styles[i] != BorderStyle_Solid) + return false; + if (!colors[i].isOpaque()) + return false; + if (!radii[i].isEmpty()) + return false; + } + if (bi != 0 && bi->pixmap.hasAlpha()) + return false; + return true; + } +}; + + +struct QStyleSheetOutlineData : public QStyleSheetBorderData +{ + QStyleSheetOutlineData() + { + for (int i = 0; i < 4; i++) { + offsets[i] = 0; + } + } + + QStyleSheetOutlineData(int *b, QBrush *c, QCss::BorderStyle *s, QSize *r, int *o) + : QStyleSheetBorderData(b, c, s, r) + { + for (int i = 0; i < 4; i++) { + offsets[i] = o[i]; + } + } + + int offsets[4]; +}; + +struct QStyleSheetBoxData : public QSharedData +{ + QStyleSheetBoxData(int *m, int *p, int s) : spacing(s) + { + for (int i = 0; i < 4; i++) { + margins[i] = m[i]; + paddings[i] = p[i]; + } + } + + int margins[4]; + int paddings[4]; + + int spacing; +}; + +struct QStyleSheetPaletteData : public QSharedData +{ + QStyleSheetPaletteData(const QBrush &fg, const QBrush &sfg, const QBrush &sbg, + const QBrush &abg) + : foreground(fg), selectionForeground(sfg), selectionBackground(sbg), + alternateBackground(abg) { } + + QBrush foreground; + QBrush selectionForeground; + QBrush selectionBackground; + QBrush alternateBackground; +}; + +struct QStyleSheetGeometryData : public QSharedData +{ + QStyleSheetGeometryData(int w, int h, int minw, int minh, int maxw, int maxh) + : minWidth(minw), minHeight(minh), width(w), height(h), maxWidth(maxw), maxHeight(maxh) { } + + int minWidth, minHeight, width, height, maxWidth, maxHeight; +}; + +struct QStyleSheetPositionData : public QSharedData +{ + QStyleSheetPositionData(int l, int t, int r, int b, Origin o, Qt::Alignment p, QCss::PositionMode m, Qt::Alignment a = 0) + : left(l), top(t), bottom(b), right(r), origin(o), position(p), mode(m), textAlignment(a) { } + + int left, top, bottom, right; + Origin origin; + Qt::Alignment position; + QCss::PositionMode mode; + Qt::Alignment textAlignment; +}; + +struct QStyleSheetImageData : public QSharedData +{ + QStyleSheetImageData(const QIcon &i, Qt::Alignment a, const QSize &sz) + : icon(i), alignment(a), size(sz) { } + + QIcon icon; + Qt::Alignment alignment; + QSize size; +}; + +class QRenderRule +{ +public: + QRenderRule() : features(0), hasFont(false), pal(0), b(0), bg(0), bd(0), ou(0), geo(0), p(0), img(0), clipset(0) { } + QRenderRule(const QVector &, const QWidget *); + ~QRenderRule() { } + + QRect borderRect(const QRect &r) const; + QRect outlineRect(const QRect &r) const; + QRect paddingRect(const QRect &r) const; + QRect contentsRect(const QRect &r) const; + + enum { Margin = 1, Border = 2, Padding = 4, All=Margin|Border|Padding }; + QRect boxRect(const QRect &r, int flags = All) const; + QSize boxSize(const QSize &s, int flags = All) const; + QRect originRect(const QRect &rect, Origin origin) const; + + QPainterPath borderClip(QRect rect); + void drawBorder(QPainter *, const QRect&); + void drawOutline(QPainter *, const QRect&); + void drawBorderImage(QPainter *, const QRect&); + void drawBackground(QPainter *, const QRect&, const QPoint& = QPoint(0, 0)); + void drawBackgroundImage(QPainter *, const QRect&, QPoint = QPoint(0, 0)); + void drawFrame(QPainter *, const QRect&); + void drawImage(QPainter *p, const QRect &rect); + void drawRule(QPainter *, const QRect&); + void configurePalette(QPalette *, QPalette::ColorGroup, const QWidget *, bool); + void configurePalette(QPalette *p, QPalette::ColorRole fr, QPalette::ColorRole br); + + const QStyleSheetPaletteData *palette() const { return pal; } + const QStyleSheetBoxData *box() const { return b; } + const QStyleSheetBackgroundData *background() const { return bg; } + const QStyleSheetBorderData *border() const { return bd; } + const QStyleSheetOutlineData *outline() const { return ou; } + const QStyleSheetGeometryData *geometry() const { return geo; } + const QStyleSheetPositionData *position() const { return p; } + + bool hasPalette() const { return pal != 0; } + bool hasBackground() const { return bg != 0 && (!bg->pixmap.isNull() || bg->brush.style() != Qt::NoBrush); } + bool hasGradientBackground() const { return bg && bg->brush.style() >= Qt::LinearGradientPattern + && bg->brush.style() <= Qt::ConicalGradientPattern; } + + bool hasNativeBorder() const { + return bd == 0 + || (!bd->hasBorderImage() && bd->styles[0] == BorderStyle_Native); + } + + bool hasNativeOutline() const { + return (ou == 0 + || (!ou->hasBorderImage() && ou->styles[0] == BorderStyle_Native)); + } + + bool baseStyleCanDraw() const { + if (!hasBackground() || (background()->brush.style() == Qt::NoBrush && bg->pixmap.isNull())) + return true; + if (bg && !bg->pixmap.isNull()) + return false; + if (hasGradientBackground()) + return features & StyleFeature_BackgroundGradient; + return features & StyleFeature_BackgroundColor; + } + + bool hasBox() const { return b != 0; } + bool hasBorder() const { return bd != 0; } + bool hasOutline() const { return ou != 0; } + bool hasPosition() const { return p != 0; } + bool hasGeometry() const { return geo != 0; } + bool hasDrawable() const { return !hasNativeBorder() || hasBackground() || hasImage(); } + bool hasImage() const { return img != 0; } + + QSize minimumContentsSize() const + { return geo ? QSize(geo->minWidth, geo->minHeight) : QSize(0, 0); } + QSize minimumSize() const + { return boxSize(minimumContentsSize()); } + + QSize contentsSize() const + { return geo ? QSize(geo->width, geo->height) + : ((img && img->size.isValid()) ? img->size : QSize()); } + QSize contentsSize(const QSize &sz) const + { + QSize csz = contentsSize(); + if (csz.width() == -1) csz.setWidth(sz.width()); + if (csz.height() == -1) csz.setHeight(sz.height()); + return csz; + } + bool hasContentsSize() const + { return (geo && (geo->width != -1 || geo->height != -1)) || (img && img->size.isValid()); } + + QSize size() const { return boxSize(contentsSize()); } + QSize size(const QSize &sz) const { return boxSize(contentsSize(sz)); } + QSize adjustSize(const QSize &sz) + { + if (!geo) + return sz; + QSize csz = contentsSize(); + if (csz.width() == -1) csz.setWidth(sz.width()); + if (csz.height() == -1) csz.setHeight(sz.height()); + if (geo->maxWidth != -1 && csz.width() > geo->maxWidth) csz.setWidth(geo->maxWidth); + if (geo->maxHeight != -1 && csz.height() > geo->maxHeight) csz.setHeight(geo->maxHeight); + csz=csz.expandedTo(QSize(geo->minWidth, geo->minHeight)); + return csz; + } + + int features; + QBrush defaultBackground; + QFont font; + bool hasFont; + + QHash styleHints; + bool hasStyleHint(const QString& sh) const { return styleHints.contains(sh); } + QVariant styleHint(const QString& sh) const { return styleHints.value(sh); } + + void fixupBorder(int); + + QSharedDataPointer pal; + QSharedDataPointer b; + QSharedDataPointer bg; + QSharedDataPointer bd; + QSharedDataPointer ou; + QSharedDataPointer geo; + QSharedDataPointer p; + QSharedDataPointer img; + + // Shouldn't be here + void setClip(QPainter *p, const QRect &rect); + void unsetClip(QPainter *); + int clipset; + QPainterPath clipPath; +}; + +/////////////////////////////////////////////////////////////////////////////////////////// +static const char *knownStyleHints[] = { + "activate-on-singleclick", + "alignment", + "arrow-keys-navigate-into-children", + "backward-icon", + "button-layout", + "cd-icon", + "combobox-list-mousetracking", + "combobox-popup", + "computer-icon", + "desktop-icon", + "dialog-apply-icon", + "dialog-cancel-icon", + "dialog-close-icon", + "dialog-discard-icon", + "dialog-help-icon", + "dialog-no-icon", + "dialog-ok-icon", + "dialog-open-icon", + "dialog-reset-icon", + "dialog-save-icon", + "dialog-yes-icon", + "dialogbuttonbox-buttons-have-icons", + "directory-closed-icon", + "directory-icon", + "directory-link-icon", + "directory-open-icon", + "dither-disable-text", + "dockwidget-close-icon", + "downarrow-icon", + "dvd-icon", + "etch-disabled-text", + "file-icon", + "file-link-icon", + "filedialog-backward-icon", // unused + "filedialog-contentsview-icon", + "filedialog-detailedview-icon", + "filedialog-end-icon", + "filedialog-infoview-icon", + "filedialog-listview-icon", + "filedialog-new-directory-icon", + "filedialog-parent-directory-icon", + "filedialog-start-icon", + "floppy-icon", + "forward-icon", + "gridline-color", + "harddisk-icon", + "home-icon", + "icon-size", + "leftarrow-icon", + "lineedit-password-character", + "mdi-fill-space-on-maximize", + "menu-scrollable", + "menubar-altkey-navigation", + "menubar-separator", + "messagebox-critical-icon", + "messagebox-information-icon", + "messagebox-question-icon", + "messagebox-text-interaction-flags", + "messagebox-warning-icon", + "mouse-tracking", + "network-icon", + "opacity", + "paint-alternating-row-colors-for-empty-area", + "rightarrow-icon", + "scrollbar-contextmenu", + "scrollbar-leftclick-absolute-position", + "scrollbar-middleclick-absolute-position", + "scrollbar-roll-between-buttons", + "scrollbar-scroll-when-pointer-leaves-control", + "scrollview-frame-around-contents", + "show-decoration-selected", + "spinbox-click-autorepeat-rate", + "spincontrol-disable-on-bounds", + "tabbar-elide-mode", + "tabbar-prefer-no-arrows", + "titlebar-close-icon", + "titlebar-contexthelp-icon", + "titlebar-maximize-icon", + "titlebar-menu-icon", + "titlebar-minimize-icon", + "titlebar-normal-icon", + "titlebar-shade-icon", + "titlebar-unshade-icon", + "toolbutton-popup-delay", + "trash-icon", + "uparrow-icon" +}; + +static const int numKnownStyleHints = sizeof(knownStyleHints)/sizeof(knownStyleHints[0]); + +static QList subControlLayout(const QString& layout) +{ + QList buttons; + for (int i = 0; i < layout.count(); i++) { + int button = layout[i].toAscii(); + switch (button) { + case 'm': + buttons.append(PseudoElement_MdiMinButton); + buttons.append(PseudoElement_TitleBarMinButton); + break; + case 'M': + buttons.append(PseudoElement_TitleBarMaxButton); + break; + case 'X': + buttons.append(PseudoElement_MdiCloseButton); + buttons.append(PseudoElement_TitleBarCloseButton); + break; + case 'N': + buttons.append(PseudoElement_MdiNormalButton); + buttons.append(PseudoElement_TitleBarNormalButton); + break; + case 'I': + buttons.append(PseudoElement_TitleBarSysMenu); + break; + case 'T': + buttons.append(PseudoElement_TitleBar); + break; + case 'H': + buttons.append(PseudoElement_TitleBarContextHelpButton); + break; + case 'S': + buttons.append(PseudoElement_TitleBarShadeButton); + break; + default: + buttons.append(button); + break; + } + } + return buttons; +} + +namespace { + struct ButtonInfo { + QRenderRule rule; + int element; + int offset; + int where; + int width; + }; +} + +QHash QStyleSheetStyle::titleBarLayout(const QWidget *w, const QStyleOptionTitleBar *tb) const +{ + QHash layoutRects; + const bool isMinimized = tb->titleBarState & Qt::WindowMinimized; + const bool isMaximized = tb->titleBarState & Qt::WindowMaximized; + QRenderRule subRule = renderRule(w, tb); + QRect cr = subRule.contentsRect(tb->rect); + QList layout = subRule.styleHint(QLatin1String("button-layout")).toList(); + if (layout.isEmpty()) + layout = subControlLayout(QLatin1String("I(T)HSmMX")); + + int offsets[3] = { 0, 0, 0 }; + enum Where { Left, Right, Center, NoWhere } where = Left; + QList infos; + for (int i = 0; i < layout.count(); i++) { + ButtonInfo info; + info.element = layout[i].toInt(); + if (info.element == '(') { + where = Center; + } else if (info.element == ')') { + where = Right; + } else { + switch (info.element) { + case PseudoElement_TitleBar: + if (!(tb->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint))) + continue; + break; + case PseudoElement_TitleBarContextHelpButton: + if (!(tb->titleBarFlags & Qt::WindowContextHelpButtonHint)) + continue; + break; + case PseudoElement_TitleBarMinButton: + if (!(tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + continue; + if (isMinimized) + info.element = PseudoElement_TitleBarNormalButton; + break; + case PseudoElement_TitleBarMaxButton: + if (!(tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + continue; + if (isMaximized) + info.element = PseudoElement_TitleBarNormalButton; + break; + case PseudoElement_TitleBarShadeButton: + if (!(tb->titleBarFlags & Qt::WindowShadeButtonHint)) + continue; + if (isMinimized) + info.element = PseudoElement_TitleBarUnshadeButton; + break; + case PseudoElement_TitleBarCloseButton: + case PseudoElement_TitleBarSysMenu: + if (!(tb->titleBarFlags & Qt::WindowSystemMenuHint)) + continue; + break; + default: + continue; + } + if (info.element == PseudoElement_TitleBar) { + info.width = tb->fontMetrics.width(tb->text) + 6; + subRule.geo = new QStyleSheetGeometryData(info.width, tb->fontMetrics.height(), -1, -1, -1, -1); + } else { + subRule = renderRule(w, tb, info.element); + info.width = subRule.size().width(); + } + info.rule = subRule; + info.offset = offsets[where]; + info.where = where; + infos.append(info); + + offsets[where] += info.width; + } + } + + for (int i = 0; i < infos.count(); i++) { + ButtonInfo info = infos[i]; + QRect lr = cr; + switch (info.where) { + case Center: { + lr.setLeft(cr.left() + offsets[Left]); + lr.setRight(cr.right() - offsets[Right]); + QRect r(0, 0, offsets[Center], lr.height()); + r.moveCenter(lr.center()); + r.setLeft(r.left()+info.offset); + r.setWidth(info.width); + lr = r; + break; } + case Left: + lr.translate(info.offset, 0); + lr.setWidth(info.width); + break; + case Right: + lr.moveLeft(cr.right() + 1 - offsets[Right] + info.offset); + lr.setWidth(info.width); + break; + default: + break; + } + QStyle::SubControl control = knownPseudoElements[info.element].subControl; + layoutRects[control] = positionRect(w, info.rule, info.element, lr, tb->direction); + } + + return layoutRects; +} + +static QStyle::StandardPixmap subControlIcon(int pe) +{ + switch (pe) { + case PseudoElement_MdiCloseButton: return QStyle::SP_TitleBarCloseButton; + case PseudoElement_MdiMinButton: return QStyle::SP_TitleBarMinButton; + case PseudoElement_MdiNormalButton: return QStyle::SP_TitleBarNormalButton; + case PseudoElement_TitleBarCloseButton: return QStyle::SP_TitleBarCloseButton; + case PseudoElement_TitleBarMinButton: return QStyle::SP_TitleBarMinButton; + case PseudoElement_TitleBarMaxButton: return QStyle::SP_TitleBarMaxButton; + case PseudoElement_TitleBarShadeButton: return QStyle::SP_TitleBarShadeButton; + case PseudoElement_TitleBarUnshadeButton: return QStyle::SP_TitleBarUnshadeButton; + case PseudoElement_TitleBarNormalButton: return QStyle::SP_TitleBarNormalButton; + case PseudoElement_TitleBarContextHelpButton: return QStyle::SP_TitleBarContextHelpButton; + default: break; + } + return QStyle::SP_CustomBase; +} + +QRenderRule::QRenderRule(const QVector &declarations, const QWidget *widget) +: features(0), hasFont(false), pal(0), b(0), bg(0), bd(0), ou(0), geo(0), p(0), img(0), clipset(0) +{ + QPalette palette = QApplication::palette(); // ###: ideally widget's palette + ValueExtractor v(declarations, palette); + features = v.extractStyleFeatures(); + + int w = -1, h = -1, minw = -1, minh = -1, maxw = -1, maxh = -1; + if (v.extractGeometry(&w, &h, &minw, &minh, &maxw, &maxh)) + geo = new QStyleSheetGeometryData(w, h, minw, minh, maxw, maxh); + + int left = 0, top = 0, right = 0, bottom = 0; + Origin origin = Origin_Unknown; + Qt::Alignment position = 0; + QCss::PositionMode mode = PositionMode_Unknown; + Qt::Alignment textAlignment = 0; + if (v.extractPosition(&left, &top, &right, &bottom, &origin, &position, &mode, &textAlignment)) + p = new QStyleSheetPositionData(left, top, right, bottom, origin, position, mode, textAlignment); + + int margins[4], paddings[4], spacing = -1; + for (int i = 0; i < 4; i++) + margins[i] = paddings[i] = 0; + if (v.extractBox(margins, paddings, &spacing)) + b = new QStyleSheetBoxData(margins, paddings, spacing); + + int borders[4]; + QBrush colors[4]; + QCss::BorderStyle styles[4]; + QSize radii[4]; + for (int i = 0; i < 4; i++) { + borders[i] = 0; + styles[i] = BorderStyle_None; + } + if (v.extractBorder(borders, colors, styles, radii)) + bd = new QStyleSheetBorderData(borders, colors, styles, radii); + + int offsets[4]; + for (int i = 0; i < 4; i++) { + borders[i] = offsets[i] = 0; + styles[i] = BorderStyle_None; + } + if (v.extractOutline(borders, colors, styles, radii, offsets)) + ou = new QStyleSheetOutlineData(borders, colors, styles, radii, offsets); + + QBrush brush; + QString uri; + Repeat repeat = Repeat_XY; + Qt::Alignment alignment = Qt::AlignTop | Qt::AlignLeft; + Attachment attachment = Attachment_Scroll; + origin = Origin_Padding; + Origin clip = Origin_Border; + if (v.extractBackground(&brush, &uri, &repeat, &alignment, &origin, &attachment, &clip)) + bg = new QStyleSheetBackgroundData(brush, QPixmap(uri), repeat, alignment, origin, attachment, clip); + + QBrush sfg, fg; + QBrush sbg, abg; + if (v.extractPalette(&fg, &sfg, &sbg, &abg)) + pal = new QStyleSheetPaletteData(fg, sfg, sbg, abg); + + QIcon icon; + alignment = Qt::AlignCenter; + QSize size; + if (v.extractImage(&icon, &alignment, &size)) + img = new QStyleSheetImageData(icon, alignment, size); + + int adj = -255; + hasFont = v.extractFont(&font, &adj); + +#ifndef QT_NO_TOOLTIP + if (widget && qstrcmp(widget->metaObject()->className(), "QTipLabel") == 0) + palette = QToolTip::palette(); +#endif + + for (int i = 0; i < declarations.count(); i++) { + const Declaration& decl = declarations.at(i); + if (decl.d->propertyId == BorderImage) { + QString uri; + QCss::TileMode horizStretch, vertStretch; + int cuts[4]; + + decl.borderImageValue(&uri, cuts, &horizStretch, &vertStretch); + if (uri.isEmpty() || uri == QLatin1String("none")) { + if (bd && bd->bi) + bd->bi->pixmap = QPixmap(); + } else { + if (!bd) + bd = new QStyleSheetBorderData; + if (!bd->bi) + bd->bi = new QStyleSheetBorderImageData; + + QStyleSheetBorderImageData *bi = bd->bi; + bi->pixmap = QPixmap(uri); + for (int i = 0; i < 4; i++) + bi->cuts[i] = cuts[i]; + bi->horizStretch = horizStretch; + bi->vertStretch = vertStretch; + } + } else if (decl.d->propertyId == QtBackgroundRole) { + if (bg && bg->brush.style() != Qt::NoBrush) + continue; + int role = decl.d->values.at(0).variant.toInt(); + if (role >= Value_FirstColorRole && role <= Value_LastColorRole) + defaultBackground = palette.color((QPalette::ColorRole)(role-Value_FirstColorRole)); + } else if (decl.d->property.startsWith(QLatin1String("qproperty-"), Qt::CaseInsensitive)) { + // intentionally left blank... + } else if (decl.d->propertyId == UnknownProperty) { + bool knownStyleHint = false; + for (int i = 0; i < numKnownStyleHints; i++) { + QLatin1String styleHint(knownStyleHints[i]); + if (decl.d->property.compare(styleHint) == 0) { + QString hintName = QString(styleHint); + QVariant hintValue; + if (hintName.endsWith(QLatin1String("alignment"))) { + hintValue = (int) decl.alignmentValue(); + } else if (hintName.endsWith(QLatin1String("color"))) { + hintValue = (int) decl.colorValue().rgba(); + } else if (hintName.endsWith(QLatin1String("size"))) { + hintValue = decl.sizeValue(); + } else if (hintName.endsWith(QLatin1String("icon"))) { + hintValue = decl.iconValue(); + } else if (hintName == QLatin1String("button-layout") + && decl.d->values.count() != 0 && decl.d->values.at(0).type == Value::String) { + hintValue = subControlLayout(decl.d->values.at(0).variant.toString()); + } else { + int integer; + decl.intValue(&integer); + hintValue = integer; + } + styleHints[decl.d->property] = hintValue; + knownStyleHint = true; + break; + } + } + if (!knownStyleHint) + qDebug("Unknown property %s", qPrintable(decl.d->property)); + } + } + + if (widget) { + QStyleSheetStyle *style = const_cast(globalStyleSheetStyle); + if (!style) + style = qobject_cast(widget->style()); + if (style) + fixupBorder(style->nativeFrameWidth(widget)); + + } + if (hasBorder() && border()->hasBorderImage()) + defaultBackground = QBrush(); +} + +QRect QRenderRule::borderRect(const QRect& r) const +{ + if (!hasBox()) + return r; + const int* m = box()->margins; + return r.adjusted(m[LeftEdge], m[TopEdge], -m[RightEdge], -m[BottomEdge]); +} + +QRect QRenderRule::outlineRect(const QRect& r) const +{ + QRect br = borderRect(r); + if (!hasOutline()) + return br; + const int *b = outline()->borders; + return r.adjusted(b[LeftEdge], b[TopEdge], -b[RightEdge], -b[BottomEdge]); +} + +QRect QRenderRule::paddingRect(const QRect& r) const +{ + QRect br = borderRect(r); + if (!hasBorder()) + return br; + const int *b = border()->borders; + return br.adjusted(b[LeftEdge], b[TopEdge], -b[RightEdge], -b[BottomEdge]); +} + +QRect QRenderRule::contentsRect(const QRect& r) const +{ + QRect pr = paddingRect(r); + if (!hasBox()) + return pr; + const int *p = box()->paddings; + return pr.adjusted(p[LeftEdge], p[TopEdge], -p[RightEdge], -p[BottomEdge]); +} + +QRect QRenderRule::boxRect(const QRect& cr, int flags) const +{ + QRect r = cr; + if (hasBox()) { + if (flags & Margin) { + const int *m = box()->margins; + r.adjust(-m[LeftEdge], -m[TopEdge], m[RightEdge], m[BottomEdge]); + } + if (flags & Padding) { + const int *p = box()->paddings; + r.adjust(-p[LeftEdge], -p[TopEdge], p[RightEdge], p[BottomEdge]); + } + } + if (hasBorder() && (flags & Border)) { + const int *b = border()->borders; + r.adjust(-b[LeftEdge], -b[TopEdge], b[RightEdge], b[BottomEdge]); + } + return r; +} + +QSize QRenderRule::boxSize(const QSize &cs, int flags) const +{ + QSize bs = boxRect(QRect(QPoint(0, 0), cs), flags).size(); + if (cs.width() < 0) bs.setWidth(-1); + if (cs.height() < 0) bs.setHeight(-1); + return bs; +} + +void QRenderRule::fixupBorder(int nativeWidth) +{ + if (bd == 0) + return; + + if (!bd->hasBorderImage() || bd->bi->pixmap.isNull()) { + bd->bi = 0; + // ignore the color, border of edges that have none border-style + QBrush color = pal ? pal->foreground : QBrush(); + const bool hasRadius = bd->radii[0].isValid() || bd->radii[1].isValid() + || bd->radii[2].isValid() || bd->radii[3].isValid(); + for (int i = 0; i < 4; i++) { + if ((bd->styles[i] == BorderStyle_Native) && hasRadius) + bd->styles[i] = BorderStyle_None; + + switch (bd->styles[i]) { + case BorderStyle_None: + // border-style: none forces width to be 0 + bd->colors[i] = QBrush(); + bd->borders[i] = 0; + break; + case BorderStyle_Native: + if (bd->borders[i] == 0) + bd->borders[i] = nativeWidth; + // intentional fall through + default: + if (!bd->colors[i].style() != Qt::NoBrush) // auto-acquire 'color' + bd->colors[i] = color; + break; + } + } + + return; + } + + // inspect the border image + QStyleSheetBorderImageData *bi = bd->bi; + if (bi->cuts[0] == -1) { + for (int i = 0; i < 4; i++) // assume, cut = border + bi->cuts[i] = int(border()->borders[i]); + } +} + +void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect) +{ + setClip(p, rect); + static const Qt::TileRule tileMode2TileRule[] = { + Qt::StretchTile, Qt::RoundTile, Qt::StretchTile, Qt::RepeatTile, Qt::StretchTile }; + + const QStyleSheetBorderImageData *borderImageData = border()->borderImage(); + const int *targetBorders = border()->borders; + const int *sourceBorders = borderImageData->cuts; + QMargins sourceMargins(sourceBorders[LeftEdge], sourceBorders[TopEdge], + sourceBorders[RightEdge], sourceBorders[BottomEdge]); + QMargins targetMargins(targetBorders[LeftEdge], targetBorders[TopEdge], + targetBorders[RightEdge], targetBorders[BottomEdge]); + + bool wasSmoothPixmapTransform = p->renderHints() & QPainter::SmoothPixmapTransform; + p->setRenderHint(QPainter::SmoothPixmapTransform); + qDrawBorderPixmap(p, rect, targetMargins, borderImageData->pixmap, + QRect(QPoint(), borderImageData->pixmap.size()), sourceMargins, + QTileRules(tileMode2TileRule[borderImageData->horizStretch], tileMode2TileRule[borderImageData->vertStretch])); + p->setRenderHint(QPainter::SmoothPixmapTransform, wasSmoothPixmapTransform); + unsetClip(p); +} + +QRect QRenderRule::originRect(const QRect &rect, Origin origin) const +{ + switch (origin) { + case Origin_Padding: + return paddingRect(rect); + case Origin_Border: + return borderRect(rect); + case Origin_Content: + return contentsRect(rect); + case Origin_Margin: + default: + return rect; + } +} + +void QRenderRule::drawBackgroundImage(QPainter *p, const QRect &rect, QPoint off) +{ + if (!hasBackground()) + return; + + const QPixmap& bgp = background()->pixmap; + if (bgp.isNull()) + return; + + setClip(p, borderRect(rect)); + + if (background()->origin != background()->clip) { + p->save(); + p->setClipRect(originRect(rect, background()->clip), Qt::IntersectClip); + } + + if (background()->attachment == Attachment_Fixed) + off = QPoint(0, 0); + + QRect r = originRect(rect, background()->origin); + QRect aligned = QStyle::alignedRect(Qt::LeftToRight, background()->position, bgp.size(), r); + QRect inter = aligned.translated(-off).intersected(r); + + switch (background()->repeat) { + case Repeat_Y: + p->drawTiledPixmap(inter.x(), r.y(), inter.width(), r.height(), bgp, + inter.x() - aligned.x() + off.x(), + bgp.height() - int(aligned.y() - r.y()) % bgp.height() + off.y()); + break; + case Repeat_X: + p->drawTiledPixmap(r.x(), inter.y(), r.width(), inter.height(), bgp, + bgp.width() - int(aligned.x() - r.x())%bgp.width() + off.x(), + inter.y() - aligned.y() + off.y()); + break; + case Repeat_XY: + p->drawTiledPixmap(r, bgp, + QPoint(bgp.width() - int(aligned.x() - r.x())% bgp.width() + off.x(), + bgp.height() - int(aligned.y() - r.y())%bgp.height() + off.y())); + break; + case Repeat_None: + default: + p->drawPixmap(inter.x(), inter.y(), bgp, inter.x() - aligned.x() + off.x(), + inter.y() - aligned.y() + off.y(), inter.width(), inter.height()); + break; + } + + + if (background()->origin != background()->clip) + p->restore(); + + unsetClip(p); +} + +void QRenderRule::drawOutline(QPainter *p, const QRect &rect) +{ + if (!hasOutline()) + return; + + bool wasAntialiased = p->renderHints() & QPainter::Antialiasing; + p->setRenderHint(QPainter::Antialiasing); + qDrawBorder(p, rect, ou->styles, ou->borders, ou->colors, ou->radii); + p->setRenderHint(QPainter::Antialiasing, wasAntialiased); +} + +void QRenderRule::drawBorder(QPainter *p, const QRect& rect) +{ + if (!hasBorder()) + return; + + if (border()->hasBorderImage()) { + drawBorderImage(p, rect); + return; + } + + bool wasAntialiased = p->renderHints() & QPainter::Antialiasing; + p->setRenderHint(QPainter::Antialiasing); + qDrawBorder(p, rect, bd->styles, bd->borders, bd->colors, bd->radii); + p->setRenderHint(QPainter::Antialiasing, wasAntialiased); +} + +QPainterPath QRenderRule::borderClip(QRect r) +{ + if (!hasBorder()) + return QPainterPath(); + + QSize tlr, trr, blr, brr; + qNormalizeRadii(r, bd->radii, &tlr, &trr, &blr, &brr); + if (tlr.isNull() && trr.isNull() && blr.isNull() && brr.isNull()) + return QPainterPath(); + + const QRectF rect(r); + const int *borders = border()->borders; + QPainterPath path; + qreal curY = rect.y() + borders[TopEdge]/2.0; + path.moveTo(rect.x() + tlr.width(), curY); + path.lineTo(rect.right() - trr.width(), curY); + qreal curX = rect.right() - borders[RightEdge]/2.0; + path.arcTo(curX - 2*trr.width() + borders[RightEdge], curY, + trr.width()*2 - borders[RightEdge], trr.height()*2 - borders[TopEdge], 90, -90); + + path.lineTo(curX, rect.bottom() - brr.height()); + curY = rect.bottom() - borders[BottomEdge]/2.0; + path.arcTo(curX - 2*brr.width() + borders[RightEdge], curY - 2*brr.height() + borders[BottomEdge], + brr.width()*2 - borders[RightEdge], brr.height()*2 - borders[BottomEdge], 0, -90); + + path.lineTo(rect.x() + blr.width(), curY); + curX = rect.left() + borders[LeftEdge]/2.0; + path.arcTo(curX, rect.bottom() - 2*blr.height() + borders[BottomEdge]/2, + blr.width()*2 - borders[LeftEdge], blr.height()*2 - borders[BottomEdge], 270, -90); + + path.lineTo(curX, rect.top() + tlr.height()); + path.arcTo(curX, rect.top() + borders[TopEdge]/2, + tlr.width()*2 - borders[LeftEdge], tlr.height()*2 - borders[TopEdge], 180, -90); + + path.closeSubpath(); + return path; +} + +/*! \internal + Clip the painter to the border (in case we are using radius border) + */ +void QRenderRule::setClip(QPainter *p, const QRect &rect) +{ + if (clipset++) + return; + clipPath = borderClip(rect); + if (!clipPath.isEmpty()) { + p->save(); + p->setClipPath(clipPath, Qt::IntersectClip); + } +} + +void QRenderRule::unsetClip(QPainter *p) +{ + if (--clipset) + return; + if (!clipPath.isEmpty()) + p->restore(); +} + +void QRenderRule::drawBackground(QPainter *p, const QRect& rect, const QPoint& off) +{ + QBrush brush = hasBackground() ? background()->brush : QBrush(); + if (brush.style() == Qt::NoBrush) + brush = defaultBackground; + + if (brush.style() != Qt::NoBrush) { + Origin origin = hasBackground() ? background()->clip : Origin_Border; + // ### fix for gradients + const QPainterPath &borderPath = borderClip(originRect(rect, origin)); + if (!borderPath.isEmpty()) { + // Drawn intead of being used as clipping path for better visual quality + bool wasAntialiased = p->renderHints() & QPainter::Antialiasing; + p->setRenderHint(QPainter::Antialiasing); + p->fillPath(borderPath, brush); + p->setRenderHint(QPainter::Antialiasing, wasAntialiased); + } else { + p->fillRect(originRect(rect, origin), brush); + } + } + + drawBackgroundImage(p, rect, off); +} + +void QRenderRule::drawFrame(QPainter *p, const QRect& rect) +{ + drawBackground(p, rect); + if (hasBorder()) + drawBorder(p, borderRect(rect)); +} + +void QRenderRule::drawImage(QPainter *p, const QRect &rect) +{ + if (!hasImage()) + return; + img->icon.paint(p, rect, img->alignment); +} + +void QRenderRule::drawRule(QPainter *p, const QRect& rect) +{ + drawFrame(p, rect); + drawImage(p, contentsRect(rect)); +} + +// *shudder* , *horror*, *whoa* <-- what you might feel when you see the functions below +void QRenderRule::configurePalette(QPalette *p, QPalette::ColorRole fr, QPalette::ColorRole br) +{ + if (bg && bg->brush.style() != Qt::NoBrush) { + if (br != QPalette::NoRole) + p->setBrush(br, bg->brush); + p->setBrush(QPalette::Window, bg->brush); + if (bg->brush.style() == Qt::SolidPattern) { + p->setBrush(QPalette::Light, bg->brush.color().lighter(115)); + p->setBrush(QPalette::Midlight, bg->brush.color().lighter(107)); + p->setBrush(QPalette::Dark, bg->brush.color().darker(150)); + p->setBrush(QPalette::Shadow, bg->brush.color().darker(300)); + } + } + + if (!hasPalette()) + return; + + if (pal->foreground.style() != Qt::NoBrush) { + if (fr != QPalette::NoRole) + p->setBrush(fr, pal->foreground); + p->setBrush(QPalette::WindowText, pal->foreground); + p->setBrush(QPalette::Text, pal->foreground); + } + if (pal->selectionBackground.style() != Qt::NoBrush) + p->setBrush(QPalette::Highlight, pal->selectionBackground); + if (pal->selectionForeground.style() != Qt::NoBrush) + p->setBrush(QPalette::HighlightedText, pal->selectionForeground); + if (pal->alternateBackground.style() != Qt::NoBrush) + p->setBrush(QPalette::AlternateBase, pal->alternateBackground); +} + +void QRenderRule::configurePalette(QPalette *p, QPalette::ColorGroup cg, const QWidget *w, bool embedded) +{ + if (bg && bg->brush.style() != Qt::NoBrush) { + p->setBrush(cg, QPalette::Base, bg->brush); // for windows, windowxp + p->setBrush(cg, QPalette::Button, bg->brush); // for plastique + p->setBrush(cg, w->backgroundRole(), bg->brush); + p->setBrush(cg, QPalette::Window, bg->brush); + } + + if (embedded) { + /* For embedded widgets (ComboBox, SpinBox and ScrollArea) we want the embedded widget + * to be transparent when we have a transparent background or border image */ + if ((hasBackground() && background()->isTransparent()) + || (hasBorder() && border()->hasBorderImage() && !border()->borderImage()->pixmap.isNull())) + p->setBrush(cg, w->backgroundRole(), Qt::NoBrush); + } + + if (!hasPalette()) + return; + + if (pal->foreground.style() != Qt::NoBrush) { + p->setBrush(cg, QPalette::ButtonText, pal->foreground); + p->setBrush(cg, w->foregroundRole(), pal->foreground); + p->setBrush(cg, QPalette::WindowText, pal->foreground); + p->setBrush(cg, QPalette::Text, pal->foreground); + } + if (pal->selectionBackground.style() != Qt::NoBrush) + p->setBrush(cg, QPalette::Highlight, pal->selectionBackground); + if (pal->selectionForeground.style() != Qt::NoBrush) + p->setBrush(cg, QPalette::HighlightedText, pal->selectionForeground); + if (pal->alternateBackground.style() != Qt::NoBrush) + p->setBrush(cg, QPalette::AlternateBase, pal->alternateBackground); +} + +/////////////////////////////////////////////////////////////////////////////// +// Style rules +#define WIDGET(x) (static_cast(x.ptr)) + +static inline QWidget *parentWidget(const QWidget *w) +{ + if(qobject_cast(w) && qstrcmp(w->metaObject()->className(), "QTipLabel") == 0) { + QWidget *p = qvariant_cast(w->property("_q_stylesheet_parent")); + if (p) + return p; + } + return w->parentWidget(); +} + +class QStyleSheetStyleSelector : public StyleSelector +{ +public: + QStyleSheetStyleSelector() { } + + QStringList nodeNames(NodePtr node) const + { + if (isNullNode(node)) + return QStringList(); + const QMetaObject *metaObject = WIDGET(node)->metaObject(); +#ifndef QT_NO_TOOLTIP + if (qstrcmp(metaObject->className(), "QTipLabel") == 0) + return QStringList(QLatin1String("QToolTip")); +#endif + QStringList result; + do { + result += QString::fromLatin1(metaObject->className()).replace(QLatin1Char(':'), QLatin1Char('-')); + metaObject = metaObject->superClass(); + } while (metaObject != 0); + return result; + } + QString attribute(NodePtr node, const QString& name) const + { + if (isNullNode(node)) + return QString(); + + QHash &cache = m_attributeCache[WIDGET(node)]; + QHash::const_iterator cacheIt = cache.constFind(name); + if (cacheIt != cache.constEnd()) + return cacheIt.value(); + + QVariant value = WIDGET(node)->property(name.toLatin1()); + if (!value.isValid()) { + if (name == QLatin1String("class")) { + QString className = QString::fromLatin1(WIDGET(node)->metaObject()->className()); + if (className.contains(QLatin1Char(':'))) + className.replace(QLatin1Char(':'), QLatin1Char('-')); + cache[name] = className; + return className; + } else if (name == QLatin1String("style")) { + QStyleSheetStyle *proxy = qobject_cast(WIDGET(node)->style()); + if (proxy) { + QString styleName = QString::fromLatin1(proxy->baseStyle()->metaObject()->className()); + cache[name] = styleName; + return styleName; + } + } + } + QString valueStr; + if(value.type() == QVariant::StringList || value.type() == QVariant::List) + valueStr = value.toStringList().join(QLatin1String(" ")); + else + valueStr = value.toString(); + cache[name] = valueStr; + return valueStr; + } + bool nodeNameEquals(NodePtr node, const QString& nodeName) const + { + if (isNullNode(node)) + return false; + const QMetaObject *metaObject = WIDGET(node)->metaObject(); +#ifndef QT_NO_TOOLTIP + if (qstrcmp(metaObject->className(), "QTipLabel") == 0) + return nodeName == QLatin1String("QToolTip"); +#endif + do { + const ushort *uc = (const ushort *)nodeName.constData(); + const ushort *e = uc + nodeName.length(); + const uchar *c = (uchar *)metaObject->className(); + while (*c && uc != e && (*uc == *c || (*c == ':' && *uc == '-'))) { + ++uc; + ++c; + } + if (uc == e && !*c) + return true; + metaObject = metaObject->superClass(); + } while (metaObject != 0); + return false; + } + bool hasAttributes(NodePtr) const + { return true; } + QStringList nodeIds(NodePtr node) const + { return isNullNode(node) ? QStringList() : QStringList(WIDGET(node)->objectName()); } + bool isNullNode(NodePtr node) const + { return node.ptr == 0; } + NodePtr parentNode(NodePtr node) const + { NodePtr n; n.ptr = isNullNode(node) ? 0 : parentWidget(WIDGET(node)); return n; } + NodePtr previousSiblingNode(NodePtr) const + { NodePtr n; n.ptr = 0; return n; } + NodePtr duplicateNode(NodePtr node) const + { return node; } + void freeNode(NodePtr) const + { } + +private: + mutable QHash > m_attributeCache; +}; + +QVector QStyleSheetStyle::styleRules(const QWidget *w) const +{ + QHash >::const_iterator cacheIt = styleSheetCaches->styleRulesCache.constFind(w); + if (cacheIt != styleSheetCaches->styleRulesCache.constEnd()) + return cacheIt.value(); + + if (!initWidget(w)) { + return QVector(); + } + + QStyleSheetStyleSelector styleSelector; + + StyleSheet defaultSs; + QHash::const_iterator defaultCacheIt = styleSheetCaches->styleSheetCache.constFind(baseStyle()); + if (defaultCacheIt == styleSheetCaches->styleSheetCache.constEnd()) { + defaultSs = getDefaultStyleSheet(); + QStyle *bs = baseStyle(); + styleSheetCaches->styleSheetCache.insert(bs, defaultSs); + QObject::connect(bs, SIGNAL(destroyed(QObject*)), styleSheetCaches, SLOT(styleDestroyed(QObject*)), Qt::UniqueConnection); + } else { + defaultSs = defaultCacheIt.value(); + } + styleSelector.styleSheets += defaultSs; + + if (!qApp->styleSheet().isEmpty()) { + StyleSheet appSs; + QHash::const_iterator appCacheIt = styleSheetCaches->styleSheetCache.constFind(qApp); + if (appCacheIt == styleSheetCaches->styleSheetCache.constEnd()) { + QString ss = qApp->styleSheet(); + if (ss.startsWith(QLatin1String("file:///"))) + ss.remove(0, 8); + parser.init(ss, qApp->styleSheet() != ss); + if (!parser.parse(&appSs)) + qWarning("Could not parse application stylesheet"); + appSs.origin = StyleSheetOrigin_Inline; + appSs.depth = 1; + styleSheetCaches->styleSheetCache.insert(qApp, appSs); + } else { + appSs = appCacheIt.value(); + } + styleSelector.styleSheets += appSs; + } + + QVector widgetSs; + for (const QWidget *wid = w; wid; wid = parentWidget(wid)) { + if (wid->styleSheet().isEmpty()) + continue; + StyleSheet ss; + QHash::const_iterator widCacheIt = styleSheetCaches->styleSheetCache.constFind(wid); + if (widCacheIt == styleSheetCaches->styleSheetCache.constEnd()) { + parser.init(wid->styleSheet()); + if (!parser.parse(&ss)) { + parser.init(QLatin1String("* {") + wid->styleSheet() + QLatin1Char('}')); + if (!parser.parse(&ss)) + qWarning("Could not parse stylesheet of widget %p", wid); + } + ss.origin = StyleSheetOrigin_Inline; + styleSheetCaches->styleSheetCache.insert(wid, ss); + } else { + ss = widCacheIt.value(); + } + widgetSs.append(ss); + } + + for (int i = 0; i < widgetSs.count(); i++) + widgetSs[i].depth = widgetSs.count() - i + 2; + + styleSelector.styleSheets += widgetSs; + + StyleSelector::NodePtr n; + n.ptr = (void *)w; + QVector rules = styleSelector.styleRulesForNode(n); + styleSheetCaches->styleRulesCache.insert(w, rules); + return rules; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Rendering rules +static QVector declarations(const QVector &styleRules, const QString &part, quint64 pseudoClass = PseudoClass_Unspecified) +{ + QVector decls; + for (int i = 0; i < styleRules.count(); i++) { + const Selector& selector = styleRules.at(i).selectors.at(0); + // Rules with pseudo elements don't cascade. This is an intentional + // diversion for CSS + if (part.compare(selector.pseudoElement(), Qt::CaseInsensitive) != 0) + continue; + quint64 negated = 0; + quint64 cssClass = selector.pseudoClass(&negated); + if ((pseudoClass == PseudoClass_Any) || (cssClass == PseudoClass_Unspecified) + || ((((cssClass & pseudoClass) == cssClass)) && ((negated & pseudoClass) == 0))) + decls += styleRules.at(i).declarations; + } + return decls; +} + +int QStyleSheetStyle::nativeFrameWidth(const QWidget *w) +{ + QStyle *base = baseStyle(); + +#ifndef QT_NO_SPINBOX + if (qobject_cast(w)) + return base->pixelMetric(QStyle::PM_SpinBoxFrameWidth, 0, w); +#endif + +#ifndef QT_NO_COMBOBOX + if (qobject_cast(w)) + return base->pixelMetric(QStyle::PM_ComboBoxFrameWidth, 0, w); +#endif + +#ifndef QT_NO_MENU + if (qobject_cast(w)) + return base->pixelMetric(QStyle::PM_MenuPanelWidth, 0, w); +#endif + +#ifndef QT_NO_MENUBAR + if (qobject_cast(w)) + return base->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, w); +#endif +#ifndef QT_NO_FRAME + if (const QFrame *frame = qobject_cast(w)) { + if (frame->frameShape() == QFrame::NoFrame) + return 0; + } +#endif + + if (qstrcmp(w->metaObject()->className(), "QTipLabel") == 0) + return base->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, w); + + return base->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, w); +} + +static quint64 pseudoClass(QStyle::State state) +{ + quint64 pc = 0; + if (state & QStyle::State_Enabled) { + pc |= PseudoClass_Enabled; + if (state & QStyle::State_MouseOver) + pc |= PseudoClass_Hover; + } else { + pc |= PseudoClass_Disabled; + } + if (state & QStyle::State_Active) + pc |= PseudoClass_Active; + if (state & QStyle::State_Window) + pc |= PseudoClass_Window; + if (state & QStyle::State_Sunken) + pc |= PseudoClass_Pressed; + if (state & QStyle::State_HasFocus) + pc |= PseudoClass_Focus; + if (state & QStyle::State_On) + pc |= (PseudoClass_On | PseudoClass_Checked); + if (state & QStyle::State_Off) + pc |= (PseudoClass_Off | PseudoClass_Unchecked); + if (state & QStyle::State_NoChange) + pc |= PseudoClass_Indeterminate; + if (state & QStyle::State_Selected) + pc |= PseudoClass_Selected; + if (state & QStyle::State_Horizontal) + pc |= PseudoClass_Horizontal; + else + pc |= PseudoClass_Vertical; + if (state & (QStyle::State_Open | QStyle::State_On | QStyle::State_Sunken)) + pc |= PseudoClass_Open; + else + pc |= PseudoClass_Closed; + if (state & QStyle::State_Children) + pc |= PseudoClass_Children; + if (state & QStyle::State_Sibling) + pc |= PseudoClass_Sibling; + if (state & QStyle::State_ReadOnly) + pc |= PseudoClass_ReadOnly; + if (state & QStyle::State_Item) + pc |= PseudoClass_Item; +#ifdef QT_KEYPAD_NAVIGATION + if (state & QStyle::State_HasEditFocus) + pc |= PseudoClass_EditFocus; +#endif + return pc; +} + +static void qt_check_if_internal_widget(const QWidget **w, int *element) +{ +#ifdef QT_NO_DOCKWIDGET + Q_UNUSED(w); + Q_UNUSED(element); +#else + if (*w && qstrcmp((*w)->metaObject()->className(), "QDockWidgetTitleButton") == 0) { + if ((*w)->objectName() == QLatin1String("qt_dockwidget_closebutton")) { + *element = PseudoElement_DockWidgetCloseButton; + } else if ((*w)->objectName() == QLatin1String("qt_dockwidget_floatbutton")) { + *element = PseudoElement_DockWidgetFloatButton; + } + *w = (*w)->parentWidget(); + } +#endif +} + +QRenderRule QStyleSheetStyle::renderRule(const QWidget *w, int element, quint64 state) const +{ + qt_check_if_internal_widget(&w, &element); + QHash &cache = styleSheetCaches->renderRulesCache[w][element]; + QHash::const_iterator cacheIt = cache.constFind(state); + if (cacheIt != cache.constEnd()) + return cacheIt.value(); + + if (!initWidget(w)) + return QRenderRule(); + + quint64 stateMask = 0; + const QVector rules = styleRules(w); + for (int i = 0; i < rules.count(); i++) { + const Selector& selector = rules.at(i).selectors.at(0); + quint64 negated = 0; + stateMask |= selector.pseudoClass(&negated); + stateMask |= negated; + } + + cacheIt = cache.constFind(state & stateMask); + if (cacheIt != cache.constEnd()) { + const QRenderRule &newRule = cacheIt.value(); + cache[state] = newRule; + return newRule; + } + + + const QString part = QLatin1String(knownPseudoElements[element].name); + QVector decls = declarations(rules, part, state); + QRenderRule newRule(decls, w); + cache[state] = newRule; + if ((state & stateMask) != state) + cache[state&stateMask] = newRule; + return newRule; +} + +QRenderRule QStyleSheetStyle::renderRule(const QWidget *w, const QStyleOption *opt, int pseudoElement) const +{ + quint64 extraClass = 0; + QStyle::State state = opt ? opt->state : QStyle::State(QStyle::State_None); + + if (const QStyleOptionComplex *complex = qstyleoption_cast(opt)) { + if (pseudoElement != PseudoElement_None) { + // if not an active subcontrol, just pass enabled/disabled + QStyle::SubControl subControl = knownPseudoElements[pseudoElement].subControl; + + if (!(complex->activeSubControls & subControl)) + state &= (QStyle::State_Enabled | QStyle::State_Horizontal | QStyle::State_HasFocus); + } + + switch (pseudoElement) { + case PseudoElement_ComboBoxDropDown: + case PseudoElement_ComboBoxArrow: + state |= (complex->state & (QStyle::State_On|QStyle::State_ReadOnly)); + break; + case PseudoElement_SpinBoxUpButton: + case PseudoElement_SpinBoxDownButton: + case PseudoElement_SpinBoxUpArrow: + case PseudoElement_SpinBoxDownArrow: +#ifndef QT_NO_SPINBOX + if (const QStyleOptionSpinBox *sb = qstyleoption_cast(opt)) { + bool on = false; + bool up = pseudoElement == PseudoElement_SpinBoxUpButton + || pseudoElement == PseudoElement_SpinBoxUpArrow; + if ((sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) && up) + on = true; + else if ((sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) && !up) + on = true; + state |= (on ? QStyle::State_On : QStyle::State_Off); + } +#endif // QT_NO_SPINBOX + break; + case PseudoElement_GroupBoxTitle: + state |= (complex->state & (QStyle::State_MouseOver | QStyle::State_Sunken)); + break; + case PseudoElement_ToolButtonMenu: + case PseudoElement_ToolButtonMenuArrow: + case PseudoElement_ToolButtonDownArrow: + state |= complex->state & QStyle::State_MouseOver; + if (complex->state & QStyle::State_Sunken || + complex->activeSubControls & QStyle::SC_ToolButtonMenu) + state |= QStyle::State_Sunken; + break; + case PseudoElement_SliderGroove: + state |= complex->state & QStyle::State_MouseOver; + break; + default: + break; + } + + if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)) { + // QStyle::State_On is set when the popup is being shown + // Propagate EditField Pressed state + if (pseudoElement == PseudoElement_None + && (complex->activeSubControls & QStyle::SC_ComboBoxEditField) + && (!(state & QStyle::State_MouseOver))) { + state |= QStyle::State_Sunken; + } + + if (!combo->frame) + extraClass |= PseudoClass_Frameless; + if (!combo->editable) + extraClass |= PseudoClass_ReadOnly; + else + extraClass |= PseudoClass_Editable; +#ifndef QT_NO_SPINBOX + } else if (const QStyleOptionSpinBox *spin = qstyleoption_cast(opt)) { + if (!spin->frame) + extraClass |= PseudoClass_Frameless; +#endif // QT_NO_SPINBOX + } else if (const QStyleOptionGroupBox *gb = qstyleoption_cast(opt)) { + if (gb->features & QStyleOptionFrameV2::Flat) + extraClass |= PseudoClass_Flat; + if (gb->lineWidth == 0) + extraClass |= PseudoClass_Frameless; + } else if (const QStyleOptionTitleBar *tb = qstyleoption_cast(opt)) { + if (tb->titleBarState & Qt::WindowMinimized) { + extraClass |= PseudoClass_Minimized; + } + else if (tb->titleBarState & Qt::WindowMaximized) + extraClass |= PseudoClass_Maximized; + } + } else { + // handle simple style options + if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { + if (mi->menuItemType == QStyleOptionMenuItem::DefaultItem) + extraClass |= PseudoClass_Default; + if (mi->checkType == QStyleOptionMenuItem::Exclusive) + extraClass |= PseudoClass_Exclusive; + else if (mi->checkType == QStyleOptionMenuItem::NonExclusive) + extraClass |= PseudoClass_NonExclusive; + if (mi->checkType != QStyleOptionMenuItem::NotCheckable) + extraClass |= (mi->checked) ? (PseudoClass_On|PseudoClass_Checked) + : (PseudoClass_Off|PseudoClass_Unchecked); + } else if (const QStyleOptionHeader *hdr = qstyleoption_cast(opt)) { + if (hdr->position == QStyleOptionHeader::OnlyOneSection) + extraClass |= PseudoClass_OnlyOne; + else if (hdr->position == QStyleOptionHeader::Beginning) + extraClass |= PseudoClass_First; + else if (hdr->position == QStyleOptionHeader::End) + extraClass |= PseudoClass_Last; + else if (hdr->position == QStyleOptionHeader::Middle) + extraClass |= PseudoClass_Middle; + + if (hdr->selectedPosition == QStyleOptionHeader::NextAndPreviousAreSelected) + extraClass |= (PseudoClass_NextSelected | PseudoClass_PreviousSelected); + else if (hdr->selectedPosition == QStyleOptionHeader::NextIsSelected) + extraClass |= PseudoClass_NextSelected; + else if (hdr->selectedPosition == QStyleOptionHeader::PreviousIsSelected) + extraClass |= PseudoClass_PreviousSelected; +#ifndef QT_NO_TABWIDGET + } else if (const QStyleOptionTabWidgetFrame *tab = qstyleoption_cast(opt)) { + switch (tab->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + extraClass |= PseudoClass_Top; + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + extraClass |= PseudoClass_Bottom; + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + extraClass |= PseudoClass_Left; + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + extraClass |= PseudoClass_Right; + break; + default: + break; + } +#endif +#ifndef QT_NO_TABBAR + } else if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + if (tab->position == QStyleOptionTab::OnlyOneTab) + extraClass |= PseudoClass_OnlyOne; + else if (tab->position == QStyleOptionTab::Beginning) + extraClass |= PseudoClass_First; + else if (tab->position == QStyleOptionTab::End) + extraClass |= PseudoClass_Last; + else if (tab->position == QStyleOptionTab::Middle) + extraClass |= PseudoClass_Middle; + + if (tab->selectedPosition == QStyleOptionTab::NextIsSelected) + extraClass |= PseudoClass_NextSelected; + else if (tab->selectedPosition == QStyleOptionTab::PreviousIsSelected) + extraClass |= PseudoClass_PreviousSelected; + + switch (tab->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + extraClass |= PseudoClass_Top; + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + extraClass |= PseudoClass_Bottom; + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + extraClass |= PseudoClass_Left; + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + extraClass |= PseudoClass_Right; + break; + default: + break; + } +#endif // QT_NO_TABBAR + } else if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + if (btn->features & QStyleOptionButton::Flat) + extraClass |= PseudoClass_Flat; + if (btn->features & QStyleOptionButton::DefaultButton) + extraClass |= PseudoClass_Default; + } else if (const QStyleOptionFrame *frm = qstyleoption_cast(opt)) { + if (frm->lineWidth == 0) + extraClass |= PseudoClass_Frameless; + if (const QStyleOptionFrameV2 *frame2 = qstyleoption_cast(opt)) { + if (frame2->features & QStyleOptionFrameV2::Flat) + extraClass |= PseudoClass_Flat; + } + } +#ifndef QT_NO_TOOLBAR + else if (const QStyleOptionToolBar *tb = qstyleoption_cast(opt)) { + if (tb->toolBarArea == Qt::LeftToolBarArea) + extraClass |= PseudoClass_Left; + else if (tb->toolBarArea == Qt::RightToolBarArea) + extraClass |= PseudoClass_Right; + else if (tb->toolBarArea == Qt::TopToolBarArea) + extraClass |= PseudoClass_Top; + else if (tb->toolBarArea == Qt::BottomToolBarArea) + extraClass |= PseudoClass_Bottom; + + if (tb->positionWithinLine == QStyleOptionToolBar::Beginning) + extraClass |= PseudoClass_First; + else if (tb->positionWithinLine == QStyleOptionToolBar::Middle) + extraClass |= PseudoClass_Middle; + else if (tb->positionWithinLine == QStyleOptionToolBar::End) + extraClass |= PseudoClass_Last; + else if (tb->positionWithinLine == QStyleOptionToolBar::OnlyOne) + extraClass |= PseudoClass_OnlyOne; + } +#endif // QT_NO_TOOLBAR +#ifndef QT_NO_TOOLBOX + else if (const QStyleOptionToolBoxV2 *tab = qstyleoption_cast(opt)) { + if (tab->position == QStyleOptionToolBoxV2::OnlyOneTab) + extraClass |= PseudoClass_OnlyOne; + else if (tab->position == QStyleOptionToolBoxV2::Beginning) + extraClass |= PseudoClass_First; + else if (tab->position == QStyleOptionToolBoxV2::End) + extraClass |= PseudoClass_Last; + else if (tab->position == QStyleOptionToolBoxV2::Middle) + extraClass |= PseudoClass_Middle; + + if (tab->selectedPosition == QStyleOptionToolBoxV2::NextIsSelected) + extraClass |= PseudoClass_NextSelected; + else if (tab->selectedPosition == QStyleOptionToolBoxV2::PreviousIsSelected) + extraClass |= PseudoClass_PreviousSelected; + } +#endif // QT_NO_TOOLBOX +#ifndef QT_NO_DOCKWIDGET + else if (const QStyleOptionDockWidgetV2 *dw = qstyleoption_cast(opt)) { + if (dw->verticalTitleBar) + extraClass |= PseudoClass_Vertical; + else + extraClass |= PseudoClass_Horizontal; + if (dw->closable) + extraClass |= PseudoClass_Closable; + if (dw->floatable) + extraClass |= PseudoClass_Floatable; + if (dw->movable) + extraClass |= PseudoClass_Movable; + } +#endif // QT_NO_DOCKWIDGET +#ifndef QT_NO_ITEMVIEWS + else if (const QStyleOptionViewItemV2 *v2 = qstyleoption_cast(opt)) { + if (v2->features & QStyleOptionViewItemV2::Alternate) + extraClass |= PseudoClass_Alternate; + if (const QStyleOptionViewItemV4 *v4 = qstyleoption_cast(opt)) { + if (v4->viewItemPosition == QStyleOptionViewItemV4::OnlyOne) + extraClass |= PseudoClass_OnlyOne; + else if (v4->viewItemPosition == QStyleOptionViewItemV4::Beginning) + extraClass |= PseudoClass_First; + else if (v4->viewItemPosition == QStyleOptionViewItemV4::End) + extraClass |= PseudoClass_Last; + else if (v4->viewItemPosition == QStyleOptionViewItemV4::Middle) + extraClass |= PseudoClass_Middle; + } + } +#endif +#ifndef QT_NO_LINEEDIT + // LineEdit sets Sunken flag to indicate Sunken frame (argh) + if (const QLineEdit *lineEdit = qobject_cast(w)) { + state &= ~QStyle::State_Sunken; + if (lineEdit->hasFrame()) { + extraClass &= ~PseudoClass_Frameless; + } else { + extraClass |= PseudoClass_Frameless; + } + } else +#endif + if (const QFrame *frm = qobject_cast(w)) { + if (frm->lineWidth() == 0) + extraClass |= PseudoClass_Frameless; + } + } + + return renderRule(w, pseudoElement, pseudoClass(state) | extraClass); +} + +bool QStyleSheetStyle::hasStyleRule(const QWidget *w, int part) const +{ + QHash &cache = styleSheetCaches->hasStyleRuleCache[w]; + QHash::const_iterator cacheIt = cache.constFind(part); + if (cacheIt != cache.constEnd()) + return cacheIt.value(); + + if (!initWidget(w)) + return false; + + + const QVector &rules = styleRules(w); + if (part == PseudoElement_None) { + bool result = w && !rules.isEmpty(); + cache[part] = result; + return result; + } + + QString pseudoElement = QLatin1String(knownPseudoElements[part].name); + QVector declarations; + for (int i = 0; i < rules.count(); i++) { + const Selector& selector = rules.at(i).selectors.at(0); + if (pseudoElement.compare(selector.pseudoElement(), Qt::CaseInsensitive) == 0) { + cache[part] = true; + return true; + } + } + + cache[part] = false; + return false; +} + +static Origin defaultOrigin(int pe) +{ + switch (pe) { + case PseudoElement_ScrollBarAddPage: + case PseudoElement_ScrollBarSubPage: + case PseudoElement_ScrollBarAddLine: + case PseudoElement_ScrollBarSubLine: + case PseudoElement_ScrollBarFirst: + case PseudoElement_ScrollBarLast: + case PseudoElement_GroupBoxTitle: + case PseudoElement_GroupBoxIndicator: // never used + case PseudoElement_ToolButtonMenu: + case PseudoElement_SliderAddPage: + case PseudoElement_SliderSubPage: + return Origin_Border; + + case PseudoElement_SpinBoxUpButton: + case PseudoElement_SpinBoxDownButton: + case PseudoElement_PushButtonMenuIndicator: + case PseudoElement_ComboBoxDropDown: + case PseudoElement_ToolButtonDownArrow: + case PseudoElement_MenuCheckMark: + case PseudoElement_MenuIcon: + case PseudoElement_MenuRightArrow: + return Origin_Padding; + + case PseudoElement_Indicator: + case PseudoElement_ExclusiveIndicator: + case PseudoElement_ComboBoxArrow: + case PseudoElement_ScrollBarSlider: + case PseudoElement_ScrollBarUpArrow: + case PseudoElement_ScrollBarDownArrow: + case PseudoElement_ScrollBarLeftArrow: + case PseudoElement_ScrollBarRightArrow: + case PseudoElement_SpinBoxUpArrow: + case PseudoElement_SpinBoxDownArrow: + case PseudoElement_ToolButtonMenuArrow: + case PseudoElement_HeaderViewUpArrow: + case PseudoElement_HeaderViewDownArrow: + case PseudoElement_SliderGroove: + case PseudoElement_SliderHandle: + return Origin_Content; + + default: + return Origin_Margin; + } +} + +static Qt::Alignment defaultPosition(int pe) +{ + switch (pe) { + case PseudoElement_Indicator: + case PseudoElement_ExclusiveIndicator: + case PseudoElement_MenuCheckMark: + case PseudoElement_MenuIcon: + return Qt::AlignLeft | Qt::AlignVCenter; + + case PseudoElement_ScrollBarAddLine: + case PseudoElement_ScrollBarLast: + case PseudoElement_SpinBoxDownButton: + case PseudoElement_PushButtonMenuIndicator: + case PseudoElement_ToolButtonDownArrow: + return Qt::AlignRight | Qt::AlignBottom; + + case PseudoElement_ScrollBarSubLine: + case PseudoElement_ScrollBarFirst: + case PseudoElement_SpinBoxUpButton: + case PseudoElement_ComboBoxDropDown: + case PseudoElement_ToolButtonMenu: + case PseudoElement_DockWidgetCloseButton: + case PseudoElement_DockWidgetFloatButton: + return Qt::AlignRight | Qt::AlignTop; + + case PseudoElement_ScrollBarUpArrow: + case PseudoElement_ScrollBarDownArrow: + case PseudoElement_ScrollBarLeftArrow: + case PseudoElement_ScrollBarRightArrow: + case PseudoElement_SpinBoxUpArrow: + case PseudoElement_SpinBoxDownArrow: + case PseudoElement_ComboBoxArrow: + case PseudoElement_DownArrow: + case PseudoElement_ToolButtonMenuArrow: + case PseudoElement_SliderGroove: + return Qt::AlignCenter; + + case PseudoElement_GroupBoxTitle: + case PseudoElement_GroupBoxIndicator: // never used + return Qt::AlignLeft | Qt::AlignTop; + + case PseudoElement_HeaderViewUpArrow: + case PseudoElement_HeaderViewDownArrow: + case PseudoElement_MenuRightArrow: + return Qt::AlignRight | Qt::AlignVCenter; + + default: + return 0; + } +} + +QSize QStyleSheetStyle::defaultSize(const QWidget *w, QSize sz, const QRect& rect, int pe) const +{ + QStyle *base = baseStyle(); + + switch (pe) { + case PseudoElement_Indicator: + case PseudoElement_MenuCheckMark: + if (sz.width() == -1) + sz.setWidth(base->pixelMetric(PM_IndicatorWidth, 0, w)); + if (sz.height() == -1) + sz.setHeight(base->pixelMetric(PM_IndicatorHeight, 0, w)); + break; + + case PseudoElement_ExclusiveIndicator: + case PseudoElement_GroupBoxIndicator: + if (sz.width() == -1) + sz.setWidth(base->pixelMetric(PM_ExclusiveIndicatorWidth, 0, w)); + if (sz.height() == -1) + sz.setHeight(base->pixelMetric(PM_ExclusiveIndicatorHeight, 0, w)); + break; + + case PseudoElement_PushButtonMenuIndicator: { + int pm = base->pixelMetric(PM_MenuButtonIndicator, 0, w); + if (sz.width() == -1) + sz.setWidth(pm); + if (sz.height() == -1) + sz.setHeight(pm); + } + break; + + case PseudoElement_ComboBoxDropDown: + if (sz.width() == -1) + sz.setWidth(16); + break; + + case PseudoElement_ComboBoxArrow: + case PseudoElement_DownArrow: + case PseudoElement_ToolButtonMenuArrow: + case PseudoElement_ToolButtonDownArrow: + case PseudoElement_MenuRightArrow: + if (sz.width() == -1) + sz.setWidth(13); + if (sz.height() == -1) + sz.setHeight(13); + break; + + case PseudoElement_SpinBoxUpButton: + case PseudoElement_SpinBoxDownButton: + if (sz.width() == -1) + sz.setWidth(16); + if (sz.height() == -1) + sz.setHeight(rect.height()/2); + break; + + case PseudoElement_ToolButtonMenu: + if (sz.width() == -1) + sz.setWidth(base->pixelMetric(PM_MenuButtonIndicator, 0, w)); + break; + + case PseudoElement_HeaderViewUpArrow: + case PseudoElement_HeaderViewDownArrow: { + int pm = base->pixelMetric(PM_HeaderMargin, 0, w); + if (sz.width() == -1) + sz.setWidth(pm); + if (sz.height() == 1) + sz.setHeight(pm); + break; + } + + case PseudoElement_ScrollBarFirst: + case PseudoElement_ScrollBarLast: + case PseudoElement_ScrollBarAddLine: + case PseudoElement_ScrollBarSubLine: + case PseudoElement_ScrollBarSlider: { + int pm = pixelMetric(QStyle::PM_ScrollBarExtent, 0, w); + if (sz.width() == -1) + sz.setWidth(pm); + if (sz.height() == -1) + sz.setHeight(pm); + break; + } + + case PseudoElement_DockWidgetCloseButton: + case PseudoElement_DockWidgetFloatButton: { + int iconSize = pixelMetric(PM_SmallIconSize, 0, w); + return QSize(iconSize, iconSize); + } + + default: + break; + } + + // expand to rectangle + if (sz.height() == -1) + sz.setHeight(rect.height()); + if (sz.width() == -1) + sz.setWidth(rect.width()); + + return sz; +} + +static PositionMode defaultPositionMode(int pe) +{ + switch (pe) { + case PseudoElement_ScrollBarFirst: + case PseudoElement_ScrollBarLast: + case PseudoElement_ScrollBarAddLine: + case PseudoElement_ScrollBarSubLine: + case PseudoElement_ScrollBarAddPage: + case PseudoElement_ScrollBarSubPage: + case PseudoElement_ScrollBarSlider: + case PseudoElement_SliderGroove: + case PseudoElement_SliderHandle: + case PseudoElement_TabWidgetPane: + return PositionMode_Absolute; + default: + return PositionMode_Static; + } +} + +QRect QStyleSheetStyle::positionRect(const QWidget *w, const QRenderRule &rule2, int pe, + const QRect &originRect, Qt::LayoutDirection dir) const +{ + const QStyleSheetPositionData *p = rule2.position(); + PositionMode mode = (p && p->mode != PositionMode_Unknown) ? p->mode : defaultPositionMode(pe); + Qt::Alignment position = (p && p->position != 0) ? p->position : defaultPosition(pe); + QRect r; + + if (mode != PositionMode_Absolute) { + QSize sz = defaultSize(w, rule2.size(), originRect, pe); + sz = sz.expandedTo(rule2.minimumContentsSize()); + r = QStyle::alignedRect(dir, position, sz, originRect); + if (p) { + int left = p->left ? p->left : -p->right; + int top = p->top ? p->top : -p->bottom; + r.translate(dir == Qt::LeftToRight ? left : -left, top); + } + } else { + r = p ? originRect.adjusted(dir == Qt::LeftToRight ? p->left : p->right, p->top, + dir == Qt::LeftToRight ? -p->right : -p->left, -p->bottom) + : originRect; + if (rule2.hasContentsSize()) { + QSize sz = rule2.size().expandedTo(rule2.minimumContentsSize()); + if (sz.width() == -1) sz.setWidth(r.width()); + if (sz.height() == -1) sz.setHeight(r.height()); + r = QStyle::alignedRect(dir, position, sz, r); + } + } + return r; +} + +QRect QStyleSheetStyle::positionRect(const QWidget *w, const QRenderRule& rule1, const QRenderRule& rule2, int pe, + const QRect& rect, Qt::LayoutDirection dir) const +{ + const QStyleSheetPositionData *p = rule2.position(); + Origin origin = (p && p->origin != Origin_Unknown) ? p->origin : defaultOrigin(pe); + QRect originRect = rule1.originRect(rect, origin); + return positionRect(w, rule2, pe, originRect, dir); +} + + +/** \internal + For widget that have an embedded widget (such as combobox) return that embedded widget. + otherwise return the widget itself + */ +static QWidget *embeddedWidget(QWidget *w) +{ +#ifndef QT_NO_COMBOBOX + if (QComboBox *cmb = qobject_cast(w)) { + if (cmb->isEditable()) + return cmb->lineEdit(); + else + return cmb; + } +#endif + +#ifndef QT_NO_SPINBOX + if (QAbstractSpinBox *sb = qobject_cast(w)) + return sb->findChild(); +#endif + +#ifndef QT_NO_SCROLLAREA + if (QAbstractScrollArea *sa = qobject_cast(w)) + return sa->viewport(); +#endif + + return w; +} + +/** \internal + in case w is an embedded widget, return the container widget + (i.e, the widget for which the rules actualy apply) + (exemple, if w is a lineedit embedded in a combobox, return the combobox) + + if w is not embedded, return w itself +*/ +static QWidget *containerWidget(const QWidget *w) +{ +#ifndef QT_NO_LINEEDIT + if (qobject_cast(w)) { + //if the QLineEdit is an embeddedWidget, we need the rule of the real widget +#ifndef QT_NO_COMBOBOX + if (qobject_cast(w->parentWidget())) + return w->parentWidget(); +#endif +#ifndef QT_NO_SPINBOX + if (qobject_cast(w->parentWidget())) + return w->parentWidget(); +#endif + } +#endif // QT_NO_LINEEDIT + +#ifndef QT_NO_SCROLLAREA + if (const QAbstractScrollArea *sa = qobject_cast(w->parentWidget())) { + if (sa->viewport() == w) + return w->parentWidget(); + } +#endif + + return const_cast(w); +} + +/** \internal + returns true if the widget can NOT be styled directly + */ +static bool unstylable(const QWidget *w) +{ + if (w->windowType() == Qt::Desktop) + return true; + + if (!w->styleSheet().isEmpty()) + return false; + + if (containerWidget(w) != w) + return true; + +#ifndef QT_NO_FRAME + // detect QComboBoxPrivateContainer + else if (qobject_cast(w)) { + if (0 +#ifndef QT_NO_COMBOBOX + || qobject_cast(w->parentWidget()) +#endif + ) + return true; + } +#endif + return false; +} + +static quint64 extendedPseudoClass(const QWidget *w) +{ + quint64 pc = w->isWindow() ? quint64(PseudoClass_Window) : 0; + if (const QAbstractSlider *slider = qobject_cast(w)) { + pc |= ((slider->orientation() == Qt::Vertical) ? PseudoClass_Vertical : PseudoClass_Horizontal); + } else +#ifndef QT_NO_COMBOBOX + if (const QComboBox *combo = qobject_cast(w)) { + if (combo->isEditable()) + pc |= (combo->isEditable() ? PseudoClass_Editable : PseudoClass_ReadOnly); + } else +#endif +#ifndef QT_NO_LINEEDIT + if (const QLineEdit *edit = qobject_cast(w)) { + pc |= (edit->isReadOnly() ? PseudoClass_ReadOnly : PseudoClass_Editable); + } else +#endif + { } // required for the above ifdef'ery to work + return pc; +} + +// sets up the geometry of the widget. We set a dynamic property when +// we modify the min/max size of the widget. The min/max size is restored +// to their original value when a new stylesheet that does not contain +// the CSS properties is set and when the widget has this dynamic property set. +// This way we don't trample on users who had setup a min/max size in code and +// don't use stylesheets at all. +void QStyleSheetStyle::setGeometry(QWidget *w) +{ + QRenderRule rule = renderRule(w, PseudoElement_None, PseudoClass_Enabled | extendedPseudoClass(w)); + const QStyleSheetGeometryData *geo = rule.geometry(); + if (w->property("_q_stylesheet_minw").toBool() + && ((!rule.hasGeometry() || geo->minWidth == -1))) { + w->setMinimumWidth(0); + w->setProperty("_q_stylesheet_minw", QVariant()); + } + if (w->property("_q_stylesheet_minh").toBool() + && ((!rule.hasGeometry() || geo->minHeight == -1))) { + w->setMinimumHeight(0); + w->setProperty("_q_stylesheet_minh", QVariant()); + } + if (w->property("_q_stylesheet_maxw").toBool() + && ((!rule.hasGeometry() || geo->maxWidth == -1))) { + w->setMaximumWidth(QWIDGETSIZE_MAX); + w->setProperty("_q_stylesheet_maxw", QVariant()); + } + if (w->property("_q_stylesheet_maxh").toBool() + && ((!rule.hasGeometry() || geo->maxHeight == -1))) { + w->setMaximumHeight(QWIDGETSIZE_MAX); + w->setProperty("_q_stylesheet_maxh", QVariant()); + } + + + if (rule.hasGeometry()) { + if (geo->minWidth != -1) { + w->setProperty("_q_stylesheet_minw", true); + w->setMinimumWidth(rule.boxSize(QSize(qMax(geo->width, geo->minWidth), 0)).width()); + } + if (geo->minHeight != -1) { + w->setProperty("_q_stylesheet_minh", true); + w->setMinimumHeight(rule.boxSize(QSize(0, qMax(geo->height, geo->minHeight))).height()); + } + if (geo->maxWidth != -1) { + w->setProperty("_q_stylesheet_maxw", true); + w->setMaximumWidth(rule.boxSize(QSize(qMin(geo->width == -1 ? QWIDGETSIZE_MAX : geo->width, + geo->maxWidth == -1 ? QWIDGETSIZE_MAX : geo->maxWidth), 0)).width()); + } + if (geo->maxHeight != -1) { + w->setProperty("_q_stylesheet_maxh", true); + w->setMaximumHeight(rule.boxSize(QSize(0, qMin(geo->height == -1 ? QWIDGETSIZE_MAX : geo->height, + geo->maxHeight == -1 ? QWIDGETSIZE_MAX : geo->maxHeight))).height()); + } + } +} + +void QStyleSheetStyle::setProperties(QWidget *w) +{ + QHash propertyHash; + QVector decls = declarations(styleRules(w), QString()); + + // run through the declarations in order + for (int i = 0; i < decls.count(); i++) { + const Declaration &decl = decls.at(i); + QString property = decl.d->property; + if (!property.startsWith(QLatin1String("qproperty-"), Qt::CaseInsensitive)) + continue; + property.remove(0, 10); // strip "qproperty-" + const QVariant value = w->property(property.toLatin1()); + const QMetaObject *metaObject = w->metaObject(); + int index = metaObject->indexOfProperty(property.toLatin1()); + if (index == -1) { + qWarning() << w << " does not have a property named " << property; + continue; + } + QMetaProperty metaProperty = metaObject->property(index); + if (!metaProperty.isWritable() || !metaProperty.isDesignable()) { + qWarning() << w << " cannot design property named " << property; + continue; + } + QVariant v; + switch (value.type()) { + case QVariant::Icon: v = decl.iconValue(); break; + case QVariant::Image: v = QImage(decl.uriValue()); break; + case QVariant::Pixmap: v = QPixmap(decl.uriValue()); break; + case QVariant::Rect: v = decl.rectValue(); break; + case QVariant::Size: v = decl.sizeValue(); break; + case QVariant::Color: v = decl.colorValue(); break; + case QVariant::Brush: v = decl.brushValue(); break; +#ifndef QT_NO_SHORTCUT + case QVariant::KeySequence: v = QKeySequence(decl.d->values.at(0).variant.toString()); break; +#endif + default: v = decl.d->values.at(0).variant; break; + } + propertyHash[property] = v; + } + // apply the values + const QList properties = propertyHash.keys(); + for (int i = 0; i < properties.count(); i++) { + const QString &property = properties.at(i); + w->setProperty(property.toLatin1(), propertyHash[property]); + } +} + +void QStyleSheetStyle::setPalette(QWidget *w) +{ + struct RuleRoleMap { + int state; + QPalette::ColorGroup group; + } map[3] = { + { int(PseudoClass_Active | PseudoClass_Enabled), QPalette::Active }, + { PseudoClass_Disabled, QPalette::Disabled }, + { PseudoClass_Enabled, QPalette::Inactive } + }; + + QPalette p = w->palette(); + QWidget *ew = embeddedWidget(w); + + for (int i = 0; i < 3; i++) { + QRenderRule rule = renderRule(w, PseudoElement_None, map[i].state | extendedPseudoClass(w)); + if (i == 0) { + if (!w->property("_q_styleSheetWidgetFont").isValid()) { + saveWidgetFont(w, w->font()); + } + updateStyleSheetFont(w); + if (ew != w) + updateStyleSheetFont(ew); + } + + rule.configurePalette(&p, map[i].group, ew, ew != w); + } + + styleSheetCaches->customPaletteWidgets.insert(w, w->palette()); + w->setPalette(p); + if (ew != w) + ew->setPalette(p); +} + +void QStyleSheetStyle::unsetPalette(QWidget *w) +{ + if (styleSheetCaches->customPaletteWidgets.contains(w)) { + QPalette p = styleSheetCaches->customPaletteWidgets.value(w); + w->setPalette(p); + QWidget *ew = embeddedWidget(w); + if (ew != w) + ew->setPalette(p); + styleSheetCaches->customPaletteWidgets.remove(w); + } + QVariant oldFont = w->property("_q_styleSheetWidgetFont"); + if (oldFont.isValid()) { + w->setFont(qvariant_cast(oldFont)); + } + if (styleSheetCaches->autoFillDisabledWidgets.contains(w)) { + embeddedWidget(w)->setAutoFillBackground(true); + styleSheetCaches->autoFillDisabledWidgets.remove(w); + } +} + +static void updateWidgets(const QList& widgets) +{ + if (!styleSheetCaches->styleRulesCache.isEmpty() || !styleSheetCaches->hasStyleRuleCache.isEmpty() || !styleSheetCaches->renderRulesCache.isEmpty()) { + for (int i = 0; i < widgets.size(); ++i) { + const QWidget *widget = widgets.at(i); + styleSheetCaches->styleRulesCache.remove(widget); + styleSheetCaches->hasStyleRuleCache.remove(widget); + styleSheetCaches->renderRulesCache.remove(widget); + } + } + for (int i = 0; i < widgets.size(); ++i) { + QWidget *widget = const_cast(widgets.at(i)); + if (widget == 0) + continue; + widget->style()->polish(widget); + QEvent event(QEvent::StyleChange); + QApplication::sendEvent(widget, &event); + widget->update(); + widget->updateGeometry(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// The stylesheet style +int QStyleSheetStyle::numinstances = 0; + +QStyleSheetStyle::QStyleSheetStyle(QStyle *base) + : QWindowsStyle(*new QStyleSheetStylePrivate), base(base), refcount(1) +{ + ++numinstances; + if (numinstances == 1) { + styleSheetCaches = new QStyleSheetStyleCaches; + } +} + +QStyleSheetStyle::~QStyleSheetStyle() +{ + --numinstances; + if (numinstances == 0) { + delete styleSheetCaches; + } +} +QStyle *QStyleSheetStyle::baseStyle() const +{ + if (base) + return base; + if (QStyleSheetStyle *me = qobject_cast(QApplication::style())) + return me->base; + return QApplication::style(); +} + +void QStyleSheetStyleCaches::widgetDestroyed(QObject *o) +{ + styleRulesCache.remove((const QWidget *)o); + hasStyleRuleCache.remove((const QWidget *)o); + renderRulesCache.remove((const QWidget *)o); + customPaletteWidgets.remove((const QWidget *)o); + styleSheetCache.remove((const QWidget *)o); + autoFillDisabledWidgets.remove((const QWidget *)o); +} + +void QStyleSheetStyleCaches::styleDestroyed(QObject *o) +{ + styleSheetCache.remove(o); +} + +/*! + * Make sure that the cache will be clean by connecting destroyed if needed. + * return false if the widget is not stylable; + */ +bool QStyleSheetStyle::initWidget(const QWidget *w) const +{ + if (!w) + return false; + if(w->testAttribute(Qt::WA_StyleSheet)) + return true; + + if(unstylable(w)) + return false; + + const_cast(w)->setAttribute(Qt::WA_StyleSheet, true); + QObject::connect(w, SIGNAL(destroyed(QObject*)), styleSheetCaches, SLOT(widgetDestroyed(QObject*)), Qt::UniqueConnection); + return true; +} + +void QStyleSheetStyle::polish(QWidget *w) +{ + baseStyle()->polish(w); + RECURSION_GUARD(return) + + if (!initWidget(w)) + return; + + if (styleSheetCaches->styleRulesCache.contains(w)) { + // the widget accessed its style pointer before polish (or repolish) + // (exemple: the QAbstractSpinBox constructor ask for the stylehint) + styleSheetCaches->styleRulesCache.remove(w); + styleSheetCaches->hasStyleRuleCache.remove(w); + styleSheetCaches->renderRulesCache.remove(w); + } + setGeometry(w); + setProperties(w); + unsetPalette(w); + setPalette(w); + + //set the WA_Hover attribute if one of the selector depends of the hover state + QVector rules = styleRules(w); + for (int i = 0; i < rules.count(); i++) { + const Selector& selector = rules.at(i).selectors.at(0); + quint64 negated = 0; + quint64 cssClass = selector.pseudoClass(&negated); + if ( cssClass & PseudoClass_Hover || negated & PseudoClass_Hover) { + w->setAttribute(Qt::WA_Hover); + embeddedWidget(w)->setAttribute(Qt::WA_Hover); + } + } + + +#ifndef QT_NO_SCROLLAREA + if (QAbstractScrollArea *sa = qobject_cast(w)) { + QRenderRule rule = renderRule(sa, PseudoElement_None, PseudoClass_Enabled); + if ((rule.hasBorder() && rule.border()->hasBorderImage()) + || (rule.hasBackground() && !rule.background()->pixmap.isNull())) { + QObject::connect(sa->horizontalScrollBar(), SIGNAL(valueChanged(int)), + sa, SLOT(update()), Qt::UniqueConnection); + QObject::connect(sa->verticalScrollBar(), SIGNAL(valueChanged(int)), + sa, SLOT(update()), Qt::UniqueConnection); + } + } +#endif + +#ifndef QT_NO_PROGRESSBAR + if (QProgressBar *pb = qobject_cast(w)) { + QWindowsStyle::polish(pb); + } +#endif + + QRenderRule rule = renderRule(w, PseudoElement_None, PseudoClass_Any); + if (rule.hasDrawable() || rule.hasBox()) { + if (w->metaObject() == &QWidget::staticMetaObject +#ifndef QT_NO_ITEMVIEWS + || qobject_cast(w) +#endif +#ifndef QT_NO_TABBAR + || qobject_cast(w) +#endif +#ifndef QT_NO_FRAME + || qobject_cast(w) +#endif +#ifndef QT_NO_MAINWINDOW + || qobject_cast(w) +#endif +#ifndef QT_NO_MDIAREA + || qobject_cast(w) +#endif +#ifndef QT_NO_MENUBAR + || qobject_cast(w) +#endif + || qobject_cast(w)) { + w->setAttribute(Qt::WA_StyledBackground, true); + } + QWidget *ew = embeddedWidget(w); + if (ew->autoFillBackground()) { + ew->setAutoFillBackground(false); + styleSheetCaches->autoFillDisabledWidgets.insert(w); + if (ew != w) { //eg. viewport of a scrollarea + //(in order to draw the background anyway in case we don't.) + ew->setAttribute(Qt::WA_StyledBackground, true); + } + } + if (!rule.hasBackground() || rule.background()->isTransparent() || rule.hasBox() + || (!rule.hasNativeBorder() && !rule.border()->isOpaque())) + w->setAttribute(Qt::WA_OpaquePaintEvent, false); + } +} + +void QStyleSheetStyle::polish(QApplication *app) +{ + baseStyle()->polish(app); +} + +void QStyleSheetStyle::polish(QPalette &pal) +{ + baseStyle()->polish(pal); +} + +void QStyleSheetStyle::repolish(QWidget *w) +{ + QList children = w->findChildren(QString()); + children.append(w); + styleSheetCaches->styleSheetCache.remove(w); + updateWidgets(children); +} + +void QStyleSheetStyle::repolish(QApplication *app) +{ + Q_UNUSED(app); + const QList allWidgets = styleSheetCaches->styleRulesCache.keys(); + styleSheetCaches->styleSheetCache.remove(qApp); + styleSheetCaches->styleRulesCache.clear(); + styleSheetCaches->hasStyleRuleCache.clear(); + styleSheetCaches->renderRulesCache.clear(); + updateWidgets(allWidgets); +} + +void QStyleSheetStyle::unpolish(QWidget *w) +{ + if (!w || !w->testAttribute(Qt::WA_StyleSheet)) { + baseStyle()->unpolish(w); + return; + } + + styleSheetCaches->styleRulesCache.remove(w); + styleSheetCaches->hasStyleRuleCache.remove(w); + styleSheetCaches->renderRulesCache.remove(w); + styleSheetCaches->styleSheetCache.remove(w); + unsetPalette(w); + w->setProperty("_q_stylesheet_minw", QVariant()); + w->setProperty("_q_stylesheet_minh", QVariant()); + w->setProperty("_q_stylesheet_maxw", QVariant()); + w->setProperty("_q_stylesheet_maxh", QVariant()); + w->setAttribute(Qt::WA_StyleSheet, false); + QObject::disconnect(w, 0, this, 0); +#ifndef QT_NO_SCROLLAREA + if (QAbstractScrollArea *sa = qobject_cast(w)) { + QObject::disconnect(sa->horizontalScrollBar(), SIGNAL(valueChanged(int)), + sa, SLOT(update())); + QObject::disconnect(sa->verticalScrollBar(), SIGNAL(valueChanged(int)), + sa, SLOT(update())); + } +#endif +#ifndef QT_NO_PROGRESSBAR + if (QProgressBar *pb = qobject_cast(w)) + QWindowsStyle::unpolish(pb); +#endif + baseStyle()->unpolish(w); +} + +void QStyleSheetStyle::unpolish(QApplication *app) +{ + baseStyle()->unpolish(app); + RECURSION_GUARD(return) + styleSheetCaches->styleRulesCache.clear(); + styleSheetCaches->hasStyleRuleCache.clear(); + styleSheetCaches->renderRulesCache.clear(); + styleSheetCaches->styleSheetCache.remove(qApp); +} + +#ifndef QT_NO_TABBAR +inline static bool verticalTabs(QTabBar::Shape shape) +{ + return shape == QTabBar::RoundedWest + || shape == QTabBar::RoundedEast + || shape == QTabBar::TriangularWest + || shape == QTabBar::TriangularEast; +} +#endif // QT_NO_TABBAR + +void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, + const QWidget *w) const +{ + RECURSION_GUARD(baseStyle()->drawComplexControl(cc, opt, p, w); return) + + QRenderRule rule = renderRule(w, opt); + + switch (cc) { + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(opt)) { + QStyleOptionComboBox cmbOpt(*cmb); + cmbOpt.rect = rule.borderRect(opt->rect); + if (rule.hasNativeBorder()) { + rule.drawBackgroundImage(p, cmbOpt.rect); + rule.configurePalette(&cmbOpt.palette, QPalette::ButtonText, QPalette::Button); + bool customDropDown = (opt->subControls & QStyle::SC_ComboBoxArrow) + && (hasStyleRule(w, PseudoElement_ComboBoxDropDown) || hasStyleRule(w, PseudoElement_ComboBoxArrow)); + if (customDropDown) + cmbOpt.subControls &= ~QStyle::SC_ComboBoxArrow; + if (rule.baseStyleCanDraw()) { + baseStyle()->drawComplexControl(cc, &cmbOpt, p, w); + } else { + QWindowsStyle::drawComplexControl(cc, &cmbOpt, p, w); + } + if (!customDropDown) + return; + } else { + rule.drawRule(p, opt->rect); + } + + if (opt->subControls & QStyle::SC_ComboBoxArrow) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_ComboBoxDropDown); + if (subRule.hasDrawable()) { + QRect r = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w); + subRule.drawRule(p, r); + QRenderRule subRule2 = renderRule(w, opt, PseudoElement_ComboBoxArrow); + r = positionRect(w, subRule, subRule2, PseudoElement_ComboBoxArrow, r, opt->direction); + subRule2.drawRule(p, r); + } else { + cmbOpt.subControls = QStyle::SC_ComboBoxArrow; + QWindowsStyle::drawComplexControl(cc, &cmbOpt, p, w); + } + } + + return; + } + break; + +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spin = qstyleoption_cast(opt)) { + QStyleOptionSpinBox spinOpt(*spin); + rule.configurePalette(&spinOpt.palette, QPalette::ButtonText, QPalette::Button); + rule.configurePalette(&spinOpt.palette, QPalette::Text, QPalette::Base); + spinOpt.rect = rule.borderRect(opt->rect); + bool customUp = true, customDown = true; + QRenderRule upRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton); + QRenderRule downRule = renderRule(w, opt, PseudoElement_SpinBoxDownButton); + bool upRuleMatch = upRule.hasGeometry() || upRule.hasPosition(); + bool downRuleMatch = downRule.hasGeometry() || downRule.hasPosition(); + if (rule.hasNativeBorder() && !upRuleMatch && !downRuleMatch) { + rule.drawBackgroundImage(p, spinOpt.rect); + customUp = (opt->subControls & QStyle::SC_SpinBoxUp) + && (hasStyleRule(w, PseudoElement_SpinBoxUpButton) || hasStyleRule(w, PseudoElement_UpArrow)); + if (customUp) + spinOpt.subControls &= ~QStyle::SC_SpinBoxUp; + customDown = (opt->subControls & QStyle::SC_SpinBoxDown) + && (hasStyleRule(w, PseudoElement_SpinBoxDownButton) || hasStyleRule(w, PseudoElement_DownArrow)); + if (customDown) + spinOpt.subControls &= ~QStyle::SC_SpinBoxDown; + if (rule.baseStyleCanDraw()) { + baseStyle()->drawComplexControl(cc, &spinOpt, p, w); + } else { + QWindowsStyle::drawComplexControl(cc, &spinOpt, p, w); + } + if (!customUp && !customDown) + return; + } else { + rule.drawRule(p, opt->rect); + } + + if ((opt->subControls & QStyle::SC_SpinBoxUp) && customUp) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton); + if (subRule.hasDrawable()) { + QRect r = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w); + subRule.drawRule(p, r); + QRenderRule subRule2 = renderRule(w, opt, PseudoElement_SpinBoxUpArrow); + r = positionRect(w, subRule, subRule2, PseudoElement_SpinBoxUpArrow, r, opt->direction); + subRule2.drawRule(p, r); + } else { + spinOpt.subControls = QStyle::SC_SpinBoxUp; + QWindowsStyle::drawComplexControl(cc, &spinOpt, p, w); + } + } + + if ((opt->subControls & QStyle::SC_SpinBoxDown) && customDown) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_SpinBoxDownButton); + if (subRule.hasDrawable()) { + QRect r = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w); + subRule.drawRule(p, r); + QRenderRule subRule2 = renderRule(w, opt, PseudoElement_SpinBoxDownArrow); + r = positionRect(w, subRule, subRule2, PseudoElement_SpinBoxDownArrow, r, opt->direction); + subRule2.drawRule(p, r); + } else { + spinOpt.subControls = QStyle::SC_SpinBoxDown; + QWindowsStyle::drawComplexControl(cc, &spinOpt, p, w); + } + } + return; + } + break; +#endif // QT_NO_SPINBOX + + case CC_GroupBox: + if (const QStyleOptionGroupBox *gb = qstyleoption_cast(opt)) { + + QRect labelRect, checkBoxRect, titleRect, frameRect; + bool hasTitle = (gb->subControls & QStyle::SC_GroupBoxCheckBox) || !gb->text.isEmpty(); + + if (!rule.hasDrawable() && (!hasTitle || !hasStyleRule(w, PseudoElement_GroupBoxTitle)) + && !hasStyleRule(w, PseudoElement_Indicator) && !rule.hasBox() && !rule.hasFont && !rule.hasPalette()) { + // let the native style draw the combobox if there is no style for it. + break; + } + rule.drawBackground(p, opt->rect); + + QRenderRule titleRule = renderRule(w, opt, PseudoElement_GroupBoxTitle); + bool clipSet = false; + + if (hasTitle) { + labelRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w); + //Some native style (such as mac) may return a too small rectangle (because they use smaller fonts), so we may need to expand it a little bit. + labelRect.setSize(labelRect.size().expandedTo(ParentStyle::subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, w).size())); + if (gb->subControls & QStyle::SC_GroupBoxCheckBox) { + checkBoxRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, w); + titleRect = titleRule.boxRect(checkBoxRect.united(labelRect)); + } else { + titleRect = titleRule.boxRect(labelRect); + } + if (!titleRule.hasBackground() || !titleRule.background()->isTransparent()) { + clipSet = true; + p->save(); + p->setClipRegion(QRegion(opt->rect) - titleRect); + } + } + + frameRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, w); + QStyleOptionFrameV2 frame; + frame.QStyleOption::operator=(*gb); + frame.features = gb->features; + frame.lineWidth = gb->lineWidth; + frame.midLineWidth = gb->midLineWidth; + frame.rect = frameRect; + drawPrimitive(PE_FrameGroupBox, &frame, p, w); + + if (clipSet) + p->restore(); + + // draw background and frame of the title + if (hasTitle) + titleRule.drawRule(p, titleRect); + + // draw the indicator + if (gb->subControls & QStyle::SC_GroupBoxCheckBox) { + QStyleOptionButton box; + box.QStyleOption::operator=(*gb); + box.rect = checkBoxRect; + drawPrimitive(PE_IndicatorCheckBox, &box, p, w); + } + + // draw the text + if (!gb->text.isEmpty()) { + int alignment = int(Qt::AlignCenter | Qt::TextShowMnemonic); + if (!styleHint(QStyle::SH_UnderlineShortcut, opt, w)) { + alignment |= Qt::TextHideMnemonic; + } + + QPalette pal = gb->palette; + if (gb->textColor.isValid()) + pal.setColor(QPalette::WindowText, gb->textColor); + titleRule.configurePalette(&pal, QPalette::WindowText, QPalette::Window); + drawItemText(p, labelRect, alignment, pal, gb->state & State_Enabled, + gb->text, QPalette::WindowText); + + if (gb->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*gb); + fropt.rect = labelRect; + drawPrimitive(PE_FrameFocusRect, &fropt, p, w); + } + } + + return; + } + break; + + case CC_ToolButton: + if (const QStyleOptionToolButton *tool = qstyleoption_cast(opt)) { + QStyleOptionToolButton toolOpt(*tool); + rule.configurePalette(&toolOpt.palette, QPalette::ButtonText, QPalette::Button); + toolOpt.font = rule.font.resolve(toolOpt.font); + toolOpt.rect = rule.borderRect(opt->rect); + bool customArrow = (tool->features & (QStyleOptionToolButton::HasMenu | QStyleOptionToolButton::MenuButtonPopup)); + bool customDropDown = tool->features & QStyleOptionToolButton::MenuButtonPopup; + if (rule.hasNativeBorder()) { + if (tool->subControls & SC_ToolButton) { + //in some case (eg. the button is "auto raised") the style doesn't draw the background + //so we need to draw the background. + // use the same condition as in QCommonStyle + State bflags = tool->state & ~State_Sunken; + if (bflags & State_AutoRaise && (!(bflags & State_MouseOver) || !(bflags & State_Enabled))) + bflags &= ~State_Raised; + if (tool->state & State_Sunken && tool->activeSubControls & SC_ToolButton) + bflags |= State_Sunken; + if (!(bflags & (State_Sunken | State_On | State_Raised))) + rule.drawBackground(p, toolOpt.rect); + } + customArrow = customArrow && hasStyleRule(w, PseudoElement_ToolButtonDownArrow); + if (customArrow) + toolOpt.features &= ~QStyleOptionToolButton::HasMenu; + customDropDown = customDropDown && hasStyleRule(w, PseudoElement_ToolButtonMenu); + if (customDropDown) + toolOpt.subControls &= ~QStyle::SC_ToolButtonMenu; + + if (rule.baseStyleCanDraw() && !(tool->features & QStyleOptionToolButton::Arrow)) { + baseStyle()->drawComplexControl(cc, &toolOpt, p, w); + } else { + QWindowsStyle::drawComplexControl(cc, &toolOpt, p, w); + } + + if (!customArrow && !customDropDown) + return; + } else { + rule.drawRule(p, opt->rect); + toolOpt.rect = rule.contentsRect(opt->rect); + if (rule.hasFont) + toolOpt.font = rule.font; + drawControl(CE_ToolButtonLabel, &toolOpt, p, w); + } + + QRenderRule subRule = renderRule(w, opt, PseudoElement_ToolButtonMenu); + QRect r = subControlRect(CC_ToolButton, opt, QStyle::SC_ToolButtonMenu, w); + if (customDropDown) { + if (opt->subControls & QStyle::SC_ToolButtonMenu) { + if (subRule.hasDrawable()) { + subRule.drawRule(p, r); + } else { + toolOpt.rect = r; + baseStyle()->drawPrimitive(PE_IndicatorButtonDropDown, &toolOpt, p, w); + } + } + } + + if (customArrow) { + QRenderRule subRule2 = customDropDown ? renderRule(w, opt, PseudoElement_ToolButtonMenuArrow) + : renderRule(w, opt, PseudoElement_ToolButtonDownArrow); + QRect r2 = customDropDown + ? positionRect(w, subRule, subRule2, PseudoElement_ToolButtonMenuArrow, r, opt->direction) + : positionRect(w, rule, subRule2, PseudoElement_ToolButtonDownArrow, opt->rect, opt->direction); + if (subRule2.hasDrawable()) { + subRule2.drawRule(p, r2); + } else { + toolOpt.rect = r2; + baseStyle()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &toolOpt, p, w); + } + } + + return; + } + break; + +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + if (const QStyleOptionSlider *sb = qstyleoption_cast(opt)) { + QStyleOptionSlider sbOpt(*sb); + if (!rule.hasDrawable()) { + sbOpt.rect = rule.borderRect(opt->rect); + rule.drawBackgroundImage(p, opt->rect); + baseStyle()->drawComplexControl(cc, &sbOpt, p, w); + } else { + rule.drawRule(p, opt->rect); + QWindowsStyle::drawComplexControl(cc, opt, p, w); + } + return; + } + break; +#endif // QT_NO_SCROLLBAR + +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + rule.drawRule(p, opt->rect); + + QRenderRule grooveSubRule = renderRule(w, opt, PseudoElement_SliderGroove); + QRenderRule handleSubRule = renderRule(w, opt, PseudoElement_SliderHandle); + if (!grooveSubRule.hasDrawable()) { + QStyleOptionSlider slOpt(*slider); + bool handleHasRule = handleSubRule.hasDrawable(); + // If the style specifies a different handler rule, draw the groove without the handler. + if (handleHasRule) + slOpt.subControls &= ~SC_SliderHandle; + baseStyle()->drawComplexControl(cc, &slOpt, p, w); + if (!handleHasRule) + return; + } + + QRect gr = subControlRect(cc, opt, SC_SliderGroove, w); + if (slider->subControls & SC_SliderGroove) { + grooveSubRule.drawRule(p, gr); + } + + if (slider->subControls & SC_SliderHandle) { + QRect hr = subControlRect(cc, opt, SC_SliderHandle, w); + + QRenderRule subRule1 = renderRule(w, opt, PseudoElement_SliderSubPage); + if (subRule1.hasDrawable()) { + QRect r(gr.topLeft(), + slider->orientation == Qt::Horizontal + ? QPoint(hr.x()+hr.width()/2, gr.y()+gr.height() - 1) + : QPoint(gr.x()+gr.width() - 1, hr.y()+hr.height()/2)); + subRule1.drawRule(p, r); + } + + QRenderRule subRule2 = renderRule(w, opt, PseudoElement_SliderAddPage); + if (subRule2.hasDrawable()) { + QRect r(slider->orientation == Qt::Horizontal + ? QPoint(hr.x()+hr.width()/2+1, gr.y()) + : QPoint(gr.x(), hr.y()+hr.height()/2+1), + gr.bottomRight()); + subRule2.drawRule(p, r); + } + + handleSubRule.drawRule(p, handleSubRule.boxRect(hr, Margin)); + } + + if (slider->subControls & SC_SliderTickmarks) { + // TODO... + } + + return; + } + break; +#endif // QT_NO_SLIDER + + case CC_MdiControls: + if (hasStyleRule(w, PseudoElement_MdiCloseButton) + || hasStyleRule(w, PseudoElement_MdiNormalButton) + || hasStyleRule(w, PseudoElement_MdiMinButton)) { + QList layout = rule.styleHint(QLatin1String("button-layout")).toList(); + if (layout.isEmpty()) + layout = subControlLayout(QLatin1String("mNX")); + + QStyleOptionComplex optCopy(*opt); + optCopy.subControls = 0; + for (int i = 0; i < layout.count(); i++) { + int layoutButton = layout[i].toInt(); + if (layoutButton < PseudoElement_MdiCloseButton + || layoutButton > PseudoElement_MdiNormalButton) + continue; + QStyle::SubControl control = knownPseudoElements[layoutButton].subControl; + if (!(opt->subControls & control)) + continue; + QRenderRule subRule = renderRule(w, opt, layoutButton); + if (subRule.hasDrawable()) { + QRect rect = subRule.boxRect(subControlRect(CC_MdiControls, opt, control, w), Margin); + subRule.drawRule(p, rect); + QIcon icon = standardIcon(subControlIcon(layoutButton), opt); + icon.paint(p, subRule.contentsRect(rect), Qt::AlignCenter); + } else { + optCopy.subControls |= control; + } + } + + if (optCopy.subControls) + baseStyle()->drawComplexControl(CC_MdiControls, &optCopy, p, w); + return; + } + break; + + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_TitleBar); + if (!subRule.hasDrawable() && !subRule.hasBox() && !subRule.hasBorder()) + break; + subRule.drawRule(p, opt->rect); + QHash layout = titleBarLayout(w, tb); + + QRect ir; + ir = layout[SC_TitleBarLabel]; + if (ir.isValid()) { + if (subRule.hasPalette()) + p->setPen(subRule.palette()->foreground.color()); + p->fillRect(ir, Qt::white); + p->drawText(ir.x(), ir.y(), ir.width(), ir.height(), Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text); + } + + QPixmap pm; + + ir = layout[SC_TitleBarSysMenu]; + if (ir.isValid()) { + QRenderRule subSubRule = renderRule(w, opt, PseudoElement_TitleBarSysMenu); + subSubRule.drawRule(p, ir); + ir = subSubRule.contentsRect(ir); + if (!tb->icon.isNull()) { + tb->icon.paint(p, ir); + } else { + int iconSize = pixelMetric(PM_SmallIconSize, tb, w); + pm = standardIcon(SP_TitleBarMenuButton, 0, w).pixmap(iconSize, iconSize); + drawItemPixmap(p, ir, Qt::AlignCenter, pm); + } + } + + ir = layout[SC_TitleBarCloseButton]; + if (ir.isValid()) { + QRenderRule subSubRule = renderRule(w, opt, PseudoElement_TitleBarCloseButton); + subSubRule.drawRule(p, ir); + + QSize sz = subSubRule.contentsRect(ir).size(); + if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool) + pm = standardIcon(SP_DockWidgetCloseButton, 0, w).pixmap(sz); + else + pm = standardIcon(SP_TitleBarCloseButton, 0, w).pixmap(sz); + drawItemPixmap(p, ir, Qt::AlignCenter, pm); + } + + int pes[] = { + PseudoElement_TitleBarMaxButton, + PseudoElement_TitleBarMinButton, + PseudoElement_TitleBarNormalButton, + PseudoElement_TitleBarShadeButton, + PseudoElement_TitleBarUnshadeButton, + PseudoElement_TitleBarContextHelpButton + }; + + for (unsigned int i = 0; i < sizeof(pes)/sizeof(int); i++) { + int pe = pes[i]; + QStyle::SubControl sc = knownPseudoElements[pe].subControl; + ir = layout[sc]; + if (!ir.isValid()) + continue; + QRenderRule subSubRule = renderRule(w, opt, pe); + subSubRule.drawRule(p, ir); + pm = standardIcon(subControlIcon(pe), 0, w).pixmap(subSubRule.contentsRect(ir).size()); + drawItemPixmap(p, ir, Qt::AlignCenter, pm); + } + + return; + } + break; + + + default: + break; + } + + baseStyle()->drawComplexControl(cc, opt, p, w); +} + +void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p, + const QWidget *w) const +{ + RECURSION_GUARD(baseStyle()->drawControl(ce, opt, p, w); return) + + QRenderRule rule = renderRule(w, opt); + int pe1 = PseudoElement_None, pe2 = PseudoElement_None; + bool fallback = false; + + switch (ce) { + case CE_ToolButtonLabel: + if (const QStyleOptionToolButton *btn = qstyleoption_cast(opt)) { + if (rule.hasBox() || btn->features & QStyleOptionToolButton::Arrow) { + QCommonStyle::drawControl(ce, opt, p, w); + } else { + QStyleOptionToolButton butOpt(*btn); + rule.configurePalette(&butOpt.palette, QPalette::ButtonText, QPalette::Button); + baseStyle()->drawControl(ce, &butOpt, p, w); + } + return; + } + break; + + case CE_FocusFrame: + if (!rule.hasNativeBorder()) { + rule.drawBorder(p, opt->rect); + return; + } + break; + + case CE_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + if (rule.hasDrawable() || rule.hasBox() || rule.hasPosition() || rule.hasPalette() || + ((btn->features & QStyleOptionButton::HasMenu) && hasStyleRule(w, PseudoElement_PushButtonMenuIndicator))) { + ParentStyle::drawControl(ce, opt, p, w); + return; + } + } + break; + case CE_PushButtonBevel: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + QStyleOptionButton btnOpt(*btn); + btnOpt.rect = rule.borderRect(opt->rect); + if (rule.hasNativeBorder()) { + rule.drawBackgroundImage(p, btnOpt.rect); + rule.configurePalette(&btnOpt.palette, QPalette::ButtonText, QPalette::Button); + bool customMenu = (btn->features & QStyleOptionButton::HasMenu + && hasStyleRule(w, PseudoElement_PushButtonMenuIndicator)); + if (customMenu) + btnOpt.features &= ~QStyleOptionButton::HasMenu; + if (rule.baseStyleCanDraw()) { + baseStyle()->drawControl(ce, &btnOpt, p, w); + } else { + QWindowsStyle::drawControl(ce, &btnOpt, p, w); + } + if (!customMenu) + return; + } else { + rule.drawRule(p, opt->rect); + } + + if (btn->features & QStyleOptionButton::HasMenu) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_PushButtonMenuIndicator); + QRect ir = positionRect(w, rule, subRule, PseudoElement_PushButtonMenuIndicator, opt->rect, opt->direction); + if (subRule.hasDrawable()) { + subRule.drawRule(p, ir); + } else { + btnOpt.rect = ir; + baseStyle()->drawPrimitive(PE_IndicatorArrowDown, &btnOpt, p, w); + } + } + } + return; + + case CE_PushButtonLabel: + if (const QStyleOptionButton *button = qstyleoption_cast(opt)) { + QStyleOptionButton butOpt(*button); + rule.configurePalette(&butOpt.palette, QPalette::ButtonText, QPalette::Button); + if (rule.hasPosition() && rule.position()->textAlignment != 0) { + Qt::Alignment textAlignment = rule.position()->textAlignment; + QRect textRect = button->rect; + uint tf = Qt::TextShowMnemonic; + const uint verticalAlignMask = Qt::AlignVCenter | Qt::AlignTop | Qt::AlignLeft; + tf |= (textAlignment & verticalAlignMask) ? (textAlignment & verticalAlignMask) : Qt::AlignVCenter; + if (!styleHint(SH_UnderlineShortcut, button, w)) + tf |= Qt::TextHideMnemonic; + if (!button->icon.isNull()) { + //Group both icon and text + QRect iconRect; + QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled; + if (mode == QIcon::Normal && button->state & State_HasFocus) + mode = QIcon::Active; + QIcon::State state = QIcon::Off; + if (button->state & State_On) + state = QIcon::On; + + QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state); + int labelWidth = pixmap.width(); + int labelHeight = pixmap.height(); + int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint() + int textWidth = button->fontMetrics.boundingRect(opt->rect, tf, button->text).width(); + if (!button->text.isEmpty()) + labelWidth += (textWidth + iconSpacing); + + //Determine label alignment: + if (textAlignment & Qt::AlignLeft) { /*left*/ + iconRect = QRect(textRect.x(), textRect.y() + (textRect.height() - labelHeight) / 2, + pixmap.width(), pixmap.height()); + } else if (textAlignment & Qt::AlignHCenter) { /* center */ + iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2, + textRect.y() + (textRect.height() - labelHeight) / 2, + pixmap.width(), pixmap.height()); + } else { /*right*/ + iconRect = QRect(textRect.x() + textRect.width() - labelWidth, + textRect.y() + (textRect.height() - labelHeight) / 2, + pixmap.width(), pixmap.height()); + } + + iconRect = visualRect(button->direction, textRect, iconRect); + + tf |= Qt::AlignLeft; //left align, we adjust the text-rect instead + + if (button->direction == Qt::RightToLeft) + textRect.setRight(iconRect.left() - iconSpacing); + else + textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing); + + if (button->state & (State_On | State_Sunken)) + iconRect.translate(pixelMetric(PM_ButtonShiftHorizontal, opt, w), + pixelMetric(PM_ButtonShiftVertical, opt, w)); + p->drawPixmap(iconRect, pixmap); + } else { + tf |= textAlignment; + } + if (button->state & (State_On | State_Sunken)) + textRect.translate(pixelMetric(PM_ButtonShiftHorizontal, opt, w), + pixelMetric(PM_ButtonShiftVertical, opt, w)); + + if (button->features & QStyleOptionButton::HasMenu) { + int indicatorSize = pixelMetric(PM_MenuButtonIndicator, button, w); + if (button->direction == Qt::LeftToRight) + textRect = textRect.adjusted(0, 0, -indicatorSize, 0); + else + textRect = textRect.adjusted(indicatorSize, 0, 0, 0); + } + drawItemText(p, textRect, tf, butOpt.palette, (button->state & State_Enabled), + button->text, QPalette::ButtonText); + } else { + ParentStyle::drawControl(ce, &butOpt, p, w); + } + } + return; + + case CE_RadioButton: + case CE_CheckBox: + if (rule.hasBox() || !rule.hasNativeBorder() || rule.hasDrawable() || hasStyleRule(w, PseudoElement_Indicator)) { + rule.drawRule(p, opt->rect); + ParentStyle::drawControl(ce, opt, p, w); + return; + } else if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + QStyleOptionButton butOpt(*btn); + rule.configurePalette(&butOpt.palette, QPalette::ButtonText, QPalette::Button); + baseStyle()->drawControl(ce, &butOpt, p, w); + return; + } + break; + case CE_RadioButtonLabel: + case CE_CheckBoxLabel: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + QStyleOptionButton butOpt(*btn); + rule.configurePalette(&butOpt.palette, QPalette::ButtonText, QPalette::Button); + ParentStyle::drawControl(ce, &butOpt, p, w); + } + return; + + case CE_Splitter: + pe1 = PseudoElement_SplitterHandle; + break; + + case CE_ToolBar: + if (rule.hasBackground()) { + rule.drawBackground(p, opt->rect); + } + if (rule.hasBorder()) { + rule.drawBorder(p, rule.borderRect(opt->rect)); + } else { +#ifndef QT_NO_TOOLBAR + if (const QStyleOptionToolBar *tb = qstyleoption_cast(opt)) { + QStyleOptionToolBar newTb(*tb); + newTb.rect = rule.borderRect(opt->rect); + baseStyle()->drawControl(ce, &newTb, p, w); + } +#endif // QT_NO_TOOLBAR + } + return; + + case CE_MenuEmptyArea: + case CE_MenuBarEmptyArea: + if (rule.hasDrawable()) { + // Drawn by PE_Widget + return; + } + break; + + case CE_MenuTearoff: + case CE_MenuScroller: + if (const QStyleOptionMenuItem *m = qstyleoption_cast(opt)) { + QStyleOptionMenuItem mi(*m); + int pe = ce == CE_MenuTearoff ? PseudoElement_MenuTearoff : PseudoElement_MenuScroller; + QRenderRule subRule = renderRule(w, opt, pe); + mi.rect = subRule.contentsRect(opt->rect); + rule.configurePalette(&mi.palette, QPalette::ButtonText, QPalette::Button); + subRule.configurePalette(&mi.palette, QPalette::ButtonText, QPalette::Button); + + if (subRule.hasDrawable()) { + subRule.drawRule(p, opt->rect); + } else { + baseStyle()->drawControl(ce, &mi, p, w); + } + } + return; + + case CE_MenuItem: + if (const QStyleOptionMenuItem *m = qstyleoption_cast(opt)) { + QStyleOptionMenuItem mi(*m); + + int pseudo = (mi.menuItemType == QStyleOptionMenuItem::Separator) ? PseudoElement_MenuSeparator : PseudoElement_Item; + QRenderRule subRule = renderRule(w, opt, pseudo); + mi.rect = subRule.contentsRect(opt->rect); + rule.configurePalette(&mi.palette, QPalette::ButtonText, QPalette::Button); + rule.configurePalette(&mi.palette, QPalette::HighlightedText, QPalette::Highlight); + subRule.configurePalette(&mi.palette, QPalette::ButtonText, QPalette::Button); + subRule.configurePalette(&mi.palette, QPalette::HighlightedText, QPalette::Highlight); + QFont oldFont = p->font(); + if (subRule.hasFont) + p->setFont(subRule.font.resolve(p->font())); + + // We fall back to drawing with the style sheet code whenever at least one of the + // items are styled in an incompatible way, such as having a background image. + QRenderRule allRules = renderRule(w, PseudoElement_Item, PseudoClass_Any); + + if ((pseudo == PseudoElement_MenuSeparator) && subRule.hasDrawable()) { + subRule.drawRule(p, opt->rect); + } else if ((pseudo == PseudoElement_Item) + && (allRules.hasBox() || allRules.hasBorder() + || (allRules.background() && !allRules.background()->pixmap.isNull()))) { + subRule.drawRule(p, opt->rect); + if (subRule.hasBackground()) { + mi.palette.setBrush(QPalette::Highlight, Qt::NoBrush); + mi.palette.setBrush(QPalette::Button, Qt::NoBrush); + } else { + mi.palette.setBrush(QPalette::Highlight, mi.palette.brush(QPalette::Button)); + } + mi.palette.setBrush(QPalette::HighlightedText, mi.palette.brush(QPalette::ButtonText)); + + bool checkable = mi.checkType != QStyleOptionMenuItem::NotCheckable; + bool checked = checkable ? mi.checked : false; + + bool dis = !(opt->state & QStyle::State_Enabled), + act = opt->state & QStyle::State_Selected; + + if (!mi.icon.isNull()) { + QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; + if (act && !dis) + mode = QIcon::Active; + QPixmap pixmap; + if (checked) + pixmap = mi.icon.pixmap(pixelMetric(PM_SmallIconSize), mode, QIcon::On); + else + pixmap = mi.icon.pixmap(pixelMetric(PM_SmallIconSize), mode); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + QRenderRule iconRule = renderRule(w, opt, PseudoElement_MenuIcon); + if (!iconRule.hasGeometry()) { + iconRule.geo = new QStyleSheetGeometryData(pixw, pixh, pixw, pixh, -1, -1); + } else { + iconRule.geo->width = pixw; + iconRule.geo->height = pixh; + } + QRect iconRect = positionRect(w, subRule, iconRule, PseudoElement_MenuIcon, opt->rect, opt->direction); + iconRule.drawRule(p, iconRect); + QRect pmr(0, 0, pixw, pixh); + pmr.moveCenter(iconRect.center()); + p->drawPixmap(pmr.topLeft(), pixmap); + } else if (checkable) { + QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark); + if (subSubRule.hasDrawable() || checked) { + QStyleOptionMenuItem newMi = mi; + newMi.rect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction); + drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w); + } + } + + QRect textRect = subRule.contentsRect(opt->rect); + textRect.setWidth(textRect.width() - mi.tabWidth); + QString s = mi.text; + p->setPen(mi.palette.buttonText().color()); + if (!s.isEmpty()) { + int text_flags = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!styleHint(SH_UnderlineShortcut, &mi, w)) + text_flags |= Qt::TextHideMnemonic; + int t = s.indexOf(QLatin1Char('\t')); + if (t >= 0) { + QRect vShortcutRect = visualRect(opt->direction, mi.rect, + QRect(textRect.topRight(), QPoint(mi.rect.right(), textRect.bottom()))); + p->drawText(vShortcutRect, text_flags, s.mid(t + 1)); + s = s.left(t); + } + p->drawText(textRect, text_flags, s.left(t)); + } + + if (mi.menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow + PrimitiveElement arrow = (opt->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; + QRenderRule subRule2 = renderRule(w, opt, PseudoElement_MenuRightArrow); + mi.rect = positionRect(w, subRule, subRule2, PseudoElement_MenuRightArrow, opt->rect, mi.direction); + drawPrimitive(arrow, &mi, p, w); + } + } else if (hasStyleRule(w, PseudoElement_MenuCheckMark) || hasStyleRule(w, PseudoElement_MenuRightArrow)) { + QWindowsStyle::drawControl(ce, &mi, p, w); + if (mi.checkType != QStyleOptionMenuItem::NotCheckable && !mi.checked) { + // We have a style defined, but QWindowsStyle won't draw anything if not checked. + // So we mimick what QWindowsStyle would do. + int checkcol = qMax(mi.maxIconWidth, QWindowsStylePrivate::windowsCheckMarkWidth); + QRect vCheckRect = visualRect(opt->direction, mi.rect, QRect(mi.rect.x(), mi.rect.y(), checkcol, mi.rect.height())); + if (mi.state.testFlag(State_Enabled) && mi.state.testFlag(State_Selected)) { + qDrawShadePanel(p, vCheckRect, mi.palette, true, 1, &mi.palette.brush(QPalette::Button)); + } else { + QBrush fill(mi.palette.light().color(), Qt::Dense4Pattern); + qDrawShadePanel(p, vCheckRect, mi.palette, true, 1, &fill); + } + QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark); + if (subSubRule.hasDrawable()) { + QStyleOptionMenuItem newMi(mi); + newMi.rect = visualRect(opt->direction, mi.rect, QRect(mi.rect.x() + QWindowsStylePrivate::windowsItemFrame, + mi.rect.y() + QWindowsStylePrivate::windowsItemFrame, + checkcol - 2 * QWindowsStylePrivate::windowsItemFrame, + mi.rect.height() - 2 * QWindowsStylePrivate::windowsItemFrame)); + drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w); + } + } + } else { + if (rule.hasDrawable() && !subRule.hasDrawable() && !(opt->state & QStyle::State_Selected)) { + mi.palette.setColor(QPalette::Window, Qt::transparent); + mi.palette.setColor(QPalette::Button, Qt::transparent); + } + if (rule.baseStyleCanDraw() && subRule.baseStyleCanDraw()) { + baseStyle()->drawControl(ce, &mi, p, w); + } else { + ParentStyle::drawControl(ce, &mi, p, w); + } + } + + if (subRule.hasFont) + p->setFont(oldFont); + + return; + } + return; + + case CE_MenuBarItem: + if (const QStyleOptionMenuItem *m = qstyleoption_cast(opt)) { + QStyleOptionMenuItem mi(*m); + QRenderRule subRule = renderRule(w, opt, PseudoElement_Item); + mi.rect = subRule.contentsRect(opt->rect); + rule.configurePalette(&mi.palette, QPalette::ButtonText, QPalette::Button); + subRule.configurePalette(&mi.palette, QPalette::ButtonText, QPalette::Button); + + if (subRule.hasDrawable()) { + subRule.drawRule(p, opt->rect); + QCommonStyle::drawControl(ce, &mi, p, w); + } else { + if (rule.hasDrawable() && !(opt->state & QStyle::State_Selected)) { + // So that the menu bar background is not hidden by the items + mi.palette.setColor(QPalette::Window, Qt::transparent); + mi.palette.setColor(QPalette::Button, Qt::transparent); + } + baseStyle()->drawControl(ce, &mi, p, w); + } + } + return; + +#ifndef QT_NO_COMBOBOX + case CE_ComboBoxLabel: + if (!rule.hasBox()) + break; + if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { + QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, w); + p->save(); + p->setClipRect(editRect); + if (!cb->currentIcon.isNull()) { + int spacing = rule.hasBox() ? rule.box()->spacing : -1; + if (spacing == -1) + spacing = 6; + QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal : QIcon::Disabled; + QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode); + QRect iconRect(editRect); + iconRect.setWidth(cb->iconSize.width()); + iconRect = alignedRect(cb->direction, + Qt::AlignLeft | Qt::AlignVCenter, + iconRect.size(), editRect); + drawItemPixmap(p, iconRect, Qt::AlignCenter, pixmap); + + if (cb->direction == Qt::RightToLeft) + editRect.translate(-spacing - cb->iconSize.width(), 0); + else + editRect.translate(cb->iconSize.width() + spacing, 0); + } + if (!cb->currentText.isEmpty() && !cb->editable) { + QPalette styledPalette(cb->palette); + rule.configurePalette(&styledPalette, QPalette::Text, QPalette::Base); + drawItemText(p, editRect.adjusted(0, 0, 0, 0), Qt::AlignLeft | Qt::AlignVCenter, styledPalette, + cb->state & State_Enabled, cb->currentText, QPalette::Text); + } + p->restore(); + return; + } + break; +#endif // QT_NO_COMBOBOX + + case CE_Header: + if (hasStyleRule(w, PseudoElement_HeaderViewUpArrow) + || hasStyleRule(w, PseudoElement_HeaderViewDownArrow)) { + ParentStyle::drawControl(ce, opt, p, w); + return; + } + if(hasStyleRule(w, PseudoElement_HeaderViewSection)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection); + if (!subRule.hasNativeBorder() || !subRule.baseStyleCanDraw() + || subRule.hasBackground() || subRule.hasPalette()) { + ParentStyle::drawControl(ce, opt, p, w); + return; + } + } + break; + case CE_HeaderSection: + if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection); + if (subRule.hasNativeBorder()) { + QStyleOptionHeader hdr(*header); + subRule.configurePalette(&hdr.palette, QPalette::ButtonText, QPalette::Button); + + if (subRule.baseStyleCanDraw()) { + baseStyle()->drawControl(CE_HeaderSection, &hdr, p, w); + } else { + QWindowsStyle::drawControl(CE_HeaderSection, &hdr, p, w); + } + } else { + subRule.drawRule(p, opt->rect); + } + return; + } + break; + + case CE_HeaderLabel: + if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { + QStyleOptionHeader hdr(*header); + QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection); + subRule.configurePalette(&hdr.palette, QPalette::ButtonText, QPalette::Button); + QFont oldFont = p->font(); + if (subRule.hasFont) + p->setFont(subRule.font.resolve(p->font())); + baseStyle()->drawControl(ce, &hdr, p, w); + if (subRule.hasFont) + p->setFont(oldFont); + return; + } + break; + + case CE_HeaderEmptyArea: + if (rule.hasDrawable()) { + return; + } + break; + + case CE_ProgressBar: + QWindowsStyle::drawControl(ce, opt, p, w); + return; + + case CE_ProgressBarGroove: + if (!rule.hasNativeBorder()) { + rule.drawRule(p, rule.boxRect(opt->rect, Margin)); + return; + } + break; + + case CE_ProgressBarContents: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_ProgressBarChunk); + if (subRule.hasDrawable()) { + if (const QStyleOptionProgressBarV2 *pb = qstyleoption_cast(opt)) { + p->save(); + p->setClipRect(pb->rect); + + qint64 minimum = qint64(pb->minimum); + qint64 maximum = qint64(pb->maximum); + qint64 progress = qint64(pb->progress); + bool vertical = (pb->orientation == Qt::Vertical); + bool inverted = pb->invertedAppearance; + + QTransform m; + QRect rect = pb->rect; + if (vertical) { + rect = QRect(rect.y(), rect.x(), rect.height(), rect.width()); + m.rotate(90); + m.translate(0, -(rect.height() + rect.y()*2)); + } + + bool reverse = ((!vertical && (pb->direction == Qt::RightToLeft)) || vertical); + if (inverted) + reverse = !reverse; + const bool indeterminate = pb->minimum == pb->maximum; + qreal fillRatio = indeterminate ? 0.50 : qreal(progress - minimum)/(maximum - minimum); + int fillWidth = int(rect.width() * fillRatio); + int chunkWidth = fillWidth; + if (subRule.hasContentsSize()) { + QSize sz = subRule.size(); + chunkWidth = (opt->state & QStyle::State_Horizontal) ? sz.width() : sz.height(); + } + + QRect r = rect; + if (pb->minimum == 0 && pb->maximum == 0) { + Q_D(const QWindowsStyle); + int chunkCount = fillWidth/chunkWidth; + int offset = (d->animateStep*8%rect.width()); + int x = reverse ? r.left() + r.width() - offset - chunkWidth : r.x() + offset; + while (chunkCount > 0) { + r.setRect(x, rect.y(), chunkWidth, rect.height()); + r = m.mapRect(QRectF(r)).toRect(); + subRule.drawRule(p, r); + x += reverse ? -chunkWidth : chunkWidth; + if (reverse ? x < rect.left() : x > rect.right()) + break; + --chunkCount; + } + + r = rect; + x = reverse ? r.right() - (r.left() - x - chunkWidth) + : r.left() + (x - r.right() - chunkWidth); + while (chunkCount > 0) { + r.setRect(x, rect.y(), chunkWidth, rect.height()); + r = m.mapRect(QRectF(r)).toRect(); + subRule.drawRule(p, r); + x += reverse ? -chunkWidth : chunkWidth; + --chunkCount; + }; + } else { + int x = reverse ? r.left() + r.width() - chunkWidth : r.x(); + + for (int i = 0; i < ceil(qreal(fillWidth)/chunkWidth); ++i) { + r.setRect(x, rect.y(), chunkWidth, rect.height()); + r = m.mapRect(QRectF(r)).toRect(); + subRule.drawRule(p, r); + x += reverse ? -chunkWidth : chunkWidth; + } + } + + p->restore(); + return; + } + } + } + break; + + case CE_ProgressBarLabel: + if (const QStyleOptionProgressBarV2 *pb = qstyleoption_cast(opt)) { + if (rule.hasBox() || rule.hasBorder() || hasStyleRule(w, PseudoElement_ProgressBarChunk)) { + drawItemText(p, pb->rect, pb->textAlignment | Qt::TextSingleLine, pb->palette, + pb->state & State_Enabled, pb->text, QPalette::Text); + } else { + QStyleOptionProgressBarV2 pbCopy(*pb); + rule.configurePalette(&pbCopy.palette, QPalette::HighlightedText, QPalette::Highlight); + baseStyle()->drawControl(ce, &pbCopy, p, w); + } + return; + } + break; + + case CE_SizeGrip: + if (const QStyleOptionSizeGrip *sgOpt = qstyleoption_cast(opt)) { + if (rule.hasDrawable()) { + rule.drawFrame(p, opt->rect); + p->save(); + switch (sgOpt->corner) { + case Qt::BottomRightCorner: break; + case Qt::BottomLeftCorner: p->rotate(90); break; + case Qt::TopLeftCorner: p->rotate(180); break; + case Qt::TopRightCorner: p->rotate(270); break; + default: break; + } + rule.drawImage(p, opt->rect); + p->restore(); + } else { + QStyleOptionSizeGrip sg(*sgOpt); + sg.rect = rule.contentsRect(opt->rect); + baseStyle()->drawControl(CE_SizeGrip, &sg, p, w); + } + return; + } + break; + + case CE_ToolBoxTab: + QWindowsStyle::drawControl(ce, opt, p, w); + return; + + case CE_ToolBoxTabShape: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_ToolBoxTab); + if (subRule.hasDrawable()) { + subRule.drawRule(p, opt->rect); + return; + } + } + break; + + case CE_ToolBoxTabLabel: + if (const QStyleOptionToolBox *box = qstyleoption_cast(opt)) { + QStyleOptionToolBox boxCopy(*box); + QRenderRule subRule = renderRule(w, opt, PseudoElement_ToolBoxTab); + subRule.configurePalette(&boxCopy.palette, QPalette::ButtonText, QPalette::Button); + QFont oldFont = p->font(); + if (subRule.hasFont) + p->setFont(subRule.font); + boxCopy.rect = subRule.contentsRect(opt->rect); + QWindowsStyle::drawControl(ce, &boxCopy, p , w); + if (subRule.hasFont) + p->setFont(oldFont); + return; + } + break; + + case CE_ScrollBarAddPage: + pe1 = PseudoElement_ScrollBarAddPage; + break; + + case CE_ScrollBarSubPage: + pe1 = PseudoElement_ScrollBarSubPage; + break; + + case CE_ScrollBarAddLine: + pe1 = PseudoElement_ScrollBarAddLine; + pe2 = (opt->state & QStyle::State_Horizontal) ? PseudoElement_ScrollBarRightArrow : PseudoElement_ScrollBarDownArrow; + fallback = true; + break; + + case CE_ScrollBarSubLine: + pe1 = PseudoElement_ScrollBarSubLine; + pe2 = (opt->state & QStyle::State_Horizontal) ? PseudoElement_ScrollBarLeftArrow : PseudoElement_ScrollBarUpArrow; + fallback = true; + break; + + case CE_ScrollBarFirst: + pe1 = PseudoElement_ScrollBarFirst; + break; + + case CE_ScrollBarLast: + pe1 = PseudoElement_ScrollBarLast; + break; + + case CE_ScrollBarSlider: + pe1 = PseudoElement_ScrollBarSlider; + fallback = true; + break; + +#ifndef QT_NO_ITEMVIEWS + case CE_ItemViewItem: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_ViewItem); + if (subRule.hasDrawable() || hasStyleRule(w, PseudoElement_Indicator)) { + QStyleOptionViewItemV4 optCopy(*vopt); + subRule.configurePalette(&optCopy.palette, vopt->state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text, + vopt->state & QStyle::State_Selected ? QPalette::Highlight : QPalette::Base); + QWindowsStyle::drawControl(ce, &optCopy, p, w); + } else { + QStyleOptionViewItemV4 voptCopy(*vopt); + subRule.configurePalette(&voptCopy.palette, QPalette::Text, QPalette::NoRole); + baseStyle()->drawControl(ce, &voptCopy, p, w); + } + return; + } + break; +#endif // QT_NO_ITEMVIEWS + +#ifndef QT_NO_TABBAR + case CE_TabBarTab: + if (hasStyleRule(w, PseudoElement_TabBarTab)) { + QWindowsStyle::drawControl(ce, opt, p, w); + return; + } + break; + + case CE_TabBarTabLabel: + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + QStyleOptionTabV3 tabCopy(*tab); + QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTab); + QRect r = positionRect(w, subRule, PseudoElement_TabBarTab, opt->rect, opt->direction); + if (ce == CE_TabBarTabShape && subRule.hasDrawable()) { + subRule.drawRule(p, r); + return; + } + subRule.configurePalette(&tabCopy.palette, QPalette::WindowText, QPalette::Window); + QFont oldFont = p->font(); + if (subRule.hasFont) + p->setFont(subRule.font); + if (subRule.hasBox() || !subRule.hasNativeBorder()) { + tabCopy.rect = ce == CE_TabBarTabShape ? subRule.borderRect(r) + : subRule.contentsRect(r); + QWindowsStyle::drawControl(ce, &tabCopy, p, w); + } else { + baseStyle()->drawControl(ce, &tabCopy, p, w); + } + if (subRule.hasFont) + p->setFont(oldFont); + + return; + } + break; +#endif // QT_NO_TABBAR + + case CE_ColumnViewGrip: + if (rule.hasDrawable()) { + rule.drawRule(p, opt->rect); + return; + } + break; + + case CE_DockWidgetTitle: + if (const QStyleOptionDockWidgetV2 *dwOpt = qstyleoption_cast(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_DockWidgetTitle); + if (!subRule.hasDrawable() && !subRule.hasPosition()) + break; + if (subRule.hasDrawable()) { + subRule.drawRule(p, opt->rect); + } else { + QStyleOptionDockWidgetV2 dwCopy(*dwOpt); + dwCopy.title = QString(); + baseStyle()->drawControl(ce, &dwCopy, p, w); + } + + if (!dwOpt->title.isEmpty()) { + QRect r = opt->rect; + if (dwOpt->verticalTitleBar) { + QSize s = r.size(); + s.transpose(); + r.setSize(s); + + p->save(); + p->translate(r.left(), r.top() + r.width()); + p->rotate(-90); + p->translate(-r.left(), -r.top()); + } + + Qt::Alignment alignment = 0; + if (subRule.hasPosition()) + alignment = subRule.position()->textAlignment; + if (alignment == 0) + alignment = Qt::AlignLeft; + drawItemText(p, subRule.contentsRect(opt->rect), + alignment | Qt::TextShowMnemonic, dwOpt->palette, + dwOpt->state & State_Enabled, dwOpt->title, + QPalette::WindowText); + + if (dwOpt->verticalTitleBar) + p->restore(); + } + + return; + } + break; + case CE_ShapedFrame: + if (const QStyleOptionFrame *frm = qstyleoption_cast(opt)) { + if (rule.hasNativeBorder()) { + QStyleOptionFrameV3 frmOpt(*frm); + rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base); + frmOpt.rect = rule.borderRect(frmOpt.rect); + baseStyle()->drawControl(ce, &frmOpt, p, w); + } + // else, borders are already drawn in PE_Widget + } + return; + + + default: + break; + } + + if (pe1 != PseudoElement_None) { + QRenderRule subRule = renderRule(w, opt, pe1); + if (subRule.bg != 0 || subRule.hasDrawable()) { + //We test subRule.bg directly because hasBackground() would return false for background:none. + //But we still don't want the default drawning in that case (example for QScrollBar::add-page) (task 198926) + subRule.drawRule(p, opt->rect); + } else if (fallback) { + QWindowsStyle::drawControl(ce, opt, p, w); + pe2 = PseudoElement_None; + } else { + baseStyle()->drawControl(ce, opt, p, w); + } + if (pe2 != PseudoElement_None) { + QRenderRule subSubRule = renderRule(w, opt, pe2); + QRect r = positionRect(w, subRule, subSubRule, pe2, opt->rect, opt->direction); + subSubRule.drawRule(p, r); + } + return; + } + + baseStyle()->drawControl(ce, opt, p, w); +} + +void QStyleSheetStyle::drawItemPixmap(QPainter *p, const QRect &rect, int alignment, const + QPixmap &pixmap) const +{ + baseStyle()->drawItemPixmap(p, rect, alignment, pixmap); +} + +void QStyleSheetStyle::drawItemText(QPainter *painter, const QRect& rect, int alignment, const QPalette &pal, + bool enabled, const QString& text, QPalette::ColorRole textRole) const +{ + baseStyle()->drawItemText(painter, rect, alignment, pal, enabled, text, textRole); +} + +void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *w) const +{ + RECURSION_GUARD(baseStyle()->drawPrimitive(pe, opt, p, w); return) + + int pseudoElement = PseudoElement_None; + QRenderRule rule = renderRule(w, opt); + QRect rect = opt->rect; + + switch (pe) { + + case PE_FrameStatusBar: { + QRenderRule subRule = renderRule(w->parentWidget(), opt, PseudoElement_Item); + if (subRule.hasDrawable()) { + subRule.drawRule(p, opt->rect); + return; + } + break; + } + + case PE_IndicatorArrowDown: + pseudoElement = PseudoElement_DownArrow; + break; + + case PE_IndicatorArrowUp: + pseudoElement = PseudoElement_UpArrow; + break; + + case PE_IndicatorRadioButton: + pseudoElement = PseudoElement_ExclusiveIndicator; + break; + + case PE_IndicatorViewItemCheck: + pseudoElement = PseudoElement_ViewItemIndicator; + break; + + case PE_IndicatorCheckBox: + pseudoElement = PseudoElement_Indicator; + break; + + case PE_IndicatorHeaderArrow: + if (const QStyleOptionHeader *hdr = qstyleoption_cast(opt)) { + pseudoElement = hdr->sortIndicator == QStyleOptionHeader::SortUp + ? PseudoElement_HeaderViewUpArrow + : PseudoElement_HeaderViewDownArrow; + } + break; + + case PE_PanelButtonTool: + case PE_PanelButtonCommand: + if (qobject_cast(w) && rule.hasBackground() && rule.hasNativeBorder()) { + //the window style will draw the borders + ParentStyle::drawPrimitive(pe, opt, p, w); + if (!rule.background()->pixmap.isNull() || rule.hasImage()) { + rule.drawRule(p, rule.boxRect(opt->rect, QRenderRule::Margin).adjusted(1,1,-1,-1)); + } + return; + } + if (!rule.hasNativeBorder()) { + rule.drawRule(p, rule.boxRect(opt->rect, QRenderRule::Margin)); + return; + } + break; + + case PE_IndicatorButtonDropDown: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_ToolButtonMenu); + if (!subRule.hasNativeBorder()) { + rule.drawBorder(p, opt->rect); + return; + } + break; + } + + case PE_FrameDefaultButton: + if (rule.hasNativeBorder()) { + if (rule.baseStyleCanDraw()) + break; + QWindowsStyle::drawPrimitive(pe, opt, p, w); + } + return; + + case PE_FrameWindow: + case PE_FrameDockWidget: + case PE_Frame: + if (const QStyleOptionFrame *frm = qstyleoption_cast(opt)) { + if (rule.hasNativeBorder()) { + QStyleOptionFrameV2 frmOpt(*frm); + rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base); + if (!qstyleoption_cast(opt)) //if it comes from CE_ShapedFrame, the margins are already sustracted + frmOpt.rect = rule.borderRect(frmOpt.rect); + baseStyle()->drawPrimitive(pe, &frmOpt, p, w); + } else { + rule.drawBorder(p, rule.borderRect(opt->rect)); + } + } + return; + + case PE_PanelLineEdit: + if (const QStyleOptionFrame *frm = qstyleoption_cast(opt)) { +#ifndef QT_NO_SPINBOX + if (w && qobject_cast(w->parentWidget())) { + QRenderRule spinboxRule = renderRule(w->parentWidget(), opt); + if (!spinboxRule.hasNativeBorder() || !spinboxRule.baseStyleCanDraw()) + return; + rule = spinboxRule; + } +#endif + if (rule.hasNativeBorder()) { + QStyleOptionFrame frmOpt(*frm); + rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base); + frmOpt.rect = rule.borderRect(frmOpt.rect); + if (rule.baseStyleCanDraw()) { + rule.drawBackgroundImage(p, opt->rect); + baseStyle()->drawPrimitive(pe, &frmOpt, p, w); + } else { + rule.drawBackground(p, opt->rect); + if (frmOpt.lineWidth > 0) + baseStyle()->drawPrimitive(PE_FrameLineEdit, &frmOpt, p, w); + } + } else { + rule.drawRule(p, opt->rect); + } + } + return; + + case PE_Widget: + if (w && !rule.hasDrawable()) { + QWidget *container = containerWidget(w); + if (styleSheetCaches->autoFillDisabledWidgets.contains(container) + && (container == w || !renderRule(container, opt).hasBackground())) { + //we do not have a background, but we disabled the autofillbackground anyway. so fill the background now. + // (this may happen if we have rules like :focus) + p->fillRect(opt->rect, opt->palette.brush(w->backgroundRole())); + } + break; + } +#ifndef QT_NO_SCROLLAREA + if (const QAbstractScrollArea *sa = qobject_cast(w)) { + const QAbstractScrollAreaPrivate *sap = sa->d_func(); + rule.drawBackground(p, opt->rect, sap->contentsOffset()); + if (rule.hasBorder()) { + QRect brect = rule.borderRect(opt->rect); + if (styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, opt, w)) { + QRect r = brect.adjusted(0, 0, sa->verticalScrollBar()->isVisible() ? -sa->verticalScrollBar()->width() : 0, + sa->horizontalScrollBar()->isVisible() ? -sa->horizontalScrollBar()->height() : 0); + brect = QStyle::visualRect(opt->direction, brect, r); + } + rule.drawBorder(p, brect); + } + break; + } +#endif + //fall tghought + case PE_PanelMenu: + case PE_PanelStatusBar: + if(rule.hasDrawable()) { + rule.drawRule(p, opt->rect); + return; + } + break; + + case PE_FrameMenu: + if (rule.hasDrawable()) { + // Drawn by PE_PanelMenu + return; + } + break; + + case PE_PanelMenuBar: + if (rule.hasDrawable()) { + // Drawn by PE_Widget + return; + } + break; + + case PE_IndicatorToolBarSeparator: + case PE_IndicatorToolBarHandle: { + PseudoElement ps = pe == PE_IndicatorToolBarHandle ? PseudoElement_ToolBarHandle : PseudoElement_ToolBarSeparator; + QRenderRule subRule = renderRule(w, opt, ps); + if (subRule.hasDrawable()) { + subRule.drawRule(p, opt->rect); + return; + } + } + break; + + case PE_IndicatorMenuCheckMark: + pseudoElement = PseudoElement_MenuCheckMark; + break; + + case PE_IndicatorArrowLeft: + pseudoElement = PseudoElement_LeftArrow; + break; + + case PE_IndicatorArrowRight: + pseudoElement = PseudoElement_RightArrow; + break; + + case PE_IndicatorColumnViewArrow: + if (const QStyleOptionViewItem *viewOpt = qstyleoption_cast(opt)) { + bool reverse = (viewOpt->direction == Qt::RightToLeft); + pseudoElement = reverse ? PseudoElement_LeftArrow : PseudoElement_RightArrow; + } else { + pseudoElement = PseudoElement_RightArrow; + } + break; + + case PE_IndicatorBranch: + if (const QStyleOptionViewItemV2 *v2 = qstyleoption_cast(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_TreeViewBranch); + if (subRule.hasDrawable()) { + if ((v2->state & QStyle::State_Selected) && v2->showDecorationSelected) + p->fillRect(v2->rect, v2->palette.highlight()); + else if (v2->features & QStyleOptionViewItemV2::Alternate) + p->fillRect(v2->rect, v2->palette.alternateBase()); + subRule.drawRule(p, opt->rect); + } else { + baseStyle()->drawPrimitive(pe, v2, p, w); + } + } + return; + + case PE_PanelTipLabel: + if (!rule.hasDrawable()) + break; + + if (const QStyleOptionFrame *frmOpt = qstyleoption_cast(opt)) { + if (rule.hasNativeBorder()) { + rule.drawBackground(p, opt->rect); + QStyleOptionFrame optCopy(*frmOpt); + optCopy.rect = rule.borderRect(opt->rect); + optCopy.palette.setBrush(QPalette::Window, Qt::NoBrush); // oh dear + baseStyle()->drawPrimitive(pe, &optCopy, p, w); + } else { + rule.drawRule(p, opt->rect); + } + } + return; + + case PE_FrameGroupBox: + if (rule.hasNativeBorder()) + break; + rule.drawBorder(p, opt->rect); + return; + +#ifndef QT_NO_TABWIDGET + case PE_FrameTabWidget: + if (const QStyleOptionTabWidgetFrame *frm = qstyleoption_cast(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_TabWidgetPane); + if (subRule.hasNativeBorder()) { + subRule.drawBackground(p, opt->rect); + QStyleOptionTabWidgetFrameV2 frmCopy(*frm); + subRule.configurePalette(&frmCopy.palette, QPalette::WindowText, QPalette::Window); + baseStyle()->drawPrimitive(pe, &frmCopy, p, w); + } else { + subRule.drawRule(p, opt->rect); + } + return; + } + break; +#endif // QT_NO_TABWIDGET + + case PE_IndicatorProgressChunk: + pseudoElement = PseudoElement_ProgressBarChunk; + break; + + case PE_IndicatorTabTear: + pseudoElement = PseudoElement_TabBarTear; + break; + + case PE_FrameFocusRect: + if (!rule.hasNativeOutline()) { + rule.drawOutline(p, opt->rect); + return; + } + break; + + case PE_IndicatorDockWidgetResizeHandle: + pseudoElement = PseudoElement_DockWidgetSeparator; + break; + + case PE_PanelItemViewItem: + pseudoElement = PseudoElement_ViewItem; + break; + + case PE_PanelScrollAreaCorner: + pseudoElement = PseudoElement_ScrollAreaCorner; + break; + + case PE_IndicatorSpinDown: + case PE_IndicatorSpinMinus: + pseudoElement = PseudoElement_SpinBoxDownArrow; + break; + + case PE_IndicatorSpinUp: + case PE_IndicatorSpinPlus: + pseudoElement = PseudoElement_SpinBoxUpArrow; + break; +#ifndef QT_NO_TABBAR + case PE_IndicatorTabClose: + if (w) + w = w->parentWidget(); //match on the QTabBar instead of the CloseButton + pseudoElement = PseudoElement_TabBarTabCloseButton; +#endif + + default: + break; + } + + if (pseudoElement != PseudoElement_None) { + QRenderRule subRule = renderRule(w, opt, pseudoElement); + if (subRule.hasDrawable()) { + subRule.drawRule(p, rect); + } else { + baseStyle()->drawPrimitive(pe, opt, p, w); + } + } else { + baseStyle()->drawPrimitive(pe, opt, p, w); + } +} + +QPixmap QStyleSheetStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap& pixmap, + const QStyleOption *option) const +{ + return baseStyle()->generatedIconPixmap(iconMode, pixmap, option); +} + +QStyle::SubControl QStyleSheetStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *w) const +{ + RECURSION_GUARD(return baseStyle()->hitTestComplexControl(cc, opt, pt, w)) + switch (cc) { + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(opt)) { + QRenderRule rule = renderRule(w, opt, PseudoElement_TitleBar); + if (rule.hasDrawable() || rule.hasBox() || rule.hasBorder()) { + QHash layout = titleBarLayout(w, tb); + QRect r; + QStyle::SubControl sc = QStyle::SC_None; + uint ctrl = SC_TitleBarSysMenu; + while (ctrl <= SC_TitleBarLabel) { + r = layout[QStyle::SubControl(ctrl)]; + if (r.isValid() && r.contains(pt)) { + sc = QStyle::SubControl(ctrl); + break; + } + ctrl <<= 1; + } + return sc; + } + } + break; + + case CC_MdiControls: + if (hasStyleRule(w, PseudoElement_MdiCloseButton) + || hasStyleRule(w, PseudoElement_MdiNormalButton) + || hasStyleRule(w, PseudoElement_MdiMinButton)) + return QWindowsStyle::hitTestComplexControl(cc, opt, pt, w); + break; + + case CC_ScrollBar: { + QRenderRule rule = renderRule(w, opt); + if (!rule.hasDrawable() && !rule.hasBox()) + break; + } + // intentionally falls through + case CC_SpinBox: + case CC_GroupBox: + case CC_ComboBox: + case CC_Slider: + case CC_ToolButton: + return QWindowsStyle::hitTestComplexControl(cc, opt, pt, w); + default: + break; + } + + return baseStyle()->hitTestComplexControl(cc, opt, pt, w); +} + +QRect QStyleSheetStyle::itemPixmapRect(const QRect &rect, int alignment, const QPixmap &pixmap) const +{ + return baseStyle()->itemPixmapRect(rect, alignment, pixmap); +} + +QRect QStyleSheetStyle::itemTextRect(const QFontMetrics &metrics, const QRect& rect, int alignment, + bool enabled, const QString& text) const +{ + return baseStyle()->itemTextRect(metrics, rect, alignment, enabled, text); +} + +int QStyleSheetStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWidget *w) const +{ + RECURSION_GUARD(return baseStyle()->pixelMetric(m, opt, w)) + + QRenderRule rule = renderRule(w, opt); + QRenderRule subRule; + + switch (m) { + case PM_MenuButtonIndicator: +#ifndef QT_NO_TOOLBUTTON + // QToolButton adds this directly to the width + if (qobject_cast(w) && (rule.hasBox() || !rule.hasNativeBorder())) + return 0; +#endif + subRule = renderRule(w, opt, PseudoElement_PushButtonMenuIndicator); + if (subRule.hasContentsSize()) + return subRule.size().width(); + break; + + case PM_ButtonShiftHorizontal: + case PM_ButtonShiftVertical: + case PM_ButtonMargin: + case PM_ButtonDefaultIndicator: + if (rule.hasBox()) + return 0; + break; + + case PM_DefaultFrameWidth: + if (!rule.hasNativeBorder()) + return rule.border()->borders[LeftEdge]; + break; + + case PM_ExclusiveIndicatorWidth: + case PM_IndicatorWidth: + case PM_ExclusiveIndicatorHeight: + case PM_IndicatorHeight: + subRule = renderRule(w, opt, PseudoElement_Indicator); + if (subRule.hasContentsSize()) { + return (m == PM_ExclusiveIndicatorWidth) || (m == PM_IndicatorWidth) + ? subRule.size().width() : subRule.size().height(); + } + break; + + case PM_DockWidgetFrameWidth: + case PM_ToolTipLabelFrameWidth: // border + margin + padding (support only one width) + if (!rule.hasDrawable()) + break; + + return (rule.border() ? rule.border()->borders[LeftEdge] : 0) + + (rule.hasBox() ? rule.box()->margins[LeftEdge] + rule.box()->paddings[LeftEdge]: 0); + + case PM_ToolBarFrameWidth: + if (rule.hasBorder() || rule.hasBox()) + return (rule.border() ? rule.border()->borders[LeftEdge] : 0) + + (rule.hasBox() ? rule.box()->paddings[LeftEdge]: 0); + break; + + case PM_MenuPanelWidth: + case PM_MenuBarPanelWidth: + if (rule.hasBorder() || rule.hasBox()) + return (rule.border() ? rule.border()->borders[LeftEdge] : 0) + + (rule.hasBox() ? rule.box()->margins[LeftEdge]: 0); + break; + + + case PM_MenuHMargin: + case PM_MenuBarHMargin: + if (rule.hasBox()) + return rule.box()->paddings[LeftEdge]; + break; + + case PM_MenuVMargin: + case PM_MenuBarVMargin: + if (rule.hasBox()) + return rule.box()->paddings[TopEdge]; + break; + + case PM_DockWidgetTitleBarButtonMargin: + case PM_ToolBarItemMargin: + if (rule.hasBox()) + return rule.box()->margins[TopEdge]; + break; + + case PM_ToolBarItemSpacing: + case PM_MenuBarItemSpacing: + if (rule.hasBox() && rule.box()->spacing != -1) + return rule.box()->spacing; + break; + + case PM_MenuTearoffHeight: + case PM_MenuScrollerHeight: { + PseudoElement ps = m == PM_MenuTearoffHeight ? PseudoElement_MenuTearoff : PseudoElement_MenuScroller; + subRule = renderRule(w, opt, ps); + if (subRule.hasContentsSize()) + return subRule.size().height(); + break; + } + + case PM_ToolBarExtensionExtent: + break; + + case PM_SplitterWidth: + case PM_ToolBarSeparatorExtent: + case PM_ToolBarHandleExtent: { + PseudoElement ps; + if (m == PM_ToolBarHandleExtent) ps = PseudoElement_ToolBarHandle; + else if (m == PM_SplitterWidth) ps = PseudoElement_SplitterHandle; + else ps = PseudoElement_ToolBarSeparator; + subRule = renderRule(w, opt, ps); + if (subRule.hasContentsSize()) { + QSize sz = subRule.size(); + return (opt && opt->state & QStyle::State_Horizontal) ? sz.width() : sz.height(); + } + break; + } + + case PM_RadioButtonLabelSpacing: + if (rule.hasBox() && rule.box()->spacing != -1) + return rule.box()->spacing; + break; + case PM_CheckBoxLabelSpacing: + if (qobject_cast(w)) { + if (rule.hasBox() && rule.box()->spacing != -1) + return rule.box()->spacing; + } + // assume group box + subRule = renderRule(w, opt, PseudoElement_GroupBoxTitle); + if (subRule.hasBox() && subRule.box()->spacing != -1) + return subRule.box()->spacing; + break; + +#ifndef QT_NO_SCROLLBAR + case PM_ScrollBarExtent: + if (rule.hasContentsSize()) { + QSize sz = rule.size(); + if (const QStyleOptionSlider *sb = qstyleoption_cast(opt)) + return sb->orientation == Qt::Horizontal ? sz.height() : sz.width(); + return sz.width() == -1 ? sz.height() : sz.width(); + } + break; + + case PM_ScrollBarSliderMin: + if (hasStyleRule(w, PseudoElement_ScrollBarSlider)) { + subRule = renderRule(w, opt, PseudoElement_ScrollBarSlider); + QSize msz = subRule.minimumSize(); + if (const QStyleOptionSlider *sb = qstyleoption_cast(opt)) + return sb->orientation == Qt::Horizontal ? msz.width() : msz.height(); + return msz.width() == -1 ? msz.height() : msz.width(); + } + break; + + case PM_ScrollView_ScrollBarSpacing: + if(!rule.hasNativeBorder() || rule.hasBox()) + return 0; + break; +#endif // QT_NO_SCROLLBAR + + case PM_ProgressBarChunkWidth: + subRule = renderRule(w, opt, PseudoElement_ProgressBarChunk); + if (subRule.hasContentsSize()) { + QSize sz = subRule.size(); + return (opt->state & QStyle::State_Horizontal) + ? sz.width() : sz.height(); + } + break; + +#ifndef QT_NO_TABWIDGET + case PM_TabBarTabHSpace: + case PM_TabBarTabVSpace: + subRule = renderRule(w, opt, PseudoElement_TabBarTab); + if (subRule.hasBox() || subRule.hasBorder()) + return 0; + break; + + case PM_TabBarScrollButtonWidth: { + subRule = renderRule(w, opt, PseudoElement_TabBarScroller); + if (subRule.hasContentsSize()) { + QSize sz = subRule.size(); + return sz.width() != -1 ? sz.width() : sz.height(); + } + } + break; + + case PM_TabBarTabShiftHorizontal: + case PM_TabBarTabShiftVertical: + subRule = renderRule(w, opt, PseudoElement_TabBarTab); + if (subRule.hasBox()) + return 0; + break; + + case PM_TabBarBaseOverlap: { + const QWidget *tabWidget = qobject_cast(w) ? w : w->parentWidget(); + if (hasStyleRule(tabWidget, PseudoElement_TabWidgetPane)) { + return 0; + } + break; + } +#endif // QT_NO_TABWIDGET + + case PM_SliderThickness: // horizontal slider's height (sizeHint) + case PM_SliderLength: // minimum length of slider + if (rule.hasContentsSize()) { + bool horizontal = opt->state & QStyle::State_Horizontal; + if (m == PM_SliderThickness) { + QSize sz = rule.size(); + return horizontal ? sz.height() : sz.width(); + } else { + QSize msz = rule.minimumContentsSize(); + return horizontal ? msz.width() : msz.height(); + } + } + break; + + case PM_SliderControlThickness: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_SliderHandle); + if (!subRule.hasContentsSize()) + break; + QSize size = subRule.size(); + return (opt->state & QStyle::State_Horizontal) ? size.height() : size.width(); + } + + case PM_ToolBarIconSize: + case PM_ListViewIconSize: + case PM_IconViewIconSize: + case PM_TabBarIconSize: + case PM_MessageBoxIconSize: + case PM_ButtonIconSize: + case PM_SmallIconSize: + if (rule.hasStyleHint(QLatin1String("icon-size"))) { + return rule.styleHint(QLatin1String("icon-size")).toSize().width(); + } + break; + + case PM_DockWidgetTitleMargin: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_DockWidgetTitle); + if (!subRule.hasBox()) + break; + return (subRule.border() ? subRule.border()->borders[TopEdge] : 0) + + (subRule.hasBox() ? subRule.box()->margins[TopEdge] + subRule.box()->paddings[TopEdge]: 0); + } + + case PM_DockWidgetSeparatorExtent: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_DockWidgetSeparator); + if (!subRule.hasContentsSize()) + break; + QSize sz = subRule.size(); + return qMax(sz.width(), sz.height()); + } + + case PM_TitleBarHeight: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_TitleBar); + if (subRule.hasContentsSize()) + return subRule.size().height(); + else if (subRule.hasBox() || subRule.hasBorder()) { + QFontMetrics fm = opt ? opt->fontMetrics : w->fontMetrics(); + return subRule.size(QSize(0, fm.height())).height(); + } + break; + } + + case PM_MdiSubWindowFrameWidth: + if (rule.hasBox() || rule.hasBorder()) { + return (rule.border() ? rule.border()->borders[LeftEdge] : 0) + + (rule.hasBox() ? rule.box()->paddings[LeftEdge]+rule.box()->margins[LeftEdge]: 0); + } + break; + + case PM_MdiSubWindowMinimizedWidth: { + QRenderRule subRule = renderRule(w, PseudoElement_None, PseudoClass_Minimized); + int width = subRule.size().width(); + if (width != -1) + return width; + break; + } + default: + break; + } + + return baseStyle()->pixelMetric(m, opt, w); +} + +QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, + const QSize &csz, const QWidget *w) const +{ + RECURSION_GUARD(return baseStyle()->sizeFromContents(ct, opt, csz, w)) + + QRenderRule rule = renderRule(w, opt); + QSize sz = rule.adjustSize(csz); + + switch (ct) { + case CT_SpinBox: // ### hopelessly broken QAbstractSpinBox (part 1) + if (rule.hasBox() || !rule.hasNativeBorder()) + return csz; + return rule.baseStyleCanDraw() ? baseStyle()->sizeFromContents(ct, opt, sz, w) + : QWindowsStyle::sizeFromContents(ct, opt, sz, w); + case CT_ToolButton: + if (rule.hasBox() || !rule.hasNativeBorder() || !rule.baseStyleCanDraw()) + sz += QSize(3, 3); // ### broken QToolButton + //fall thought + case CT_ComboBox: + case CT_PushButton: + if (rule.hasBox() || !rule.hasNativeBorder()) { + if(ct == CT_ComboBox) { + //add some space for the drop down. + QRenderRule subRule = renderRule(w, opt, PseudoElement_ComboBoxDropDown); + QRect comboRect = positionRect(w, rule, subRule, PseudoElement_ComboBoxDropDown, opt->rect, opt->direction); + //+2 because there is hardcoded margins in QCommonStyle::drawControl(CE_ComboBoxLabel) + sz += QSize(comboRect.width() + 2, 0); + } + return rule.boxSize(sz); + } + sz = rule.baseStyleCanDraw() ? baseStyle()->sizeFromContents(ct, opt, sz, w) + : QWindowsStyle::sizeFromContents(ct, opt, sz, w); + return rule.boxSize(sz, Margin); + + case CT_HeaderSection: { + if (const QStyleOptionHeader *hdr = qstyleoption_cast(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection); + if (subRule.hasGeometry() || subRule.hasBox() || !subRule.hasNativeBorder()) { + sz = subRule.adjustSize(csz); + if (!subRule.hasGeometry()) { + QSize nativeContentsSize; + bool nullIcon = hdr->icon.isNull(); + int iconSize = nullIcon ? 0 : pixelMetric(QStyle::PM_SmallIconSize, hdr, w); + QSize txt = hdr->fontMetrics.size(0, hdr->text); + nativeContentsSize.setHeight(qMax(iconSize, txt.height())); + nativeContentsSize.setWidth(iconSize + txt.width()); + sz = sz.expandedTo(nativeContentsSize); + } + return subRule.size(sz); + } + return subRule.baseStyleCanDraw() ? baseStyle()->sizeFromContents(ct, opt, sz, w) + : QWindowsStyle::sizeFromContents(ct, opt, sz, w); + } + } + break; + case CT_GroupBox: + case CT_LineEdit: +#ifndef QT_NO_SPINBOX + // ### hopelessly broken QAbstractSpinBox (part 2) + if (QAbstractSpinBox *spinBox = qobject_cast(w ? w->parentWidget() : 0)) { + QRenderRule rule = renderRule(spinBox, opt); + if (rule.hasBox() || !rule.hasNativeBorder()) + return csz; + return rule.baseStyleCanDraw() ? baseStyle()->sizeFromContents(ct, opt, sz, w) + : QWindowsStyle::sizeFromContents(ct, opt, sz, w); + } +#endif + if (rule.hasBox() || !rule.hasNativeBorder()) { + return rule.boxSize(sz); + } + break; + + case CT_CheckBox: + case CT_RadioButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + if (rule.hasBox() || rule.hasBorder() || hasStyleRule(w, PseudoElement_Indicator)) { + bool isRadio = (ct == CT_RadioButton); + int iw = pixelMetric(isRadio ? PM_ExclusiveIndicatorWidth + : PM_IndicatorWidth, btn, w); + int ih = pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight + : PM_IndicatorHeight, btn, w); + + int spacing = pixelMetric(isRadio ? PM_RadioButtonLabelSpacing + : PM_CheckBoxLabelSpacing, btn, w); + sz.setWidth(sz.width() + iw + spacing); + sz.setHeight(qMax(sz.height(), ih)); + return rule.boxSize(sz); + } + } + break; + + case CT_Menu: + case CT_MenuBar: // already has everything! + case CT_ScrollBar: + if (rule.hasBox() || rule.hasBorder()) + return sz; + break; + + case CT_MenuItem: + if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { + PseudoElement pe = (mi->menuItemType == QStyleOptionMenuItem::Separator) + ? PseudoElement_MenuSeparator : PseudoElement_Item; + QRenderRule subRule = renderRule(w, opt, pe); + if ((pe == PseudoElement_MenuSeparator) && subRule.hasContentsSize()) { + return QSize(sz.width(), subRule.size().height()); + } else if ((pe == PseudoElement_Item) && (subRule.hasBox() || subRule.hasBorder())) { + int width = csz.width(); + if (mi->text.contains(QLatin1Char('\t'))) + width += 12; //as in QCommonStyle + return subRule.boxSize(subRule.adjustSize(QSize(width, csz.height()))); + } + } + break; + + case CT_Splitter: + case CT_MenuBarItem: { + PseudoElement pe = (ct == CT_Splitter) ? PseudoElement_SplitterHandle : PseudoElement_Item; + QRenderRule subRule = renderRule(w, opt, pe); + if (subRule.hasBox() || subRule.hasBorder()) + return subRule.boxSize(sz); + break; + } + + case CT_ProgressBar: + case CT_SizeGrip: + return (rule.hasContentsSize()) + ? rule.size(sz) + : rule.boxSize(baseStyle()->sizeFromContents(ct, opt, sz, w)); + break; + + case CT_Slider: + if (rule.hasBorder() || rule.hasBox() || rule.hasGeometry()) + return rule.boxSize(sz); + break; + +#ifndef QT_NO_TABBAR + case CT_TabBarTab: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTab); + if (subRule.hasBox() || !subRule.hasNativeBorder()) { + int spaceForIcon = 0; + bool vertical = false; + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + if (!tab->icon.isNull()) + spaceForIcon = 6 /* icon offset */ + 4 /* spacing */ + 2 /* magic */; // ###: hardcoded to match with common style + vertical = verticalTabs(tab->shape); + } + sz = csz + QSize(vertical ? 0 : spaceForIcon, vertical ? spaceForIcon : 0); + return subRule.boxSize(subRule.adjustSize(sz)); + } +#ifdef Q_WS_MAC + if (baseStyle()->inherits("QMacStyle")) { + //adjust the size after the call to the style because the mac style ignore the size arguments anyway. + //this might cause the (max-){width,height} property to include the native style border while they should not. + return subRule.adjustSize(baseStyle()->sizeFromContents(ct, opt, csz, w)); + } +#endif + sz = subRule.adjustSize(csz); + break; + } +#endif // QT_NO_TABBAR + + case CT_MdiControls: + if (const QStyleOptionComplex *ccOpt = qstyleoption_cast(opt)) { + if (!hasStyleRule(w, PseudoElement_MdiCloseButton) + && !hasStyleRule(w, PseudoElement_MdiNormalButton) + && !hasStyleRule(w, PseudoElement_MdiMinButton)) + break; + + QList layout = rule.styleHint(QLatin1String("button-layout")).toList(); + if (layout.isEmpty()) + layout = subControlLayout(QLatin1String("mNX")); + + int width = 0, height = 0; + for (int i = 0; i < layout.count(); i++) { + int layoutButton = layout[i].toInt(); + if (layoutButton < PseudoElement_MdiCloseButton + || layoutButton > PseudoElement_MdiNormalButton) + continue; + QStyle::SubControl sc = knownPseudoElements[layoutButton].subControl; + if (!(ccOpt->subControls & sc)) + continue; + QRenderRule subRule = renderRule(w, opt, layoutButton); + QSize sz = subRule.size(); + width += sz.width(); + height = qMax(height, sz.height()); + } + + return QSize(width, height); + } + break; + +#ifndef QT_NO_ITEMVIEWS + case CT_ItemViewItem: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_ViewItem); + sz = baseStyle()->sizeFromContents(ct, opt, csz, w); + sz = subRule.adjustSize(sz); + if (subRule.hasBox() || subRule.hasBorder()) + sz = subRule.boxSize(sz); + return sz; + } +#endif // QT_NO_ITEMVIEWS + + default: + break; + } + + return baseStyle()->sizeFromContents(ct, opt, sz, w); +} + +/*! + \internal +*/ +static QLatin1String propertyNameForStandardPixmap(QStyle::StandardPixmap sp) +{ + switch (sp) { + case QStyle::SP_TitleBarMenuButton: return QLatin1String("titlebar-menu-icon"); + case QStyle::SP_TitleBarMinButton: return QLatin1String("titlebar-minimize-icon"); + case QStyle::SP_TitleBarMaxButton: return QLatin1String("titlebar-maximize-icon"); + case QStyle::SP_TitleBarCloseButton: return QLatin1String("titlebar-close-icon"); + case QStyle::SP_TitleBarNormalButton: return QLatin1String("titlebar-normal-icon"); + case QStyle::SP_TitleBarShadeButton: return QLatin1String("titlebar-shade-icon"); + case QStyle::SP_TitleBarUnshadeButton: return QLatin1String("titlebar-unshade-icon"); + case QStyle::SP_TitleBarContextHelpButton: return QLatin1String("titlebar-contexthelp-icon"); + case QStyle::SP_DockWidgetCloseButton: return QLatin1String("dockwidget-close-icon"); + case QStyle::SP_MessageBoxInformation: return QLatin1String("messagebox-information-icon"); + case QStyle::SP_MessageBoxWarning: return QLatin1String("messagebox-warning-icon"); + case QStyle::SP_MessageBoxCritical: return QLatin1String("messagebox-critical-icon"); + case QStyle::SP_MessageBoxQuestion: return QLatin1String("messagebox-question-icon"); + case QStyle::SP_DesktopIcon: return QLatin1String("desktop-icon"); + case QStyle::SP_TrashIcon: return QLatin1String("trash-icon"); + case QStyle::SP_ComputerIcon: return QLatin1String("computer-icon"); + case QStyle::SP_DriveFDIcon: return QLatin1String("floppy-icon"); + case QStyle::SP_DriveHDIcon: return QLatin1String("harddisk-icon"); + case QStyle::SP_DriveCDIcon: return QLatin1String("cd-icon"); + case QStyle::SP_DriveDVDIcon: return QLatin1String("dvd-icon"); + case QStyle::SP_DriveNetIcon: return QLatin1String("network-icon"); + case QStyle::SP_DirOpenIcon: return QLatin1String("directory-open-icon"); + case QStyle::SP_DirClosedIcon: return QLatin1String("directory-closed-icon"); + case QStyle::SP_DirLinkIcon: return QLatin1String("directory-link-icon"); + case QStyle::SP_FileIcon: return QLatin1String("file-icon"); + case QStyle::SP_FileLinkIcon: return QLatin1String("file-link-icon"); + case QStyle::SP_FileDialogStart: return QLatin1String("filedialog-start-icon"); + case QStyle::SP_FileDialogEnd: return QLatin1String("filedialog-end-icon"); + case QStyle::SP_FileDialogToParent: return QLatin1String("filedialog-parent-directory-icon"); + case QStyle::SP_FileDialogNewFolder: return QLatin1String("filedialog-new-directory-icon"); + case QStyle::SP_FileDialogDetailedView: return QLatin1String("filedialog-detailedview-icon"); + case QStyle::SP_FileDialogInfoView: return QLatin1String("filedialog-infoview-icon"); + case QStyle::SP_FileDialogContentsView: return QLatin1String("filedialog-contentsview-icon"); + case QStyle::SP_FileDialogListView: return QLatin1String("filedialog-listview-icon"); + case QStyle::SP_FileDialogBack: return QLatin1String("filedialog-backward-icon"); + case QStyle::SP_DirIcon: return QLatin1String("directory-icon"); + case QStyle::SP_DialogOkButton: return QLatin1String("dialog-ok-icon"); + case QStyle::SP_DialogCancelButton: return QLatin1String("dialog-cancel-icon"); + case QStyle::SP_DialogHelpButton: return QLatin1String("dialog-help-icon"); + case QStyle::SP_DialogOpenButton: return QLatin1String("dialog-open-icon"); + case QStyle::SP_DialogSaveButton: return QLatin1String("dialog-save-icon"); + case QStyle::SP_DialogCloseButton: return QLatin1String("dialog-close-icon"); + case QStyle::SP_DialogApplyButton: return QLatin1String("dialog-apply-icon"); + case QStyle::SP_DialogResetButton: return QLatin1String("dialog-reset-icon"); + case QStyle::SP_DialogDiscardButton: return QLatin1String("discard-icon"); + case QStyle::SP_DialogYesButton: return QLatin1String("dialog-yes-icon"); + case QStyle::SP_DialogNoButton: return QLatin1String("dialog-no-icon"); + case QStyle::SP_ArrowUp: return QLatin1String("uparrow-icon"); + case QStyle::SP_ArrowDown: return QLatin1String("downarrow-icon"); + case QStyle::SP_ArrowLeft: return QLatin1String("leftarrow-icon"); + case QStyle::SP_ArrowRight: return QLatin1String("rightarrow-icon"); + case QStyle::SP_ArrowBack: return QLatin1String("backward-icon"); + case QStyle::SP_ArrowForward: return QLatin1String("forward-icon"); + case QStyle::SP_DirHomeIcon: return QLatin1String("home-icon"); + default: return QLatin1String(""); + } +} + +QIcon QStyleSheetStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt, + const QWidget *w) const +{ + RECURSION_GUARD(return baseStyle()->standardIcon(standardIcon, opt, w)) + QString s = propertyNameForStandardPixmap(standardIcon); + if (!s.isEmpty()) { + QRenderRule rule = renderRule(w, opt); + if (rule.hasStyleHint(s)) + return qvariant_cast(rule.styleHint(s)); + } + return baseStyle()->standardIcon(standardIcon, opt, w); +} + +QPalette QStyleSheetStyle::standardPalette() const +{ + return baseStyle()->standardPalette(); +} + +QPixmap QStyleSheetStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *w) const +{ + RECURSION_GUARD(return baseStyle()->standardPixmap(standardPixmap, opt, w)) + QString s = propertyNameForStandardPixmap(standardPixmap); + if (!s.isEmpty()) { + QRenderRule rule = renderRule(w, opt); + if (rule.hasStyleHint(s)) { + QIcon icon = qvariant_cast(rule.styleHint(s)); + return icon.pixmap(16, 16); // ###: unhard-code this if someone complains + } + } + return baseStyle()->standardPixmap(standardPixmap, opt, w); +} + +int QStyleSheetStyle::layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, + Qt::Orientation orientation, const QStyleOption *option, + const QWidget *widget) const +{ + return baseStyle()->layoutSpacing(control1, control2, orientation, option, widget); +} + +int QStyleSheetStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1 , + QSizePolicy::ControlType control2, + Qt::Orientation orientation, + const QStyleOption * option , + const QWidget * widget) const +{ + return baseStyle()->layoutSpacing(control1, control2, orientation, option, widget); +} + +int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w, + QStyleHintReturn *shret) const +{ + RECURSION_GUARD(return baseStyle()->styleHint(sh, opt, w, shret)) + // Prevent endless loop if somebody use isActiveWindow property as selector. + // QWidget::isActiveWindow uses this styleHint to determine if the window is active or not + if (sh == SH_Widget_ShareActivation) + return baseStyle()->styleHint(sh, opt, w, shret); + + QRenderRule rule = renderRule(w, opt); + QString s; + switch (sh) { + case SH_LineEdit_PasswordCharacter: s = QLatin1String("lineedit-password-character"); break; + case SH_DitherDisabledText: s = QLatin1String("dither-disabled-text"); break; + case SH_EtchDisabledText: s = QLatin1String("etch-disabled-text"); break; + case SH_ItemView_ActivateItemOnSingleClick: s = QLatin1String("activate-on-singleclick"); break; + case SH_ItemView_ShowDecorationSelected: s = QLatin1String("show-decoration-selected"); break; + case SH_Table_GridLineColor: s = QLatin1String("gridline-color"); break; + case SH_DialogButtonLayout: s = QLatin1String("button-layout"); break; + case SH_ToolTipLabel_Opacity: s = QLatin1String("opacity"); break; + case SH_ComboBox_Popup: s = QLatin1String("combobox-popup"); break; + case SH_ComboBox_ListMouseTracking: s = QLatin1String("combobox-list-mousetracking"); break; + case SH_MenuBar_AltKeyNavigation: s = QLatin1String("menubar-altkey-navigation"); break; + case SH_Menu_Scrollable: s = QLatin1String("menu-scrollable"); break; + case SH_DrawMenuBarSeparator: s = QLatin1String("menubar-separator"); break; + case SH_MenuBar_MouseTracking: s = QLatin1String("mouse-tracking"); break; + case SH_SpinBox_ClickAutoRepeatRate: s = QLatin1String("spinbox-click-autorepeat-rate"); break; + case SH_SpinControls_DisableOnBounds: s = QLatin1String("spincontrol-disable-on-bounds"); break; + case SH_MessageBox_TextInteractionFlags: s = QLatin1String("messagebox-text-interaction-flags"); break; + case SH_ToolButton_PopupDelay: s = QLatin1String("toolbutton-popup-delay"); break; + case SH_ToolBox_SelectedPageTitleBold: + if (renderRule(w, opt, PseudoElement_ToolBoxTab).hasFont) + return 0; + break; + case SH_GroupBox_TextLabelColor: + if (rule.hasPalette() && rule.palette()->foreground.style() != Qt::NoBrush) + return rule.palette()->foreground.color().rgba(); + break; + case SH_ScrollView_FrameOnlyAroundContents: s = QLatin1String("scrollview-frame-around-contents"); break; + case SH_ScrollBar_ContextMenu: s = QLatin1String("scrollbar-contextmenu"); break; + case SH_ScrollBar_LeftClickAbsolutePosition: s = QLatin1String("scrollbar-leftclick-absolute-position"); break; + case SH_ScrollBar_MiddleClickAbsolutePosition: s = QLatin1String("scrollbar-middleclick-absolute-position"); break; + case SH_ScrollBar_RollBetweenButtons: s = QLatin1String("scrollbar-roll-between-buttons"); break; + case SH_ScrollBar_ScrollWhenPointerLeavesControl: s = QLatin1String("scrollbar-scroll-when-pointer-leaves-control"); break; + case SH_TabBar_Alignment: +#ifndef QT_NO_TABWIDGET + if (qobject_cast(w)) { + rule = renderRule(w, opt, PseudoElement_TabWidgetTabBar); + if (rule.hasPosition()) + return rule.position()->position; + } +#endif // QT_NO_TABWIDGET + s = QLatin1String("alignment"); + break; +#ifndef QT_NO_TABBAR + case SH_TabBar_CloseButtonPosition: + rule = renderRule(w, opt, PseudoElement_TabBarTabCloseButton); + if (rule.hasPosition()) { + Qt::Alignment align = rule.position()->position; + if (align & Qt::AlignLeft || align & Qt::AlignTop) + return QTabBar::LeftSide; + if (align & Qt::AlignRight || align & Qt::AlignBottom) + return QTabBar::RightSide; + } + break; +#endif + case SH_TabBar_ElideMode: s = QLatin1String("tabbar-elide-mode"); break; + case SH_TabBar_PreferNoArrows: s = QLatin1String("tabbar-prefer-no-arrows"); break; + case SH_ComboBox_PopupFrameStyle: +#ifndef QT_NO_COMBOBOX + if (qobject_cast(w)) { + QAbstractItemView *view = w->findChild(); + if (view) { + view->ensurePolished(); + QRenderRule subRule = renderRule(view, PseudoElement_None); + if (subRule.hasBox() || !subRule.hasNativeBorder()) + return QFrame::NoFrame; + } + } +#endif // QT_NO_COMBOBOX + break; + case SH_DialogButtonBox_ButtonsHaveIcons: s = QLatin1String("dialogbuttonbox-buttons-have-icons"); break; + case SH_Workspace_FillSpaceOnMaximize: s = QLatin1String("mdi-fill-space-on-maximize"); break; + case SH_TitleBar_NoBorder: + if (rule.hasBorder()) + return !rule.border()->borders[LeftEdge]; + break; + case SH_TitleBar_AutoRaise: { // plain absurd + QRenderRule subRule = renderRule(w, opt, PseudoElement_TitleBar); + if (subRule.hasDrawable()) + return 1; + break; + } + case SH_ItemView_ArrowKeysNavigateIntoChildren: s = QLatin1String("arrow-keys-navigate-into-children"); break; + case SH_ItemView_PaintAlternatingRowColorsForEmptyArea: s = QLatin1String("paint-alternating-row-colors-for-empty-area"); break; + default: break; + } + if (!s.isEmpty() && rule.hasStyleHint(s)) { + return rule.styleHint(s).toInt(); + } + + return baseStyle()->styleHint(sh, opt, w, shret); +} + +QRect QStyleSheetStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, + const QWidget *w) const +{ + RECURSION_GUARD(return baseStyle()->subControlRect(cc, opt, sc, w)) + + QRenderRule rule = renderRule(w, opt); + switch (cc) { + case CC_ComboBox: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { + if (rule.hasBox() || !rule.hasNativeBorder()) { + switch (sc) { + case SC_ComboBoxFrame: return rule.borderRect(opt->rect); + case SC_ComboBoxEditField: + { + QRenderRule subRule = renderRule(w, opt, PseudoElement_ComboBoxDropDown); + QRect r = rule.contentsRect(opt->rect); + QRect r2 = positionRect(w, rule, subRule, PseudoElement_ComboBoxDropDown, + opt->rect, opt->direction); + if (subRule.hasPosition() && subRule.position()->position & Qt::AlignLeft) { + return visualRect(opt->direction, r, r.adjusted(r2.width(),0,0,0)); + } else { + return visualRect(opt->direction, r, r.adjusted(0,0,-r2.width(),0)); + } + } + case SC_ComboBoxArrow: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_ComboBoxDropDown); + return positionRect(w, rule, subRule, PseudoElement_ComboBoxDropDown, opt->rect, opt->direction); + } + case SC_ComboBoxListBoxPopup: + default: + return baseStyle()->subControlRect(cc, opt, sc, w); + } + } + + QStyleOptionComboBox comboBox(*cb); + comboBox.rect = rule.borderRect(opt->rect); + return rule.baseStyleCanDraw() ? baseStyle()->subControlRect(cc, &comboBox, sc, w) + : QWindowsStyle::subControlRect(cc, &comboBox, sc, w); + } + break; + +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spin = qstyleoption_cast(opt)) { + QRenderRule upRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton); + QRenderRule downRule = renderRule(w, opt, PseudoElement_SpinBoxDownButton); + bool ruleMatch = rule.hasBox() || !rule.hasNativeBorder(); + bool upRuleMatch = upRule.hasGeometry() || upRule.hasPosition(); + bool downRuleMatch = downRule.hasGeometry() || upRule.hasPosition(); + if (ruleMatch || upRuleMatch || downRuleMatch) { + switch (sc) { + case SC_SpinBoxFrame: + return rule.borderRect(opt->rect); + case SC_SpinBoxEditField: + { + QRect r = rule.contentsRect(opt->rect); + // Use the widest button on each side to determine edit field size. + Qt::Alignment upAlign, downAlign; + + upAlign = upRule.hasPosition() ? upRule.position()->position + : Qt::Alignment(Qt::AlignRight); + upAlign = resolveAlignment(opt->direction, upAlign); + + downAlign = downRule.hasPosition() ? downRule.position()->position + : Qt::Alignment(Qt::AlignRight); + downAlign = resolveAlignment(opt->direction, downAlign); + + int upSize = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w).width(); + int downSize = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w).width(); + int widestL = qMax((upAlign & Qt::AlignLeft) ? upSize : 0, + (downAlign & Qt::AlignLeft) ? downSize : 0); + int widestR = qMax((upAlign & Qt::AlignRight) ? upSize : 0, + (downAlign & Qt::AlignRight) ? downSize : 0); + r.setRight(r.right() - widestR); + r.setLeft(r.left() + widestL); + return r; + } + case SC_SpinBoxDown: + if (downRuleMatch) + return positionRect(w, rule, downRule, PseudoElement_SpinBoxDownButton, + opt->rect, opt->direction); + break; + case SC_SpinBoxUp: + if (upRuleMatch) + return positionRect(w, rule, upRule, PseudoElement_SpinBoxUpButton, + opt->rect, opt->direction); + break; + default: + break; + } + + return baseStyle()->subControlRect(cc, opt, sc, w); + } + + QStyleOptionSpinBox spinBox(*spin); + spinBox.rect = rule.borderRect(opt->rect); + return rule.baseStyleCanDraw() ? baseStyle()->subControlRect(cc, &spinBox, sc, w) + : QWindowsStyle::subControlRect(cc, &spinBox, sc, w); + } + break; +#endif // QT_NO_SPINBOX + + case CC_GroupBox: + if (const QStyleOptionGroupBox *gb = qstyleoption_cast(opt)) { + switch (sc) { + case SC_GroupBoxFrame: + case SC_GroupBoxContents: { + if (rule.hasBox() || !rule.hasNativeBorder()) { + return sc == SC_GroupBoxFrame ? rule.borderRect(opt->rect) + : rule.contentsRect(opt->rect); + } + QStyleOptionGroupBox groupBox(*gb); + groupBox.rect = rule.borderRect(opt->rect); + return baseStyle()->subControlRect(cc, &groupBox, sc, w); + } + default: + case SC_GroupBoxLabel: + case SC_GroupBoxCheckBox: { + QRenderRule indRule = renderRule(w, opt, PseudoElement_GroupBoxIndicator); + QRenderRule labelRule = renderRule(w, opt, PseudoElement_GroupBoxTitle); + if (!labelRule.hasPosition() && !labelRule.hasGeometry() && !labelRule.hasBox() + && !labelRule.hasBorder() && !indRule.hasContentsSize()) { + QStyleOptionGroupBox groupBox(*gb); + groupBox.rect = rule.borderRect(opt->rect); + return baseStyle()->subControlRect(cc, &groupBox, sc, w); + } + int tw = opt->fontMetrics.width(gb->text); + int th = opt->fontMetrics.height(); + int spacing = pixelMetric(QStyle::PM_CheckBoxLabelSpacing, opt, w); + int iw = pixelMetric(QStyle::PM_IndicatorWidth, opt, w); + int ih = pixelMetric(QStyle::PM_IndicatorHeight, opt, w); + + if (gb->subControls & QStyle::SC_GroupBoxCheckBox) { + tw = tw + iw + spacing; + th = qMax(th, ih); + } + if (!labelRule.hasGeometry()) { + labelRule.geo = new QStyleSheetGeometryData(tw, th, tw, th, -1, -1); + } else { + labelRule.geo->width = tw; + labelRule.geo->height = th; + } + if (!labelRule.hasPosition()) { + labelRule.p = new QStyleSheetPositionData(0, 0, 0, 0, defaultOrigin(PseudoElement_GroupBoxTitle), + gb->textAlignment, PositionMode_Static); + } + QRect r = positionRect(w, rule, labelRule, PseudoElement_GroupBoxTitle, + opt->rect, opt->direction); + if (gb->subControls & SC_GroupBoxCheckBox) { + r = labelRule.contentsRect(r); + if (sc == SC_GroupBoxLabel) { + r.setLeft(r.left() + iw + spacing); + r.setTop(r.center().y() - th/2); + } else { + r = QRect(r.left(), r.center().y() - ih/2, iw, ih); + } + return r; + } else { + return labelRule.contentsRect(r); + } + } + } // switch + } + break; + + case CC_ToolButton: + if (const QStyleOptionToolButton *tb = qstyleoption_cast(opt)) { + if (rule.hasBox() || !rule.hasNativeBorder()) { + switch (sc) { + case SC_ToolButton: return rule.borderRect(opt->rect); + case SC_ToolButtonMenu: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_ToolButtonMenu); + return positionRect(w, rule, subRule, PseudoElement_ToolButtonMenu, opt->rect, opt->direction); + } + default: + break; + } + } + + QStyleOptionToolButton tool(*tb); + tool.rect = rule.borderRect(opt->rect); + return rule.baseStyleCanDraw() ? baseStyle()->subControlRect(cc, &tool, sc, w) + : QWindowsStyle::subControlRect(cc, &tool, sc, w); + } + break; + +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + if (const QStyleOptionSlider *sb = qstyleoption_cast(opt)) { + QStyleOptionSlider styleOptionSlider(*sb); + styleOptionSlider.rect = rule.borderRect(opt->rect); + if (rule.hasDrawable() || rule.hasBox()) { + QRect grooveRect; + if (!rule.hasBox()) { + grooveRect = rule.baseStyleCanDraw() ? baseStyle()->subControlRect(cc, sb, SC_ScrollBarGroove, w) + : QWindowsStyle::subControlRect(cc, sb, SC_ScrollBarGroove, w); + } else { + grooveRect = rule.contentsRect(opt->rect); + } + + PseudoElement pe = PseudoElement_None; + + switch (sc) { + case SC_ScrollBarGroove: + return grooveRect; + case SC_ScrollBarAddPage: + case SC_ScrollBarSubPage: + case SC_ScrollBarSlider: { + QRect contentRect = grooveRect; + if (hasStyleRule(w, PseudoElement_ScrollBarSlider)) { + QRenderRule sliderRule = renderRule(w, opt, PseudoElement_ScrollBarSlider); + Origin origin = sliderRule.hasPosition() ? sliderRule.position()->origin : defaultOrigin(PseudoElement_ScrollBarSlider); + contentRect = rule.originRect(opt->rect, origin); + } + int maxlen = (styleOptionSlider.orientation == Qt::Horizontal) ? contentRect.width() : contentRect.height(); + int sliderlen; + if (sb->maximum != sb->minimum) { + uint range = sb->maximum - sb->minimum; + sliderlen = (qint64(sb->pageStep) * maxlen) / (range + sb->pageStep); + + int slidermin = pixelMetric(PM_ScrollBarSliderMin, sb, w); + if (sliderlen < slidermin || range > INT_MAX / 2) + sliderlen = slidermin; + if (sliderlen > maxlen) + sliderlen = maxlen; + } else { + sliderlen = maxlen; + } + + int sliderstart = (styleOptionSlider.orientation == Qt::Horizontal ? contentRect.left() : contentRect.top()) + + sliderPositionFromValue(sb->minimum, sb->maximum, sb->sliderPosition, + maxlen - sliderlen, sb->upsideDown); + + QRect sr = (sb->orientation == Qt::Horizontal) + ? QRect(sliderstart, contentRect.top(), sliderlen, contentRect.height()) + : QRect(contentRect.left(), sliderstart, contentRect.width(), sliderlen); + if (sc == SC_ScrollBarSlider) { + return sr; + } else if (sc == SC_ScrollBarSubPage) { + return QRect(contentRect.topLeft(), sb->orientation == Qt::Horizontal ? sr.bottomLeft() : sr.topRight()); + } else { // SC_ScrollBarAddPage + return QRect(sb->orientation == Qt::Horizontal ? sr.topRight() : sr.bottomLeft(), contentRect.bottomRight()); + } + break; + } + case SC_ScrollBarAddLine: pe = PseudoElement_ScrollBarAddLine; break; + case SC_ScrollBarSubLine: pe = PseudoElement_ScrollBarSubLine; break; + case SC_ScrollBarFirst: pe = PseudoElement_ScrollBarFirst; break; + case SC_ScrollBarLast: pe = PseudoElement_ScrollBarLast; break; + default: break; + } + if (hasStyleRule(w,pe)) { + QRenderRule subRule = renderRule(w, opt, pe); + if (subRule.hasPosition() || subRule.hasGeometry() || subRule.hasBox()) { + const QStyleSheetPositionData *pos = subRule.position(); + QRect originRect = grooveRect; + if (rule.hasBox()) { + Origin origin = (pos && pos->origin != Origin_Unknown) ? pos->origin : defaultOrigin(pe); + originRect = rule.originRect(opt->rect, origin); + } + return positionRect(w, subRule, pe, originRect, styleOptionSlider.direction); + } + } + } + return rule.baseStyleCanDraw() ? baseStyle()->subControlRect(cc, &styleOptionSlider, sc, w) + : QWindowsStyle::subControlRect(cc, &styleOptionSlider, sc, w); + } + break; +#endif // QT_NO_SCROLLBAR + +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_SliderGroove); + if (!subRule.hasDrawable()) + break; + subRule.img = 0; + QRect gr = positionRect(w, rule, subRule, PseudoElement_SliderGroove, opt->rect, opt->direction); + switch (sc) { + case SC_SliderGroove: + return gr; + case SC_SliderHandle: { + bool horizontal = slider->orientation & Qt::Horizontal; + QRect cr = subRule.contentsRect(gr); + QRenderRule subRule2 = renderRule(w, opt, PseudoElement_SliderHandle); + int len = horizontal ? subRule2.size().width() : subRule2.size().height(); + subRule2.img = 0; + subRule2.geo = 0; + cr = positionRect(w, subRule2, PseudoElement_SliderHandle, cr, opt->direction); + int thickness = horizontal ? cr.height() : cr.width(); + int sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum, slider->sliderPosition, + (horizontal ? cr.width() : cr.height()) - len, slider->upsideDown); + cr = horizontal ? QRect(cr.x() + sliderPos, cr.y(), len, thickness) + : QRect(cr.x(), cr.y() + sliderPos, thickness, len); + return subRule2.borderRect(cr); + break; } + case SC_SliderTickmarks: + // TODO... + default: + break; + } + } + break; +#endif // QT_NO_SLIDER + + case CC_MdiControls: + if (hasStyleRule(w, PseudoElement_MdiCloseButton) + || hasStyleRule(w, PseudoElement_MdiNormalButton) + || hasStyleRule(w, PseudoElement_MdiMinButton)) { + QList layout = rule.styleHint(QLatin1String("button-layout")).toList(); + if (layout.isEmpty()) + layout = subControlLayout(QLatin1String("mNX")); + + int x = 0, width = 0; + QRenderRule subRule; + for (int i = 0; i < layout.count(); i++) { + int layoutButton = layout[i].toInt(); + if (layoutButton < PseudoElement_MdiCloseButton + || layoutButton > PseudoElement_MdiNormalButton) + continue; + QStyle::SubControl control = knownPseudoElements[layoutButton].subControl; + if (!(opt->subControls & control)) + continue; + subRule = renderRule(w, opt, layoutButton); + width = subRule.size().width(); + if (sc == control) + break; + x += width; + } + + return subRule.borderRect(QRect(x, opt->rect.top(), width, opt->rect.height())); + } + break; + + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_TitleBar); + if (!subRule.hasDrawable() && !subRule.hasBox() && !subRule.hasBorder()) + break; + QHash layoutRects = titleBarLayout(w, tb); + return layoutRects.value(sc); + } + break; + + default: + break; + } + + return baseStyle()->subControlRect(cc, opt, sc, w); +} + +QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, const QWidget *w) const +{ + RECURSION_GUARD(return baseStyle()->subElementRect(se, opt, w)) + + QRenderRule rule = renderRule(w, opt); +#ifndef QT_NO_TABBAR + int pe = PseudoElement_None; +#endif + + switch (se) { + case SE_PushButtonContents: + case SE_PushButtonFocusRect: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + QStyleOptionButton btnOpt(*btn); + if (rule.hasBox() || !rule.hasNativeBorder()) + return visualRect(opt->direction, opt->rect, rule.contentsRect(opt->rect)); + return rule.baseStyleCanDraw() ? baseStyle()->subElementRect(se, &btnOpt, w) + : QWindowsStyle::subElementRect(se, &btnOpt, w); + } + break; + + case SE_LineEditContents: + case SE_FrameContents: + case SE_ShapedFrameContents: + if (rule.hasBox() || !rule.hasNativeBorder()) { + return visualRect(opt->direction, opt->rect, rule.contentsRect(opt->rect)); + } + break; + + case SE_CheckBoxIndicator: + case SE_RadioButtonIndicator: + if (rule.hasBox() || rule.hasBorder() || hasStyleRule(w, PseudoElement_Indicator)) { + PseudoElement pe = se == SE_CheckBoxIndicator ? PseudoElement_Indicator : PseudoElement_ExclusiveIndicator; + QRenderRule subRule = renderRule(w, opt, pe); + return positionRect(w, rule, subRule, pe, opt->rect, opt->direction); + } + break; + + case SE_CheckBoxContents: + case SE_RadioButtonContents: + if (rule.hasBox() || rule.hasBorder() || hasStyleRule(w, PseudoElement_Indicator)) { + bool isRadio = se == SE_RadioButtonContents; + QRect ir = subElementRect(isRadio ? SE_RadioButtonIndicator : SE_CheckBoxIndicator, + opt, w); + ir = visualRect(opt->direction, opt->rect, ir); + int spacing = pixelMetric(isRadio ? PM_RadioButtonLabelSpacing : PM_CheckBoxLabelSpacing, 0, w); + QRect cr = rule.contentsRect(opt->rect); + ir.setRect(ir.left() + ir.width() + spacing, cr.y(), + cr.width() - ir.width() - spacing, cr.height()); + return visualRect(opt->direction, opt->rect, ir); + } + break; + + case SE_ToolBoxTabContents: + if (w && hasStyleRule(w->parentWidget(), PseudoElement_ToolBoxTab)) { + QRenderRule subRule = renderRule(w->parentWidget(), opt, PseudoElement_ToolBoxTab); + return visualRect(opt->direction, opt->rect, subRule.contentsRect(opt->rect)); + } + break; + + case SE_RadioButtonFocusRect: + case SE_RadioButtonClickRect: // focusrect | indicator + if (rule.hasBox() || rule.hasBorder() || hasStyleRule(w, PseudoElement_Indicator)) { + return opt->rect; + } + break; + + case SE_CheckBoxFocusRect: + case SE_CheckBoxClickRect: // relies on indicator and contents + return ParentStyle::subElementRect(se, opt, w); + +#ifndef QT_NO_ITEMVIEWS + case SE_ViewItemCheckIndicator: + if (!qstyleoption_cast(opt)) { + return subElementRect(SE_CheckBoxIndicator, opt, w); + } + // intentionally falls through + case SE_ItemViewItemText: + case SE_ItemViewItemDecoration: + case SE_ItemViewItemFocusRect: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_ViewItem); + PseudoElement pe = PseudoElement_None; + if (se == SE_ItemViewItemText || se == SE_ItemViewItemFocusRect) + pe = PseudoElement_ViewItemText; + else if (se == SE_ItemViewItemDecoration && vopt->features & QStyleOptionViewItemV2::HasDecoration) + pe = PseudoElement_ViewItemIcon; + else if (se == SE_ItemViewItemCheckIndicator && vopt->features & QStyleOptionViewItemV2::HasCheckIndicator) + pe = PseudoElement_ViewItemIndicator; + else + break; + if (subRule.hasGeometry() || subRule.hasBox() || !subRule.hasNativeBorder() || hasStyleRule(w, pe)) { + QRenderRule subRule2 = renderRule(w, opt, pe); + QStyleOptionViewItemV4 optCopy(*vopt); + optCopy.rect = subRule.contentsRect(vopt->rect); + QRect rect = ParentStyle::subElementRect(se, &optCopy, w); + return positionRect(w, subRule2, pe, rect, opt->direction); + } + } + break; +#endif // QT_NO_ITEMVIEWS + + case SE_HeaderArrow: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewUpArrow); + if (subRule.hasPosition() || subRule.hasGeometry()) + return positionRect(w, rule, subRule, PseudoElement_HeaderViewUpArrow, opt->rect, opt->direction); + } + break; + + case SE_HeaderLabel: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection); + if (subRule.hasBox() || !subRule.hasNativeBorder()) + return subRule.contentsRect(opt->rect); + } + break; + + case SE_ProgressBarGroove: + case SE_ProgressBarContents: + case SE_ProgressBarLabel: + if (const QStyleOptionProgressBarV2 *pb = qstyleoption_cast(opt)) { + if (rule.hasBox() || !rule.hasNativeBorder() || rule.hasPosition() || hasStyleRule(w, PseudoElement_ProgressBarChunk)) { + if (se == SE_ProgressBarGroove) + return rule.borderRect(pb->rect); + else if (se == SE_ProgressBarContents) + return rule.contentsRect(pb->rect); + + QSize sz = pb->fontMetrics.size(0, pb->text); + return QStyle::alignedRect(Qt::LeftToRight, rule.hasPosition() ? rule.position()->textAlignment : pb->textAlignment, + sz, pb->rect); + } + } + break; + +#ifndef QT_NO_TABBAR + case SE_TabWidgetLeftCorner: + pe = PseudoElement_TabWidgetLeftCorner; + // intentionally falls through + case SE_TabWidgetRightCorner: + if (pe == PseudoElement_None) + pe = PseudoElement_TabWidgetRightCorner; + // intentionally falls through + case SE_TabWidgetTabBar: + if (pe == PseudoElement_None) + pe = PseudoElement_TabWidgetTabBar; + // intentionally falls through + case SE_TabWidgetTabPane: + case SE_TabWidgetTabContents: + if (pe == PseudoElement_None) + pe = PseudoElement_TabWidgetPane; + + if (hasStyleRule(w, pe)) { + QRect r = QWindowsStyle::subElementRect(pe == PseudoElement_TabWidgetPane ? SE_TabWidgetTabPane : se, opt, w); + QRenderRule subRule = renderRule(w, opt, pe); + r = positionRect(w, subRule, pe, r, opt->direction); + if (pe == PseudoElement_TabWidgetTabBar) { + Q_ASSERT(opt); + r = opt->rect.intersected(r); + } + if (se == SE_TabWidgetTabContents) + r = subRule.contentsRect(r); + return r; + } + break; + + case SE_TabBarTearIndicator: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTear); + if (subRule.hasContentsSize()) { + QRect r; + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + switch (tab->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + r.setRect(tab->rect.left(), tab->rect.top(), subRule.size().width(), opt->rect.height()); + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + r.setRect(tab->rect.left(), tab->rect.top(), opt->rect.width(), subRule.size().height()); + break; + default: + break; + } + r = visualRect(opt->direction, opt->rect, r); + } + return r; + } + break; + } + case SE_TabBarTabText: + case SE_TabBarTabLeftButton: + case SE_TabBarTabRightButton: { + QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTab); + if (subRule.hasBox() || !subRule.hasNativeBorder()) { + return ParentStyle::subElementRect(se, opt, w); + } + break; + } +#endif // QT_NO_TABBAR + + case SE_DockWidgetCloseButton: + case SE_DockWidgetFloatButton: { + PseudoElement pe = (se == SE_DockWidgetCloseButton) ? PseudoElement_DockWidgetCloseButton : PseudoElement_DockWidgetFloatButton; + QRenderRule subRule2 = renderRule(w, opt, pe); + if (!subRule2.hasPosition()) + break; + QRenderRule subRule = renderRule(w, opt, PseudoElement_DockWidgetTitle); + return positionRect(w, subRule, subRule2, pe, opt->rect, opt->direction); + } + +#ifndef QT_NO_TOOLBAR + case SE_ToolBarHandle: + if (hasStyleRule(w, PseudoElement_ToolBarHandle)) + return ParentStyle::subElementRect(se, opt, w); + break; +#endif //QT_NO_TOOLBAR + + default: + break; + } + + return baseStyle()->subElementRect(se, opt, w); +} + +bool QStyleSheetStyle::event(QEvent *e) +{ + return (baseStyle()->event(e) && e->isAccepted()) || ParentStyle::event(e); +} + +void QStyleSheetStyle::updateStyleSheetFont(QWidget* w) const +{ + QWidget *container = containerWidget(w); + QRenderRule rule = renderRule(container, PseudoElement_None, + PseudoClass_Active | PseudoClass_Enabled | extendedPseudoClass(container)); + QFont font = rule.font.resolve(w->font()); + + if ((!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation)) + && isNaturalChild(w) && qobject_cast(w->parent())) { + + font = font.resolve(static_cast(w->parent())->font()); + } + + if (w->data->fnt == font) + return; + +#ifdef QT3_SUPPORT + QFont old = w->data->fnt; +#endif + w->data->fnt = font; +#if defined(Q_WS_X11) + // make sure the font set on this widget is associated with the correct screen + //w->data->fnt.x11SetScreen(w->d_func()->xinfo.screen()); +#endif + + QEvent e(QEvent::FontChange); + QApplication::sendEvent(w, &e); +#ifdef QT3_SUPPORT + w->fontChange(old); +#endif +} + +void QStyleSheetStyle::saveWidgetFont(QWidget* w, const QFont& font) const +{ + w->setProperty("_q_styleSheetWidgetFont", font); +} + +void QStyleSheetStyle::clearWidgetFont(QWidget* w) const +{ + w->setProperty("_q_styleSheetWidgetFont", QVariant(QVariant::Invalid)); +} + +// Polish palette that should be used for a particular widget, with particular states +// (eg. :focus, :hover, ...) +// this is called by widgets that paint themself in their paint event +// Returns true if there is a new palette in pal. +bool QStyleSheetStyle::styleSheetPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal) +{ + if (!w || !opt || !pal) + return false; + + RECURSION_GUARD(return false) + + w = containerWidget(w); + + QRenderRule rule = renderRule(w, PseudoElement_None, pseudoClass(opt->state) | extendedPseudoClass(w)); + if (!rule.hasPalette()) + return false; + + rule.configurePalette(pal, QPalette::NoRole, QPalette::NoRole); + return true; +} + +Qt::Alignment QStyleSheetStyle::resolveAlignment(Qt::LayoutDirection layDir, Qt::Alignment src) +{ + if (layDir == Qt::LeftToRight || src & Qt::AlignAbsolute) + return src; + + if (src & Qt::AlignLeft) { + src &= ~Qt::AlignLeft; + src |= Qt::AlignRight; + } else if (src & Qt::AlignRight) { + src &= ~Qt::AlignRight; + src |= Qt::AlignLeft; + } + src |= Qt::AlignAbsolute; + return src; +} + +// Returns whether the given QWidget has a "natural" parent, meaning that +// the parent contains this child as part of its normal operation. +// An example is the QTabBar inside a QTabWidget. +// This does not mean that any QTabBar which is a child of QTabWidget will +// match, only the one that was created by the QTabWidget initialization +// (and hence has the correct object name). +bool QStyleSheetStyle::isNaturalChild(const QWidget *w) +{ + if (w->objectName().startsWith(QLatin1String("qt_"))) + return true; + + return false; +} + +QT_END_NAMESPACE + +#include "moc_qstylesheetstyle_p.cpp" + +#endif // QT_NO_STYLE_STYLESHEET diff --git a/src/widgets/styles/qstylesheetstyle_default.cpp b/src/widgets/styles/qstylesheetstyle_default.cpp new file mode 100644 index 0000000000..76ffac8187 --- /dev/null +++ b/src/widgets/styles/qstylesheetstyle_default.cpp @@ -0,0 +1,512 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* This is the default Qt style sheet. + + IMPORTANT: This style sheet is primarily meant for defining feature + capablities of styles. Do NOT add default styling rules here. When in + doubt ask the stylesheet maintainer. + + The stylesheet in here used to be in a CSS file, but was moved here to + avoid parsing overhead. +*/ + +#include "private/qcssparser_p.h" +#include "qstylesheetstyle_p.h" + +#ifndef QT_NO_STYLE_STYLESHEET + +QT_BEGIN_NAMESPACE + +using namespace QCss; + +// This is the class name of the selector. +// Use an empty string where you would use '*' in CSS. +// Ex. QHeaderView + +#define SET_ELEMENT_NAME(x) \ + bSelector.elementName = (x) + +// This acts as both pseudo state and sub control. The first parameter is the +// string name, and the second is the PseudoClass_* constant. +// The sub control specifier is always the first, and has the type +// PseudoClass_Unknown. +// If there is no PseudoClass_Unknown as the first pseudo, it is assumed to be +// a pseudo state. +// Ex. QComboBox::drop-down:enabled +// ^ ^ + +#define ADD_PSEUDO(x, y) \ + pseudo.type = (y); \ + pseudo.name = (x); \ + bSelector.pseudos << pseudo + +// This is attributes. The third parameter is AttributeSelector::* +// Ex. QComboBox[style="QWindowsXPStyle"] +// ^ ^ + +#define ADD_ATTRIBUTE_SELECTOR(x, y, z) \ + attr.name = (x); \ + attr.value = (y); \ + attr.valueMatchCriterium = (z); \ + bSelector.attributeSelectors << attr + +// Adds the current basic selector to the rule. +// Several basic selectors behave as AND (space in CSS). + +#define ADD_BASIC_SELECTOR \ + selector.basicSelectors << bSelector; \ + bSelector.ids.clear(); \ + bSelector.pseudos.clear(); \ + bSelector.attributeSelectors.clear() + +// Adds the current selector to the rule. +// Several selectors behave as OR (comma in CSS). + +#define ADD_SELECTOR \ + styleRule.selectors << selector; \ + selector.basicSelectors.clear() + +// Sets the name of a property. +// Ex. background: red; +// ^ + +#define SET_PROPERTY(x, y) \ + decl.d->property = (x); \ + decl.d->propertyId = (y) + +// Adds a value to the current property. +// The first parameter should be Value::KnownIdentifier if the value can be +// found among the Value_* constants, in which case the second should be that +// constant. Otherwise the first parameter is Value::Identifier and the second +// is a string. +// Adding more values is the same as seperating by spaces in CSS. +// Ex. border: 2px solid black; +// ^ ^ ^ + +#define ADD_VALUE(x, y) \ + value.type = (x); \ + value.variant = (y); \ + decl.d->values << value + +// Adds the current declaration to the rule. +// Ex. border: 2px solid black; +// \----------------------/ + +#define ADD_DECLARATION \ + styleRule.declarations << decl; \ + decl.d.detach(); \ + decl.d->values.clear() + +// Adds the rule to the stylesheet. +// Use at the end of every CSS block. + +#define ADD_STYLE_RULE \ + sheet.styleRules << styleRule; \ + styleRule.selectors.clear(); \ + styleRule.declarations.clear() + +StyleSheet QStyleSheetStyle::getDefaultStyleSheet() const +{ + StyleSheet sheet; + StyleRule styleRule; + BasicSelector bSelector; + Selector selector; + Declaration decl; + QCss::Value value; + Pseudo pseudo; + AttributeSelector attr; + + // pixmap based style doesn't support any features + bool styleIsPixmapBased = baseStyle()->inherits("QMacStyle") + || baseStyle()->inherits("QWindowsXPStyle") + || baseStyle()->inherits("QGtkStyle") + || baseStyle()->inherits("QS60Style"); + + + /*QLineEdit { + -qt-background-role: base; + border: native; + -qt-style-features: background-color; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QLineEdit")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("-qt-background-role"), QtBackgroundRole); + ADD_VALUE(Value::KnownIdentifier, Value_Base); + ADD_DECLARATION; + + SET_PROPERTY(QLatin1String("border"), Border); + ADD_VALUE(Value::KnownIdentifier, Value_Native); + ADD_DECLARATION; + + SET_PROPERTY(QLatin1String("-qt-style-features"), QtStyleFeatures); + ADD_VALUE(Value::Identifier, QString::fromLatin1("background-color")); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QLineEdit:no-frame { + border: none; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QLineEdit")); + ADD_PSEUDO(QLatin1String("no-frame"), PseudoClass_Frameless); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("border"), Border); + ADD_VALUE(Value::KnownIdentifier, Value_None); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QFrame { + border: native; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QFrame")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("border"), Border); + ADD_VALUE(Value::KnownIdentifier, Value_Native); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QLabel, QToolBox { + background: none; + border-image: none; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QLabel")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_ELEMENT_NAME(QLatin1String("QToolBox")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("background"), Background); + ADD_VALUE(Value::KnownIdentifier, Value_None); + ADD_DECLARATION; + + SET_PROPERTY(QLatin1String("border-image"), BorderImage); + ADD_VALUE(Value::KnownIdentifier, Value_None); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QGroupBox { + border: native; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QGroupBox")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("border"), Border); + ADD_VALUE(Value::KnownIdentifier, Value_Native); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + + /*QToolTip { + -qt-background-role: window; + border: native; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QToolTip")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("-qt-background-role"), QtBackgroundRole); + ADD_VALUE(Value::KnownIdentifier, Value_Window); + ADD_DECLARATION; + + SET_PROPERTY(QLatin1String("border"), Border); + ADD_VALUE(Value::KnownIdentifier, Value_Native); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QPushButton, QToolButton { + border-style: native; + -qt-style-features: background-color; //only for not pixmap based styles + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QPushButton")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_ELEMENT_NAME(QLatin1String("QToolButton")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("border-style"), BorderStyles); + ADD_VALUE(Value::KnownIdentifier, Value_Native); + ADD_DECLARATION; + + if (!styleIsPixmapBased) { + SET_PROPERTY(QLatin1String("-qt-style-features"), QtStyleFeatures); + ADD_VALUE(Value::Identifier, QString::fromLatin1("background-color")); + ADD_DECLARATION; + } + + + ADD_STYLE_RULE; + } + + + /*QComboBox { + border: native; + -qt-style-features: background-color background-gradient; //only for not pixmap based styles + -qt-background-role: base; + }*/ + + { + SET_ELEMENT_NAME(QLatin1String("QComboBox")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("border"), Border); + ADD_VALUE(Value::KnownIdentifier, Value_Native); + ADD_DECLARATION; + + if (!styleIsPixmapBased) { + SET_PROPERTY(QLatin1String("-qt-style-features"), QtStyleFeatures); + ADD_VALUE(Value::Identifier, QString::fromLatin1("background-color")); + ADD_VALUE(Value::Identifier, QString::fromLatin1("background-gradient")); + ADD_DECLARATION; + } + + SET_PROPERTY(QLatin1String("-qt-background-role"), QtBackgroundRole); + ADD_VALUE(Value::KnownIdentifier, Value_Base); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QComboBox[style="QPlastiqueStyle"][readOnly="true"], + QComboBox[style="QCleanlooksStyle"][readOnly="true"] + { + -qt-background-role: button; + }*/ + if (baseStyle()->inherits("QPlastiqueStyle") || baseStyle()->inherits("QCleanlooksStyle")) + { + SET_ELEMENT_NAME(QLatin1String("QComboBox")); + ADD_ATTRIBUTE_SELECTOR(QLatin1String("readOnly"), QLatin1String("true"), AttributeSelector::MatchEqual); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("-qt-background-role"), QtBackgroundRole); + ADD_VALUE(Value::KnownIdentifier, Value_Button); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QAbstractSpinBox { + border: native; + -qt-style-features: background-color; + -qt-background-role: base; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QAbstractSpinBox")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("border"), Border); + ADD_VALUE(Value::KnownIdentifier, Value_Native); + ADD_DECLARATION; + + SET_PROPERTY(QLatin1String("-qt-style-features"), QtStyleFeatures); + ADD_VALUE(Value::Identifier, QString::fromLatin1("background-color")); + ADD_DECLARATION; + + SET_PROPERTY(QLatin1String("-qt-background-role"), QtBackgroundRole); + ADD_VALUE(Value::KnownIdentifier, Value_Base); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QMenu { + -qt-background-role: window; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QMenu")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("-qt-background-role"), QtBackgroundRole); + ADD_VALUE(Value::KnownIdentifier, Value_Window); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + /*QMenu::item { + -qt-style-features: background-color; + }*/ + if (!styleIsPixmapBased) { + SET_ELEMENT_NAME(QLatin1String("QMenu")); + ADD_PSEUDO(QLatin1String("item"), PseudoClass_Unknown); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("-qt-style-features"), QtStyleFeatures); + ADD_VALUE(Value::Identifier, QString::fromLatin1("background-color")); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QHeaderView { + -qt-background-role: window; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QHeaderView")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("-qt-background-role"), QtBackgroundRole); + ADD_VALUE(Value::KnownIdentifier, Value_Window); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QTableCornerButton::section, QHeaderView::section { + -qt-background-role: button; + -qt-style-features: background-color; //if style is not pixmap based + border: native; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QTableCornerButton")); + ADD_PSEUDO(QLatin1String("section"), PseudoClass_Unknown); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_ELEMENT_NAME(QLatin1String("QHeaderView")); + ADD_PSEUDO(QLatin1String("section"), PseudoClass_Unknown); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("-qt-background-role"), QtBackgroundRole); + ADD_VALUE(Value::KnownIdentifier, Value_Button); + ADD_DECLARATION; + + if (!styleIsPixmapBased) { + SET_PROPERTY(QLatin1String("-qt-style-features"), QtStyleFeatures); + ADD_VALUE(Value::Identifier, QString::fromLatin1("background-color")); + ADD_DECLARATION; + } + + SET_PROPERTY(QLatin1String("border"), Border); + ADD_VALUE(Value::KnownIdentifier, Value_Native); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QProgressBar { + -qt-background-role: base; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QProgressBar")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("-qt-background-role"), QtBackgroundRole); + ADD_VALUE(Value::KnownIdentifier, Value_Base); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QScrollBar { + -qt-background-role: window; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QScrollBar")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("-qt-background-role"), QtBackgroundRole); + ADD_VALUE(Value::KnownIdentifier, Value_Window); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QDockWidget { + border: native; + }*/ + { + SET_ELEMENT_NAME(QLatin1String("QDockWidget")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + SET_PROPERTY(QLatin1String("border"), Border); + ADD_VALUE(Value::KnownIdentifier, Value_Native); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + sheet.origin = StyleSheetOrigin_UserAgent; + sheet.buildIndexes(); + return sheet; +} + +#endif // #ifndef QT_NO_STYLE_STYLESHEET + +QT_END_NAMESPACE diff --git a/src/widgets/styles/qstylesheetstyle_p.h b/src/widgets/styles/qstylesheetstyle_p.h new file mode 100644 index 0000000000..1f331b2642 --- /dev/null +++ b/src/widgets/styles/qstylesheetstyle_p.h @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLESHEETSTYLE_P_H +#define QSTYLESHEETSTYLE_P_H + +#include "QtGui/qwindowsstyle.h" + +#ifndef QT_NO_STYLE_STYLESHEET + +#include "QtGui/qstyleoption.h" +#include "QtCore/qhash.h" +#include "QtGui/qevent.h" +#include "QtCore/qvector.h" +#include "QtGui/qapplication.h" +#include "private/qcssparser_p.h" +#include "QtGui/qbrush.h" + +QT_BEGIN_NAMESPACE + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +class QRenderRule; +class QAbstractScrollArea; +class QStyleSheetStylePrivate; +class QStyleOptionTitleBar; + +class Q_AUTOTEST_EXPORT QStyleSheetStyle : public QWindowsStyle +{ + typedef QWindowsStyle ParentStyle; + + Q_OBJECT +public: + QStyleSheetStyle(QStyle *baseStyle); + ~QStyleSheetStyle(); + + void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, + const QWidget *w = 0) const; + void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const; + void drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const; + void drawItemText(QPainter *painter, const QRect& rect, int alignment, const QPalette &pal, + bool enabled, const QString& text, QPalette::ColorRole textRole = QPalette::NoRole) const; + void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const; + QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *option) const; + SubControl hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *w = 0) const; + QRect itemPixmapRect(const QRect &rect, int alignment, const QPixmap &pixmap) const; + QRect itemTextRect(const QFontMetrics &metrics, const QRect &rect, int alignment, bool enabled, + const QString &text) const; + int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const; + void polish(QWidget *widget); + void polish(QApplication *app); + void polish(QPalette &pal); + QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, + const QSize &contentsSize, const QWidget *widget = 0) const; + QPalette standardPalette() const; + QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option = 0, + const QWidget *w = 0 ) const; + int layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, + Qt::Orientation orientation, const QStyleOption *option = 0, + const QWidget *widget = 0) const; + int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0, + QStyleHintReturn *shret = 0) const; + QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const; + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, + const QWidget *w = 0) const; + + // These functions are called from QApplication/QWidget. Be careful. + QStyle *baseStyle() const; + void repolish(QWidget *widget); + void repolish(QApplication *app); + + void unpolish(QWidget *widget); + void unpolish(QApplication *app); + + QStyle *base; + void ref() { ++refcount; } + void deref() { Q_ASSERT(refcount > 0); if (!--refcount) delete this; } + + void updateStyleSheetFont(QWidget* w) const; + void saveWidgetFont(QWidget* w, const QFont& font) const; + void clearWidgetFont(QWidget* w) const; + + bool styleSheetPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal); + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt = 0, + const QWidget *widget = 0) const; + int layoutSpacingImplementation(QSizePolicy::ControlType control1, + QSizePolicy::ControlType control2, + Qt::Orientation orientation, + const QStyleOption *option = 0, + const QWidget *widget = 0) const; + +protected: + bool event(QEvent *e); + +private: + int refcount; + + friend class QRenderRule; + int nativeFrameWidth(const QWidget *); + QRenderRule renderRule(const QWidget *, int, quint64 = 0) const; + QRenderRule renderRule(const QWidget *, const QStyleOption *, int = 0) const; + QSize defaultSize(const QWidget *, QSize, const QRect&, int) const; + QRect positionRect(const QWidget *, const QRenderRule&, const QRenderRule&, int, + const QRect&, Qt::LayoutDirection) const; + QRect positionRect(const QWidget *w, const QRenderRule &rule2, int pe, + const QRect &originRect, Qt::LayoutDirection dir) const; + + mutable QCss::Parser parser; + + void setPalette(QWidget *); + void unsetPalette(QWidget *); + void setProperties(QWidget *); + void setGeometry(QWidget *); + QVector styleRules(const QWidget *w) const; + bool hasStyleRule(const QWidget *w, int part) const; + + QHash titleBarLayout(const QWidget *w, const QStyleOptionTitleBar *tb) const; + + QCss::StyleSheet getDefaultStyleSheet() const; + + static Qt::Alignment resolveAlignment(Qt::LayoutDirection, Qt::Alignment); + static bool isNaturalChild(const QWidget *w); + bool initWidget(const QWidget *w) const; +public: + static int numinstances; + +private: + Q_DISABLE_COPY(QStyleSheetStyle) + Q_DECLARE_PRIVATE(QStyleSheetStyle) +}; + +class QStyleSheetStyleCaches : public QObject +{ + Q_OBJECT +public Q_SLOTS: + void widgetDestroyed(QObject *); + void styleDestroyed(QObject *); +public: + QHash > styleRulesCache; + QHash > hasStyleRuleCache; + typedef QHash > QRenderRules; + QHash renderRulesCache; + QHash customPaletteWidgets; // widgets whose palette we tampered + QHash styleSheetCache; // parsed style sheets + QSet autoFillDisabledWidgets; +}; + + +QT_END_NAMESPACE +#endif // QT_NO_STYLE_STYLESHEET +#endif // QSTYLESHEETSTYLE_P_H diff --git a/src/widgets/styles/qwindowscestyle.cpp b/src/widgets/styles/qwindowscestyle.cpp new file mode 100644 index 0000000000..d7947bc653 --- /dev/null +++ b/src/widgets/styles/qwindowscestyle.cpp @@ -0,0 +1,2429 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowscestyle.h" + +#if !defined(QT_NO_STYLE_WINDOWSCE) || defined(QT_PLUGIN) + +#include "qpainterpath.h" +#include "qapplication.h" +#include "qdockwidget.h" +#include "qtoolbar.h" +#include "qpaintengine.h" +#include "qpainter.h" +#include "qstyleoption.h" +#include "qwindowscestyle_p.h" +#include "qdebug.h" + +QT_BEGIN_NAMESPACE + +static const int windowsItemFrame = 2; // menu item frame width +static const int windowsItemHMargin = 3; // menu item hor text margin +static const int windowsItemVMargin = 2; // menu item ver text margin +static const int windowsArrowHMargin = 6; // arrow horizontal margin +static const int windowsRightBorder = 15; // right border on windows +static const int windowsCheckMarkWidth = 14; // checkmarks width on windows + +static const int windowsCEitemViewCheckBoxSize = 14; +static const int windowsCEFrameGroupBoxOffset = 9; +static const int windowsCEIndicatorSize = 14; +static const int windowsCEExclusiveIndicatorSize = 14; +static const int windowsCESliderThickness = 24; +static const int windowsCEIconSize = 16; + +static const QColor windowsCECheckBoxGradientColorBegin = QColor(222, 224, 214); +static const QColor windowsCECheckBoxGradientColorEnd = QColor(255, 255, 255); + +enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight }; + +QWindowsCEStyle::QWindowsCEStyle() : QWindowsStyle() { + qApp->setEffectEnabled(Qt::UI_FadeMenu, false); + qApp->setEffectEnabled(Qt::UI_AnimateMenu, false); +} + +void QWindowsCEStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const { + + bool doRestore = false; + QRect rect = option->rect; + + switch (element) { + case PE_PanelButtonTool: { + if ( +#ifndef QT_NO_TOOLBAR + (widget && qobject_cast(widget->parentWidget())) || +#endif +#ifndef QT_NO_DOCKWIDGET + (widget && widget->inherits("QDockWidgetTitleButton")) || +#endif + (option->state & (State_Sunken | State_On))) + QWindowsCEStylePrivate::drawWinCEButton(painter, option->rect.adjusted(0, 0, 0, 0), + option->palette, option->state & (State_Sunken | State_On), + &option->palette.button()); + if (option->state & (State_On)){ + QBrush fill = QBrush(option->palette.midlight().color(), Qt::Dense4Pattern); + painter->fillRect(option->rect.adjusted(windowsItemFrame , windowsItemFrame , + -windowsItemFrame , -windowsItemFrame ), fill); + } + break; } + case PE_IndicatorButtonDropDown: + QWindowsCEStylePrivate::drawWinCEButton(painter, option->rect, option->palette, + option->state & (State_Sunken | State_On), + &option->palette.brush(QPalette::Button)); + break; +#ifndef QT_NO_TABBAR + case PE_IndicatorTabTear: + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { + bool rtl = tab->direction == Qt::RightToLeft; + QRect rect = tab->rect; + QPainterPath path; + rect.setTop(rect.top() + ((tab->state & State_Selected) ? 1 : 3)); + rect.setBottom(rect.bottom() - ((tab->state & State_Selected) ? 0 : 2)); + path.moveTo(QPoint(rtl ? rect.right() : rect.left(), rect.top())); + int count = 3; + for(int jags = 1; jags <= count; ++jags, rtl = !rtl) + path.lineTo(QPoint(rtl ? rect.left() : rect.right(), rect.top() + jags * rect.height()/count)); + + painter->setPen(QPen(tab->palette.light(), qreal(.8))); + painter->setBrush(tab->palette.background()); + painter->setRenderHint(QPainter::Antialiasing); + painter->drawPath(path); + } + break; +#endif //QT_NO_TABBAR +#ifndef QT_NO_TOOLBAR + case PE_IndicatorToolBarSeparator: + //nothing to draw on WindowsCE + break; + case PE_IndicatorToolBarHandle: + painter->save(); + painter->translate(option->rect.x(), option->rect.y()); + if (option->state & State_Horizontal) { + int x = option->rect.width() / 2 - 4; + if (QApplication::layoutDirection() == Qt::RightToLeft) + x -= 2; + if (option->rect.height() > 4) { + QWindowsCEStylePrivate::drawWinCEButton(painter,x - 1, 0, 7, option->rect.height(), + option->palette, false, 0); + QWindowsCEStylePrivate::drawWinCEPanel(painter, x, 1, 3, option->rect.height() - 1, + option->palette, false, 0); + QWindowsCEStylePrivate::drawWinCEPanel(painter, x + 3, 1, 3, option->rect.height() - 1, + option->palette, false, 0); + painter->setPen(option->palette.button().color()); + painter->drawLine(x + 4, 2, x + 4,option->rect.height() - 2); + } + } else { + if (option->rect.width() > 4) { + int y = option->rect.height() / 2 - 4; + QWindowsCEStylePrivate::drawWinCEPanel(painter, 2, y, option->rect.width() - 2, 3, + option->palette, false, 0); + QWindowsCEStylePrivate::drawWinCEPanel(painter, 2, y + 3, option->rect.width() - 2, 3, + option->palette, false, 0); + } + } + painter->restore(); + break; + +#endif // QT_NO_TOOLBAR + case PE_FrameButtonTool: { +#ifndef QT_NO_DOCKWIDGET + if (widget && widget->inherits("QDockWidgetTitleButton")) { + if (const QDockWidget *dw = qobject_cast(widget->parent())) + if (dw->isFloating()){ + QWindowsCEStylePrivate::drawWinCEButton(painter, option->rect.adjusted(1, 1, 0, 0), + option->palette, option->state & (State_Sunken | State_On), + &option->palette.button()); + return; + } + } +#endif // QT_NO_DOCKWIDGET + QBrush fill; + bool stippled; + bool panel = (element == PE_PanelButtonTool); + if ((!(option->state & State_Sunken )) + && (!(option->state & State_Enabled) + || ((option->state & State_Enabled ) && !(option->state & State_MouseOver))) + && (option->state & State_On)) { + fill = QBrush(option->palette.light().color(), Qt::Dense4Pattern); + stippled = true; + } else { + fill = option->palette.brush(QPalette::Button); + stippled = false; + } + if (option->state & (State_Raised | State_Sunken | State_On)) { + if (option->state & State_AutoRaise) { + if(option->state & (State_Enabled | State_Sunken | State_On)){ + if (panel) + QWindowsCEStylePrivate::drawWinCEPanel(painter, option->rect, option->palette, + option->state & (State_Sunken | State_On), &fill); + else + qDrawShadeRect(painter, option->rect, option->palette, + option->state & (State_Sunken | State_On), 1); + } + if (stippled) { + painter->setPen(option->palette.button().color()); + painter->drawRect(option->rect.adjusted(1, 1, -2, -2)); + } + } else { + QWindowsCEStylePrivate::drawWinCEButton(painter, option->rect, option->palette, + option->state & (State_Sunken | State_On), panel ? &fill : 0); + } + } else { + painter->fillRect(option->rect, fill); + } + break; } + + case PE_PanelButtonBevel: { + QBrush fill; + bool panel = element != PE_FrameButtonBevel; + painter->setBrushOrigin(option->rect.topLeft()); + if (!(option->state & State_Sunken) && (option->state & State_On)) + fill = QBrush(option->palette.light().color(), Qt::Dense4Pattern); + else + fill = option->palette.brush(QPalette::Button); + + if (option->state & (State_Raised | State_On | State_Sunken)) { + QWindowsCEStylePrivate::drawWinCEButton(painter, option->rect, option->palette, + option->state & (State_Sunken | State_On), + panel ? &fill : 0); ; + } else { + if (panel) + painter->fillRect(option->rect, fill); + else + painter->drawRect(option->rect); + } + break; } + + case PE_FrameGroupBox: + if (const QStyleOptionFrame *frame = qstyleoption_cast(option)) { + QRect fr = frame->rect; + painter->setPen(frame->palette.shadow().color()); + painter->drawRect(fr.x(), fr.y(), fr.x() + fr.width() - 1, + fr.y() + fr.height() - windowsCEFrameGroupBoxOffset); + } + break; + + case PE_IndicatorCheckBox: { + QBrush fill; + if (option->state & State_NoChange) + fill = QBrush(option->palette.base().color(), Qt::Dense4Pattern); + else if (option->state & State_Sunken) + fill = option->palette.button(); + else if (option->state & State_Enabled) + fill = option->palette.base(); + else + fill = option->palette.background(); + painter->save(); + doRestore = true; + painter->fillRect(option->rect,fill); + painter->setPen(option->palette.dark().color()); + painter->drawRect(option->rect); + painter->setPen(option->palette.shadow().color()); + painter->drawLine(option->rect.x() + 1,option->rect.y() + 1, + option->rect.x() + option->rect.width() - 1, option->rect.y() + 1); + painter->drawLine(option->rect.x() + 1,option->rect.y() + 1, + option->rect.x() + 1, option->rect.y() + option->rect.height() - 1); + //fall through... + } + case PE_IndicatorViewItemCheck: + case PE_Q3CheckListIndicator: { + if (!doRestore) { + painter->save(); + doRestore = true; + } + int arrowSize= 2; + if (element == PE_Q3CheckListIndicator || element == PE_IndicatorViewItemCheck) { + QLinearGradient linearGradient(QPoint(option->rect.x(),option->rect.y()), QPoint(option->rect.x()+option->rect.width(), + option->rect.y()+option->rect.height())); + linearGradient.setColorAt(0, windowsCECheckBoxGradientColorBegin); + linearGradient.setColorAt(1, windowsCECheckBoxGradientColorEnd); + painter->setBrush(linearGradient); + painter->setPen(Qt::NoPen); + if (option->state & State_NoChange) + painter->setBrush(option->palette.brush(QPalette::Button)); + painter->setPen(option->palette.link().color()); + painter->drawRect(option->rect.x(), option->rect.y(), windowsCEitemViewCheckBoxSize, windowsCEitemViewCheckBoxSize); + painter->setPen(option->palette.brightText().color()); + arrowSize= 3; + } + if (!(option->state & State_Off)) { + QLineF lines[9]; + int i, xx, yy; + xx = option->rect.x() + 4; + yy = option->rect.y() + 6; + for (i = 0; i < 4; ++i) { + lines[i] = QLineF(xx, yy, xx, yy + arrowSize); + ++xx; + ++yy; + } + yy -= 2; + for (i = 4; i < 9; ++i) { + lines[i] = QLineF(xx, yy, xx, yy + arrowSize); + ++xx; + --yy; + } + painter->drawLines(lines, 9); + } + if (doRestore) + painter->restore(); + + break; } + case PE_IndicatorRadioButton: { + QRect ir = option->rect; + painter->save(); + painter->setPen(Qt::NoPen); + painter->setBrush(option->palette.light()); + painter->drawEllipse(option->rect); + painter->setPen(option->palette.shadow().color()); + painter->setBrush(option->palette.shadow().color()); + painter->drawArc(option->rect, 0, 360 * 16); + painter->drawArc(option->rect.x() + 1, option->rect.y() + 1, option->rect.width() - 2, + option->rect.height() - 2, 40 * 16, 180 * 16); + painter->setPen(option->palette.light().color()); + painter->drawPoint(option->rect.x() + 11, option->rect.y() + 3); + painter->drawPoint(option->rect.x() + 3,option->rect.y() + 3); + painter->setPen(option->palette.shadow().color()); + painter->drawPoint(option->rect.x() +3,option->rect.y() + 12); + if (option->state & (State_Sunken | State_On)) { + painter->setPen(Qt::NoPen); + painter->setBrush(option->palette.text()); + painter->drawEllipse(option->rect.x() +3,option->rect.y()+ 2,9,10); + } + painter->restore(); + break; } + case PE_PanelMenuBar: + painter->save(); + painter->setPen(option->palette.shadow().color()); + painter->drawRect(option->rect); + painter->restore(); + break; + case PE_PanelButtonCommand: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + QBrush fill; + State flags = option->state; + QPalette pal = option->palette; + QRect r = option->rect; + if (! (flags & State_Sunken) && (flags & State_On)) + fill = QBrush(pal.light().color(), Qt::Dense4Pattern); + else + fill = pal.brush(QPalette::Button); + if (btn->features & QStyleOptionButton::DefaultButton && flags & State_Sunken) { + painter->setPen(pal.dark().color()); + painter->setBrush(fill); + painter->drawRect(r.adjusted(0, 0, -1, -1)); + } else if (flags & (State_Raised | State_Sunken | State_On | State_Sunken)) { + QWindowsCEStylePrivate::drawWinCEButton(painter, r, pal, flags & (State_Sunken | State_On), + &fill); + } else { + painter->fillRect(r, fill); + } + + } + break; + case PE_FrameDefaultButton: { + painter->setPen(option->palette.shadow().color()); + QRect rect = option->rect; + rect.adjust(0, 0, -1, -1); + painter->drawRect(rect); + break; } + case PE_IndicatorSpinPlus: + case PE_IndicatorSpinMinus: { + QRect r = option->rect; + int fw = pixelMetric(PM_DefaultFrameWidth, option, widget)+2; + QRect br = r.adjusted(fw, fw, -fw, -fw); + int offset = (option->state & State_Sunken) ? 1 : 0; + int step = (br.width() + 4) / 5; + painter->fillRect(br.x() + offset, br.y() + offset +br.height() / 2 - step / 2, + br.width(), step, + option->palette.buttonText()); + if (element == PE_IndicatorSpinPlus) + painter->fillRect(br.x() + br.width() / 2 - step / 2 + offset, br.y() + offset+4, + step, br.height()-7, + option->palette.buttonText()); + break; } + case PE_IndicatorSpinUp: + case PE_IndicatorSpinDown: { + painter->save(); + QPoint points[7]; + switch (element) { + case PE_IndicatorSpinUp: + points[0] = QPoint(-2, -4); + points[1] = QPoint(-2, 2); + points[2] = QPoint(-1, -3); + points[3] = QPoint(-1, 1); + points[4] = QPoint(0, -2); + points[5] = QPoint(0, 0); + points[6] = QPoint(1, -1); + break; + case PE_IndicatorSpinDown: + points[0] = QPoint(0, -4); + points[1] = QPoint(0, 2); + points[2] = QPoint(-1, -3); + points[3] = QPoint(-1, 1); + points[4] = QPoint(-2, -2); + points[5] = QPoint(-2, 0); + points[6] = QPoint(-3, -1); + break; + default: + break; + } + if (option->state & State_Sunken) + painter->translate(pixelMetric(PM_ButtonShiftHorizontal), + pixelMetric(PM_ButtonShiftVertical)); + if (option->state & State_Enabled) { + painter->translate(option->rect.x() + option->rect.width() / 2, + option->rect.y() + option->rect.height() / 2); + painter->setPen(option->palette.buttonText().color()); + painter->drawLine(points[0], points[1]); + painter->drawLine(points[2], points[3]); + painter->drawLine(points[4], points[5]); + painter->drawPoint(points[6]); + } else { + painter->translate(option->rect.x() + option->rect.width() / 2 + 1, + option->rect.y() + option->rect.height() / 2 + 1); + painter->setPen(option->palette.light().color()); + painter->drawLine(points[0], points[1]); + painter->drawLine(points[2], points[3]); + painter->drawLine(points[4], points[5]); + painter->drawPoint(points[6]); + painter->translate(-1, -1); + painter->setPen(option->palette.mid().color()); + painter->drawLine(points[0], points[1]); + painter->drawLine(points[2], points[3]); + painter->drawLine(points[4], points[5]); + painter->drawPoint(points[6]); + } + + painter->restore(); + break; } + case PE_IndicatorArrowUp: + case PE_IndicatorArrowDown: + case PE_IndicatorArrowRight: + case PE_IndicatorArrowLeft: { + painter->save(); + QPoint points[9]; + switch (element) { + case PE_IndicatorArrowUp: + + points[0] = QPoint(-4, 2); + points[1] = QPoint(4, 2); + points[2] = QPoint(-3, 1); + points[3] = QPoint(3, 1); + points[4] = QPoint(-2, 0); + points[5] = QPoint(2, 0); + points[6] = QPoint(-1, -1); + points[7] = QPoint(1, -1); + points[8] = QPoint(0, -2); + break; + case PE_IndicatorArrowDown: + + points[0] = QPoint(-4, -2); + points[1] = QPoint(4, -2); + points[2] = QPoint(-3, -1); + points[3] = QPoint(3, -1); + points[4] = QPoint(-2, 0); + points[5] = QPoint(2, 0); + points[6] = QPoint(-1, 1); + points[7] = QPoint(1, 1); + points[8] = QPoint(0, 2); + break; + case PE_IndicatorArrowRight: + points[0] = QPoint(-3, -4); + points[1] = QPoint(-3, 4); + points[2] = QPoint(-2, -3); + points[3] = QPoint(-2, 3); + points[4] = QPoint(-1, -2); + points[5] = QPoint(-1, 2); + points[6] = QPoint(0, -1); + points[7] = QPoint(0, 1); + points[8] = QPoint(1, 0); + break; + case PE_IndicatorArrowLeft: + points[0] = QPoint(1, -4); + points[1] = QPoint(1, 4); + points[2] = QPoint(0, -3); + points[3] = QPoint(0, 3); + points[4] = QPoint(-1, -2); + points[5] = QPoint(-1, 2); + points[6] = QPoint(-2, -1); + points[7] = QPoint(-2, 1); + points[8] = QPoint(-3, 0); + break; + default: + break; + } + if (option->state & State_Sunken) + painter->translate(pixelMetric(PM_ButtonShiftHorizontal), + pixelMetric(PM_ButtonShiftVertical)); + if (option->state & State_Enabled) { + painter->translate(option->rect.x() + option->rect.width() / 2, + option->rect.y() + option->rect.height() / 2); + painter->setPen(option->palette.buttonText().color()); + painter->drawLine(points[0], points[1]); + painter->drawLine(points[2], points[3]); + painter->drawLine(points[4], points[5]); + painter->drawLine(points[6], points[7]); + painter->drawPoint(points[8]); + } else { + painter->translate(option->rect.x() + option->rect.width() / 2 + 1, + option->rect.y() + option->rect.height() / 2 + 1); + painter->setPen(option->palette.light().color()); + painter->drawLine(points[0], points[1]); + painter->drawLine(points[2], points[3]); + painter->drawLine(points[4], points[5]); + painter->drawLine(points[6], points[7]); + painter->drawPoint(points[8]); + painter->translate(-1, -1); + painter->setPen(option->palette.mid().color()); + painter->drawLine(points[0], points[1]); + painter->drawLine(points[2], points[3]); + painter->drawLine(points[4], points[5]); + painter->drawLine(points[6], points[7]); + painter->drawPoint(points[8]); + } + painter->restore(); + break; } + + case PE_FrameWindow: { + QPalette popupPal = option->palette; + popupPal.setColor(QPalette::Light, option->palette.background().color()); + popupPal.setColor(QPalette::Midlight, option->palette.light().color()); + QWindowsCEStylePrivate::drawWinCEPanel(painter, option->rect, popupPal, option->state & State_Sunken); + break; } + + case PE_Frame: + case PE_FrameMenu: + if (const QStyleOptionFrame *frame = qstyleoption_cast(option)) { + QPalette popupPal = frame->palette; + QRect r = frame->rect; + qDrawPlainRect(painter, r, frame->palette.shadow().color(),1); + } + break; + case PE_FrameStatusBar: + QWindowsCEStylePrivate::drawWinCEPanel(painter, option->rect, option->palette, true, 0); + break; + + case PE_FrameTabWidget: { + QRect rect = option->rect; + QPalette pal = option->palette; + QWindowsCEStylePrivate::drawWinCEButton(painter, option->rect, option->palette, false, 0); + break; } + default: + QWindowsStyle::drawPrimitive(element, option, painter, widget); + break; + } +} + +void QWindowsCEStyle::drawControl(ControlElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const { + switch (element) { + #ifndef QT_NO_MENU + case CE_MenuTearoff: { + if(option->state & State_Selected) { + if(pixelMetric(PM_MenuPanelWidth, option, widget) > 1) + qDrawShadePanel(painter, option->rect.x(), option->rect.y(), option->rect.width(), + option->rect.height(), option->palette, false, 2, + &option->palette.brush(QPalette::Button)); + else + qDrawShadePanel(painter, option->rect.x() + 1, option->rect.y() + 1, option->rect.width() - 2, + option->rect.height() - 2, option->palette, true, 1, &option->palette.brush(QPalette::Button)); + } else { + painter->fillRect(option->rect, option->palette.brush(QPalette::Button)); + } + painter->setPen(QPen(option->palette.dark().color(), 1, Qt::DashLine)); + painter->drawLine(option->rect.x()+2, option->rect.y()+option->rect.height()/2-1, option->rect.x()+option->rect.width()-4, + option->rect.y()+option->rect.height()/2-1); + painter->setPen(QPen(option->palette.light().color(), 1, Qt::DashLine)); + painter->drawLine(option->rect.x()+2, option->rect.y()+option->rect.height()/2, option->rect.x()+option->rect.width()-4, + option->rect.y()+option->rect.height()/2); + break; } + + + case CE_MenuBarItem: + if (const QStyleOptionMenuItem *mbi = qstyleoption_cast(option)) { + bool active = mbi->state & State_Selected; + bool hasFocus = mbi->state & State_HasFocus; + bool down = mbi->state & State_Sunken; + QStyleOptionMenuItem newMbi = *mbi; + if (active || hasFocus) { + QBrush b = mbi->palette.brush(QPalette::Highlight); + if (active && down) { + painter->fillRect(mbi->rect.adjusted(0, 1, 0, -1), b); + } + } + uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip + | Qt::TextSingleLine; + if (!styleHint(SH_UnderlineShortcut, mbi, widget)) + alignment |= Qt::TextHideMnemonic; + + painter->save(); + QFont f = painter->font(); + f.setBold(true); + painter->setFont(f); + QPixmap pix = mbi->icon.pixmap(pixelMetric(PM_SmallIconSize), + (mbi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled); + if (!pix.isNull()) + drawItemPixmap(painter,mbi->rect, alignment, pix); + else + if (active && down) + drawItemText(painter, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, + mbi->text, QPalette::Light); + else + drawItemText(painter, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, + mbi->text, QPalette::ButtonText); + painter->restore(); + } + break; + + case CE_MenuBarEmptyArea: + painter->save(); + painter->setPen(option->palette.shadow().color()); + if (widget && !widget->testAttribute(Qt::WA_NoSystemBackground)) { + painter->eraseRect(option->rect); + QRect r = option->rect; + painter->drawLine(r.x() + 1, r.y() + 1, r.x()+ 1, r.y()+ r.height() - 2); + painter->drawLine(r.x() - 2 + r.width(), r.y() + 1, r.x() - 2 + r.width(), r.y() + r.height() - 2); + painter->drawLine(r.x() + 1, r.y() +1, r.x() - 1 + r.width(), r.y() + 1); + painter->drawLine(r.x() + 1, r.y() + r.height()-2 , r.x() - 2 + r.width(), r.y() + r.height() - 2); + } + painter->restore(); + break; + + case CE_MenuItem: + if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) { + int x, y, w, h; + menuitem->rect.getRect(&x, &y, &w, &h); + int tab = menuitem->tabWidth; + bool dis = !(menuitem->state & State_Enabled); + bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable + ? menuitem->checked : false; + bool act = menuitem->state & State_Selected; + + // windows always has a check column, regardless whether we have an icon or not + int checkcol = qMax(menuitem->maxIconWidth, windowsCheckMarkWidth); + QBrush fill = menuitem->palette.brush(act ? QPalette::Highlight : QPalette::Button); + painter->fillRect(menuitem->rect.adjusted(1, 1, 0, 0), fill); + + if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) { + int yoff = y-1 + h / 2; + painter->setPen(menuitem->palette.shadow().color()); + painter->drawLine(x + 4, yoff + 1, x + w - 8, yoff + 1); + return; + } + + QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(), + menuitem->rect.y(), checkcol, menuitem->rect.height())); + if (checked) { + if (act && !dis) { + qDrawPlainRect(painter, vCheckRect, + menuitem->palette.button().color(), 1, + &menuitem->palette.brush(QPalette::Button)); + } else { + QBrush fill(menuitem->palette.button().color(), Qt::Dense4Pattern); + qDrawPlainRect(painter, vCheckRect,menuitem->palette.button().color(), 1, &fill); + } + } else if (!act) { + painter->fillRect(vCheckRect, menuitem->palette.brush(QPalette::Button)); + } + // On Windows Style, if we have a checkable item and an icon we + // draw the icon recessed to indicate an item is checked. If we + // have no icon, we draw a checkmark instead. + if (!menuitem->icon.isNull()) { + QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; + if (act && !dis) + mode = QIcon::Active; + QPixmap pixmap; + if (checked) + pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize), mode, QIcon::On); + else + pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize), mode); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + if (act && !dis && !checked) + qDrawPlainRect(painter, vCheckRect, menuitem->palette.button().color(), 1, + &menuitem->palette.brush(QPalette::Button)); + QRect pmr(0, 0, pixw, pixh); + pmr.moveCenter(vCheckRect.center()); + painter->setPen(menuitem->palette.text().color()); + painter->drawPixmap(pmr.topLeft(), pixmap); + } else if (checked) { + QStyleOptionMenuItem newMi = *menuitem; + newMi.state = State_None; + if (!dis) + newMi.state |= State_Enabled; + if (act) + newMi.state |= State_On; + newMi.rect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x() + + windowsItemFrame, menuitem->rect.y() + windowsItemFrame, + checkcol - 2 * windowsItemFrame, menuitem->rect.height() - 2*windowsItemFrame)); + drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, painter, widget); + } + painter->setPen(act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color()); + + QColor discol; + if (dis) { + discol = menuitem->palette.text().color(); + painter->setPen(discol); + } + int xm = windowsItemFrame + checkcol + windowsItemHMargin; + int xpos = menuitem->rect.x() + xm; + QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); + QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect); + QString s = menuitem->text; + if (!s.isEmpty()) { // draw text + painter->save(); + int t = s.indexOf(QLatin1Char('\t')); + int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!styleHint(SH_UnderlineShortcut, menuitem, widget)) + text_flags |= Qt::TextHideMnemonic; + text_flags |= Qt::AlignLeft; + if (t >= 0) { + QRect vShortcutRect = visualRect(option->direction, menuitem->rect, + QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom()))); + if (dis && !act) + painter->setPen(discol); + painter->drawText(vShortcutRect, text_flags, s.mid(t + 1)); + s = s.left(t); + } + QFont font = menuitem->font; + if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) + font.setBold(true); + painter->setFont(font); + if (dis && !act) + painter->setPen(discol); + painter->drawText(vTextRect, text_flags, s.left(t)); + painter->restore(); + } + if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow + int dim = (h - 2 * windowsItemFrame) / 2; + PrimitiveElement arrow; + arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorSpinDown : PE_IndicatorSpinUp; + xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim; + QRect vSubMenuRect = visualRect(option->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim)); + QStyleOptionMenuItem newMI = *menuitem; + newMI.rect = vSubMenuRect; + newMI.state = dis ? State_None : State_Enabled; + if (act) + newMI.palette.setColor(QPalette::ButtonText, + newMI.palette.highlightedText().color()); + drawPrimitive(arrow, &newMI, painter, widget); + } + } + break; +#endif // QT_NO_MENU + case CE_MenuVMargin: + painter->fillRect(option->rect, Qt::white); + break; + case CE_MenuEmptyArea: + QWindowsStyle::drawControl(element,option, painter, widget); + break; + +#ifndef QT_NO_TABBAR + case CE_TabBarTab: + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { + drawControl(CE_TabBarTabShape, tab, painter, widget); + drawControl(CE_TabBarTabLabel, tab, painter, widget); + } + break; + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { + bool rtlHorTabs = (tab->direction == Qt::RightToLeft + && (tab->shape == QTabBar::RoundedNorth + || tab->shape == QTabBar::RoundedSouth)); + bool selected = tab->state & State_Selected; + bool lastTab = ((!rtlHorTabs && tab->position == QStyleOptionTab::End) + || (rtlHorTabs + && tab->position == QStyleOptionTab::Beginning)); + bool firstTab = ((!rtlHorTabs + && tab->position == QStyleOptionTab::Beginning) + || (rtlHorTabs + && tab->position == QStyleOptionTab::End)); + bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab; + bool previousSelected = + ((!rtlHorTabs + && tab->selectedPosition == QStyleOptionTab::PreviousIsSelected) + || (rtlHorTabs + && tab->selectedPosition == QStyleOptionTab::NextIsSelected)); + bool nextSelected = + ((!rtlHorTabs + && tab->selectedPosition == QStyleOptionTab::NextIsSelected) + || (rtlHorTabs + && tab->selectedPosition + == QStyleOptionTab::PreviousIsSelected)); + int tabBarAlignment = styleHint(SH_TabBar_Alignment, tab, widget); + bool leftAligned = (!rtlHorTabs && tabBarAlignment == Qt::AlignLeft) + || (rtlHorTabs + && tabBarAlignment == Qt::AlignRight); + + bool rightAligned = (!rtlHorTabs && tabBarAlignment == Qt::AlignRight) + || (rtlHorTabs + && tabBarAlignment == Qt::AlignLeft); + QColor light = tab->palette.light().color(); + QColor midlight = tab->palette.midlight().color(); + QColor dark = tab->palette.dark().color(); + QColor shadow = tab->palette.shadow().color(); + QColor background = tab->palette.background().color(); + int borderThinkness = pixelMetric(PM_TabBarBaseOverlap, tab, widget); + if (selected) + borderThinkness /= 2; + QRect r2(option->rect); + int x1 = r2.left(); + int x2 = r2.right(); + int y1 = r2.top(); + int y2 = r2.bottom(); + switch (tab->shape) { + default: + QCommonStyle::drawControl(element, tab, painter, widget); + break; + case QTabBar::RoundedNorth: { + if (!selected) { + y1 += 2; + x1 += firstTab ? borderThinkness : 0; + x2 -= lastTab ? borderThinkness : 0; + } + + painter->fillRect(QRect(x1 + 1, y1 + 1, (x2 - x1) - 1, (y2 - y1) - 2), tab->palette.background()); + + // Delete border + if (selected) { + painter->setPen(background); + painter->drawLine(x1, y2 - 1, x2, y2 - 1); + painter->drawLine(x1, y2 + 1, x2, y2 + 1); + painter->drawLine(x1, y2, x2, y2); + } + // Left + if (firstTab || selected || onlyOne || !previousSelected) { + painter->setPen(dark); + painter->drawLine(x1, y1 + 2, x1, y2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness)); + painter->drawPoint(x1 + 1, y1 + 1); + painter->setPen(midlight); + painter->drawLine(x1 + 1, y1 + 2, x1 + 1, y2 - + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness)); + + } + // Top + { + int beg = x1 + (previousSelected ? 0 : 2); + int end = x2 - (nextSelected ? 0 : 2); + painter->setPen(dark); + painter->drawLine(beg, y1, end, y1); + + painter->setPen(midlight); + painter->drawLine(beg, y1 + 1, end, y1 + 1); + + } + // Right + if (lastTab || selected || onlyOne || !nextSelected) { + painter->setPen(shadow); + painter->drawLine(x2, y1 + 2, x2, y2 - ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness)); + painter->drawPoint(x2 - 1, y1 + 1); + painter->setPen(dark); + painter->drawLine(x2 - 1, y1 + 2, x2 - 1, y2 - ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness)); + } + break; } + case QTabBar::RoundedSouth: { + if (!selected) { + y2 -= 2; + x1 += firstTab ? borderThinkness : 0; + x2 -= lastTab ? borderThinkness : 0; + } + + painter->fillRect(QRect(x1 + 1, y1 + 2, (x2 - x1) - 1, (y2 - y1) - 1), tab->palette.background()); + + // Delete border + if (selected) { + painter->setPen(background); + painter->drawLine(x1, y1 + 1, x2 - 1, y1 + 1); + painter->drawLine(x1, y1 - 1, x2 - 1, y1 - 1); + painter->drawLine(x1, y1, x2 - 1, y1); + } + // Left + if (firstTab || selected || onlyOne || !previousSelected) { + painter->setPen(dark); + painter->drawLine(x1, y2 - 2, x1, y1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness)); + painter->drawPoint(x1 + 1, y2 - 1); + painter->setPen(midlight); + painter->drawLine(x1 + 1, y2 - 2, x1 + 1, y1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness)); + } + // Bottom + { + int beg = x1 + (previousSelected ? 0 : 2); + int end = x2 - (nextSelected ? 0 : 2); + painter->setPen(shadow); + painter->drawLine(beg, y2, end, y2); + painter->setPen(dark); + painter->drawLine(beg, y2 - 1, end, y2 - 1); + } + // Right + if (lastTab || selected || onlyOne || !nextSelected) { + painter->setPen(shadow); + painter->drawLine(x2, y2 - 2, x2, y1 + ((onlyOne || lastTab) && selected && + rightAligned ? 0 : borderThinkness)); + painter->drawPoint(x2 - 1, y2 - 1); + painter->setPen(dark); + painter->drawLine(x2 - 1, y2 - 2, x2 - 1, y1 + ((onlyOne || lastTab) && selected && + rightAligned ? 0 : borderThinkness)); + } + break; } + case QTabBar::RoundedWest: { + if (!selected) { + x1 += 2; + y1 += firstTab ? borderThinkness : 0; + y2 -= lastTab ? borderThinkness : 0; + } + + painter->fillRect(QRect(x1 + 1, y1 + 1, (x2 - x1) - 2, (y2 - y1) - 1), tab->palette.background()); + + // Delete border + if (selected) { + painter->setPen(background); + painter->drawLine(x2 - 1, y1, x2 - 1, y2); + painter->drawLine(x2, y1, x2, y2); + } + // Top + if (firstTab || selected || onlyOne || !previousSelected) { + painter->setPen(dark); + painter->drawLine(x1 + 2, y1, x2 - ((onlyOne || firstTab) && selected && + leftAligned ? 0 : borderThinkness), y1); + painter->drawPoint(x1 + 1, y1 + 1); + painter->setPen(midlight); + painter->drawLine(x1 + 2, y1 + 1, x2 - ((onlyOne || firstTab) && selected && + leftAligned ? 0 : borderThinkness), y1 + 1); + } + // Left + { + int beg = y1 + (previousSelected ? 0 : 2); + int end = y2 - (nextSelected ? 0 : 2); + painter->setPen(dark); + painter->drawLine(x1, beg, x1, end); + painter->setPen(midlight); + painter->drawLine(x1 + 1, beg, x1 + 1, end); + } + // Bottom + if (lastTab || selected || onlyOne || !nextSelected) { + painter->setPen(shadow); + painter->drawLine(x1 + 3, y2, x2 - ((onlyOne || lastTab) && selected && + rightAligned ? 0 : borderThinkness), y2); + painter->drawPoint(x1 + 2, y2 - 1); + painter->setPen(dark); + painter->drawLine(x1 + 3, y2 - 1, x2 - ((onlyOne || lastTab) && selected && + rightAligned ? 0 : borderThinkness), y2 - 1); + painter->drawPoint(x1 + 1, y2 - 1); + painter->drawPoint(x1 + 2, y2); + } + break; } + case QTabBar::RoundedEast: { + if (!selected) { + x2 -= 2; + y1 += firstTab ? borderThinkness : 0; + y2 -= lastTab ? borderThinkness : 0; + } + + painter->fillRect(QRect(x1 + 2, y1 + 1, (x2 - x1) - 1, (y2 - y1) - 1), tab->palette.background()); + + // Delete border + if (selected) { + painter->setPen(background); + painter->drawLine(x1 + 1, y1, x1 + 1, y2 - 1); + painter->drawLine(x1, y1, x1, y2 - 1); + } + // Top + if (firstTab || selected || onlyOne || !previousSelected) { + painter->setPen(dark); + painter->drawLine(x2 - 2, y1, x1 + ((onlyOne || firstTab) && selected && + leftAligned ? 0 : borderThinkness), y1); + painter->drawPoint(x2 - 1, y1 + 1); + painter->setPen(midlight); + painter->drawLine(x2 - 3, y1 + 1, x1 + ((onlyOne || firstTab) && + selected && leftAligned ? 0 : borderThinkness), y1 + 1); + painter->drawPoint(x2 - 1, y1); + + } + // Right + { + int beg = y1 + (previousSelected ? 0 : 2); + int end = y2 - (nextSelected ? 0 : 2); + painter->setPen(shadow); + painter->drawLine(x2, beg, x2, end); + painter->setPen(dark); + painter->drawLine(x2 - 1, beg, x2 - 1, end); + } + // Bottom + if (lastTab || selected || onlyOne || !nextSelected) { + painter->setPen(shadow); + painter->drawLine(x2 - 2, y2, x1 + ((onlyOne || lastTab) && + selected && rightAligned ? 0 : borderThinkness), y2); + painter->drawPoint(x2 - 1, y2 - 1); + painter->setPen(dark); + painter->drawLine(x2 - 2, y2 - 1, x1 + ((onlyOne || lastTab) && + selected && rightAligned ? 0 : borderThinkness), y2 - 1); + } + break; } + } + } + break; +#endif // QT_NO_TABBAR + + case CE_ToolBar: { + QRect rect = option->rect; + painter->setPen(QPen(option->palette.dark().color())); + painter->drawLine(rect.topRight().x()-1, + rect.topRight().y(), + rect.bottomRight().x()-1, + rect.bottomRight().y()); + painter->drawLine(rect.bottomLeft().x(), + rect.bottomLeft().y(), + rect.bottomRight().x(), + rect.bottomRight().y()); + painter->setPen(QPen(option->palette.light().color())); + painter->drawLine(rect.topRight().x(), + rect.topRight().y(), + rect.bottomRight().x(), + rect.bottomRight().y()); + painter->drawLine(rect.topLeft().x(), + rect.topLeft().y(), + rect.topRight().x(), + rect.topRight().y()); + + break; } +#ifndef QT_NO_SCROLLBAR + case CE_ScrollBarSubLine: + case CE_ScrollBarAddLine: { + if (option->state & State_Sunken) { + QStyleOption buttonOpt = *option; + + drawPrimitive(PE_PanelButtonBevel, &buttonOpt, painter, widget); + } else { + QStyleOption buttonOpt = *option; + if (!(buttonOpt.state & State_Sunken)) + buttonOpt.state |= State_Raised; + drawPrimitive(PE_PanelButtonBevel, &buttonOpt, painter, widget); + } + PrimitiveElement arrow; + if (option->state & State_Horizontal) { + if (element == CE_ScrollBarAddLine) + arrow = option->direction == Qt::LeftToRight ? PE_IndicatorArrowRight : PE_IndicatorArrowLeft; + else + arrow = option->direction == Qt::LeftToRight ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; + } else { + if (element == CE_ScrollBarAddLine) + arrow = PE_IndicatorArrowDown; + else + arrow = PE_IndicatorArrowUp; + } + drawPrimitive(arrow, option, painter, widget); + break; } + case CE_ScrollBarAddPage: + case CE_ScrollBarSubPage: { + QBrush br; + QBrush bg = painter->background(); + Qt::BGMode bg_mode = painter->backgroundMode(); + painter->setPen(Qt::NoPen); + painter->setBackgroundMode(Qt::OpaqueMode); + + if (option->state & State_Sunken) { + br = QBrush(option->palette.shadow().color(), Qt::Dense4Pattern); + painter->setBackground(option->palette.dark().color()); + painter->setBrush(br); + } else { + QPixmap pm = option->palette.brush(QPalette::Light).texture(); + if (option->state & State_Enabled) + br = !pm.isNull() ? QBrush(pm) : QBrush(option->palette.button().color(), Qt::Dense4Pattern); + else + br = !pm.isNull() ? QBrush(pm) : QBrush(option->palette.light().color(), Qt::Dense4Pattern); + painter->setBackground(option->palette.base().color()); + painter->setBrush(br); + } + painter->drawRect(option->rect); + painter->setBackground(bg); + painter->setBackgroundMode(bg_mode); + break; } + case CE_ScrollBarSlider: + if (!(option->state & State_Enabled)) { + QStyleOptionButton buttonOpt; + buttonOpt.QStyleOption::operator=(*option); + buttonOpt.state = State_Enabled | State_Raised; + drawPrimitive(PE_PanelButtonBevel, &buttonOpt, painter, widget); + QPixmap pm = option->palette.brush(QPalette::Light).texture(); + QBrush br = !pm.isNull() ? QBrush(pm) : QBrush(option->palette.light().color(), Qt::Dense4Pattern); + painter->setPen(Qt::NoPen); + painter->setBrush(br); + painter->setBackgroundMode(Qt::OpaqueMode); + painter->drawRect(option->rect.adjusted(2, 2, -2, -2)); + } else { + QStyleOptionButton buttonOpt; + buttonOpt.QStyleOption::operator=(*option); + buttonOpt.state = State_Enabled | State_Raised; + drawPrimitive(PE_PanelButtonBevel, &buttonOpt, painter, widget); + } + break; +#endif // QT_NO_SCROLLBAR + case CE_HeaderSection: { + QBrush fill; + if (option->state & State_On) + fill = QBrush(option->palette.light().color(), Qt::Dense4Pattern); + else + fill = option->palette.brush(QPalette::Button); + + if (option->state & (State_Raised | State_Sunken)) { + QWindowsCEStylePrivate::drawWinCEButton(painter, option->rect, option->palette, + option->state & State_Sunken, &fill); + } else { + painter->fillRect(option->rect, fill); + } + break; } + + case CE_DockWidgetTitle: + QWindowsStyle::drawControl(element,option, painter, widget); + break; + + case CE_PushButtonLabel: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + painter->save(); + QFont f = painter->font(); + f.setBold(true); + painter->setFont(f); + QRect ir = btn->rect; + uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic; + if (!styleHint(SH_UnderlineShortcut, btn, widget)) + tf |= Qt::TextHideMnemonic; + + if (btn->state & (State_On | State_Sunken)) + ir.translate(pixelMetric(PM_ButtonShiftHorizontal, option, widget), + pixelMetric(PM_ButtonShiftVertical, option, widget)); + if (!btn->icon.isNull()) { + QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal + : QIcon::Disabled; + if (mode == QIcon::Normal && btn->state & State_HasFocus) + mode = QIcon::Active; + QIcon::State state = QIcon::Off; + if (btn->state & State_On) + state = QIcon::On; + QPixmap pixmap = btn->icon.pixmap(btn->iconSize, mode, state); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + //Center the icon if there is no text + + QPoint point; + if (btn->text.isEmpty()) { + point = QPoint(ir.x() + ir.width() / 2 - pixw / 2, + ir.y() + ir.height() / 2 - pixh / 2); + } else { + point = QPoint(ir.x() + 2, ir.y() + ir.height() / 2 - pixh / 2); + } + if (btn->direction == Qt::RightToLeft) + point.rx() += pixw; + + if ((btn->state & (State_On | State_Sunken)) && btn->direction == Qt::RightToLeft) + point.rx() -= pixelMetric(PM_ButtonShiftHorizontal, option, widget) * 2; + + painter->drawPixmap(visualPos(btn->direction, btn->rect, point), pixmap); + + if (btn->direction == Qt::RightToLeft) + ir.translate(-4, 0); + else + ir.translate(pixw + 4, 0); + ir.setWidth(ir.width() - (pixw + 4)); + // left-align text if there is + if (!btn->text.isEmpty()) + tf |= Qt::AlignLeft; + } else { + tf |= Qt::AlignHCenter; + } + drawItemText(painter, ir, tf, btn->palette, (btn->state & State_Enabled), + btn->text, QPalette::ButtonText); + painter->restore(); + } + break; + default: + QWindowsStyle::drawControl(element, option, painter, widget); + break; + } +} + +void QWindowsCEStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const { + switch (control) { + #ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + int thickness = pixelMetric(PM_SliderControlThickness, slider, widget); + int len = pixelMetric(PM_SliderLength, slider, widget); + int ticks = slider->tickPosition; + QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, widget); + QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, widget); + + if ((slider->subControls & SC_SliderGroove) && groove.isValid()) { + int mid = thickness / 2; + if (ticks & QSlider::TicksAbove) + mid += len / 8; + if (ticks & QSlider::TicksBelow) + mid -= len / 8; + + painter->setPen(slider->palette.shadow().color()); + if (slider->orientation == Qt::Horizontal) { + QWindowsCEStylePrivate::drawWinCEPanel(painter, groove.x(), groove.y() + mid - 2, + groove.width(), 4, option->palette, true); + painter->drawLine(groove.x() + 1, groove.y() + mid - 1, + groove.x() + groove.width() - 3, groove.y() + mid - 1); + } else { + QWindowsCEStylePrivate::drawWinCEPanel(painter, groove.x() + mid - 2, groove.y(), + 4, groove.height(), option->palette, true); + painter->drawLine(groove.x() + mid - 1, groove.y() + 1, + groove.x() + mid - 1, groove.y() + groove.height() - 3); + } + } + if (slider->subControls & SC_SliderTickmarks) { + QStyleOptionSlider tmpSlider = *slider; + tmpSlider.subControls = SC_SliderTickmarks; + QCommonStyle::drawComplexControl(control, &tmpSlider, painter, widget); + } + + if (slider->subControls & SC_SliderHandle) { + // 4444440 + // 4333310 + // 4322210 + // 4322210 + // 4322210 + // 4322210 + // *43210* + // **440** + // ***0*** + const QColor c0 = slider->palette.shadow().color(); + const QColor c1 = slider->palette.dark().color(); + // const QColor c2 = g.button(); + const QColor c3 = slider->palette.midlight().color(); + const QColor c4 = slider->palette.dark().color(); + QBrush handleBrush; + + if (slider->state & State_Enabled) { + handleBrush = slider->palette.color(QPalette::Button); + } else { + handleBrush = QBrush(slider->palette.color(QPalette::Button), + Qt::Dense4Pattern); + } + + int x = handle.x(), y = handle.y(), + wi = handle.width(), he = handle.height(); + + int x1 = x; + int x2 = x + wi - 1; + int y1 = y; + int y2 = y + he - 1; + + Qt::Orientation orient = slider->orientation; + bool tickAbove = slider->tickPosition == QSlider::TicksAbove; + bool tickBelow = slider->tickPosition == QSlider::TicksBelow; + + if (slider->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*slider); + fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget); + drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + if ((tickAbove && tickBelow) || (!tickAbove && !tickBelow)) { + Qt::BGMode oldMode = painter->backgroundMode(); + painter->setBackgroundMode(Qt::OpaqueMode); + QWindowsCEStylePrivate::drawWinCEButton(painter, QRect(x, y, wi, he), slider->palette, false, + &handleBrush); + painter->setBackgroundMode(oldMode); + QBrush fill = QBrush(option->palette.light().color(), Qt::Dense4Pattern); + if (slider->state & State_Sunken) + painter->fillRect(QRectF(x1 + 2, y1 + 2, x2 - x1 - 3, y2 - y1 - 3),fill); + return; + } + QSliderDirection dir; + if (orient == Qt::Horizontal) + if (tickAbove) + dir = SlUp; + else + dir = SlDown; + else + if (tickAbove) + dir = SlLeft; + else + dir = SlRight; + QPolygon a; + int d = 0; + switch (dir) { + case SlUp: + x2++; + y1 = y1 + wi / 2; + d = (wi + 1) / 2 - 1; + a.setPoints(5, x1, y1, x1, y2, x2, y2, x2, y1, x1 + d, y1 - d); + break; + case SlDown: + x2++; + y2 = y2 - wi / 2; + d = (wi + 1) / 2 - 1; + a.setPoints(5, x1, y1, x1, y2, x1 + d, y2+d, x2, y2, x2, y1); + break; + case SlLeft: + d = (he + 1) / 2 - 1; + x1 = x1 + he / 2; + a.setPoints(5, x1, y1, x1 - d, y1 + d, x1, y2, x2, y2, x2, y1); + y1--; + break; + case SlRight: + d = (he + 1) / 2 - 1; + x2 = x2 - he / 2; + a.setPoints(5, x1, y1, x1, y2, x2, y2, x2 + d, y1 + d, x2, y1); + y1--; + break; + } + QBrush oldBrush = painter->brush(); + painter->setPen(Qt::NoPen); + painter->setBrush(handleBrush); + Qt::BGMode oldMode = painter->backgroundMode(); + painter->setBackgroundMode(Qt::OpaqueMode); + painter->drawRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); + painter->drawPolygon(a); + QBrush fill = QBrush(option->palette.light().color(), Qt::Dense4Pattern); + if (slider->state & State_Sunken) + painter->fillRect(QRectF(x1, y1, x2 - x1 + 1, y2 - y1 + 1),fill); + painter->setBrush(oldBrush); + painter->setBackgroundMode(oldMode); + + if (dir != SlUp) { + painter->setPen(c4); + painter->drawLine(x1, y1, x2, y1); + painter->setPen(c3); + painter->drawLine(x1, y1 + 1, x2, y1 + 1); + } + if (dir != SlLeft) { + painter->setPen(c3); + painter->drawLine(x1 + 1, y1 + 1, x1 + 1, y2); + painter->setPen(c4); + painter->drawLine(x1, y1, x1, y2); + } + if (dir != SlRight) { + painter->setPen(c0); + painter->drawLine(x2, y1, x2, y2); + painter->setPen(c1); + painter->drawLine(x2 - 1, y1 + 1, x2 - 1, y2 - 1); + } + if (dir != SlDown) { + painter->setPen(c0); + painter->drawLine(x1, y2, x2, y2); + painter->setPen(c1); + painter->drawLine(x1+1, y2 - 1, x2 - 1, y2 - 1); + } + + switch (dir) { + case SlUp: + if (slider->state & State_Sunken) + painter->fillRect(QRectF(x1 + 3, y1 - d + 2, x2 - x1 - 4,y1), fill); + painter->setPen(c4); + painter->drawLine(x1, y1, x1 + d, y1 - d); + painter->setPen(c0); + d = wi - d - 1; + painter->drawLine(x2, y1, x2 - d, y1 - d); + d--; + painter->setPen(c3); + painter->drawLine(x1 + 1, y1, x1 + 1 + d-1, y1 - d + 1); + painter->setPen(c1); + painter->drawLine(x2 - 1, y1, x2-1 - d, y1 - d); + break; + case SlDown: + if (slider->state & State_Sunken) + painter->fillRect(QRectF(x1 + 3, y2 - d, x2 - x1 - 4,y2 - 8), fill); + painter->setPen(c4); + painter->drawLine(x1, y2, x1 + d, y2 + d); + painter->setPen(c0); + d = wi - d - 1; + painter->drawLine(x2, y2, x2 - d, y2 + d); + d--; + painter->setPen(c3); + painter->drawLine(x1 + 1, y2, x1 + 1 + d - 1, y2 + d - 1); + painter->setPen(c1); + painter->drawLine(x2 - 1, y2, x2 - 1 - d, y2 + d); + break; + case SlLeft: + if (slider->state & State_Sunken) + painter->fillRect(QRectF(x1 - d + 2, y1 + 2, x1,y2 - y1 - 3), fill); + painter->setPen(c4); + painter->drawLine(x1, y1, x1 - d, y1 + d); + painter->setPen(c0); + d = he - d - 1; + painter->drawLine(x1, y2, x1 - d, y2 - d); + d--; + painter->setPen(c3); + painter->drawLine(x1, y1 + 1, x1 - d + 1, y1 + 1 + d - 1); + painter->setPen(c1); + painter->drawLine(x1, y2 - 1, x1 - d, y2 - 1 - d); + break; + case SlRight: + if (slider->state & State_Sunken) + painter->fillRect(QRectF(x2 - d - 4, y1 + 2, x2 - 4, y2 - y1 - 3), fill); + painter->setPen(c4); + painter->drawLine(x2, y1, x2 + d, y1 + d); + painter->setPen(c0); + d = he - d - 1; + painter->drawLine(x2, y2, x2 + d, y2 - d); + d--; + painter->setPen(c3); + painter->drawLine(x2, y1 + 1, x2 + d - 1, y1 + 1 + d - 1); + painter->setPen(c1); + painter->drawLine(x2, y2 - 1, x2 + d, y2 - 1 - d); + break; + } + } + } + break; +#endif // QT_NO_SLIDER + case CC_ToolButton: + if (const QStyleOptionToolButton *toolbutton + = qstyleoption_cast(option)) { + QRect button, menuarea; + +#ifndef QT_NO_TOOLBAR + bool flat = !(widget ? qobject_cast(widget->parentWidget()) : 0); +#else + bool flat = true; +#endif + + button = subControlRect(control, toolbutton, SC_ToolButton, widget); + menuarea = subControlRect(control, toolbutton, SC_ToolButtonMenu, widget); + + if (flat && (toolbutton->subControls & SC_ToolButtonMenu)) { + menuarea.setLeft(menuarea.left() - 4); + button.setRight(button.right() - 4); + } + + State bflags = toolbutton->state; + + if (bflags & State_AutoRaise) + if (!(bflags & State_MouseOver)) { + bflags &= ~State_Raised; + } + State mflags = bflags; + + if (toolbutton->activeSubControls & SC_ToolButton) + bflags |= State_Sunken; + if (toolbutton->activeSubControls & SC_ToolButtonMenu) + mflags |= State_Sunken; + + QStyleOption tool(0); + tool.palette = toolbutton->palette; + if (toolbutton->subControls & SC_ToolButton) { + tool.rect = button; + tool.state = bflags; + drawPrimitive(PE_PanelButtonTool, &tool, painter, widget); + } + + if (toolbutton->subControls & SC_ToolButtonMenu) { + tool.rect = menuarea; + tool.state = mflags; + tool.state = bflags; + drawPrimitive(PE_IndicatorButtonDropDown, &tool, painter, widget); + + if (!flat) { + + //connect buttons + painter->save(); + painter->setPen(tool.palette.button().color()); + painter->drawLine(tool.rect.x() - 2, tool.rect.y(), tool.rect.x() - 2, tool.rect.y() + tool.rect.height()); + painter->drawLine(tool.rect.x() - 1, tool.rect.y(), tool.rect.x() - 1, tool.rect.y() + tool.rect.height()); + painter->drawLine(tool.rect.x(), tool.rect.y(), tool.rect.x(), tool.rect.y() + tool.rect.height()); + painter->drawLine(tool.rect.x() + 1, tool.rect.y(), tool.rect.x() + 1, tool.rect.y() + tool.rect.height()); + + if (tool.state & State_Sunken) + { + painter->setPen(tool.palette.midlight().color()); + painter->drawLine(tool.rect.x() - 2, tool.rect.y() + tool.rect.height() - 2, + tool.rect.x() + 1, tool.rect.y() + tool.rect.height() -2 ); + painter->setPen(tool.palette.shadow().color()); + painter->drawLine(tool.rect.x() - 2, tool.rect.y() + 1,tool.rect.x() + 1, tool.rect.y() + 1); + painter->drawLine(tool.rect.x() - 2, tool.rect.y(), tool.rect.x() + 1, tool.rect.y()); + painter->setPen(tool.palette.light().color()); + painter->drawLine(tool.rect.x() - 2, tool.rect.y() + tool.rect.height() - 1, + tool.rect.x() + 1, tool.rect.y() + tool.rect.height() - 1); + } + else + { + painter->setPen(tool.palette.dark().color()); + painter->drawLine(tool.rect.x() - 2, tool.rect.y(),tool.rect.x() + 1, tool.rect.y()); + painter->drawLine(tool.rect.x() - 2, tool.rect.y()+tool.rect.height() - 2,tool.rect.x() + 1, + tool.rect.y() + tool.rect.height() - 2); + painter->setPen(tool.palette.midlight().color()); + painter->drawLine(tool.rect.x() - 2, tool.rect.y() + 1,tool.rect.x() + 1, tool.rect.y() + 1); + painter->setPen(tool.palette.shadow().color()); + painter->drawLine(tool.rect.x() - 2, tool.rect.y() + tool.rect.height() - 1, + tool.rect.x() + 1, tool.rect.y() + tool.rect.height() - 1); + } + painter->restore(); + } + + + if (!flat) { + tool.rect.adjust(-3,0,-3,0); + painter->save(); + painter->setPen(tool.palette.button().color()); + if (tool.state & State_Sunken) + painter->drawLine(tool.rect.x() + 2, tool.rect.y() + 10, + tool.rect.x() + tool.rect.width(), tool.rect.y() + 10); + else + painter->drawLine(tool.rect.x() + 1, tool.rect.y() + 9, tool.rect.x() + + tool.rect.width() - 1, tool.rect.y() + 9); + painter->restore(); + } else { + tool.rect.adjust(-1,0,-1,0); + } + + drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget); + } + + if (toolbutton->state & State_HasFocus) { + QStyleOptionFocusRect fr; + fr.QStyleOption::operator=(*toolbutton); + fr.rect.adjust(3, 3, -3, -3); + if (toolbutton->features & QStyleOptionToolButton::Menu) + fr.rect.adjust(0, 0, -pixelMetric(QStyle::PM_MenuButtonIndicator, + toolbutton, widget), 0); + drawPrimitive(PE_FrameFocusRect, &fr, painter, widget); + } + QStyleOptionToolButton label = *toolbutton; + int fw = pixelMetric(PM_DefaultFrameWidth, option, widget); + label.rect = button.adjusted(fw, fw, -fw, -fw); + drawControl(CE_ToolButtonLabel, &label, painter, widget); + } + break; + +#ifndef QT_NO_GROUPBOX + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(option)) { + // Draw frame + painter->save(); + QFont f = painter->font(); + f.setBold(true); + painter->setFont(f); + QStyleOptionGroupBox groupBoxFont = *groupBox; + groupBoxFont.fontMetrics = QFontMetrics(f); + QRect textRect = subControlRect(CC_GroupBox, &groupBoxFont, SC_GroupBoxLabel, widget); + QRect checkBoxRect = subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget); + if (groupBox->subControls & QStyle::SC_GroupBoxFrame) { + QStyleOptionFrameV2 frame; + frame.QStyleOption::operator=(*groupBox); + frame.features = groupBox->features; + frame.lineWidth = groupBox->lineWidth; + frame.midLineWidth = groupBox->midLineWidth; + frame.rect = subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget); + painter->save(); + + QRegion region(groupBox->rect); + if (!groupBox->text.isEmpty()) { + bool ltr = groupBox->direction == Qt::LeftToRight; + QRect finalRect = checkBoxRect.united(textRect); + if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) + finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0); + region -= finalRect; + } + painter->setClipRegion(region); + drawPrimitive(PE_FrameGroupBox, &frame, painter, widget); + painter->restore(); + } + + // Draw title + if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) { + QColor textColor = groupBox->textColor; + if (textColor.isValid()) + painter->setPen(textColor); + int alignment = int(groupBox->textAlignment); + if (!styleHint(QStyle::SH_UnderlineShortcut, option, widget)) + alignment |= Qt::TextHideMnemonic; + + drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment, + groupBox->palette, groupBox->state & State_Enabled, groupBox->text, + textColor.isValid() ? QPalette::NoRole : QPalette::WindowText); + + if (groupBox->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*groupBox); + fropt.rect = textRect; + drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + } + // Draw checkbox + if (groupBox->subControls & SC_GroupBoxCheckBox) { + QStyleOptionButton box; + box.QStyleOption::operator=(*groupBox); + box.rect = checkBoxRect; + drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget); + } + painter->restore(); + } + break; +#endif //QT_NO_GROUPBOX +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) { + QBrush editBrush = cmb->palette.brush(QPalette::Base); + if ((cmb->subControls & SC_ComboBoxFrame) && cmb->frame) + QWindowsCEStylePrivate::drawWinCEPanel(painter, option->rect, option->palette, true, &editBrush); + else + painter->fillRect(option->rect, editBrush); + + if (cmb->subControls & SC_ComboBoxArrow) { + State flags = State_None; + + QRect ar = subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget); + if (cmb->activeSubControls == SC_ComboBoxArrow) { + painter->setPen(cmb->palette.dark().color()); + painter->setBrush(cmb->palette.brush(QPalette::Button)); + painter->drawRect(ar.adjusted(0, 0, -1, -1)); + QWindowsCEStylePrivate::drawWinCEButton(painter, ar.adjusted(0, 0, -1, -1), option->palette, true, + &cmb->palette.brush(QPalette::Button)); + } else { + // Make qDrawWinButton use the right colors for drawing the shade of the button + + QWindowsCEStylePrivate::drawWinCEButton(painter, ar, option->palette, false, + &cmb->palette.brush(QPalette::Button)); + } + + ar.adjust(2, 2, -2, -2); + if (option->state & State_Enabled) + flags |= State_Enabled; + + if (cmb->activeSubControls == SC_ComboBoxArrow) + flags |= State_Sunken; + QStyleOption arrowOpt(0); + arrowOpt.rect = ar; + arrowOpt.palette = cmb->palette; + arrowOpt.state = flags; + drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget); + } + if (cmb->subControls & SC_ComboBoxEditField) { + QRect re = subControlRect(CC_ComboBox, cmb, SC_ComboBoxEditField, widget); + if (cmb->state & State_HasFocus && !cmb->editable) + painter->fillRect(re.x(), re.y(), re.width(), re.height(), + cmb->palette.brush(QPalette::Highlight)); + if (cmb->state & State_HasFocus) { + painter->setPen(cmb->palette.highlightedText().color()); + painter->setBackground(cmb->palette.highlight()); + } else { + painter->setPen(cmb->palette.text().color()); + painter->setBackground(cmb->palette.background()); + } + if (cmb->state & State_HasFocus && !cmb->editable) { + QStyleOptionFocusRect focus; + focus.QStyleOption::operator=(*cmb); + focus.rect = subElementRect(SE_ComboBoxFocusRect, cmb, widget); + focus.state |= State_FocusAtBorder; + focus.backgroundColor = cmb->palette.highlight().color(); + drawPrimitive(PE_FrameFocusRect, &focus, painter, widget); + } + } + } + break; +#endif // QT_NO_COMBOBOX +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *sb = qstyleoption_cast(option)) { + QStyleOptionSpinBox copy = *sb; + PrimitiveElement pe; + + if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) { + QRect r = subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget); + QWindowsCEStylePrivate::drawWinCEPanel(painter, r, option->palette, true); + } + QPalette shadePal(option->palette); + shadePal.setColor(QPalette::Button, option->palette.light().color()); + shadePal.setColor(QPalette::Light, option->palette.button().color()); + + bool reverse = QApplication::layoutDirection() == Qt::RightToLeft; + + if (sb->subControls & SC_SpinBoxUp) { + copy.subControls = SC_SpinBoxUp; + QPalette pal2 = sb->palette; + if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled)) { + pal2.setCurrentColorGroup(QPalette::Disabled); + copy.state &= ~State_Enabled; + } + copy.palette = pal2; + if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken)) { + copy.state |= State_On; + copy.state |= State_Sunken; + } else { + copy.state |= State_Raised; + copy.state &= ~State_Sunken; + } + if (reverse) + pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus + : PE_IndicatorSpinDown); + else + pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus + : PE_IndicatorSpinUp); + copy.rect = subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget); + QWindowsCEStylePrivate::drawWinCEButton(painter, copy.rect, option->palette, copy.state & (State_Sunken | State_On), + ©.palette.brush(QPalette::Button)); + copy.rect.adjust(3, 0, -4, 0); + drawPrimitive(pe, ©, painter, widget); + } + if (sb->subControls & SC_SpinBoxDown) { + copy.subControls = SC_SpinBoxDown; + copy.state = sb->state; + QPalette pal2 = sb->palette; + if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled)) { + pal2.setCurrentColorGroup(QPalette::Disabled); + copy.state &= ~State_Enabled; + } + copy.palette = pal2; + + if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken)) { + copy.state |= State_On; + copy.state |= State_Sunken; + } else { + copy.state |= State_Raised; + copy.state &= ~State_Sunken; + } + if (reverse) + pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus + : PE_IndicatorSpinUp); + else + pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus + : PE_IndicatorSpinDown); + copy.rect = subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget); + QWindowsCEStylePrivate::drawWinCEButton(painter, copy.rect, shadePal, copy.state & (State_Sunken | State_On), + ©.palette.brush(QPalette::Button)); + + copy.rect.adjust(3, 0, -4, 0); + if (pe == PE_IndicatorArrowUp || pe == PE_IndicatorArrowDown) { + copy.rect = copy.rect.adjusted(1, 1, -1, -1); + drawPrimitive(pe, ©, painter, widget); + } + else { + drawPrimitive(pe, ©, painter, widget); + } + if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) { + QRect r = subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget); + painter->save(); + painter->setPen(option->palette.light().color()); + painter->drawLine(r.x() + 1 + r.width(), r.y() - 2, r.x() + 1 + r.width(), r.y() + r.height() + 1); + painter->setPen(option->palette.midlight().color()); + painter->drawLine(r.x() + r.width(), r.y() - 1, r.x() + r.width(), r.y() + r.height()); + painter->restore(); + } + } + } + break; +#endif // QT_NO_SPINBOX + + default: + QWindowsStyle::drawComplexControl(control, option, painter, widget); + break; + } +} + +void QWindowsCEStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal, + bool enabled, const QString& text, QPalette::ColorRole textRole) const { + if (text.isEmpty()) + return; + QPen savedPen; + if (textRole != QPalette::NoRole) { + savedPen = painter->pen(); + painter->setPen(pal.color(textRole)); + } + if (!enabled) { + QPen pen = painter->pen(); + painter->setPen(pal.light().color()); + //painter->drawText(rect.adjusted(1, 1, 1, 1), alignment, text); + painter->setPen(pen); + } + painter->drawText(rect, alignment, text); + if (textRole != QPalette::NoRole) + painter->setPen(savedPen); +} + + +QSize QWindowsCEStyle::sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const { + QSize newSize = QWindowsStyle::sizeFromContents(type, option, size, widget); + switch (type) { + case CT_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + newSize = QWindowsStyle::sizeFromContents(type, option, size, widget); + int w = newSize.width(), + h = newSize.height(); + int defwidth = 0; + if (btn->features & QStyleOptionButton::AutoDefaultButton) + defwidth = 2 * pixelMetric(PM_ButtonDefaultIndicator, btn, widget); + if (w < 75 + defwidth && btn->icon.isNull()) + w = 75 + defwidth; + if (h < 23 + defwidth) + h = 23 + defwidth; + newSize = QSize(w+14, h); + } + break; + + case CT_RadioButton: + case CT_CheckBox: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + bool isRadio = (type == CT_RadioButton); + QRect irect = visualRect(btn->direction, btn->rect, + subElementRect(isRadio ? SE_RadioButtonIndicator + : SE_CheckBoxIndicator, btn, widget)); + int h = pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight + : PM_IndicatorHeight, btn, widget); + int margins = (!btn->icon.isNull() && btn->text.isEmpty()) ? 0 : 10; + newSize += QSize(irect.right() + margins, 4); + newSize.setHeight(qMax(newSize.height(), h)); + } + break; + case CT_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) { + int fw = cmb->frame ? pixelMetric(PM_ComboBoxFrameWidth, option, widget) * 2 : 0; + newSize = QSize(newSize.width() + fw -1, qMax(24, newSize.height() + fw-1)); + } + break; +#ifndef QT_NO_SPINBOX + case CT_SpinBox: + if (const QStyleOptionSpinBox *spnb = qstyleoption_cast(option)) { + int fw = spnb->frame ? pixelMetric(PM_SpinBoxFrameWidth, option, widget) * 2 : 0; + newSize = QSize(newSize.width() + fw - 5, newSize.height() + fw - 6); + } + break; +#endif + case CT_LineEdit: + newSize += QSize(0,1); + break; + case CT_MenuBarItem: + newSize += QSize(5, 1); + break; + case CT_MenuItem: + newSize += QSize(0, -2); + break; + case CT_MenuBar: + newSize += QSize(0, -1); + break; + case CT_ToolButton: + if (const QStyleOptionToolButton *b = qstyleoption_cast(option)) { + if (b->toolButtonStyle != Qt::ToolButtonIconOnly) + newSize = QSize(newSize.width() + 1, newSize.height() - 1); + else + newSize = QSize(newSize.width() + 1, newSize.height()); + } + break; + + default: + break; + } + return newSize; +} + +QRect QWindowsCEStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const { + QRect rect = QWindowsStyle::subElementRect(element, option, widget); + switch (element) { +#ifndef QT_NO_COMBOBOX + case SE_ComboBoxFocusRect: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(option)) { + int margin = cb->frame ? 3 : 0; + rect.setRect(margin, margin, option->rect.width() - 2*margin - 20, option->rect.height() - 2*margin); + rect = visualRect(option->direction, option->rect, rect); + } + break; +#endif // QT_NO_COMBOBOX + default: + break; + } + return rect; +} + +QRect QWindowsCEStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, + SubControl subControl, const QWidget *widget) const { + QRect rect = QWindowsStyle::subControlRect(control, option, subControl, widget); + switch (control) { +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget); + int thickness = pixelMetric(PM_SliderControlThickness, slider, widget); + + switch (subControl) { + case SC_SliderHandle: { + int sliderPos = 0; + int len = pixelMetric(PM_SliderLength, slider, widget); + bool horizontal = slider->orientation == Qt::Horizontal; + sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum, + slider->sliderPosition, + (horizontal ? slider->rect.width() + : slider->rect.height()) - len, + slider->upsideDown); + if (horizontal) + rect.setRect(slider->rect.x() + sliderPos, slider->rect.y() + tickOffset, len, thickness); + else + rect.setRect(slider->rect.x() + tickOffset, slider->rect.y() + sliderPos, thickness, len); + break; } + default: + break; + } + rect = visualRect(slider->direction, slider->rect, rect); + } + break; +#endif //QT_NO_SLIDER +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(option)) { + int x = cb->rect.x(), + y = cb->rect.y(), + wi = cb->rect.width(), + he = cb->rect.height(); + int xpos = x; + int margin = cb->frame ? 3 : 0; + int bmarg = cb->frame ? 2 : 0; + xpos += wi - (he - 2*bmarg) - bmarg; + switch (subControl) { + case SC_ComboBoxArrow: + rect.setRect(xpos, y + bmarg, he - 2*bmarg, he - 2*bmarg); + break; + case SC_ComboBoxEditField: + rect.setRect(x + margin, y + margin, wi - 2 * margin - (he - 2*bmarg), he - 2 * margin); + break; + case SC_ComboBoxListBoxPopup: + rect = cb->rect; + break; + case SC_ComboBoxFrame: + rect = cb->rect; + break; + default: + break; + } + rect = visualRect(cb->direction, cb->rect, rect); + } +#endif //QT_NO_COMBOBOX +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(option)) { + QSize bs; + int fw = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0; + bs.setWidth(qMax(18, (spinbox->rect.height() / 2 - fw + 1))); + // 1.6 -approximate golden mean + bs.setHeight(qMax(18, qMin((bs.height() * 8 / 5), (spinbox->rect.width() / 4)))); + bs = bs.expandedTo(QApplication::globalStrut()); + int y = fw; + int x, lx, rx; + x = spinbox->rect.width() - y - bs.width() * 2; + lx = fw; + rx = x - fw; + switch (subControl) { + case SC_SpinBoxUp: + rect = QRect(x + bs.width(), y, bs.width(), bs.height()); + break; + case SC_SpinBoxDown: + rect = QRect(x, y , bs.width(), bs.height()); + break; + case SC_SpinBoxEditField: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) { + rect = QRect(lx, fw, spinbox->rect.width() - 2*fw - 2, spinbox->rect.height() - 2*fw); + } else { + rect = QRect(lx, fw, rx-2, spinbox->rect.height() - 2*fw); + } + break; + case SC_SpinBoxFrame: + rect = spinbox->rect; + default: + break; + } + rect = visualRect(spinbox->direction, spinbox->rect, rect); + } + break; +#endif // Qt_NO_SPINBOX +#ifndef QT_NO_GROUPBOX + case CC_GroupBox: { + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(option)) { + switch (subControl) { + case SC_GroupBoxFrame: + // FALL THROUGH + case SC_GroupBoxContents: { + int topMargin = 0; + int topHeight = 0; + int bottomMargin = 0; + int noLabelMargin = 0; + QRect frameRect = groupBox->rect; + int verticalAlignment = styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget); + if (groupBox->text.size()) { + topHeight = groupBox->fontMetrics.height(); + if (verticalAlignment & Qt::AlignVCenter) + topMargin = topHeight / 2; + else if (verticalAlignment & Qt::AlignTop) + topMargin = -topHeight/2; + } + else { + topHeight = groupBox->fontMetrics.height(); + noLabelMargin = topHeight / 2; + if (verticalAlignment & Qt::AlignVCenter) { + topMargin = topHeight / 4 - 4; + bottomMargin = topHeight / 4 - 4; + } + else if (verticalAlignment & Qt::AlignTop) { + topMargin = topHeight/2 - 4; + bottomMargin = topHeight/2 - 4; + } + } + + if (subControl == SC_GroupBoxFrame) { + frameRect.setTop(topMargin); + frameRect.setBottom(frameRect.height() + bottomMargin); + rect = frameRect; + break; + } + + int frameWidth = 0; + if ((groupBox->features & QStyleOptionFrameV2::Flat) == 0) + frameWidth = pixelMetric(PM_DefaultFrameWidth, groupBox, widget); + rect = frameRect.adjusted(frameWidth, frameWidth + topHeight, -frameWidth, -frameWidth - noLabelMargin); + break; + } + case SC_GroupBoxCheckBox: + // FALL THROUGH + case SC_GroupBoxLabel: { + QFontMetrics fontMetrics = groupBox->fontMetrics; + int h = fontMetrics.height(); + int tw = fontMetrics.size(Qt::TextShowMnemonic, groupBox->text + QLatin1Char(' ')).width(); + int marg = (groupBox->features & QStyleOptionFrameV2::Flat) ? 0 : 8; + rect = groupBox->rect.adjusted(marg, 0, -marg, 0); + rect.setHeight(h); + + int indicatorWidth = pixelMetric(PM_IndicatorWidth, option, widget); + int indicatorSpace = pixelMetric(PM_CheckBoxLabelSpacing, option, widget) - 1; + bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox; + int checkBoxSize = hasCheckBox ? (indicatorWidth + indicatorSpace) : 0; + + // Adjusted rect for label + indicatorWidth + indicatorSpace + QRect totalRect = alignedRect(groupBox->direction, groupBox->textAlignment, + QSize(tw + checkBoxSize, h), rect); + + // Adjust totalRect if checkbox is set + if (hasCheckBox) { + bool ltr = groupBox->direction == Qt::LeftToRight; + int left = 0; + // Adjust for check box + if (subControl == SC_GroupBoxCheckBox) { + int indicatorHeight = pixelMetric(PM_IndicatorHeight, option, widget); + left = ltr ? totalRect.left() : (totalRect.right() - indicatorWidth); + int top = totalRect.top() + (fontMetrics.height() - indicatorHeight) / 2; + totalRect.setRect(left, top, indicatorWidth, indicatorHeight); + // Adjust for label + } else { + left = ltr ? (totalRect.left() + checkBoxSize - 2) : totalRect.left(); + totalRect.setRect(left, totalRect.top(), + totalRect.width() - checkBoxSize, totalRect.height()); + } + } + rect = totalRect; + break; + } + default: + break; + } + } + break; + } +#endif // QT_NO_GROUPBOX + default: + break; + } + return rect; +} + +QStyle::SubControl QWindowsCEStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, + const QPoint &pos, const QWidget *widget) const { + /*switch (control) { + default: + break; + }*/ + return QWindowsStyle::hitTestComplexControl(control, option, pos, widget); +} + + +QPalette QWindowsCEStyle::standardPalette() const { + QPalette palette (Qt::black,QColor(198, 195, 198), QColor(222, 223, 222 ), + QColor(132, 130, 132), QColor(198, 195, 198) , Qt::black, Qt::white, Qt::white, QColor(198, 195, 198)); + palette.setColor(QPalette::Window, QColor(198, 195, 198)); + palette.setColor(QPalette::Base, Qt::white); + palette.setColor(QPalette::Button, QColor(198, 195, 198)); + palette.setColor(QPalette::Highlight, QColor(0, 0, 132)); + palette.setColor(QPalette::Light, Qt::white); + palette.setColor(QPalette::Midlight, QColor(222, 223, 222 )); + palette.setColor(QPalette::Dark, QColor(132, 130, 132)); + palette.setColor(QPalette::Mid, QColor(132, 130, 132)); + palette.setColor(QPalette::Shadow, QColor(0, 0, 0)); + palette.setColor(QPalette::BrightText, QColor(33, 162, 33)); //color for ItemView checked indicator (arrow) + palette.setColor(QPalette::Link, QColor(24,81,132)); // color for the box around the ItemView indicator + + return palette; +} + +void QWindowsCEStyle::polish(QApplication *app) { + QWindowsStyle::polish(app); +} + +void QWindowsCEStyle::polish(QWidget *widget) { + QWindowsStyle::polish(widget); +} + +void QWindowsCEStyle::polish(QPalette &palette) { + QWindowsStyle::polish(palette); +} + +int QWindowsCEStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWidget *widget) const { + int ret; + + switch (pm) { + case PM_DefaultFrameWidth: + ret = 1; + break; + + case PM_MenuBarHMargin: + ret = 2; + break; + case PM_MenuBarVMargin: + ret = 2; + break; + /*case PM_MenuBarItemSpacing: + ret = 2; + break;*/ + + case PM_MenuButtonIndicator: + ret = 10; + break; + + case PM_SpinBoxFrameWidth: + ret = 2; + break; + case PM_ButtonDefaultIndicator: + case PM_ButtonShiftHorizontal: + case PM_ButtonShiftVertical: + ret = 1; + break; +#ifndef QT_NO_TABBAR + case PM_TabBarTabShiftHorizontal: + ret = 0; + break; + case PM_TabBarTabShiftVertical: + ret = 6; + break; +#endif + case PM_MaximumDragDistance: + ret = 60; + break; + + case PM_IndicatorWidth: + ret = windowsCEIndicatorSize; + break; + + case PM_IndicatorHeight: + ret = windowsCEIndicatorSize; + break; + + case PM_ExclusiveIndicatorWidth: + ret = windowsCEExclusiveIndicatorSize; + break; + + case PM_ExclusiveIndicatorHeight: + ret = windowsCEExclusiveIndicatorSize;; + break; + +#ifndef QT_NO_SLIDER + case PM_SliderLength: + ret = 12; + break; + case PM_SliderThickness: + ret = windowsCESliderThickness; + break; + + case PM_TabBarScrollButtonWidth: + ret = 18; + break; + + // Returns the number of pixels to use for the business part of the + // slider (i.e., the non-tickmark portion). The remaining space is shared + // equally between the tickmark regions. + case PM_SliderControlThickness: + if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { + int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height() : sl->rect.width(); + int ticks = sl->tickPosition; + int n = 0; + if (ticks & QSlider::TicksAbove) + ++n; + if (ticks & QSlider::TicksBelow) + ++n; + if (!n) { + ret = space; + break; + } + int thick = 12; + if (ticks != QSlider::TicksBothSides && ticks != QSlider::NoTicks) + thick += pixelMetric(PM_SliderLength, sl, widget) / 4; + + space -= thick; + if (space > 0) + thick += (space * 2) / (n + 2); + ret = thick; + } else { + ret = 0; + } + break; +#endif // QT_NO_SLIDER + +#ifndef QT_NO_MENU + + case PM_SmallIconSize: + ret = windowsCEIconSize; + break; + case PM_ButtonMargin: + ret = 6; + break; + + case PM_LargeIconSize: + ret = 32; + break; + + case PM_IconViewIconSize: + ret = pixelMetric(PM_LargeIconSize, opt, widget); + break; + + case PM_ToolBarIconSize: + ret = windowsCEIconSize; + break; + case PM_DockWidgetTitleMargin: + ret = 2; + break; +#if defined(Q_WS_WIN) +// case PM_DockWidgetFrameWidth: +// ret = GetSystemMetrics(SM_CXFRAME); +// break; +#else + case PM_DockWidgetFrameWidth: + ret = 4; + break; +#endif // Q_WS_WIN + break; + +#endif // QT_NO_MENU + + case PM_TitleBarHeight: + ret = 30; + break; + case PM_ScrollBarExtent: + ret = 19; + break; + case PM_SplitterWidth: + ret = qMax(4, QApplication::globalStrut().width()); + break; + +#if defined(Q_WS_WIN) + case PM_MDIFrameWidth: + ret = 3; + break; +#endif + case PM_ToolBarItemMargin: + ret = 1; + break; + case PM_ToolBarItemSpacing: + ret = 0; + break; + case PM_ToolBarHandleExtent: + ret = 10; + break; + case PM_ButtonIconSize: + ret = 22; + break; + default: + ret = QWindowsStyle::pixelMetric(pm, opt, widget); + break; + } + return ret; +} + +QPixmap QWindowsCEStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget) const { +#ifndef QT_NO_IMAGEFORMAT_XPM + /*switch (standardPixmap) { + + default: + break; + }*/ +#endif //QT_NO_IMAGEFORMAT_XPM + return QWindowsStyle::standardPixmap(standardPixmap, opt, widget); +} + +int QWindowsCEStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWidget *widget, + QStyleHintReturn *returnData) const { + int ret; + switch (hint) { + case SH_TabBar_ElideMode: + ret = Qt::ElideMiddle; + break; + case SH_EtchDisabledText: + ret = false; + break; + case SH_RequestSoftwareInputPanel: + ret = RSIP_OnMouseClick; + break; + default: + ret = QWindowsStyle::styleHint(hint, opt, widget, returnData); + break; + } + return ret; +} + +void QWindowsCEStylePrivate::drawWinShades(QPainter *p, + int x, int y, int w, int h, + const QColor &c1, const QColor &c2, + const QColor &c3, const QColor &c4, + const QBrush *fill) { + if (w < 2 || h < 2) // can't do anything with that + return; + QPen oldPen = p->pen(); + QPoint a[3] = { QPoint(x, y+h-2), QPoint(x, y), QPoint(x+w-2, y) }; + p->setPen(c1); + p->drawPolyline(a, 3); + QPoint b[3] = { QPoint(x, y+h-1), QPoint(x+w-1, y+h-1), QPoint(x+w-1, y) }; + p->setPen(c2); + p->drawPolyline(b, 3); + if (w > 4 && h > 4) { + QPoint c[3] = { QPoint(x+1, y+h-3), QPoint(x+1, y+1), QPoint(x+w-3, y+1) }; + p->setPen(c3); + p->drawPolyline(c, 3); + QPoint d[3] = { QPoint(x+1, y+h-2), QPoint(x+w-2, y+h-2), QPoint(x+w-2, y+1) }; + p->setPen(c4); + p->drawPolyline(d, 3); + if (fill) + p->fillRect(QRect(x+2, y+2, w-4, h-4), *fill); + } + p->setPen(oldPen); +} + +void QWindowsCEStylePrivate::drawWinCEShades(QPainter *p, + int x, int y, int w, int h, + const QColor &c1, const QColor &c2, + const QColor &c3, const QColor &c4, + const QBrush *fill) { + if (w < 2 || h < 2) // can't do anything with that + return; + QPen oldPen = p->pen(); + QPoint b[3] = { QPoint(x, y+h-1), QPoint(x+w-1, y+h-1), QPoint(x+w-1, y) }; + p->setPen(c2); + p->drawPolyline(b, 3); + if (w > 4 && h > 4) { + QPoint c[3] = { QPoint(x+1, y+h-3), QPoint(x+1, y+1), QPoint(x+w-3, y+1) }; + p->setPen(c3); + p->drawPolyline(c, 3); + QPoint d[5] = { QPoint(x, y+h-2), QPoint(x+w-2, y+h-2), QPoint(x+w-2, y), QPoint(x, y), QPoint(x, y+h-2) }; + p->setPen(c4); + p->drawPolyline(d, 5); + if (fill) + p->fillRect(QRect(x+2, y+2, w-4, h-4), *fill); + } + QPoint a[3] = { QPoint(x+1, y+h-3), QPoint(x+1, y+1), QPoint(x+w-3, y+1) }; + p->setPen(c1); + p->drawPolyline(a, 3); + p->setPen(oldPen); +} + +void QWindowsCEStylePrivate::drawWinCEShadesSunken(QPainter *p, + int x, int y, int w, int h, + const QColor &c1, const QColor &c2, + const QColor &c3, const QColor &c4, + const QBrush *fill) { + if (w < 2 || h < 2) // can't do anything with that + return; + QPen oldPen = p->pen(); + + QPoint b[3] = { QPoint(x, y+h-1), QPoint(x+w-1, y+h-1), QPoint(x+w-1, y) }; + p->setPen(c2); + p->drawPolyline(b, 3); + if (w > 4 && h > 4) { + QPoint d[3] = { QPoint(x, y+h-2), QPoint(x+w-2, y+h-2), QPoint(x+w-2, y) }; + p->setPen(c4); + p->drawPolyline(d, 3); + QPoint c[3] = { QPoint(x, y+h-2), QPoint(x, y), QPoint(x+w-2, y) }; + p->setPen(c3); + p->drawPolyline(c, 3); + if (fill) + p->fillRect(QRect(x+2, y+2, w-4, h-4), *fill); + } + QPoint a[3] = { QPoint(x+1, y+h-3), QPoint(x+1, y+1), QPoint(x+w-3, y+1) }; + p->setPen(c1); + p->drawPolyline(a, 3); + p->setPen(oldPen); +} + + +void QWindowsCEStylePrivate::drawWinCEButton(QPainter *p, int x, int y, int w, int h, + const QPalette &pal, bool sunken, + const QBrush *fill) { + if (sunken) + drawWinCEShadesSunken(p, x, y, w, h, + pal.shadow().color(), pal.light().color(), pal.shadow().color(), + pal.midlight().color(), fill); + else + drawWinCEShades(p, x, y, w, h, + pal.midlight().color(), pal.shadow().color(), pal.button().color(), + pal.dark().color(), fill); +} + +void QWindowsCEStylePrivate::drawWinCEPanel(QPainter *p, int x, int y, int w, int h, + const QPalette &pal, bool sunken, + const QBrush *fill) { + if (sunken) + drawWinShades(p, x, y, w, h, + pal.dark().color(), pal.light().color(), pal.shadow().color(), + pal.midlight().color(), fill); + else + drawWinShades(p, x, y, w, h, + pal.light().color(), pal.shadow().color(), pal.button().color(), + pal.midlight().color(), fill); +} + +void QWindowsCEStylePrivate::drawWinCEButton(QPainter *p, const QRect &r, + const QPalette &pal, bool sunken, const QBrush *fill) { + drawWinCEButton(p, r.x(), r.y(), r.width(), r.height(), pal, sunken, fill); +} + +void QWindowsCEStylePrivate::drawWinCEPanel(QPainter *p, const QRect &r, + const QPalette &pal, bool sunken, const QBrush *fill) { + drawWinCEPanel(p, r.x(), r.y(), r.width(), r.height(), pal, sunken, fill); +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_WINDOWSCE diff --git a/src/widgets/styles/qwindowscestyle.h b/src/widgets/styles/qwindowscestyle.h new file mode 100644 index 0000000000..3fd83bc764 --- /dev/null +++ b/src/widgets/styles/qwindowscestyle.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSCESTYLE_H +#define QWINDOWSCESTYLE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_STYLE_WINDOWSCE) + +class Q_GUI_EXPORT QWindowsCEStyle : public QWindowsStyle +{ + Q_OBJECT +public: + QWindowsCEStyle(); + + void drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget = 0) const; + + void drawControl(ControlElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const; + + void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const; + + virtual void drawItemText(QPainter *painter, const QRect &rect, + int flags, const QPalette &pal, bool enabled, + const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const; + + QSize sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const; + + QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const; + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, + SubControl sc, const QWidget *widget) const; + + SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, + const QPoint &pos, const QWidget *widget = 0) const; + + QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget = 0) const; + int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const; + + int styleHint(StyleHint hint, const QStyleOption *opt = 0, const QWidget *widget = 0, + QStyleHintReturn *returnData = 0) const; + + void polish(QWidget *widget); + void polish(QPalette &palette); + void polish(QApplication *app); + QPalette standardPalette() const; +}; + +#endif // QT_NO_STYLE_WINDOWSCE + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QWINDOWSCESTYLE_H diff --git a/src/widgets/styles/qwindowscestyle_p.h b/src/widgets/styles/qwindowscestyle_p.h new file mode 100644 index 0000000000..c2d9c68ea7 --- /dev/null +++ b/src/widgets/styles/qwindowscestyle_p.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSCE_P_H +#define QWINDOWSCE_P_H + +#include "qwindowscestyle.h" +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class QPainter; +class QPalette; +class QPoint; +class QColor; +class QBrush; +class QRect; + +// Private class +class QWindowsCEStylePrivate : public QWindowsStylePrivate +{ + Q_DECLARE_PUBLIC(QWindowsCEStyle) +public: + inline QWindowsCEStylePrivate() + { } + + +static void drawWinCEButton(QPainter *p, int x, int y, int w, int h, + const QPalette &pal, bool sunken = false, + const QBrush *fill = 0); + +static void drawWinCEButton(QPainter *p, const QRect &r, + const QPalette &pal, bool sunken = false, + const QBrush *fill = 0); + +static void drawWinCEPanel(QPainter *p, int x, int y, int w, int h, + const QPalette &pal, bool sunken = false, + const QBrush *fill = 0); + +static void drawWinCEPanel(QPainter *p, const QRect &r, + const QPalette &pal, bool sunken = false, + const QBrush *fill = 0); + +static void drawWinShades(QPainter *p, + int x, int y, int w, int h, + const QColor &c1, const QColor &c2, + const QColor &c3, const QColor &c4, + const QBrush *fill); + +static void drawWinCEShades(QPainter *p, + int x, int y, int w, int h, + const QColor &c1, const QColor &c2, + const QColor &c3, const QColor &c4, + const QBrush *fill); + +static void drawWinCEShadesSunken(QPainter *p, + int x, int y, int w, int h, + const QColor &c1, const QColor &c2, + const QColor &c3, const QColor &c4, + const QBrush *fill); + + + + +}; + +QT_END_NAMESPACE + +#endif //QWINDOWSCE_P_H diff --git a/src/widgets/styles/qwindowsmobilestyle.cpp b/src/widgets/styles/qwindowsmobilestyle.cpp new file mode 100644 index 0000000000..32cc2e63b8 --- /dev/null +++ b/src/widgets/styles/qwindowsmobilestyle.cpp @@ -0,0 +1,7283 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsmobilestyle.h" +#include "qwindowsmobilestyle_p.h" + +#if !defined(QT_NO_STYLE_WINDOWSMOBILE) || defined(QT_PLUGIN) + +#include "qpainterpath.h" +#include "qapplication.h" +#include "qdesktopwidget.h" +#include "qwidget.h" +#include "qdockwidget.h" +#include "qframe.h" +#include "qmenu.h" +#include "qpaintengine.h" +#include "qpainter.h" +#include "qgroupbox.h" +#include "qstyleoption.h" +#include "qlistview.h" +#include "qdrawutil.h" +#include "qtoolbar.h" +#include "qabstractscrollarea.h" +#include "qabstractbutton.h" +#include "qcombobox.h" +#include "qabstractscrollarea.h" +#include "qframe.h" +#include "qscrollbar.h" +#include "qabstractitemview.h" +#include "qmenubar.h" +#include "qtoolbutton.h" +#include "qtextedit.h" +#include "qdialog.h" +#include "qdebug.h" +#include "qtabwidget.h" + +#ifdef Q_WS_WINCE +#include "qt_windows.h" +#include "qguifunctions_wince.h" +extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp +extern bool qt_wince_is_smartphone(); //defined in qguifunctions_wince.cpp +extern bool qt_wince_is_windows_mobile_65(); //defined in qguifunctions_wince.cpp +#endif // Q_WS_WINCE + +#include "qstylehelper_p.h" + +QT_BEGIN_NAMESPACE + +static const int windowsItemFrame = 1; // menu item frame width + +static const int windowsMobileitemViewCheckBoxSize = 13; +static const int windowsMobileFrameGroupBoxOffset = 9; +static const int windowsMobileIndicatorSize = 14; +static const int windowsMobileExclusiveIndicatorSize = 14; +static const int windowsMobileSliderThickness = 6; +static const int windowsMobileIconSize = 16; +static const int PE_IndicatorArrowUpBig = 0xf000101; +static const int PE_IndicatorArrowDownBig = 0xf000102; +static const int PE_IndicatorArrowLeftBig = 0xf000103; +static const int PE_IndicatorArrowRightBig = 0xf000104; + +/* XPM */ +static const char *const radiobutton_xpm[] = { + "30 30 2 1", + " c None", + ". c #000000", + " ........ ", + " .............. ", + " .... .... ", + " .... .... ", + " ... ... ", + " ... ... ", + " .. .. ", + " .. .. ", + " ... ... ", + " .. .. ", + " .. .. ", + ".. ..", + ".. ..", + ".. ..", + ".. ..", + ".. ..", + ".. ..", + ".. ..", + ".. ..", + " .. .. ", + " .. .. ", + " ... ... ", + " .. .. ", + " .. .. ", + " ... ... ", + " ... ... ", + " .... .... ", + " .... .... ", + " .............. ", + " ........ "}; + +/* XPM */ +static const char * const radiobutton_low_xpm[] = { + "15 15 2 1", + " c None", + ". c #000000", + " ..... ", + " .. .. ", + " . . ", + " . . ", + " . . ", + ". .", + ". .", + ". .", + ". .", + ". .", + " . . ", + " . . ", + " . . ", + " .. .. ", + " ..... "}; + +/* XPM */ + static const char * const arrowleft_big_xpm[] = { + "9 17 2 1", + " c None", + ". c #000000", + " .", + " ..", + " ...", + " ....", + " .....", + " ......", + " .......", + " ........", + ".........", + " ........", + " .......", + " ......", + " .....", + " ....", + " ...", + " ..", + " ."}; + +/* XPM */ + static const char * const arrowleft_xpm[] = { + "8 15 2 1", + " c None", + ". c #000000", + " .", + " ..", + " ...", + " ....", + " .....", + " ......", + " .......", + "........", + " .......", + " ......", + " .....", + " ....", + " ...", + " ..", + " ."}; + + + +/* XPM */ +static const char *const horlines_xpm[] = { + "2 2 2 1", + " c None", + ". c #000000", + " ", + ".."}; + +/* XPM */ +static const char *const vertlines_xpm[] = { + "2 2 2 1", + " c None", + ". c #000000", + ". ", + ". "}; + +/* XPM */ +static const char *const radiochecked_xpm[] = { + "18 18 2 1", + " c None", + ". c #000000", + " ...... ", + " .......... ", + " .............. ", + " .............. ", + " ................ ", + " ................ ", + "..................", + "..................", + "..................", + "..................", + "..................", + "..................", + " ................ ", + " ................ ", + " .............. ", + " .............. ", + " .......... ", + " ...... "}; + +/* XPM */ +static const char * const radiochecked_low_xpm[] = { + "9 9 2 1", + " c None", + ". c #000000", + " ... ", + " ....... ", + " ....... ", + ".........", + ".........", + ".........", + " ....... ", + " ....... ", + " ... "}; + +static const char *const arrowdown_xpm[] = { + "15 8 2 1", + " c None", + ". c #000000", + "...............", + " ............. ", + " ........... ", + " ......... ", + " ....... ", + " ..... ", + " ... ", + " . "}; + + +static const char *const arrowdown_big_xpm[] = { + "17 9 2 1", + " c None", + ". c #000000", + ".................", + " ............... ", + " ............. ", + " ........... ", + " ......... ", + " ....... ", + " ..... ", + " ... ", + " . "}; + + +/* XPM */ +static const char *const checkedlight_xpm[] = { + "24 24 2 1", + " c None", + ". c #000000", + " ", + " ", + " ", + " ", + " ", + " . ", + " .. ", + " ... ", + " .... ", + " ..... ", + " ...... ", + " . ...... ", + " .. ...... ", + " ... ...... ", + " .... ...... ", + " .......... ", + " ......... ", + " ....... ", + " ..... ", + " ... ", + " . ", + " ", + " ", + " "}; + + +/* XPM */ +static const char *const checkedbold_xpm[] = { + "26 26 2 1", + " c None", + ". c #000000", + " ", + " ", + " ", + " ", + " ", + " ", + " .. ", + " ... ", + " .... ", + " ..... ", + " .. ...... ", + " ... ....... ", + " .... ....... ", + " ..... ....... ", + " ...... ....... ", + " .............. ", + " ............ ", + " .......... ", + " ........ ", + " ...... ", + " .... ", + " .. ", + " ", + " ", + " ", + " "}; + +/* XPM */ +static const char * const checkedbold_low_xpm[] = { + "9 8 2 1", + " c None", + ". c #000000", + " .", + " ..", + ". ...", + ".. ... ", + "... ... ", + " ..... ", + " ... ", + " . "}; + +/* XPM */ +static const char * const checkedlight_low_xpm[] = { + "8 8 2 1", + " c None", + ". c #000000", + " .", + " ..", + " ...", + ". ... ", + ".. ... ", + "..... ", + " ... ", + " . "}; + +/* XPM */ +static const char * const highlightedradiobutton_xpm[] = { + "30 30 3 1", + " c None", + ". c #000000", + "+ c #0078CC", + " ........ ", + " .............. ", + " ....++++++++.... ", + " ....++++++++++++.... ", + " ...++++ ++++... ", + " ...+++ +++... ", + " ..++ ++.. ", + " ..++ ++.. ", + " ...++ ++... ", + " ..++ ++.. ", + " ..++ ++.. ", + "..++ ++..", + "..++ ++..", + "..++ ++..", + "..++ ++..", + "..++ ++..", + "..++ ++..", + "..++ ++..", + "..++ ++..", + " ..++ ++.. ", + " ..++ ++.. ", + " ...++ ++... ", + " ..++ ++.. ", + " ..++ ++.. ", + " ...+++ +++... ", + " ...++++ ++++... ", + " ....++++++++++++.... ", + " ....++++++++.... ", + " .............. ", + " ........ "}; + +/* XPM */ +static const char * const highlightedradiobutton_low_xpm[] = { + "15 15 3 1", + " c None", + ". c #000000", + "+ c #3192D6", + " ..... ", + " ..+++++.. ", + " .++ ++. ", + " .+ +. ", + " .+ +. ", + ".+ +.", + ".+ +.", + ".+ +.", + ".+ +.", + ".+ +.", + " .+ +. ", + " .+ +. ", + " .++ ++. ", + " ..+++++.. ", + " ..... "}; + +/* XPM */ +static const char * const cross_big_xpm[] = { +"28 28 4 1", +" c #09454A", +". c #218C98", +"+ c #47D8E5", +"@ c #FDFFFC", +" ", +" ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++....................++ ", +" ++....................++ ", +" ++..@@@..........@@@..++ ", +" ++..@@@@........@@@@..++ ", +" ++..@@@@@......@@@@@..++ ", +" ++...@@@@@....@@@@@...++ ", +" ++....@@@@@..@@@@@....++ ", +" ++.....@@@@@@@@@@.....++ ", +" ++......@@@@@@@@......++ ", +" ++.......@@@@@@.......++ ", +" ++.......@@@@@@.......++ ", +" ++......@@@@@@@@......++ ", +" ++.....@@@@@@@@@@.....++ ", +" ++....@@@@@..@@@@@....++ ", +" ++...@@@@@....@@@@@...++ ", +" ++..@@@@@......@@@@@..++ ", +" ++..@@@@........@@@@..++ ", +" ++..@@@..........@@@..++ ", +" ++....................++ ", +" ++....................++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ", +" "}; + +/* XPM */ +static const char * const cross_small_xpm[] = { +"14 14 4 1", +" c #09454A", +". c #218C98", +"+ c #47D8E5", +"@ c #FCFFFC", +" ", +" ++++++++++++ ", +" +..........+ ", +" +.@@....@@.+ ", +" +.@@@..@@@.+ ", +" +..@@@@@@..+ ", +" +...@@@@...+ ", +" +...@@@@...+ ", +" +..@@@@@@..+ ", +" +.@@@..@@@.+ ", +" +.@@....@@.+ ", +" +..........+ ", +" ++++++++++++ ", +" "}; + +/* XPM */ +static const char * const max_big_xpm[] = { +"28 28 4 1", +" c #09454A", +". c #218C98", +"+ c #47D8E5", +"@ c #FDFFFC", +" ", +" ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++..@@@@@@@@@@@@@@@@..++ ", +" ++..@@@@@@@@@@@@@@@@..++ ", +" ++..@@@@@@@@@@@@@@@@..++ ", +" ++..@@@@@@@@@@@@@@@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@@@@@@@@@@@@@@@..++ ", +" ++..@@@@@@@@@@@@@@@@..++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ", +" "}; + +/* XPM */ +static const char * const max_small_xpm[] = { +"14 14 4 1", +" c #09454A", +". c #218C98", +"+ c #47D8E5", +"@ c #FCFFFC", +" ", +" ++++++++++++ ", +" +..........+ ", +" +..........+ ", +" +.@@@@@@@@.+ ", +" +.@@@@@@@@.+ ", +" +.@......@.+ ", +" +.@......@.+ ", +" +.@......@.+ ", +" +.@@@@@@@@.+ ", +" +..........+ ", +" +..........+ ", +" ++++++++++++ ", +" "}; + +/* XPM */ +static const char * const normal_big_xpm[] = { +"28 28 4 1", +" c #09454A", +". c #218C98", +"+ c #47D8E5", +"@ c #FDFFFC", +" ", +" ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++....................++ ", +" ++....................++ ", +" ++..@@@@@@@@@@@@@@@@..++ ", +" ++..@@@@@@@@@@@@@@@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@............@@..++ ", +" ++..@@@@@@@@@@@@@@@@..++ ", +" ++..@@@@@@@@@@@@@@@@..++ ", +" ++....................++ ", +" ++....................++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ", +" "}; + +/* XPM */ +static const char * const normal_small_xpm[] = { +"14 14 4 1", +" c #09454A", +". c #218C98", +"+ c #47D8E5", +"@ c #FCFFFC", +" ", +" ++++++++++++ ", +" +..........+ ", +" +.@@@@@@@@.+ ", +" +.@......@.+ ", +" +.@......@.+ ", +" +.@......@.+ ", +" +.@......@.+ ", +" +.@......@.+ ", +" +.@......@.+ ", +" +.@@@@@@@@.+ ", +" +..........+ ", +" ++++++++++++ ", +" "}; + + +/* XPM */ +static const char * const min_big_xpm[] = { +"28 28 4 1", +" c #09454A", +". c #218C98", +"+ c #47D8E5", +"@ c #FDFFFC", +" ", +" ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++..@@@@@@@@@@@@@@@@..++ ", +" ++..@@@@@@@@@@@@@@@@..++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++....................++ ", +" ++++++++++++++++++++++++ ", +" ++++++++++++++++++++++++ ", +" ", +" "}; + +/* XPM */ +static const char * const min_small_xpm[] = { +"14 14 4 1", +" c #09454A", +". c #218C98", +"+ c #47D8E5", +"@ c #FCFFFC", +" ", +" ++++++++++++ ", +" +..........+ ", +" +..........+ ", +" +..........+ ", +" +..........+ ", +" +..........+ ", +" +..........+ ", +" +..........+ ", +" +.@@@@@@@@.+ ", +" +..........+ ", +" +..........+ ", +" ++++++++++++ ", +" "}; + +#ifdef Q_WS_WINCE_WM + +static char * sbhandleup_xpm[] = { +"26 41 45 1", +" c None", +". c #000000", +"+ c #E7E7E7", +"@ c #D6D7D6", +"# c #949294", +"$ c #737573", +"% c #636563", +"& c #636163", +"* c #5A5D5A", +"= c #5A595A", +"- c #525552", +"; c #525152", +"> c #4A4D4A", +", c #7B797B", +"' c #CECFCE", +") c #CED3CE", +"! c #6B6D6B", +"~ c #6B696B", +"{ c #737173", +"] c #7B7D7B", +"^ c #848684", +"/ c #848284", +"( c #8C8A8C", +"_ c #8C8E8C", +": c #B5B2B5", +"< c #FFFFFF", +"[ c #949694", +"} c #B5B6B5", +"| c #9C9A9C", +"1 c #ADAEAD", +"2 c #9C9E9C", +"3 c #BDBABD", +"4 c #BDBEBD", +"5 c #F7F3F7", +"6 c #C6C3C6", +"7 c #C6C7C6", +"8 c #A5A2A5", +"9 c #CECBCE", +"0 c #FFFBFF", +"a c #ADAAAD", +"b c #A5A6A5", +"c c #D6D3D6", +"d c #B5BAB5", +"e c #DEDFDE", +"f c #DEDBDE", +"..........................", +"+@#$%%&&&**===---;;;;>=,'+", +"+@#$%%&&&**===---;;;;>=$'+", +")$!!~~%%&&&**===---;;;;>;'", +"#{$]],,$${{{!!~~%%%&&&*-;]", +"#{$]],,$${{{!!~~%%%&&&*-;]", +",$^//]],,$${{{!!~~%%%&&*;*", +",,(^^//]],$${!!!!!~~%%%&-*", +",,(^^//]],$${!!!!!~~%%%&-*", +"]]_((^^//]$!%%~!{{!!~~%%-*", +"//#__((^^]{:<<:~!{{{!!~~=*", +"//#__((^^]{:<<:~!{{{!!~~=&", +"//###__(/$:<<<<:~{${{!!~*&", +"^^[[##_^]:<<<<<<}!{$${{!*%", +"^^[[##_^]:<<<<<<}!{$${{!*%", +"((|[[#_/:<<<<<<<<}!$$${{&~", +"((||[#^1<<<<1:<<<<}!$$$$&~", +"((||[#^1<<<<1:<<<<}!$$$$&~", +"__2|#(1<<<<}],}<<<<}{$,$%~", +"##2|_1<<<<}^((]3<<<<}{$,~!", +"##2|_1<<<<}^((]3<<<<}{$,~!", +"##2#1<<<<3^###(/4<<<<}{,~{", +"##2#1<<<<3^###(/4<<<<}{,~!", +"[[2_5<<<4(#|[[#_/6<<<<,,!{", +"[|2_5<<4_[||||[[_/7<<<,]{$", +"[|2_5<<4_[||||[[_/7<<<,]{$", +"||8_5<6#|2222|||[_/9<<,]{$", +"228#06[28888222||[_/'<,/$,", +"228#06[28888222||[_/'<,/$,", +"22a|6[8bbbb88822||[(/c](,]", +"881b8baaabbbb88222|[(^(_,]", +"881b8baaabbbb88222|[(^(_,]", +"88111111aaabbb88822|[###]/", +"bb:::11111aaabbb8822||[[/^", +"bb:::11111aaabbb8822||[[//", +"bb:::::1111aaabbb8822||[/(", +"3a1::::::1111aaabb8822|_^8", +"da1::::::1111aaabb8822|_^8", +"e1aaabbbb888822||[[##__((@", +"+e4:aaabbbb88822||[[[#[b@+", +"+e4:aaabbbb88822||[[[#[bf+"}; + +static char * sbhandledown_xpm[] = { +"26 40 46 1", +" c None", +". c #E7E7E7", +"+ c #DEDFDE", +"@ c #BDBEBD", +"# c #B5B2B5", +"$ c #ADAAAD", +"% c #A5A6A5", +"& c #A5A2A5", +"* c #9C9E9C", +"= c #9C9A9C", +"- c #949694", +"; c #949294", +"> c #D6D7D6", +", c #DEDBDE", +"' c #D6DBD6", +") c #ADAEAD", +"! c #8C8E8C", +"~ c #8C8A8C", +"{ c #BDBABD", +"] c #848684", +"^ c #B5BAB5", +"/ c #848284", +"( c #848A84", +"_ c #7B7D7B", +": c #7B797B", +"< c #C6C3C6", +"[ c #D6D3D6", +"} c #FFFBFF", +"| c #CECFCE", +"1 c #FFFFFF", +"2 c #737573", +"3 c #F7F3F7", +"4 c #CECBCE", +"5 c #737173", +"6 c #C6C7C6", +"7 c #6B6D6B", +"8 c #B5B6B5", +"9 c #6B696B", +"0 c #636563", +"a c #636163", +"b c #5A5D5A", +"c c #5A595A", +"d c #525552", +"e c #525152", +"f c #4A4D4A", +"g c #C6CBC6", +".+@#$$$%%%%&&&**==---;-%>.", +".+@#$$$%%%%&&&**==---;-%,.", +"')$$$%%%%&&&&**==--;;!!~~>", +"{$)######))))$$$%%&&**=!]&", +"^$)######))))$$$%%&&**=!]&", +"%%#####))))$$$%%%&&**==-/(", +"%%###)))))$$$%%%&&**==--/]", +"%%###)))))$$$%%%&&**==--//", +"&&))))))$$$%%%&&&**=-;;;_/", +"&&)%&%$$$%%%%&&***=-~]~!:_", +"&&)%&%$$$%%%%&&***=-~]~!:_", +"**$=<-&%%%%&&&**==-~/[_~:_", +"**&;}<-*&&&&***==-!/|1:/2:", +"**&;}<-*&&&&***==-!/|1:/2:", +"==&!31<;=****===-!/411:_5:", +"-=*!311@!-====--!/6111:_52", +"-=*!311@!-====--!/6111:_52", +"--*!3111@~;=--;!/<1111::75", +";;*;)1111{];;;~/@111185:95", +";;*;)1111{];;;~/@111185:97", +";;*=!)11118]~~_{1111852:97", +";;*=!)11118]~~_{1111852:97", +"!!*=;~)11118_:81111852:207", +"~~==-;])1111)#1111872222a9", +"~~==-;])1111)#1111872222a9", +"~~=--;!/#111111118722255a0", +"]]--;;!]_#11111187522557b0", +"]]--;;!]_#11111187522557b0", +"//;;;!!~/2#1111#95255779ba", +"//;!!~~]]_5#11#975557799cb", +"//;!!~~]]_5#11#975557799ca", +"__!~~]]//_27009755779900db", +"::~]]//__:2257777799000adb", +"::~]]//__:2257777799000adb", +":2]//__::225557799000aabeb", +";52__::225557799000aaabde_", +";52__::225557799000aaabde_", +"[2779900aaabbcccdddeeeefeg", +".>;200aaabbcccdddeeeefc:|.", +".>;200aaabbcccdddeeeefc2|."}; + +static char * sbgripdown_xpm[] = { +"26 34 39 1", +" c None", +". c #949294", +"+ c #9C9E9C", +"@ c #9C9A9C", +"# c #949694", +"$ c #8C8E8C", +"% c #8C8A8C", +"& c #848684", +"* c #848284", +"= c #7B7D7B", +"- c #7B797B", +"; c #6B696B", +"> c #636563", +", c #737573", +"' c #636163", +") c #737173", +"! c #5A5D5A", +"~ c #6B6D6B", +"{ c #5A595A", +"] c #B5B6B5", +"^ c #BDBEBD", +"/ c #ADAEAD", +"( c #BDBABD", +"_ c #525552", +": c #313031", +"< c #525152", +"[ c #ADAAAD", +"} c #BDBAB5", +"| c #4A4D4A", +"1 c #4A494A", +"2 c #C6C3C6", +"3 c #C6CBC6", +"4 c #E7E7E7", +"5 c #DEDFDE", +"6 c #E7E3E7", +"7 c #DEE3DE", +"8 c #CECBCE", +"9 c #8C928C", +"0 c #CECFCE", +"..+++@@@###...$$%&&**==-;>", +"$.++@@@@##...$$%%&**==-->>", +"$$+@@@@###..$$%%&&*==--,>>", +"$$@@@@###..$$%%&&**==-,,>'", +"%%@@@###..$$$%&&**==--,,''", +"%%@@###..$$$%&&**==--,,)''", +"%%@###...$$%%&&*==--,,))'!", +"&&###...$$%%&&**==--,)))!!", +"&&##...$$%%&&**==--,,))~!!", +"&&#...$$%%&&**==--,,))~~!{", +"**...$$%%&&**==--,,))~~;!{", +"**..$$%%&&**===--,)))~~;{{", +"**.$$%%&]^&===//,,))~~;;{{", +"==$$%%&&]^*==-((,))~~;;>{_", +"==$%%&&***::--,,::~~;;;>__", +"==%%&&&**=::-,,)::~~;;>>__", +"--%&&&**==--,,)))~~;;>>>__", +"--&&&**==--,,)))~~;;>>>'_<", +",-&&**==]^-,))[[~;;>>>''<<", +",,&**==-]^-)))}};;>>>'''<<", +",,**==--,,::)~~;::>>'''!<<", +"))*==--,,)::~~;;::>'''!!<|", +"))==--,,)))~~;;;>>'''!!!||", +"))=--,,)))~~;;;>>'''!!!{||", +"~~--,,)))~~;;;>>'''!!!{{||", +"~~-,,)))~~;;>>>'''!!!{{{|1", +";;,,)))~~;;>>>'''!!!{{{_1<", +"~;,)))~~;;>>>'''!!!{{{__1'", +"%>~))~~;;>>>'''!!!{{{__|1$", +"2>>~~~;;>>>''!!!{{{{__<113", +"4%'';;;>>>''!!!{{{{__<11%4", +"45-!!'>>>''!!!{{{{_<|11)64", +"447+!{{___<<<||||1111|+444", +"444489~__<<<||||111>$04444"}; + +static char * sbgripup_xpm[] = { +"26 34 38 1", +" c None", +". c #E7E7E7", +"+ c #D6DBD6", +"@ c #C6C7C6", +"# c #B5B6B5", +"$ c #ADAEAD", +"% c #ADAAAD", +"& c #A5A6A5", +"* c #A5A2A5", +"= c #BDBEBD", +"- c #DEDFDE", +"; c #C6CBC6", +"> c #9C9E9C", +", c #E7E3E7", +"' c #BDBABD", +") c #B5B2B5", +"! c #9C9A9C", +"~ c #DEE3DE", +"{ c #949694", +"] c #D6D7D6", +"^ c #949294", +"/ c #DEDBDE", +"( c #8C8E8C", +"_ c #8C8A8C", +": c #848684", +"< c #D6D3CE", +"[ c #CECBCE", +"} c #D6D3D6", +"| c #848284", +"1 c #313031", +"2 c #7B7D7B", +"3 c #CECFCE", +"4 c #CECBC6", +"5 c #7B797B", +"6 c #737573", +"7 c #737173", +"8 c #6B6D6B", +"9 c #6B696B", +"....+@#$$%%%%&&&***$=-....", +"...;$$$$$%%%&&&&**>>>>@...", +".,'$$)#'#####)))$$$%*!!$~.", +".=$)#'''####))))$$$%%*!{'.", +"]$$''''#####)))$$$%%%&*{^/", +"=$#'''#####)))$$$$%%&&&!^#", +"$$'''#####))))$$$%%%&&*>(!", +"$$''#####))))$$$%%%&&&*>(^", +"$$######))))$$$$%%&&&**>(_", +"%$#####))))$$$$%%%&&***>__", +"%$####))))$$$$%%%&&&**>>__", +"%%###)))))$$$%%%&&&**>>>_:", +"%%##))))<])$$%[[&&***>>!::", +"%%#)))))<]$$%%}<&&**>>!!:|", +"&%)))))$$$11%%&&11*>>>!!:|", +"&&))))$$$$11%&&&11*>>!!{||", +"&&)))$$$$$%%%&&&**>>!!!{|2", +"&&))$$$$$%%%&&&**>>>!!{{|2", +"*&)$$$$$3]%&&&4@*>>!!{{{22", +"**$$$$$%3]%&&&<<>>!!!{{^25", +"**$$$$%%%%11&**>11!!{{^^25", +"**$$$%%%%&11***>11!!{{^^55", +"**$$%%%%&&&***>>!!!{{^^(55", +">>$%%%%&&&***>>>!!{{^^((56", +">>%%%%&&&&***>>!!!{{^^((66", +">>%%%&&&&***>>!!!{{^^((_67", +"!>%%&&&&***>>>!!{{{^^(__67", +"!!%&&&&***>>>!!!{{^^((_:77", +"!!&&&&***>>>!!!{{^^((__:77", +"!!&&&****>>!!!{{^^^(__::78", +"{!&&****>>>!!{{{^^((_::|88", +"{{&****>>>!!!{{^^((__:||88", +"{{****>>>!!!{{^^^(__::|289", +"{{***>>>!!!{{{^^((_::||289"}; + +static char * sbgripmiddle_xpm[] = { +"26 2 12 1", +" c None", +". c #949294", +"+ c #A5A2A5", +"@ c #9C9E9C", +"# c #9C9A9C", +"$ c #949694", +"% c #8C8E8C", +"& c #8C8A8C", +"* c #848684", +"= c #848284", +"- c #7B7D7B", +"; c #6B696B", +"..++@@@###$$$..%%&&*==--;;", +"..++@@@###$$$..%%&&*==--;;"}; + + +static char * listviewhighmiddle_xpm[] = { +"8 46 197 2", +" c None", +". c #66759E", +"+ c #6C789D", +"@ c #6A789E", +"# c #6B789E", +"$ c #6A779D", +"% c #6C789C", +"& c #6F7D9B", +"* c #6F7D9A", +"= c #9DB6EE", +"- c #9DB6ED", +"; c #9CB6ED", +"> c #A1B6EF", +", c #A2B6F0", +"' c #93AAE9", +") c #95ABEA", +"! c #94ABEA", +"~ c #94A9E8", +"{ c #8BA8EA", +"] c #8BA7EA", +"^ c #8AA7EA", +"/ c #8EAAE8", +"( c #8FAAE8", +"_ c #88A2E7", +": c #8CA3E8", +"< c #8BA3E7", +"[ c #8BA3E8", +"} c #8BA2E7", +"| c #8CA2E7", +"1 c #8DA2E7", +"2 c #87A1E8", +"3 c #87A1E9", +"4 c #86A0E8", +"5 c #86A1E7", +"6 c #87A2E7", +"7 c #859EE9", +"8 c #849DE9", +"9 c #869EE9", +"0 c #869FE9", +"a c #7C9BEA", +"b c #7C9CEA", +"c c #7B9CEA", +"d c #7C9BE9", +"e c #7E9CE9", +"f c #7B9AEA", +"g c #7C99E9", +"h c #7C9AEA", +"i c #7B9AE8", +"j c #7A9AEA", +"k c #7996E1", +"l c #7C96E4", +"m c #7B96E3", +"n c #7B95E3", +"o c #7E95E5", +"p c #7E95E6", +"q c #7292E1", +"r c #7490DF", +"s c #7591E0", +"t c #7590DF", +"u c #7392E1", +"v c #6D8CDE", +"w c #6F8EDD", +"x c #6E8DDD", +"y c #6E8DDE", +"z c #6F8EDE", +"A c #6E8EDE", +"B c #718EDD", +"C c #728EDD", +"D c #6B89E0", +"E c #6C89DF", +"F c #6D89E0", +"G c #6D89DF", +"H c #6C88DF", +"I c #6D88DF", +"J c #6D86DD", +"K c #6086E0", +"L c #6686E0", +"M c #6586E0", +"N c #6486E0", +"O c #6485E0", +"P c #6786DF", +"Q c #5F85E0", +"R c #6583DE", +"S c #6683DE", +"T c #6682DD", +"U c #6086DF", +"V c #5F86E0", +"W c #567ED7", +"X c #567ED8", +"Y c #557DD7", +"Z c #5A7FD8", +"` c #6281DA", +" . c #5379D9", +".. c #5278D9", +"+. c #547BD8", +"@. c #4C73D7", +"#. c #4B72D2", +"$. c #4C73D4", +"%. c #4C73D3", +"&. c #4B72D4", +"*. c #4F75D3", +"=. c #5074D2", +"-. c #4971D0", +";. c #4871D0", +">. c #335ECF", +",. c #325ECB", +"'. c #335ECD", +"). c #335ECE", +"!. c #325DCD", +"~. c #2E59C9", +"{. c #3059C9", +"]. c #2F59C9", +"^. c #2F59C8", +"/. c #2B59CA", +"(. c #3355C6", +"_. c #3354C5", +":. c #3156C7", +"<. c #3056C7", +"[. c #3355C7", +"}. c #3355C5", +"|. c #254EBF", +"1. c #1F51C1", +"2. c #234FC0", +"3. c #234FBF", +"4. c #2350C0", +"5. c #1E50BE", +"6. c #1D50C0", +"7. c #264DBE", +"8. c #264CBD", +"9. c #254DBE", +"0. c #244EBF", +"a. c #254DBF", +"b. c #234CBF", +"c. c #244CC0", +"d. c #244BC0", +"e. c #234BC0", +"f. c #234BBF", +"g. c #234CBE", +"h. c #2049B7", +"i. c #2A49B5", +"j. c #2749B5", +"k. c #2749B6", +"l. c #2D49B4", +"m. c #2649B6", +"n. c #2946B5", +"o. c #2A48B6", +"p. c #2947B5", +"q. c #2946B6", +"r. c #2848B6", +"s. c #2549B5", +"t. c #2648B6", +"u. c #2744B5", +"v. c #2744B4", +"w. c #2744AF", +"x. c #2543B4", +"y. c #2543B2", +"z. c #2442B2", +"A. c #2442B3", +"B. c #2442B5", +"C. c #2543B3", +"D. c #1F40B1", +"E. c #1E40B1", +"F. c #243EAE", +"G. c #273BAC", +"H. c #263DAC", +"I. c #253CAB", +"J. c #273CAB", +"K. c #273CAC", +"L. c #263BAA", +"M. c #253CAE", +"N. c #263BA6", +"O. c #253BA5", +"P. c #253AA5", +"Q. c #253BA6", +"R. c #253CA7", +"S. c #263AA6", +"T. c #243CA6", +"U. c #253CA5", +"V. c #273BA8", +"W. c #2F4DA4", +"X. c #2F4DA3", +"Y. c #1B2F85", +"Z. c #B5B5B6", +"`. c #B5B5B5", +" + c #B5B6B6", +".+ c #B5B4B6", +"++ c #C2C3C5", +"@+ c #C0C3C3", +"#+ c #C1C3C4", +"$+ c #E3E3E3", +"%+ c #E3E3E4", +"&+ c #E4E3E4", +"*+ c #E2E3E4", +"=+ c #ECEEEB", +"-+ c #EBEDEA", +";+ c #EEF0ED", +">+ c #EFF0EE", +". + @ @ # # $ % ", +"& & * & & & & & ", +"= = - = = ; > , ", +"' ) ! ! ! ) ' ~ ", +"{ ] { { { ^ / ( ", +"_ : < [ : } | 1 ", +"2 2 2 3 2 4 5 6 ", +"7 7 7 7 7 8 9 0 ", +"a b a a a c d e ", +"f g h h h h i j ", +"k l m m m n o p ", +"q q q q q q q q ", +"r r s s s t q u ", +"v w x y z A B C ", +"D E F F G F H I ", +"J K L M N O P Q ", +"R R S S S T U V ", +"W W X X X Y Z ` ", +" . . . . ...+.W ", +" . . . . ..... .", +"@.#.$.$.%.&.*.=.", +"-.-.;.-.-.-.-.-.", +">.,.'.).).!.!.>.", +"~.{.].^.].^././.", +"(.(.(.(.(._.:.<.", +"(.(.[.[.[.[.(.}.", +"|.1.2.3.3.4.5.6.", +"7.7.7.7.7.8.9.0.", +"a.b.c.d.c.e.f.g.", +"h.i.j.k.j.k.l.m.", +"n.o.p.q.r.p.s.t.", +"u.u.v.u.u.u.u.u.", +"w.x.y.z.A.y.B.C.", +"D.D.E.D.D.D.D.D.", +"D.D.E.D.D.D.D.D.", +"F.G.H.I.J.K.L.M.", +"N.N.O.N.N.P.Q.R.", +"N.N.S.N.N.N.N.N.", +"T.N.T.T.T.U.N.V.", +"W.W.X.W.W.W.W.W.", +"W.W.W.W.W.W.W.W.", +"Y.Y.Y.Y.Y.Y.Y.Y.", +"Z.`. + +.+Z.`.`.", +"++@+#+#+#+#+@+@+", +"$+%+&+&+*+%+%+%+", +"=+-+;+-+-+>+-+-+"}; + + + +static char * listviewhighcornerleft_xpm[] = { +"100 46 1475 2", +" c None", +". c #FBFBFC", +"+ c #E8EAE7", +"@ c #758DC3", +"# c #42599E", +"$ c #28418A", +"% c #19418F", +"& c #3F5695", +"* c #415896", +"= c #435A98", +"- c #445C99", +"; c #465E9B", +"> c #48609B", +", c #49629C", +"' c #4A639D", +") c #49639D", +"! c #4A629D", +"~ c #4B639D", +"{ c #4B649D", +"] c #4C659D", +"^ c #4D669D", +"/ c #4E689D", +"( c #506A9D", +"_ c #516A9D", +": c #536B9C", +"< c #546C9C", +"[ c #566D9B", +"} c #576D9B", +"| c #586E9C", +"1 c #5B6F9D", +"2 c #61739D", +"3 c #63749E", +"4 c #64749E", +"5 c #68769E", +"6 c #6A779E", +"7 c #6B789E", +"8 c #66759E", +"9 c #6C789D", +"0 c #EEF0ED", +"a c #D0D3DC", +"b c #3E51A3", +"c c #28428B", +"d c #29428C", +"e c #425996", +"f c #455C99", +"g c #485F9C", +"h c #49619E", +"i c #4A63A0", +"j c #4B64A1", +"k c #4B65A1", +"l c #4C66A2", +"m c #4D67A2", +"n c #4F69A1", +"o c #516AA1", +"p c #536CA0", +"q c #556DA1", +"r c #576EA0", +"s c #586F9F", +"t c #586E9F", +"u c #596F9E", +"v c #5A6F9E", +"w c #5C709E", +"x c #5E719E", +"y c #5F729F", +"z c #62739F", +"A c #63739E", +"B c #64749D", +"C c #65749E", +"D c #69769D", +"E c #6C799E", +"F c #6D799F", +"G c #707D9F", +"H c #717F9E", +"I c #6E7AA1", +"J c #6C789E", +"K c #6F7C9C", +"L c #6F7D9B", +"M c #2A4AA0", +"N c #4971D0", +"O c #4C72D8", +"P c #5472C0", +"Q c #5573BF", +"R c #5774BF", +"S c #5875BF", +"T c #5976C1", +"U c #5A76C1", +"V c #5C78C2", +"W c #5E7AC2", +"X c #607CC3", +"Y c #627EC3", +"Z c #637FC4", +"` c #6581C5", +" . c #6682C6", +".. c #6783C7", +"+. c #6984C8", +"@. c #6B85C9", +"#. c #6D87CA", +"$. c #6F89CB", +"%. c #718CCD", +"&. c #748ECF", +"*. c #7690D0", +"=. c #7992D2", +"-. c #7A93D3", +";. c #7C95D5", +">. c #7F98D7", +",. c #8099D8", +"'. c #859CDB", +"). c #8AA0DD", +"!. c #8DA3DF", +"~. c #8FA5E0", +"{. c #90A5E0", +"]. c #91A6E1", +"^. c #91A5E1", +"/. c #90A4E0", +"(. c #8EA3DE", +"_. c #92A6E2", +":. c #8FA4DF", +"<. c #90A5DE", +"[. c #90A5DC", +"}. c #90A6DB", +"|. c #91A6E0", +"1. c #93A7E2", +"2. c #95AAE6", +"3. c #99AEEA", +"4. c #9AB2EA", +"5. c #99B1E9", +"6. c #99B1E7", +"7. c #98AFE6", +"8. c #93A8E2", +"9. c #97ACE7", +"0. c #9AB3EB", +"a. c #9DB5ED", +"b. c #9DB6EE", +"c. c #375095", +"d. c #4056AD", +"e. c #506DCD", +"f. c #4360CC", +"g. c #345ED6", +"h. c #335ECF", +"i. c #355ED6", +"j. c #355FD6", +"k. c #365FD6", +"l. c #355FD0", +"m. c #3760D5", +"n. c #3A63D4", +"o. c #3C63D1", +"p. c #3B63CD", +"q. c #3B63C9", +"r. c #3B62C9", +"s. c #3D63C8", +"t. c #4065C5", +"u. c #4567C5", +"v. c #496BC5", +"w. c #4F70C7", +"x. c #5273C8", +"y. c #5475CA", +"z. c #5777CB", +"A. c #5879CD", +"B. c #5A7BCE", +"C. c #5D7DCF", +"D. c #5F7ECF", +"E. c #617FD0", +"F. c #6381D1", +"G. c #6583D2", +"H. c #6785D2", +"I. c #6886D3", +"J. c #6A88D4", +"K. c #6C89D5", +"L. c #6E8BD6", +"M. c #708CD7", +"N. c #718DD8", +"O. c #738EDA", +"P. c #748FDB", +"Q. c #7691DC", +"R. c #7893DD", +"S. c #7994DD", +"T. c #7A96DE", +"U. c #7B97DF", +"V. c #7C98E0", +"W. c #7E9AE2", +"X. c #7F9BE3", +"Y. c #829DE4", +"Z. c #849FE5", +"`. c #87A0E6", +" + c #88A1E7", +".+ c #89A2E6", +"++ c #8CA3E7", +"@+ c #8EA5E9", +"#+ c #8EA6E9", +"$+ c #8FA7E9", +"%+ c #8FA8E8", +"&+ c #8FA9E8", +"*+ c #91A9E8", +"=+ c #90A7E8", +"-+ c #8FA8EA", +";+ c #90AAEA", +">+ c #93ABEA", +",+ c #95ABEA", +"'+ c #93ABE9", +")+ c #94ABEA", +"!+ c #90A9EA", +"~+ c #93AAE9", +"{+ c #273E7E", +"]+ c #345ED5", +"^+ c #3D60CE", +"/+ c #3D60CF", +"(+ c #345ECF", +"_+ c #335ED0", +":+ c #355FD3", +"<+ c #3A60CE", +"[+ c #3A5FCB", +"}+ c #385FC9", +"|+ c #3B60C8", +"1+ c #3C63CB", +"2+ c #3E64CB", +"3+ c #4166CA", +"4+ c #4568C9", +"5+ c #4A6CC7", +"6+ c #4F71C8", +"7+ c #5172CA", +"8+ c #5475CE", +"9+ c #5678D3", +"0+ c #597CD6", +"a+ c #5C7ED7", +"b+ c #5E7FD8", +"c+ c #6181D9", +"d+ c #6383DA", +"e+ c #6585DA", +"f+ c #6786DB", +"g+ c #6988DC", +"h+ c #6B8ADD", +"i+ c #6D8BDE", +"j+ c #6F8DDE", +"k+ c #718EDF", +"l+ c #728FE0", +"m+ c #7390E1", +"n+ c #7390E2", +"o+ c #7491E3", +"p+ c #7592E4", +"q+ c #7693E4", +"r+ c #7794E5", +"s+ c #7894E5", +"t+ c #7995E6", +"u+ c #7B96E6", +"v+ c #7C97E7", +"w+ c #7D9AE8", +"x+ c #7F9CE9", +"y+ c #829DE9", +"z+ c #849EE9", +"A+ c #859EE9", +"B+ c #87A0E7", +"C+ c #8AA2E7", +"D+ c #8BA3E8", +"E+ c #89A2E7", +"F+ c #8CA6EA", +"G+ c #8BA6EA", +"H+ c #8BA7EA", +"I+ c #8CA3E8", +"J+ c #8BA8EA", +"K+ c #8CA7EA", +"L+ c #8CA8EA", +"M+ c #4659C7", +"N+ c #355ECF", +"O+ c #3660CF", +"P+ c #3860CE", +"Q+ c #3961CD", +"R+ c #3B61CB", +"S+ c #3B61CA", +"T+ c #3D62CA", +"U+ c #3D63CA", +"V+ c #4165CB", +"W+ c #456ACB", +"X+ c #4B6FCD", +"Y+ c #5174CE", +"Z+ c #5275D1", +"`+ c #5477D4", +" @ c #5678D9", +".@ c #587ADB", +"+@ c #597BDB", +"@@ c #5B7DDC", +"#@ c #5E7FDC", +"$@ c #6081DD", +"%@ c #6283DE", +"&@ c #6484DF", +"*@ c #6787E0", +"=@ c #6989E1", +"-@ c #6B8BE1", +";@ c #6D8DE2", +">@ c #6F8EE3", +",@ c #718FE4", +"'@ c #7290E4", +")@ c #7491E5", +"!@ c #7692E6", +"~@ c #7793E5", +"{@ c #7894E6", +"]@ c #7895E7", +"^@ c #7996E8", +"/@ c #7A97E8", +"(@ c #7B98E9", +"_@ c #7D99E8", +":@ c #7F9AE8", +"<@ c #7F9BE9", +"[@ c #7F9CEA", +"}@ c #859EE8", +"|@ c #859FE8", +"1@ c #85A0E9", +"2@ c #869FE9", +"3@ c #86A1E7", +"4@ c #86A0E9", +"5@ c #87A1E7", +"6@ c #88A2E7", +"7@ c #87A1E9", +"8@ c #5A6FCA", +"9@ c #365FCF", +"0@ c #345ED0", +"a@ c #385FCC", +"b@ c #385FCE", +"c@ c #3A61CC", +"d@ c #3B62CD", +"e@ c #3E64CD", +"f@ c #4167CF", +"g@ c #4469CF", +"h@ c #486CD1", +"i@ c #4D71D2", +"j@ c #5175D4", +"k@ c #5376D6", +"l@ c #5578DA", +"m@ c #5679DC", +"n@ c #587BDD", +"o@ c #5A7DDE", +"p@ c #5D80DE", +"q@ c #5F82DF", +"r@ c #6284DF", +"s@ c #6585E0", +"t@ c #6787E1", +"u@ c #6988E2", +"v@ c #6B8AE2", +"w@ c #6D8CE3", +"x@ c #6E8DE3", +"y@ c #708EE4", +"z@ c #718FE3", +"A@ c #7391E4", +"B@ c #7592E5", +"C@ c #7895E5", +"D@ c #7996E6", +"E@ c #7A97E6", +"F@ c #7B98E7", +"G@ c #7A98E8", +"H@ c #7B99E9", +"I@ c #7E9AE9", +"J@ c #7D9AE9", +"K@ c #7E9AEA", +"L@ c #809CE9", +"M@ c #819DE8", +"N@ c #7F9BEA", +"O@ c #819DE9", +"P@ c #819CE9", +"Q@ c #839EE9", +"R@ c #839EE8", +"S@ c #839DEA", +"T@ c #859FE9", +"U@ c #87A0E8", +"V@ c #86A0E8", +"W@ c #87A1E8", +"X@ c #3760CF", +"Y@ c #3A61CE", +"Z@ c #3A62CD", +"`@ c #3F66CE", +" # c #4368D0", +".# c #466CD2", +"+# c #496DD5", +"@# c #4E72D6", +"## c #5175D8", +"$# c #5276DA", +"%# c #5578DC", +"&# c #577ADC", +"*# c #597CDD", +"=# c #5B7DDD", +"-# c #5D7FDE", +";# c #5E81DE", +"># c #6183DF", +",# c #6386DF", +"'# c #6687E0", +")# c #6888E0", +"!# c #6A89E1", +"~# c #6C8AE1", +"{# c #6E8CE2", +"]# c #6F8DE2", +"^# c #7390E4", +"/# c #7390E3", +"(# c #7491E4", +"_# c #7693E5", +":# c #7895E6", +"<# c #7896E6", +"[# c #7997E7", +"}# c #7B97E7", +"|# c #7B98E8", +"1# c #7C98E8", +"2# c #7E9BE9", +"3# c #809CEA", +"4# c #819CEA", +"5# c #839DE9", +"6# c #365FD0", +"7# c #3660D0", +"8# c #3961CF", +"9# c #3B63CF", +"0# c #3D64D0", +"a# c #4067D0", +"b# c #4469D2", +"c# c #466BD3", +"d# c #496ED5", +"e# c #4C71D6", +"f# c #4E72D8", +"g# c #5074D9", +"h# c #5376DB", +"i# c #5578DB", +"j# c #587ADC", +"k# c #5B7CDC", +"l# c #5D7EDD", +"m# c #5F80DD", +"n# c #6081DE", +"o# c #6383DE", +"p# c #6686DF", +"q# c #6887E0", +"r# c #6988E0", +"s# c #6B89E1", +"t# c #6C8AE0", +"u# c #6E8CE1", +"v# c #708EE2", +"w# c #718FE2", +"x# c #7290E3", +"y# c #7391E2", +"z# c #7492E1", +"A# c #7592E2", +"B# c #7691E3", +"C# c #7591E3", +"D# c #7692E3", +"E# c #7693E3", +"F# c #7793E4", +"G# c #7893E4", +"H# c #7994E5", +"I# c #7D97E8", +"J# c #7E98E8", +"K# c #7D98E8", +"L# c #7D99E9", +"M# c #7D9BEA", +"N# c #7D9CEA", +"O# c #7E99E8", +"P# c #7D9AEA", +"Q# c #7C9BEA", +"R# c #7C9CEA", +"S# c #355FCF", +"T# c #3860D0", +"U# c #3A62D0", +"V# c #3C64D1", +"W# c #4167D1", +"X# c #4369D3", +"Y# c #466BD4", +"Z# c #486DD5", +"`# c #4A6ED7", +" $ c #4C70D8", +".$ c #5478D9", +"+$ c #577BDA", +"@$ c #597DDB", +"#$ c #5B7EDB", +"$$ c #5D7FDC", +"%$ c #6182DE", +"&$ c #6284DE", +"*$ c #6485DF", +"=$ c #6586DF", +"-$ c #6787DF", +";$ c #6888DF", +">$ c #6A8ADF", +",$ c #6C8BE0", +"'$ c #6D8CE0", +")$ c #6E8DE1", +"!$ c #6F8DE1", +"~$ c #708EE1", +"{$ c #718FE0", +"]$ c #728FE1", +"^$ c #7390E0", +"/$ c #738FE0", +"($ c #7490E1", +"_$ c #7590E1", +":$ c #7591E1", +"<$ c #7592E1", +"[$ c #7692E2", +"}$ c #7794E2", +"|$ c #7894E3", +"1$ c #7996E3", +"2$ c #7A96E5", +"3$ c #7B98E6", +"4$ c #7B9AE8", +"5$ c #7C99E8", +"6$ c #7C96E5", +"7$ c #7D97E7", +"8$ c #7C99E9", +"9$ c #7B9AE9", +"0$ c #7B9AEA", +"a$ c #5B6DCF", +"b$ c #305EC8", +"c$ c #335ECE", +"d$ c #305ECA", +"e$ c #345FCF", +"f$ c #3761D0", +"g$ c #3A62D1", +"h$ c #3C64D2", +"i$ c #4066D3", +"j$ c #466BD5", +"k$ c #486ED6", +"l$ c #4A6ED6", +"m$ c #4D71D8", +"n$ c #4F72D9", +"o$ c #5073D9", +"p$ c #4F72D8", +"q$ c #5074D8", +"r$ c #5276D9", +"s$ c #587ADA", +"t$ c #5B7CDB", +"u$ c #5D7EDC", +"v$ c #5F7FDD", +"w$ c #6081DC", +"x$ c #6182DD", +"y$ c #6283DD", +"z$ c #6484DE", +"A$ c #6585DD", +"B$ c #6787DE", +"C$ c #6988DF", +"D$ c #6A89DE", +"E$ c #6C8ADF", +"F$ c #6D8BDF", +"G$ c #6E8CE0", +"H$ c #6F8DE0", +"I$ c #718EE0", +"J$ c #728FDF", +"K$ c #728FDE", +"L$ c #7290E0", +"M$ c #7190E0", +"N$ c #7291E0", +"O$ c #7191E0", +"P$ c #7392E1", +"Q$ c #7493E1", +"R$ c #7594E1", +"S$ c #7594E2", +"T$ c #7694E2", +"U$ c #7695E2", +"V$ c #7A96E4", +"W$ c #7895E2", +"X$ c #7A96E2", +"Y$ c #7A96E3", +"Z$ c #7B96E3", +"`$ c #7996E1", +" % c #7C96E4", +".% c #305EC9", +"+% c #315ECC", +"@% c #325ECE", +"#% c #3760D0", +"$% c #3962D1", +"%% c #3E66D3", +"&% c #4268D4", +"*% c #446BD5", +"=% c #476CD6", +"-% c #496ED7", +";% c #4B6FD7", +">% c #4C70D7", +",% c #4E71D7", +"'% c #5074D7", +")% c #5276D8", +"!% c #5376D8", +"~% c #5779DA", +"{% c #597ADA", +"]% c #5A7BDB", +"^% c #5B7CDA", +"/% c #5D7EDB", +"(% c #5E7FDB", +"_% c #6182DB", +":% c #6384DC", +"<% c #6586DD", +"[% c #6686DC", +"}% c #6887DD", +"|% c #6988DD", +"1% c #6A8ADE", +"2% c #6B8BDE", +"3% c #6C8CDE", +"4% c #6E8DDF", +"5% c #6E8CDF", +"6% c #6D8DDF", +"7% c #6C8BDF", +"8% c #6F8DDF", +"9% c #718FDF", +"0% c #7290DF", +"a% c #7391E0", +"b% c #7491E0", +"c% c #7292E1", +"d% c #3959C5", +"e% c #345BC5", +"f% c #315EC8", +"g% c #355BC5", +"h% c #325EC8", +"i% c #315ECB", +"j% c #345DCC", +"k% c #335ECD", +"l% c #345ECD", +"m% c #355FCE", +"n% c #3862D0", +"o% c #3E66D2", +"p% c #456BD5", +"q% c #476CD5", +"r% c #4B6ED7", +"s% c #4B6FD6", +"t% c #4B6FD5", +"u% c #4D71D6", +"v% c #5073D7", +"w% c #5174D7", +"x% c #5275D8", +"y% c #5577D8", +"z% c #5678D8", +"A% c #5779D9", +"B% c #587AD8", +"C% c #597CD9", +"D% c #5B7DD9", +"E% c #5D7FDA", +"F% c #5F80DB", +"G% c #6182DC", +"H% c #6484DC", +"I% c #6585DC", +"J% c #6787DD", +"K% c #6988DE", +"L% c #6B8ADE", +"M% c #6B8ADF", +"N% c #6989DE", +"O% c #6B89DE", +"P% c #6E8BDF", +"Q% c #708CDE", +"R% c #708DDF", +"S% c #708FDF", +"T% c #728EDF", +"U% c #6F8EDD", +"V% c #728EDD", +"W% c #7390DF", +"X% c #7490DF", +"Y% c #335DC8", +"Z% c #3759C5", +"`% c #3859C5", +" & c #335EC8", +".& c #325DCA", +"+& c #345CCB", +"@& c #335DCC", +"#& c #345DCD", +"$& c #355FCD", +"%& c #3861D0", +"&& c #3B64D1", +"*& c #3E65D2", +"=& c #4168D3", +"-& c #456AD5", +";& c #4B6ED5", +">& c #4C6FD4", +",& c #4D70D5", +"'& c #4F72D6", +")& c #5173D6", +"!& c #5375D7", +"~& c #5476D8", +"{& c #5577D7", +"]& c #5477D8", +"^& c #5677D8", +"/& c #5879D9", +"(& c #597AD9", +"_& c #5C7DDA", +":& c #6080DC", +"<& c #6080DB", +"[& c #6181DC", +"}& c #6282DC", +"|& c #6383DD", +"1& c #6484DD", +"2& c #6686DE", +"3& c #6685DE", +"4& c #6786DE", +"5& c #6687DE", +"6& c #6887DE", +"7& c #6987DE", +"8& c #6788DF", +"9& c #6785DF", +"0& c #6B89DF", +"a& c #6C89DF", +"b& c #6F8DDD", +"c& c #6D8CDE", +"d& c #445BBB", +"e& c #3759BE", +"f& c #375AC6", +"g& c #355CC8", +"h& c #345CCA", +"i& c #355ECC", +"j& c #365FCD", +"k& c #3761CE", +"l& c #3A63D0", +"m& c #3D65D1", +"n& c #466AD4", +"o& c #476BD4", +"p& c #486CD3", +"q& c #4A6ED4", +"r& c #4B6ED4", +"s& c #4E71D6", +"t& c #4F71D5", +"u& c #5072D6", +"v& c #5274D7", +"w& c #5273D7", +"x& c #5274D6", +"y& c #5476D7", +"z& c #5779D8", +"A& c #587AD9", +"B& c #5A7CDA", +"C& c #5C7DDB", +"D& c #5D7EDA", +"E& c #6081DA", +"F& c #6181DB", +"G& c #6283DC", +"H& c #6483DD", +"I& c #6483DE", +"J& c #6585DE", +"K& c #6786DF", +"L& c #6886DE", +"M& c #6887DF", +"N& c #6987DF", +"O& c #6A88DF", +"P& c #6786E0", +"Q& c #6A86DE", +"R& c #6B89E0", +"S& c #365BC8", +"T& c #365CC8", +"U& c #375DCA", +"V& c #375FCB", +"W& c #3860CD", +"X& c #3C63D0", +"Y& c #4167D2", +"Z& c #4268D2", +"`& c #4368D2", +" * c #4367D2", +".* c #4568D2", +"+* c #466AD2", +"@* c #496CD3", +"#* c #4A6DD3", +"$* c #4A6DD4", +"%* c #4D70D4", +"&* c #4F72D5", +"** c #4C70D4", +"=* c #4E72D5", +"-* c #5173D5", +";* c #5375D6", +">* c #597BDA", +",* c #5B7DDA", +"'* c #5C7EDB", +")* c #5D7FDB", +"!* c #5E80DB", +"~* c #5E81DA", +"{* c #5F81DB", +"]* c #5F82DB", +"^* c #6384DD", +"/* c #6384DE", +"(* c #6585DF", +"_* c #6486E0", +":* c #6583DD", +"<* c #6386E0", +"[* c #6686E0", +"}* c #6B86DD", +"|* c #6D86DD", +"1* c #6086E0", +"2* c #5573CD", +"3* c #3959C3", +"4* c #3959C4", +"5* c #3759C0", +"6* c #375BC7", +"7* c #365CC7", +"8* c #395FCC", +"9* c #3B62CE", +"0* c #3E64D0", +"a* c #4066D1", +"b* c #4166D1", +"c* c #4064CF", +"d* c #4065CF", +"e* c #4266D0", +"f* c #4468D1", +"g* c #4569D1", +"h* c #476BD2", +"i* c #466AD1", +"j* c #476AD2", +"k* c #456AD1", +"l* c #496DD2", +"m* c #4A6FD3", +"n* c #496ED2", +"o* c #4B70D4", +"p* c #4D71D4", +"q* c #4E72D4", +"r* c #5073D4", +"s* c #5174D5", +"t* c #5175D5", +"u* c #5276D6", +"v* c #5377D6", +"w* c #5478D7", +"x* c #5579D7", +"y* c #567AD8", +"z* c #577BD9", +"A* c #597CD8", +"B* c #5A7DD9", +"C* c #5A7ED9", +"D* c #5B7FDA", +"E* c #5C80DA", +"F* c #5D80DA", +"G* c #5E81DB", +"H* c #5D80DB", +"I* c #6082DC", +"J* c #6183DD", +"K* c #6183DE", +"L* c #6082DB", +"M* c #6282DE", +"N* c #6682DE", +"O* c #6583DE", +"P* c #3759BF", +"Q* c #375AC2", +"R* c #375AC1", +"S* c #375AC4", +"T* c #395DCA", +"U* c #3A5ECA", +"V* c #3C60CC", +"W* c #3D61CD", +"X* c #3D61CC", +"Y* c #3C61CD", +"Z* c #3E62CD", +"`* c #3F64CE", +" = c #4266CF", +".= c #4468D0", +"+= c #4267CF", +"@= c #4166CE", +"#= c #4065CE", +"$= c #4166CD", +"%= c #4267CE", +"&= c #456AD0", +"*= c #4368CE", +"== c #4468CF", +"-= c #4569D0", +";= c #486BD1", +">= c #4B6FD3", +",= c #4C70D3", +"'= c #4F73D4", +")= c #5275D5", +"!= c #5477D6", +"~= c #577BD7", +"{= c #587CD8", +"]= c #577CD8", +"^= c #597DD9", +"/= c #5A7DDA", +"(= c #597DDA", +"_= c #587CDA", +":= c #5A7EDA", +"<= c #567BD8", +"[= c #557AD9", +"}= c #567BD9", +"|= c #577CD9", +"1= c #587DD9", +"2= c #587ED9", +"3= c #577ED8", +"4= c #587DD8", +"5= c #587ED8", +"6= c #567ED7", +"7= c #526ABD", +"8= c #3759C1", +"9= c #385BC7", +"0= c #395CC8", +"a= c #3B5DC9", +"b= c #3B5ECA", +"c= c #3A5FCA", +"d= c #3B60CC", +"e= c #3C61CC", +"f= c #3D62CD", +"g= c #3E63CD", +"h= c #3C61CB", +"i= c #3C61CA", +"j= c #3D62CB", +"k= c #3F64CC", +"l= c #4065CD", +"m= c #4669D0", +"n= c #476AD0", +"o= c #496BD1", +"p= c #4A6DD2", +"q= c #4B6ED2", +"r= c #4D71D3", +"s= c #4E73D4", +"t= c #4F74D4", +"u= c #5075D5", +"v= c #5276D5", +"w= c #5377D7", +"x= c #5278D7", +"y= c #5277D6", +"z= c #5378D7", +"A= c #5379D8", +"B= c #5379D9", +"C= c #5278D8", +"D= c #5178D7", +"E= c #3355C0", +"F= c #3556C1", +"G= c #395AC6", +"H= c #385AC7", +"I= c #395BC7", +"J= c #395EC9", +"K= c #395FCA", +"L= c #3B60CA", +"M= c #3B60CB", +"N= c #375DC7", +"O= c #385EC8", +"P= c #395FC9", +"Q= c #3A60CA", +"R= c #3D63CC", +"S= c #4367CF", +"T= c #476BD1", +"U= c #4A6ED2", +"V= c #4B6FD2", +"W= c #4C6FD2", +"X= c #4D70D1", +"Y= c #4E71D2", +"Z= c #4E72D2", +"`= c #4E74D4", +" - c #4E75D5", +".- c #4E75D4", +"+- c #4F75D3", +"@- c #5075D2", +"#- c #5075D3", +"$- c #5177D7", +"%- c #5178D8", +"&- c #4F75D5", +"*- c #5076D5", +"=- c #4F76D6", +"-- c #5279D9", +";- c #3C52B1", +">- c #3656C3", +",- c #3757C5", +"'- c #3758C6", +")- c #3759C6", +"!- c #375BC6", +"~- c #385CC7", +"{- c #385DC8", +"]- c #365CC6", +"^- c #355BC6", +"/- c #355CC6", +"(- c #365DC7", +"_- c #375EC8", +":- c #375CC6", +"<- c #385EC6", +"[- c #3A5FC7", +"}- c #3C60C8", +"|- c #3D61C9", +"1- c #3E62CA", +"2- c #4063CC", +"3- c #4165CE", +"4- c #4268D0", +"5- c #4269D1", +"6- c #436AD2", +"7- c #446AD2", +"8- c #456BD2", +"9- c #496CD1", +"0- c #4C6CD0", +"a- c #4D6CCF", +"b- c #4E6DD0", +"c- c #4F6ECF", +"d- c #4E6FCF", +"e- c #4C70CF", +"f- c #4A71D0", +"g- c #4F6FCF", +"h- c #4B71D0", +"i- c #4A72D1", +"j- c #4B73D4", +"k- c #4F70D0", +"l- c #4C73D3", +"m- c #4C73D6", +"n- c #4B72D2", +"o- c #4B71D1", +"p- c #4C73D7", +"q- c #3354C0", +"r- c #3152BE", +"s- c #3052BE", +"t- c #3051BF", +"u- c #2E4FBF", +"v- c #2E4FBE", +"w- c #2E50BF", +"x- c #2F50BF", +"y- c #3156C4", +"z- c #2F56C5", +"A- c #2E57C5", +"B- c #2F57C5", +"C- c #3057C6", +"D- c #3258C6", +"E- c #3459C7", +"F- c #365AC7", +"G- c #385BC8", +"H- c #3B5DCA", +"I- c #3B5DCB", +"J- c #3C5ECC", +"K- c #3C60CD", +"L- c #3C62CE", +"M- c #3D65D0", +"N- c #3D66D1", +"O- c #4166D2", +"P- c #4667D2", +"Q- c #4A67D1", +"R- c #4C68D0", +"S- c #4C69CF", +"T- c #4D6BCE", +"U- c #4E6DCD", +"V- c #4E6ECE", +"W- c #4E6DCE", +"X- c #4970D0", +"Y- c #4770D0", +"Z- c #4B6BCE", +"`- c #4A6CCE", +" ; c #496DCF", +".; c #476FD0", +"+; c #4870D0", +"@; c #486DCF", +"#; c #242F79", +"$; c #2F41AC", +"%; c #2040B8", +"&; c #2041B8", +"*; c #2243B3", +"=; c #2243B8", +"-; c #2343B8", +";; c #2444B8", +">; c #2445B8", +",; c #2445B6", +"'; c #2445B7", +"); c #2444B9", +"!; c #2949BE", +"~; c #2649BF", +"{; c #234BBF", +"]; c #224CBF", +"^; c #224AC0", +"/; c #244CC0", +"(; c #254DC0", +"_; c #254DC1", +":; c #264DC2", +"<; c #274EC3", +"[; c #274CC3", +"}; c #274DC4", +"|; c #254DC5", +"1; c #214EC5", +"2; c #204FC6", +"3; c #1F50C8", +"4; c #2151C9", +"5; c #2B53C8", +"6; c #3154C7", +"7; c #3255C6", +"8; c #2F57C7", +"9; c #2C58C9", +"0; c #2D59CA", +"a; c #2D58C9", +"b; c #2E5BCC", +"c; c #325ECC", +"d; c #325ECB", +"e; c #1F40B1", +"f; c #1F40B2", +"g; c #1F40B3", +"h; c #2A44BD", +"i; c #2845BE", +"j; c #2745BE", +"k; c #2646BF", +"l; c #2546BE", +"m; c #2347BF", +"n; c #2147BF", +"o; c #2048C0", +"p; c #1D48C0", +"q; c #1C48C0", +"r; c #1B47C0", +"s; c #1C48BF", +"t; c #1E49BE", +"u; c #214ABD", +"v; c #244CBD", +"w; c #264DBE", +"x; c #254EC0", +"y; c #214FC2", +"z; c #1B51C5", +"A; c #1C51C7", +"B; c #2250C8", +"C; c #2A52C8", +"D; c #3254C6", +"E; c #3355C5", +"F; c #3154C8", +"G; c #3355C6", +"H; c #2F57C8", +"I; c #2E58C9", +"J; c #2E59C9", +"K; c #3059C9", +"L; c #2040B6", +"M; c #2743BB", +"N; c #2844BC", +"O; c #2743BD", +"P; c #2844BE", +"Q; c #2844BD", +"R; c #2346BE", +"S; c #2047BF", +"T; c #1E48C0", +"U; c #1D47C0", +"V; c #1D49BF", +"W; c #1F49BF", +"X; c #204ABE", +"Y; c #254DBF", +"Z; c #234EC0", +"`; c #2050C1", +" > c #1C51C3", +".> c #1F51C6", +"+> c #2651C8", +"@> c #2D53C7", +"#> c #3155C6", +"$> c #3155C7", +"%> c #3355C7", +"&> c #3254C7", +"*> c #1E40B1", +"=> c #2141B8", +"-> c #2442B9", +";> c #2744BB", +">> c #2945BB", +",> c #2A45BB", +"'> c #2944BA", +")> c #2745BB", +"!> c #2545BC", +"~> c #2246BD", +"{> c #2047BE", +"]> c #1F47BD", +"^> c #1D48BE", +"/> c #1E49C0", +"(> c #1F4AC0", +"_> c #214BBF", +":> c #244CBE", +"<> c #254DBE", +"[> c #244DBE", +"}> c #224FBF", +"|> c #2051C1", +"1> c #2151C3", +"2> c #2252C5", +"3> c #2151C1", +"4> c #2851C6", +"5> c #2A50C6", +"6> c #2E54C6", +"7> c #1F51C2", +"8> c #1D52C5", +"9> c #2651C9", +"0> c #2950C7", +"a> c #2D40A5", +"b> c #2040B0", +"c> c #1F40B0", +"d> c #223CAE", +"e> c #233CAE", +"f> c #253BAC", +"g> c #253BAD", +"h> c #233CB0", +"i> c #213EB2", +"j> c #1F3FB4", +"k> c #1E40B6", +"l> c #1F3FB7", +"m> c #1E3EB8", +"n> c #1F3FB8", +"o> c #2040B7", +"p> c #2141B6", +"q> c #2140B7", +"r> c #2241B6", +"s> c #2342B5", +"t> c #2442B6", +"u> c #2543B5", +"v> c #2643B4", +"w> c #2544B6", +"x> c #2346B8", +"y> c #2247B9", +"z> c #2048BC", +"A> c #1F48BF", +"B> c #2049C0", +"C> c #214AC0", +"D> c #224BBF", +"E> c #234CBE", +"F> c #244DBF", +"G> c #234CBF", +"H> c #264DC0", +"I> c #274EBF", +"J> c #264DBF", +"K> c #254EBF", +"L> c #2050C0", +"M> c #1F51C1", +"N> c #1E42A4", +"O> c #263BA6", +"P> c #253BA7", +"Q> c #253CA7", +"R> c #1E41A5", +"S> c #1F40AF", +"T> c #273AAC", +"U> c #1E40B0", +"V> c #1F40B5", +"W> c #1F40B6", +"X> c #1F40B8", +"Y> c #1E40B8", +"Z> c #1F3EB8", +"`> c #203FB7", +" , c #2240B6", +"., c #2341B7", +"+, c #2345B9", +"@, c #2147BB", +"#, c #2148BA", +"$, c #2049BB", +"%, c #2049BD", +"&, c #2049BF", +"*, c #224BBE", +"=, c #244DBD", +"-, c #244CBF", +";, c #182969", +">, c #273BAD", +",, c #2739AB", +"', c #263AAC", +"), c #243CAE", +"!, c #233DAE", +"~, c #213EAF", +"{, c #1F3FB0", +"], c #2040B4", +"^, c #1F3FB6", +"/, c #1E3EB7", +"(, c #2240B7", +"_, c #2341B6", +":, c #2543B4", +"<, c #2644B3", +"[, c #2544B5", +"}, c #2545B5", +"|, c #2547B6", +"1, c #2548B7", +"2, c #2349BA", +"3, c #1F49BE", +"4, c #2149BD", +"5, c #2049BE", +"6, c #214BBE", +"7, c #2249BE", +"8, c #234CBD", +"9, c #2149BE", +"0, c #1E49BF", +"a, c #253BA9", +"b, c #253BAB", +"c, c #263AAB", +"d, c #213DAF", +"e, c #203EAF", +"f, c #1D40AF", +"g, c #1D40B0", +"h, c #1E40B4", +"i, c #2241B7", +"j, c #2643B6", +"k, c #2744B5", +"l, c #2643B5", +"m, c #2346B6", +"n, c #2147B7", +"o, c #2644B6", +"p, c #2247B7", +"q, c #2248B8", +"r, c #2647B7", +"s, c #2549B7", +"t, c #2645B7", +"u, c #2148B8", +"v, c #2847B6", +"w, c #2549B6", +"x, c #2849B6", +"y, c #2049B7", +"z, c #2A49B5", +"A, c #243BA4", +"B, c #253BA5", +"C, c #253BA6", +"D, c #263AA7", +"E, c #263AA8", +"F, c #2739AA", +"G, c #243CAD", +"H, c #223DAE", +"I, c #1F3EAF", +"J, c #1E3FB0", +"K, c #1D40B1", +"L, c #1E3FB1", +"M, c #1F3FB3", +"N, c #1F3FB5", +"O, c #2140B6", +"P, c #2140B8", +"Q, c #2744B4", +"R, c #2746B6", +"S, c #2947B6", +"T, c #2946B5", +"U, c #2A48B6", +"V, c #3551A8", +"W, c #1F399C", +"X, c #143D9F", +"Y, c #263BA5", +"Z, c #273BA8", +"`, c #273BAA", +" ' c #263AAD", +".' c #233CAD", +"+' c #213DAE", +"@' c #203FB2", +"#' c #2342B6", +"$' c #2443B6", +"%' c #2543B6", +"&' c #2644B5", +"*' c #133D9E", +"=' c #263BA7", +"-' c #263BA9", +";' c #273BA9", +">' c #263AAA", +",' c #2539AB", +"'' c #2639AB", +")' c #253AAC", +"!' c #243BAD", +"~' c #223DAF", +"{' c #203FB0", +"]' c #2040B1", +"^' c #2140B3", +"/' c #2543B1", +"(' c #2744AF", +"_' c #1A3CA0", +":' c #1D3BA2", +"<' c #233BA4", +"[' c #263AA5", +"}' c #253AA5", +"|' c #263AA6", +"1' c #263BA4", +"2' c #243BA5", +"3' c #263BA8", +"4' c #223EAF", +"5' c #3B4CA5", +"6' c #1D379A", +"7' c #1E389C", +"8' c #1E399F", +"9' c #1F3BA2", +"0' c #1F3BA3", +"a' c #213BA4", +"b' c #233AA3", +"c' c #243AA3", +"d' c #2539A4", +"e' c #253AA6", +"f' c #243BA7", +"g' c #253CAA", +"h' c #253CAC", +"i' c #253CAD", +"j' c #253CAE", +"k' c #243DAE", +"l' c #213FAF", +"m' c #223FAF", +"n' c #2040AF", +"o' c #253D93", +"p' c #1D3894", +"q' c #1F379A", +"r' c #1E389B", +"s' c #1D399C", +"t' c #1C3A9D", +"u' c #1B3A9D", +"v' c #183B9E", +"w' c #163C9E", +"x' c #153C9E", +"y' c #163B9D", +"z' c #173B9D", +"A' c #193A9D", +"B' c #1C3A9E", +"C' c #1F3AA1", +"D' c #223AA4", +"E' c #253BA8", +"F' c #273BA7", +"G' c #263CAB", +"H' c #263CAC", +"I' c #243EAE", +"J' c #273BAC", +"K' c #2A3795", +"L' c #1F389B", +"M' c #1D389B", +"N' c #1C399C", +"O' c #1B399C", +"P' c #1A3A9D", +"Q' c #1D399B", +"R' c #1B399B", +"S' c #1A3A9C", +"T' c #1B3A9F", +"U' c #1D3AA0", +"V' c #203BA2", +"W' c #203BA3", +"X' c #2639A6", +"Y' c #1B3692", +"Z' c #1C3794", +"`' c #1D3796", +" ) c #1E3898", +".) c #1E389A", +"+) c #1F399B", +"@) c #1A399C", +"#) c #193A9E", +"$) c #1A3BA0", +"%) c #1C3BA2", +"&) c #1D3CA3", +"*) c #203CA4", +"=) c #223BA5", +"-) c #3C4699", +";) c #2B4595", +">) c #1C3793", +",) c #1D3895", +"') c #1E3897", +")) c #1F3998", +"!) c #1F3999", +"~) c #1F399A", +"{) c #1E399C", +"]) c #1C3B9E", +"^) c #1D3BA0", +"/) c #1E3CA2", +"() c #223CA5", +"_) c #243CA6", +":) c #596FA9", +"<) c #3B4894", +"[) c #314993", +"}) c #29499F", +"|) c #28489E", +"1) c #2B4BA1", +"2) c #2C4BA1", +"3) c #2D4CA2", +"4) c #2E4CA3", +"5) c #2F4CA4", +"6) c #2E4CA4", +"7) c #2F4DA3", +"8) c #2F4DA4", +"9) c #D3D5D2", +"0) c #3B4794", +"a) c #314791", +"b) c #304892", +"c) c #304893", +"d) c #2F4995", +"e) c #2F4997", +"f) c #2D4A9A", +"g) c #2A4A9D", +"h) c #294A9F", +"i) c #284AA0", +"j) c #294AA0", +"k) c #2B4AA1", +"l) c #2D4CA3", +"m) c #C9CAC9", +"n) c #455D9B", +"o) c #242F78", +"p) c #1B2F85", +"q) c #C6C3C8", +"r) c #B5B2B6", +"s) c #B5B7B4", +"t) c #B5B7B3", +"u) c #B5B2B5", +"v) c #B5B3B4", +"w) c #B5B5B4", +"x) c #B5B6B3", +"y) c #B5B4B4", +"z) c #B5B3B5", +"A) c #B5B4B5", +"B) c #B5B5B5", +"C) c #B5B5B3", +"D) c #B5B5B6", +"E) c #BAC3BE", +"F) c #B9C3BD", +"G) c #C1C3C4", +"H) c #BFC3C2", +"I) c #B9C3BE", +"J) c #BBC3BF", +"K) c #BDC3C1", +"L) c #C0C3C3", +"M) c #BEC3C1", +"N) c #C2C3C5", +"O) c #E6E3E8", +"P) c #E0E2DF", +"Q) c #E1E1E1", +"R) c #E2E1E3", +"S) c #E4E1E6", +"T) c #E4E2E7", +"U) c #E4E2E6", +"V) c #E3E3E4", +"W) c #E2E3E3", +"X) c #E1E3E2", +"Y) c #E3E3E3", +"Z) c #E3E3E2", +"`) c #EBEDEA", +" ! c #EAECE9", +".! c #E9EBE8", +"+! c #ECEEEB", +". . + @ # $ $ $ $ $ $ $ % $ $ $ $ $ % $ $ $ $ $ $ % $ $ $ $ $ % $ $ $ $ $ $ $ $ $ % $ $ & * = - ; > , , ' ) ! ! ~ { ] ^ / ( _ : < [ } | | 1 2 3 3 4 4 4 4 4 4 4 5 6 4 4 4 5 6 7 8 9 4 5 6 7 8 9 6 7 8 9 ", +"0 a b % $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ c d d d d $ $ $ $ $ c d e f g h i i i i j k l m n o p q r s t u v w x y z 4 A B C D 9 9 E 9 E F G H I F J K L L L L J K L L L L L L L L ", +"@ % M N O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O P Q R S T U V W X Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.b.b.b.b.b.", +"c.$ d.O e.f.g.g.g.h.g.g.g.g.g.h.h.g.g.g.g.g.h.h.g.g.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+++@+#+$+@+$+%+&+*+=+$+-+;+>+,+'+)+!+;+>+,+~+,+>+,+~+,+", +"$ {+N N f.f.f.f.h.h.h.g.f.f.h.h.h.h.g.f.f.h.h.h.h.]+^+/+(+h._+:+<+[+}+|+1+2+3+4+5+6+7+8+9+0+a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+u+v+w+x+y+z+A+B+.+C+D+E+D+F+G+H+C+I+F+G+J+K+L+H+F+G+J+K+L+H+J+H+J+H+", +"{+{+N N M+M+h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.N+N+h.h.(+O+P+P+Q+R+S+T+U+V+W+X+Y+Z+`+ @.@+@@@#@$@%@&@*@=@-@;@>@,@'@)@!@~@{@]@^@/@(@_@:@<@[@[@y+}@|@1@A+1@2@3@ +2@4@2@5@C+D+6@D+7@5@C+D+6@I+C+D+6@I+", +"{+{+8@N M+M+h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.9@9@0@N+a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@v@w@x@y@z@A@B@q+r+C@D@E@F@G@H@_@I@J@K@<@L@M@N@O@P@Q@R@S@T@A+A+U@V@W@W@A+2@U@V@W@W@U@V@W@W@", +"{+{+8@N f.M+h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.(+(+(+9@9@X@Y@Z@e@`@ #.#+#@###$#%#&#*#=#-#;#>#,#'#)#!#~#{#]#z@^#/#(#p+_#r+:#s+t+<#[#}#|#|#1#_@|#_@_@2#L@3#4#y+y+5#z+z+z+5#z+z+z+z+A+A+A+A+A+", +"{+{+8@8@f.f.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.(+6#7#8#9#0#a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#&@p#q#r#s#t#u#v#w#x#x#y#y#z#A#B#C#D#E#E#F#G#H#F#H#H#u+v+I#J#K#L#J@J@M#N#O#P#M#M#M#N#M#Q#Q#R#", +"$ {+8@e.f.f.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.S#l.7#T#U#V#W#X#Y#Z#`# $f#g###.$+$@$#$$$$@%$&$*$=$-$;$>$,$'$)$!$~$~${$]$^$/$($($_$_$:$<$_$<$[$}$|$|$1$2$2$3$}#4$5$6$7$8$8$9$8$8$8$0$8$", +"$ {+a$e.f.f.h.h.h.h.h.h.h.h.h.b$h.c$c$c$c$c$d$c$c$c$c$c$c$c$c$c$c$e$e$7#f$g$h$i$X#j$k$l$m$n$o$p$q$r$l@s$t$u$v$w$x$y$z$A$B$C$D$E$F$G$G$H$I$J$J$K$K$J$L$L$L$L$L$M$N$O$P$Q$R$S$T$U$1$V$T$W$X$Y$1$V$Y$Z$`$ %", +"$ $ a$a$f.f.b$b$b$b$b$b$b$b$b$b$b$b$b$b$b$b$b$b$.%b$b$b$.%d$+%+%@%h.e$l.#%$%h$%%&%*%=%-%;%>%,%'%)%!% @ @~%{%]%^%/%(%w$_%:%<%[%}%|%D$1%2%3%4%5%4%4%6%5%5%4%4%4%5%7%5%8%9%L$0%a%a%a%P$b%P$P$z#z#z#P$c%c%c%", +"$ $ 8@e.f.f.d%b$b$b$b$b$d%b$b$b$b$b$b$e%f%b$b$b$b$b$g%h%b$.%i%i%j%k%l%m%X@n%h$o%&%p%q%`#r%s%t%u%v%w%x%y% @z%A%B%C%D%E%F%G%:%H%I%[%J%}%K%|%D$K%D$D$L%M%M%M%M%M%D$N%O%i+P%j+Q%R%S%T%0%U%V%W%W%W%W%X%X%X%X%", +"$ $ 8@8@f.f.d%d%b$b$b$b$d%d%b$b$b$h%Y%Z%Z%h%f%f%h%Y%`%`% &h%h%.&+&@&#&$&X@%&&&*&=&-&j$Z#+#;&>&,&'&)&)&!&~&{&]&^&/&(&^%_&(%:&<&[&}&|&1&A$A$2&3&4&4&5&B$6&7&B$7&8&9&6&7&0&a&a&i+i+i+b&a&a&j+U%c&U%j+U%c&U%", +"$ $ 8@8@d&e&d%d%d%d%d%d%d%d%d%d%d%`%d%d%d%d%`%`%`%d%d%d%d%`%`%f&g&h&j%i&j&k&l&m&=&X#Y#n&o&p&q&r&>&s&t&t&u&v&w&x&y&{&z&A&B&C&D&(%(%F%F%E&F&}&}&|&G&|&H&1&I%I&A$1&}&z$z$J&K&L&M&N&O&0&P&Q&0&a&R&a&a&a&R&a&", +"{+$ 8@8@e&e&d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%`%f&S&T&U&V&W&Y@X&Y&Z&`& *.*+*@*#*@*r&$*#*r&%*&***=*-*;*y&z%A%z&A&A&>*B&,*,*'*)*!*!*~*{*F&}&{*}&{*]*G%G%y$^*/*J&(*2&_*:*<*=$[*}*<*=$<*|*1*", +"{+{+8@2*e&e&d%d%d%d%d%d%d%d%d%e&3*4*4*4*4*4*5*4*4*4*4*4*4*4*4*4*`%f&6*6*7*8*9*0*a*b*c*d*e*f*g*h*i*j*+*k*h*l*m*n*m*o*p*q*r*s*t*u*v*w*x*y*y*z*A*B*C*D*E*F*G*E*G*F*H*G*F*~*]*{*I*x$J*K*L*G%K*M*o#o#I&N*O*O*", +"{+{+8@2*e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&P*e&e&e&e&e&e&P*P*e&e&e&P*P*5*Q*R*S*T*U*V*W*X*Y*Z*`*d* =.=+=@=#=$=%=g@&=*===-=i*;=l*>=,=q*'=s*)=k@!=x*~={=]=^=/=(=_=:=(=<=<=]=[=}=|=]=]=1=2=3=|=4=5=2=2=2=3=6=6=6=", +"{+{+7=e.e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&P*P*8=9=0=a=b=U*c=d=e=f=e@#=g=h=i=i=j=k=k=l=%===m=n=o=p=q=,=r=s=t=u=v=v*w=x=x=y=z=z=A=z=A=B=C=B=D=C=B=x=B=B=B=B=B=B=B=B=B=B=B=B=B=B=", +"{+{+7=7=e&e&e&e&E=E=e&e&e&e&E=E=E=e&e&e&e&E=E=E=e&e&e&e&E=E=e&e&e&e&E=E=E=F=d%G=G=H=I=J=K=L=M=R+}+N=O=P=Q=j=i=h=R=e@@=S=-=T=h@l*U=V=W=X=Y=Z=`= - - -.-+-@- -#-$-%-$-&-*-$-=-%-----C=$-%---------B=B=B=B=", +"{+{+7=7=;-;-E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=>-,-'-)-!-6*~-{-{-]-^-/-/-(-_-:-N=<-[-}-|-1-2-3- =4-5-6-7-8-9-0-0-a-b-c-d-e-f-g-h-h-i-j-k-h-h-i-j-l-m-n-o-i-j-l-m-n-j-l-p-n-", +"{+{+7=7=;-;-E=E=E=E=E=E=E=E=q-r-s-t-t-u-u-v-v-v-u-w-x-u-u-u-u-u-u-u-u-v-v-u-u-u-u-u-v-v-u-u-u-u-v-v-u-y-z-A-B-C-D-E-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-U-V-W-V-e-X-Y-Z-`- ;.;Y-N N +;@;.;Y-N N N N N N N ", +"#;#;d&d&$;$;%;%;%;%;%;%;%;%;&;*;=;-;-;-;;;>;,;>;>;>;;;>;>;>;>;>;>;>;>;>;';);>;>;>;>;>;';>;>;>;>;>;';);!;~;{;];^;/;(;_;_;:;<;[;};};|;1;2;3;4;5;6;7;8;9;9;0;a;0;0;b;h.a;0;0;b;h.c;h.d;0;b;h.c;h.d;h.c;h.d;", +"#;#;;-;-$;$;e;e;e;e;e;e;e;e;e;e;e;f;f;f;f;e;e;e;f;f;f;f;f;f;f;f;f;f;f;f;g;%;f;f;f;f;f;g;f;f;f;f;f;g;%;h;i;j;k;l;m;n;o;p;q;r;r;s;t;u;v;w;x;y;z;A;B;C;6;D;E;F;G;G;H;I;F;G;G;H;I;J;J;K;G;H;I;J;J;K;I;J;J;K;", +"#;#;;-;-$;$;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;L;e;e;e;e;e;e;e;e;e;e;e;e;L;M;N;O;P;Q;i;i;k;R;S;T;U;q;q;V;W;X;{;Y;Z;`; >.>+>@>#>+>$>6;#>#>+>%>&>G;G;G;G;G;&>G;G;G;G;G;G;G;G;G;", +"#;#;d.;-$;$;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;*>e;e;e;e;e;e;e;e;e;e;e;e;*>=>->;>>>,>'>'>)>!>~>{>]>^>^>V;V;/>(>_>:><>[>}>|>1>2>3>2>4>5>6>7>8>9>0>G;G;G;G;9>0>G;G;G;G;G;G;G;G;", +"#;#;d.d.a>a>e;e;e;e;e;e;e;e;e;e;b>b>c>c>c>c>c>b>e;e;e;e;e;e;e;e;e;e;e;e;e;e;d>e>f>g>h>i>j>k>l>l>m>m>n>n>o>o>p>q>r>r>s>t>u>v>v>u>w>';x>y>z>t;A>B>C>D>E>E>F>G>F>H>H>I>F>Y;J>w;K>L>K>M>J>w;K>L>K>M>K>L>K>M>", +"#;#;d.d.a>a>N>e;N>O>O>O>N>e;N>O>O>P>Q>R>S>R>Q>O>O>O>N>e;N>O>O>O>N>e;N>N>O>T>e;e;e;U>U>U>U>f;V>W>o>o>o>o>X>X>Y>Y>n>n>Z>Z>`> ,.,t>t>u>u>w>+,@,#,$,%,A>&,*,=,B>[>-,w;<>C>[>-,w;w;w;w;w;-,w;w;w;w;w;w;w;w;w;", +"#;;,;-;-a>a>N>N>N>O>O>O>N>N>N>O>O>O>O>N>N>N>O>O>O>O>N>N>N>O>O>O>N>N>N>N>O>>,,,,,,,',g>),!,~,{,{,*>U>e;f;],o>%;o>^,^,/,/,l>q>(,_,t>u>:,<,v>[,},|,1,2,%,%,3,4,5,6,7,8,9,5,6,0,G>G>Y;G>6,0,G>G>Y;G>G>G>Y;G>", +";,;,;-;-O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>P>a,b,',',c,c,f>),e>d,e,{,{,U>U>f,f,U>U>g,g,*>g;h,^,^,`>`>q>i,t>j,k,k,l,w>m,n,o,p,q,r,s,t,p,u,v,w,x,y,z,u,v,w,x,y,z,w,x,y,z,", +";,;,b b O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>A,A,A,B,C,D,E,F,c,',g>G,!,H,~,e,{,I,J,J,K,K,U>f,f,J,L,M,N,L;O,i,P,.,l,Q,k,k,k,k,k,k,R,v,k,k,k,R,v,S,T,U,k,R,v,S,T,U,v,S,T,U,", +";,;,b V,W,W,X,X,O>X,X,X,X,X,O>X,X,X,X,X,X,O>X,X,X,X,X,X,O>X,X,X,X,X,O>X,X,O>O>O>O>B,B,B,B,Y,O>O>Z,`,T>T> '',g>.'+'e,{,{,e,+'+'e,e,{,J,K,e;@'N,O,#'$'%'%'j,%'j,&'k,k,%'j,&'k,k,k,k,k,&'k,k,k,k,k,k,k,k,k,", +";,;,b V,W,W,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,*'O>O>O>O>O>O>O>O>B,B,A,A,B,C,='-'`,;'>'>',''')'!'!'e>e>~'~'~,~,{'{,*>*>e;]']']']']']'^'/']']']'^'/':,(':,]'^'/':,(':,/':,(':,", +";,;,V,V,W,W,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,_':'<'['}'|'|'O>O>O>O>O>O>O>Y,Y,1'1'B,B,2'2'C,3'-'>'c,)')'!'),4'{'e;]'e;*>*>e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;", +";,;,5'5'W,W,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,W,6'6'6'7'8'9'0'a'b'c'd'd'}'}'O>O>O>O>O>O>O>O>Y,1'1'['['e'e'f'g'h'i'j'k'G,),!,l'j'm'n'b>b>),m'b>e;e;e;e;e;b>e;e;e;e;e;e;e;e;e;", +";,;,b b o'o'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'W,q'q'q'r's't'u'v'w'x'y'z'A'B'C'D'2'2'B,B,O>O>O>O>O>O>O>O>O>O>O>Y,Y,C,C,='='='E'F'3'3'3'G'Z,='F'F'G'H'I'J'F'F'G'H'I'J'G'H'I'J'", +";,;,b b K'K'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'W,W,W,W,W,L'L'q'r'M'N'O'P'u'N's'Q'R'S'A'T'U'C'V'9'0'W'D'}'X'|'O>O>B,B,O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>", +";,;,b b K'K'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'Y'Y'Y'Z'`' ).)+)+)+)W,W,W,W,L'L'q'q'r'r's'M'N'P'@)A'#)$)%)&)*)=)B,|'|'O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>", +"{+;,$ -);)K'p'p'o'p'p'p'p'p'o'p'p'p'p'p'p'o'p'p'p'p'p'p'o'p'p'p'p'p'o'o'p'p'p'p'p'p'p'p'p'p'>)>)Y'Y'>)Z',)')))!)~)+)W,W,W,W,W,W,W,W,W,W,W,L'L'{)s't'])^)/)])/)/)O>()])/)/)O>()O>_)O>/)O>()O>_)O>()O>_)O>", +":);,;,;)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)[)M M M M M M M M M M M M M M M M M M })})|)|)})M M 1)2)3)4)5)6)6)6)7)7)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)", +"9)#;;,;,$ -)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)0)a)a)a)b)c)d)e)f)g)h)i)i)j)j)M M M M M M M M M M M })})})})M k)k)M M k)l)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)", +"+ 9)m)n)$ #;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;o)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)", +"+ + 9)a m)q)r)s)r)s)r)s)r)s)r)r)s)r)s)r)s)r)r)s)r)s)r)s)r)s)r)s)r)s)r)s)r)t)u)v)w)x)x)w)y)z)A)A)B)B)B)B)w)w)C)C)w)w)B)B)B)B)B)w)w)w)w)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)D)B)B)B)B)B)D)B)B)B)D)B)", +". + + 9)9)9)q)E)q)E)q)E)q)E)q)q)E)q)E)q)E)q)q)E)q)E)q)E)q)E)q)E)q)E)q)E)q)F)G)H)E)I)J)K)H)L)L)L)L)L)L)L)H)H)M)M)H)H)L)L)G)L)L)H)H)H)H)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)N)L)L)L)L)L)N)L)L)L)N)L)", +". . 0 . + O)P)O)P)O)P)O)P)O)P)P)O)P)O)P)O)P)P)O)P)O)P)O)P)O)P)O)P)O)P)O)P)O)Q)R)S)T)U)V)W)X)W)W)V)V)V)V)V)V)V)V)Y)Y)Z)Z)Y)Z)Z)Y)Y)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)Y)V)V)V)V)V)Y)V)V)V)Y)V)", +". . . 0 0 0 . 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 `) !+ + + .! !`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)+!`)`)`)`)`)+!`)`)`)+!`)"}; + + +static char * listviewhighcornerright_xpm[] = { +"100 46 780 2", +" c None", +". c #6A779D", +"+ c #6C789C", +"@ c #6C789D", +"# c #6B789D", +"$ c #6A779E", +"% c #66759E", +"& c #64749E", +"* c #63749E", +"= c #61739D", +"- c #576D9B", +"; c #556C9C", +"> c #4D679D", +", c #4A649D", +"' c #49629D", +") c #465E9C", +"! c #40579C", +"~ c #3B5394", +"{ c #2C4E97", +"] c #314993", +"^ c #2B4595", +"/ c #1B4296", +"( c #253D93", +"_ c #19418F", +": c #0F3C96", +"< c #42599E", +"[ c #758DC3", +"} c #E8EAE7", +"| c #EEF0ED", +"1 c #FBFBFC", +"2 c #6F7D9B", +"3 c #6F7D9A", +"4 c #6E7B9C", +"5 c #67759E", +"6 c #63739E", +"7 c #62739D", +"8 c #596F9C", +"9 c #4A639D", +"0 c #47609C", +"a c #445B9F", +"b c #3E5697", +"c c #2E509A", +"d c #2D509A", +"e c #2D4F99", +"f c #2D4F98", +"g c #28418A", +"h c #3E51A3", +"i c #D0D3DC", +"j c #A1B6EF", +"k c #A2B6F0", +"l c #A1B6F0", +"m c #A3B6F0", +"n c #A0B6EF", +"o c #9DB6EE", +"p c #9CB5EF", +"q c #9CB2F0", +"r c #9FB5EE", +"s c #9CB4EB", +"t c #9AB3EC", +"u c #9AB0EC", +"v c #9DB3EB", +"w c #9BB4EC", +"x c #9BB4EE", +"y c #9BB1EF", +"z c #9BB0F0", +"A c #90ACF0", +"B c #93ABEE", +"C c #91A8EB", +"D c #8BA3E8", +"E c #88A1E7", +"F c #809DE9", +"G c #7A99E8", +"H c #7491E5", +"I c #698AE4", +"J c #6184E3", +"K c #507EDC", +"L c #4E7CDB", +"M c #4F7DDC", +"N c #5479DA", +"O c #567BDC", +"P c #577CDD", +"Q c #5074DA", +"R c #5174DB", +"S c #5175DC", +"T c #5276DD", +"U c #4D71DE", +"V c #4C72D8", +"W c #3A6CE0", +"X c #2B49A6", +"Y c #E0E2DF", +"Z c #93AAE9", +"` c #94A9E8", +" . c #94AAE9", +".. c #93A9E9", +"+. c #92AAE9", +"@. c #8DA9E8", +"#. c #8CA7E9", +"$. c #92ABE9", +"%. c #8EAAE9", +"&. c #8EA9E9", +"*. c #8FAAE9", +"=. c #8CA8E9", +"-. c #8CA2E7", +";. c #86A1E6", +">. c #839EE9", +",. c #7F9CE9", +"'. c #7A97E8", +"). c #7693E7", +"!. c #6E8EE8", +"~. c #678AE9", +"{. c #5D84E3", +"]. c #577CDF", +"^. c #4E77DF", +"/. c #4A70DB", +"(. c #4870DB", +"_. c #4870DC", +":. c #4770E3", +"<. c #496FDC", +"[. c #486EDB", +"}. c #466FE4", +"|. c #466EE3", +"1. c #4167D9", +"2. c #4066D8", +"3. c #3F66D8", +"4. c #3D64D7", +"5. c #3960DA", +"6. c #476DD9", +"7. c #446EE5", +"8. c #305EC8", +"9. c #8EAAE8", +"0. c #8FAAE8", +"a. c #91AAE9", +"b. c #8FA9E8", +"c. c #8BA8E8", +"d. c #8AA7E9", +"e. c #8BA5EA", +"f. c #8AA7E8", +"g. c #87A2E6", +"h. c #859FE8", +"i. c #7F9DE8", +"j. c #7C9AE8", +"k. c #7B95E7", +"l. c #7090E8", +"m. c #6B8BE9", +"n. c #6386E6", +"o. c #5881E1", +"p. c #5479DE", +"q. c #4D74DE", +"r. c #476EDB", +"s. c #446EE1", +"t. c #446EE0", +"u. c #446EDF", +"v. c #446DE0", +"w. c #426ADF", +"x. c #3C64DA", +"y. c #4360CC", +"z. c #D3D5D2", +"A. c #E6E3E8", +"B. c #8DA2E7", +"C. c #8CA6EA", +"D. c #8DA3E9", +"E. c #88A2E7", +"F. c #87A1E7", +"G. c #8AA1E7", +"H. c #849EE9", +"I. c #7D9AE9", +"J. c #7B98E8", +"K. c #7796E5", +"L. c #7191E7", +"M. c #688CE9", +"N. c #6687E5", +"O. c #5C83E1", +"P. c #557BDE", +"Q. c #4F76DE", +"R. c #4C72DE", +"S. c #456EDF", +"T. c #426AD9", +"U. c #4269D9", +"V. c #4269D8", +"W. c #3D64D9", +"X. c #3A61DA", +"Y. c #345ED6", +"Z. c #335ECF", +"`. c #C6C3C8", +" + c #86A1E7", +".+ c #87A2E7", +"++ c #87A0E7", +"@+ c #859EE8", +"#+ c #849DE9", +"$+ c #7E9BE9", +"%+ c #7A99E9", +"&+ c #7A95E5", +"*+ c #7593E7", +"=+ c #6F8EE9", +"-+ c #668AE5", +";+ c #6386E0", +">+ c #5B82DF", +",+ c #5379DE", +"'+ c #5075DE", +")+ c #4B6FDC", +"!+ c #446AD7", +"~+ c #4269D6", +"{+ c #4269D5", +"]+ c #3E65D7", +"^+ c #C9CAC9", +"/+ c #869EE9", +"(+ c #859FE9", +"_+ c #849FE9", +":+ c #829DE8", +"<+ c #819DE8", +"[+ c #7B9AE9", +"}+ c #7A96E6", +"|+ c #7290E8", +"1+ c #698CE6", +"2+ c #6689E0", +"3+ c #5D84E0", +"4+ c #587FDF", +"5+ c #5377DD", +"6+ c #4B74DE", +"7+ c #496BD8", +"8+ c #7C9BE9", +"9+ c #7E9CE9", +"0+ c #7D9AEA", +"a+ c #7D9BEA", +"b+ c #7D98E8", +"c+ c #7C98E8", +"d+ c #7796E4", +"e+ c #7592E6", +"f+ c #7390E1", +"g+ c #698DE0", +"h+ c #6588DE", +"i+ c #5E84E0", +"j+ c #5880DF", +"k+ c #5479DC", +"l+ c #4F75DE", +"m+ c #4A6FDB", +"n+ c #436AD7", +"o+ c #3F65D7", +"p+ c #BAC3BE", +"q+ c #7B9AE8", +"r+ c #7B9AEA", +"s+ c #7A9AEA", +"t+ c #7B99E9", +"u+ c #7D97E7", +"v+ c #7D95E6", +"w+ c #7D95E5", +"x+ c #7C95E6", +"y+ c #7493E3", +"z+ c #7290DF", +"A+ c #6C8DDE", +"B+ c #6B89E1", +"C+ c #6486DF", +"D+ c #5D81DF", +"E+ c #567DDE", +"F+ c #4F73DE", +"G+ c #496EDA", +"H+ c #355ED6", +"I+ c #345ED5", +"J+ c #7E95E5", +"K+ c #7C97E8", +"L+ c #7C97E7", +"M+ c #7B94E6", +"N+ c #7A95E4", +"O+ c #7695E5", +"P+ c #7694E4", +"Q+ c #7994E6", +"R+ c #7995E4", +"S+ c #7594E4", +"T+ c #7391E2", +"U+ c #6E8EDE", +"V+ c #6B8ADE", +"W+ c #6688DF", +"X+ c #5F84E0", +"Y+ c #5980E0", +"Z+ c #4D72DD", +"`+ c #456BD7", +" @ c #4168D6", +".@ c #3C64D7", +"+@ c #335ED0", +"@@ c #4659C7", +"#@ c #7292E1", +"$@ c #7392E1", +"%@ c #7492E1", +"&@ c #718FDF", +"*@ c #6F8EDE", +"=@ c #6D8BDE", +"-@ c #6B88DF", +";@ c #597FDF", +">@ c #557ADD", +",@ c #5176DC", +"'@ c #4D74DD", +")@ c #496DDA", +"!@ c #3860D8", +"~@ c #7391E0", +"{@ c #7290DE", +"]@ c #6D8EDD", +"^@ c #6D8DDD", +"/@ c #7190E0", +"(@ c #6C8DDD", +"_@ c #6B89DF", +":@ c #6487E0", +"<@ c #6085DF", +"[@ c #5F81DE", +"}@ c #567EDE", +"|@ c #4F74D9", +"1@ c #466BD7", +"2@ c #4067D5", +"3@ c #3C63D7", +"4@ c #335ED3", +"5@ c #335ED1", +"6@ c #718EDD", +"7@ c #728EDD", +"8@ c #748EDD", +"9@ c #708EDD", +"0@ c #6F8DDD", +"a@ c #6E8DDD", +"b@ c #6C8ADE", +"c@ c #6C89DF", +"d@ c #6988DF", +"e@ c #6387DF", +"f@ c #6282DE", +"g@ c #5681E0", +"h@ c #577BDD", +"i@ c #5277DB", +"j@ c #4D73D8", +"k@ c #4A70D8", +"l@ c #436AD5", +"m@ c #3F66D6", +"n@ c #3C63D8", +"o@ c #3960D8", +"p@ c #3860D7", +"q@ c #335ED2", +"r@ c #345ED4", +"s@ c #6C88DF", +"t@ c #6D88DF", +"u@ c #6B89DE", +"v@ c #6888DF", +"w@ c #6587E0", +"x@ c #6989DF", +"y@ c #6687E0", +"z@ c #6287E0", +"A@ c #6281DD", +"B@ c #5881E0", +"C@ c #557ADB", +"D@ c #5176D9", +"E@ c #4E75D7", +"F@ c #4A6FD8", +"G@ c #476BD6", +"H@ c #4067D6", +"I@ c #3C62D7", +"J@ c #3C60D4", +"K@ c #365ED1", +"L@ c #345ED3", +"M@ c #6786DF", +"N@ c #5F85E0", +"O@ c #5F86E0", +"P@ c #6186DF", +"Q@ c #6286E0", +"R@ c #6284DF", +"S@ c #6384DF", +"T@ c #5B7FDE", +"U@ c #577DDC", +"V@ c #557BDA", +"W@ c #5278D8", +"X@ c #4E76D6", +"Y@ c #4C72D7", +"Z@ c #486DD8", +"`@ c #4469D6", +" # c #3F62D2", +".# c #3C60CF", +"+# c #345ECF", +"@# c #6086DF", +"## c #6085E0", +"$# c #6285DF", +"%# c #6383DD", +"&# c #6481DC", +"*# c #6380DD", +"=# c #6183DE", +"-# c #6083DD", +";# c #6081DC", +"># c #6080DD", +",# c #6083DE", +"'# c #6181DC", +")# c #6280DD", +"!# c #577EDB", +"~# c #557CD7", +"{# c #4F76D6", +"]# c #4E74D7", +"^# c #466CD7", +"/# c #3B64D6", +"(# c #4261CD", +"_# c #375FCE", +":# c #5A7FD8", +"<# c #6281DA", +"[# c #5F81D8", +"}# c #5C80D8", +"|# c #557DD7", +"1# c #577ED8", +"2# c #567ED7", +"3# c #587DD8", +"4# c #577DD8", +"5# c #587ED8", +"6# c #567DD8", +"7# c #5379D9", +"8# c #5177D7", +"9# c #4D74D5", +"0# c #486ED9", +"a# c #4068D4", +"b# c #3D65D2", +"c# c #4361CC", +"d# c #345ECE", +"e# c #325DCF", +"f# c #2C5AD1", +"g# c #3959C5", +"h# c #547BD8", +"i# c #567DD7", +"j# c #557BD8", +"k# c #5279D9", +"l# c #5278D9", +"m# c #4D74D6", +"n# c #4B71D8", +"o# c #496CD8", +"p# c #4669D7", +"q# c #3D66D3", +"r# c #3F62CF", +"s# c #4260CC", +"t# c #5379D8", +"u# c #4E75D4", +"v# c #4C73D7", +"w# c #476CD7", +"x# c #4869D0", +"y# c #4067D2", +"z# c #3D64D1", +"A# c #4261CC", +"B# c #395FCE", +"C# c #4F75D3", +"D# c #5074D2", +"E# c #5174D1", +"F# c #5175D1", +"G# c #4F74D3", +"H# c #4C73D5", +"I# c #4C73D4", +"J# c #4A72D1", +"K# c #4B70CF", +"L# c #506CCC", +"M# c #4D6BCE", +"N# c #4167D0", +"O# c #3D65D1", +"P# c #3F63CF", +"Q# c #3B5FCD", +"R# c #3159CD", +"S# c #4971D0", +"T# c #4870CF", +"U# c #4C6FCF", +"V# c #4E6CCE", +"W# c #4E6BCE", +"X# c #4769CF", +"Y# c #3D66D0", +"Z# c #3C65D1", +"`# c #4062CE", +" $ c #3D5FCD", +".$ c #365FCF", +"+$ c #325DCD", +"@$ c #2D5AD0", +"#$ c #3859C5", +"$$ c #355FCF", +"%$ c #355ECF", +"&$ c #335ECE", +"*$ c #305CCD", +"=$ c #2B5ACE", +"-$ c #3056C9", +";$ c #2553C6", +">$ c #2153C8", +",$ c #1F4FC7", +"'$ c #274CC5", +")$ c #214AC7", +"!$ c #1C48C8", +"~$ c #1244C9", +"{$ c #1043C9", +"]$ c #1144C9", +"^$ c #2A45BE", +"/$ c #2744B5", +"($ c #1D49C0", +"_$ c #2B58DE", +":$ c #002D94", +"<$ c #2B59CA", +"[$ c #2A59CA", +"}$ c #2E57C8", +"|$ c #3255C6", +"1$ c #3355C5", +"2$ c #1C52C8", +"3$ c #1D50C7", +"4$ c #234FC6", +"5$ c #264CC5", +"6$ c #1D48C7", +"7$ c #1245C8", +"8$ c #1F44C2", +"9$ c #2945BE", +"0$ c #2A45BD", +"a$ c #2040BF", +"b$ c #3156C7", +"c$ c #3056C7", +"d$ c #3354C5", +"e$ c #3355C6", +"f$ c #3255C5", +"g$ c #3254C5", +"h$ c #1952C7", +"i$ c #1951C8", +"j$ c #2050C7", +"k$ c #274CC4", +"l$ c #244CC6", +"m$ c #1F49C7", +"n$ c #1E47C5", +"o$ c #2045C3", +"p$ c #1C44BF", +"q$ c #2045BE", +"r$ c #2040B8", +"s$ c #3254C6", +"t$ c #3055C6", +"u$ c #2A54C6", +"v$ c #2353C7", +"w$ c #3054C5", +"x$ c #2F55C5", +"y$ c #2A54C5", +"z$ c #2553C5", +"A$ c #2F54C5", +"B$ c #3155C6", +"C$ c #2A54C7", +"D$ c #1A52C8", +"E$ c #204FC2", +"F$ c #264DC6", +"G$ c #234BC5", +"H$ c #1D48C1", +"I$ c #1E48BF", +"J$ c #2646BE", +"K$ c #2B45BD", +"L$ c #1E43BE", +"M$ c #2643BF", +"N$ c #2243BF", +"O$ c #3049BC", +"P$ c #1E50BE", +"Q$ c #1D50C0", +"R$ c #1D50BF", +"S$ c #1852C1", +"T$ c #1E51C0", +"U$ c #214FBF", +"V$ c #2050C0", +"W$ c #244EBF", +"X$ c #2151C0", +"Y$ c #234FBF", +"Z$ c #2350C0", +"`$ c #2351C0", +" % c #244FBF", +".% c #2250C0", +"+% c #2051C0", +"@% c #1E50C0", +"#% c #244DBE", +"$% c #274DBF", +"%% c #244CBF", +"&% c #1C48C0", +"*% c #2247BF", +"=% c #2C44BD", +"-% c #1C44BE", +";% c #1444BF", +">% c #1841BF", +",% c #1F40BF", +"'% c #254DBE", +")% c #224FBE", +"!% c #224FBF", +"~% c #234EBF", +"{% c #254CBD", +"]% c #244DBD", +"^% c #244CBD", +"/% c #264DBE", +"(% c #264DBD", +"_% c #214BC0", +":% c #1D48C0", +"<% c #2347BF", +"[% c #2B44BD", +"}% c #2444BE", +"|% c #0F42BF", +"1% c #0641BF", +"2% c #0F41BF", +"3% c #1741BE", +"4% c #1F40BD", +"5% c #234BBF", +"6% c #234CBE", +"7% c #214BBE", +"8% c #244CBE", +"9% c #214ABE", +"0% c #214ABF", +"a% c #1F48C0", +"b% c #2746BE", +"c% c #1F43BE", +"d% c #0941BE", +"e% c #0342BA", +"f% c #0242BC", +"g% c #1241B8", +"h% c #1F40B7", +"i% c #2F41AC", +"j% c #2644AE", +"k% c #2D49B4", +"l% c #2649B6", +"m% c #2949B7", +"n% c #2849B5", +"o% c #2149B8", +"p% c #1E49B9", +"q% c #1F48B8", +"r% c #1F49B9", +"s% c #2545B6", +"t% c #2744B7", +"u% c #2844B7", +"v% c #2043B8", +"w% c #1241B7", +"x% c #1340B8", +"y% c #0D41B8", +"z% c #1941B8", +"A% c #1F40B8", +"B% c #203FB8", +"C% c #2549B5", +"D% c #2648B6", +"E% c #2547B7", +"F% c #2248B7", +"G% c #2048B7", +"H% c #2346B6", +"I% c #2146B6", +"J% c #2247B7", +"K% c #2148B7", +"L% c #2743B4", +"M% c #2643B5", +"N% c #2542B6", +"O% c #1D42B7", +"P% c #0E42B8", +"Q% c #0C41B8", +"R% c #1341B8", +"S% c #1740B8", +"T% c #1C41B8", +"U% c #1F40B1", +"V% c #2644B5", +"W% c #2544B5", +"X% c #2544B4", +"Y% c #2444B5", +"Z% c #2444B4", +"`% c #2744B4", +" & c #2241B7", +".& c #1D41B8", +"+& c #0B42B8", +"@& c #0942B8", +"#& c #0C42B8", +"$& c #0F41B8", +"%& c #1641B8", +"&& c #2442B5", +"*& c #2543B3", +"=& c #2342B2", +"-& c #2341B4", +";& c #2141B3", +">& c #2141B5", +",& c #2140B5", +"'& c #2040B5", +")& c #1C40B7", +"!& c #1B41B3", +"~& c #0142B6", +"{& c #0E41B7", +"]& c #1141B7", +"^& c #1440B2", +"/& c #113FB0", +"(& c #1440B0", +"_& c #213EAF", +":& c #233DAE", +"<& c #223EAF", +"[& c #1E40B1", +"}& c #173EAD", +"|& c #1440AF", +"1& c #0D40AF", +"2& c #0941B0", +"3& c #0D3FAE", +"4& c #1B3CAC", +"5& c #233CAD", +"6& c #203FB0", +"7& c #273BAD", +"8& c #1D40B0", +"9& c #2040B1", +"0& c #1E40B0", +"a& c #1C40B0", +"b& c #1B3DAC", +"c& c #143DAC", +"d& c #193DAD", +"e& c #1B3DAD", +"f& c #173DAD", +"g& c #153DAC", +"h& c #1C3CAC", +"i& c #243CAD", +"j& c #213FB0", +"k& c #263BAA", +"l& c #253CAE", +"m& c #273AAC", +"n& c #273AAD", +"o& c #253BAD", +"p& c #1D3CAC", +"q& c #243BAD", +"r& c #1E3CAC", +"s& c #263BAD", +"t& c #1A3DAC", +"u& c #143DAB", +"v& c #163DAC", +"w& c #1A3CAC", +"x& c #1F3CAD", +"y& c #263BAB", +"z& c #263BA6", +"A& c #1E42A4", +"B& c #2D40A5", +"C& c #253BA6", +"D& c #253CA7", +"E& c #263AA5", +"F& c #253BA7", +"G& c #1E3BA6", +"H& c #193DA6", +"I& c #173DA5", +"J& c #143DA6", +"K& c #1A3DA7", +"L& c #133DA6", +"M& c #123DA5", +"N& c #1A3CA7", +"O& c #243BA6", +"P& c #263AA7", +"Q& c #273BA7", +"R& c #263AA6", +"S& c #223BA6", +"T& c #1D3BA6", +"U& c #173CA6", +"V& c #133DA5", +"W& c #1B3DA6", +"X& c #193DA5", +"Y& c #123DA4", +"Z& c #163CA5", +"`& c #213CA6", +" * c #273BA8", +".* c #263BA7", +"+* c #253BA5", +"@* c #263BA5", +"#* c #1C3BA6", +"$* c #1B3BA9", +"%* c #133BA8", +"&* c #0A3BA7", +"** c #083AA6", +"=* c #123CA5", +"-* c #0839A8", +";* c #0239A6", +">* c #123AA8", +",* c #1F49C8", +"'* c #2F4DA4", +")* c #2E4DA3", +"!* c #384CA4", +"~* c #3C4DA7", +"{* c #394EA7", +"]* c #3B4CA5", +"^* c #3C52B1", +"/* c #3551A8", +"(* c #3759BE", +"_* c #4161C7", +":* c #0033A8", +"<* c #596FA9", +"[* c #2F4DA3", +"}* c #2D4BA5", +"|* c #2E4CA4", +"1* c #2C4AA5", +"2* c #2D4BA4", +"3* c #354DA4", +"4* c #3A4BA4", +"5* c #394DA6", +"6* c #4056AD", +"7* c #445BBB", +"8* c #B5B7B4", +"9* c #1B2F85", +"0* c #242F79", +"a* c #B5B5B5", +"b* c #B5B2B6", +"c* c #C0C3C3", +"d* c #E3E3E4", +"e* c #EBEDEA", +". + @ + # $ % & # $ % & # $ % & # $ % & & * = - ; > , ' ) ! ~ { { { { { { { ] ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ / / / ( / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / _ _ / / : / < [ } | | | 1 1 ", +"2 2 2 2 3 2 4 @ 3 2 4 @ 3 2 4 @ 3 2 4 @ # 5 6 7 8 ; > 9 0 a b c d e f { { { ] ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ( ( ( ( ( ( ( ( ( / / / / / / / / / / / / / / / / / _ _ _ _ _ _ _ _ _ _ _ g g _ / / : : : h i } 1 | 1 ", +"j k l m n o p q n o p q r s t u v w x y z A B C D E F G H I J K L M N O P O O Q R S T T T T T T T T T T T T T T T T T T U U U U U U U U U U U U U U U U U U U U U U U U U U U U V V V U U W X : [ Y | | ", +"Z ` . ...+.@.#...+.@.#.Z $.%.&.Z $.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.6.7.8.: h Y } 1 ", +"9.0.a.b.c.c.d.e.f.c.d.e.f.c.d.e.f.c.d.e.g.h.i.j.k.l.m.n.o.p.q.r.s.s.t.u.u.v.w.x.4.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.y.5.7.6.: / z.A.} ", +"-.B.C.D.-.E.g.F.G.E.g.F.G.E.g.F.G.E.g.F.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.V.U.U.W.X.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Z.y.Y.7.7.: : `.z.} ", +" +.+g.;.++F.@+#+++F.@+#+++F.@+#+++F.@+#+$+%+&+*+=+-+;+>+,+'+)+!+~+{+]+{+{+4.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.Y.Y.5.5.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Z.Z.Z.y.y.5.7.7.: : ^+z.Y ", +"/+(+_+#+H.H.>.:+H.H.>.:+H.H.>.:+H.H.>.<+[+}+*+|+1+2+3+4+5+6+7+{+{+4.4.4.4.4.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.Y.Y.Y.Y.Y.Y.Y.5.Y.Y.Y.Y.Y.Y.Y.Y.5.Y.Y.5.5.5.5.Y.Y.Y.Y.Y.Y.Z.Z.Z.Z.y.y.y.y.y.y.7.7.: : ^+i } ", +"8+9+0+0+a+0+0+b+a+0+0+b+a+0+0+b+a+0+0+c+d+e+f+g+h+i+j+k+l+m+n+o+4.4.4.4.5.5.5.5.5.5.Y.Y.5.5.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Y.Y.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.7.7.: : p+z.Y ", +"q+r+r+s+t+u+v+w+t+u+v+w+t+u+v+w+t+u+x+&+y+z+A+B+C+D+E+5+F+G+~+4.4.4.4.5.5.5.5.5.H+Y.Y.Y.Y.Y.Y.Y.Y.I+Y.Z.Y.Y.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.7.7.: : `.z.A.", +"J+v+K+L+M+N+O+P+Q+R+O+P+Q+R+O+P+Q+R+O+S+T+U+V+W+X+Y+P.T Z+`+ @4.4..@5.5.5.5.5.5.Y.Y.Y.I+I+I+I+I++@+@Z.Z.Y.Y.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.@@Z.7.7.: : p+z.Y ", +"#@$@$@%@%@$@#@&@#@#@#@&@#@#@#@&@#@#@#@*@=@-@;+i+;@>@,@'@)@ @4.X.5.5.H+Y.Y.Y.!@Y.Y.I++@+@Z.Z.+@Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.y.Z.6.6.: : `.z.A.", +"#@$@~@~@~@{@]@^@/@{@]@^@/@{@]@^@/@{@]@(@_@:@<@[@}@k+|@V 1@2@3@5.5.5.Y.Y.I+4@I+5@+@Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.y.Z.6.6.: : p+z.Y ", +"6@7@8@9@0@a@b@c@a@a@b@c@a@a@b@c@a@a@b@d@e@<@f@g@h@i@j@k@l@m@n@o@o@p@Y.I+q@q@r@+@Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.y.Z.6.6.: : `.z.A.", +"s@t@u@_@_@v@w@w@x@v@w@w@x@v@y@y@x@v@:@z@A@B@P C@D@E@F@G@H@I@J@K@5@+@+@+@r@I+L@Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.@@Z.W W : : p+z.Y ", +"M@N@O@P@C+Q@Q@R@C+;+Q@R@C+;+;+S@C+Q@Q@R@T@U@V@W@X@Y@Z@`@4. #.#+#Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.8.Z.Z.Z.Z.8.8.Z.Z.y.@@@@W W : : `.z.A.", +"@#O@O@##$#%#&#*#=#-#;#>#,#-#;#>#,#-#'#)#!#~#W@{#]#k@^#H@/#(#_#Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.8.8.Z.Z.Z.Z.Z.Z.Z.8.8.8.8.8.8.8.8.8.8.8.Z.Z.y.y.@@W W : : p+z.Y ", +":#<#[#}#|#1#2#3#4#5#1#4#4#1#1#4#4#1#1#6#7#8#9#V 0#`+a#b#c#d#e#Z.Z.Z.f#Z.Z.Z.f#f#f#f#f#f#f#f#f#f#g#g#g#g#g#8.8.8.8.8.8.8.8.8.g#g#g#g#8.g#8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.y.y.@@W W : : `.z.A.", +"h#2#i#6#|#j#7#k#|#j#7#7#|#j#7#7#|#j#7#l#8#m#n#n#o#p#q#r#s#d#e#Z.Z.Z.f#f#f#f#Z.f#f#g#g#g#g#g#g#g#g#g#g#g#g#8.8.8.g#g#8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.y.y.y.y.8.8.8.y.y.@@W W : : p+z.Y ", +"l#7#7#l#7#7#7#W@7#7#7#W@7#7#k#W@t#7#7#W@u#v#n#w#x#y#z#A#B#Z.e#f#f#Z.f#f#f#Z.Z.g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#8.8.8.g#g#g#g#8.8.g#g#g#g#g#g#8.8.g#8.8.y.8.8.y.y.8.y.y.y.y.@@W W : : `.z.A.", +"C#D#E#F#G#H#I#J#G#H#I#J#G#H#I#J#G#H#I#J#K#L#M#N#O#P#s#Q#+#f#R#f#f#f#f#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#@@@@y.y.@@@@y.y.W W : : p+z.Y ", +"S#S#S#S#S#T#S#U#S#T#S#U#S#T#S#U#S#T#S#U#V#W#X#Y#Z#`# $.$+$@$#$g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#@@@@@@@@@@@@@@@@@@y.y.W W : : `.z.A.", +"+$Z..$$$%$+$&$*$%$+$&$*$%$+$&$*$%$+$&$*$=$-$;$>$,$'$)$!$~${$]$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$/$/$/$/$($($_$_$:$:$p+z.Y ", +"<$<$<$<$<$[$}$|$<$[$}$|$<$[$}$|$<$[$}$|$1$2$3$4$5$)$6$7$8$9$0$a$a$a$a$a$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$/$/$/$^$^$^$/$/$/$/$/$/$/$/$/$/$/$/$/$/$($($_$_$:$:$`.z.A.", +"b$c$c$c$d$e$e$f$g$|$|$1$d$e$e$1$d$e$e$1$h$i$j$k$l$m$n$o$p$9$q$a$a$a$a$a$a$a$a$^$a$a$^$^$^$^$^$^$a$r$r$r$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$($($_$_$:$:$p+z.Y ", +"e$1$s$s$1$t$u$v$w$x$y$z$A$x$u$v$g$B$C$>$D$E$F$G$H$I$J$K$L$M$N$a$a$a$a$a$a$a$a$^$r$r$a$^$^$^$a$r$r$r$r$r$/$^$r$^$^$^$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$O$($_$_$:$:$`.z.A.", +"P$Q$R$S$T$U$V$W$X$Y$Z$W$`$ %.%W$+%U$@%#%$%%%&%($*%=%-%;%>%>%,%r$r$r$r$r$a$a$a$/$/$/$r$r$r$r$r$r$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$O$($_$_$:$:$p+z.Y ", +"'%W$)%!%~%{%'%]%~%^%'%]%~%^%'%]%~%^%/%(%_%&%:%<%[%}%|%1%2%3%4%r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$/$r$/$/$r$r$r$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$r$/$/$/$/$/$O$($_$_$:$:$`.z.A.", +"5%6%'%'%6%7%8%9%6%7%8%9%6%7%8%9%6%7%8%0%&%a%<%b%[%c%d%e%f%g%h%r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$/$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$/$/$/$/$/$/$/$/$/$/$/$/$/$/$r$r$/$/$r$r$/$r$i%j%O$($_$_$:$:$p+z.Y ", +"k%l%m%n%o%o%p%q%o%o%r%q%o%o%r%q%o%o%p%q%s%t%/$u%v%w%x%y%z%A%B%r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$/$/$/$/$/$/$/$r$r$i%i%i%r$r$i%i%i%i%i%i%i%i%i%i%i%i%r$/$/$j%j%j%j%j%j%j%j%j%O$($_$_$:$:$`.z.A.", +"C%D%E%F%G%H%I%J%K%H%I%J%K%H%I%J%K%H%I%J%L%M%N%O%P%Q%R%S%T%A%B%r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$U%U%r$r$i%i%/$/$r$r$/$/$/$/$r$r$i%i%i%i%i%i%i%i%i%i%i%i%i%i%j%i%j%j%j%j%j%j%j%j%j%j%j%j%j%O$($_$_$:$:$p+z.Y ", +"/$/$/$/$V%V%W%X%W%Y%Y%Z%W%W%Y%Z%W%W%W%`%`% &B%.&+&@&#&$&%&A%B%r$r$r$U%U%U%U%r$U%U%U%U%U%U%U%U%U%U%i%i%i%i%i%i%i%i%/$/$/$i%i%i%i%i%i%i%i%i%j%j%j%j%i%i%i%i%i%j%j%j%i%i%j%j%j%j%j%j%j%j%O$($_$_$:$:$`.z.A.", +"&&*&=&-&=&;&>&,&=&;&>&,&=&;&>&,&=&;&>&'&)&!&~&{&]&^&/&(&_&:&<&U%U%U%U%U%U%U%U%U%U%U%U%U%i%i%U%U%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%O$($_$_$:$:$p+z.Y ", +"U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%[&}&|&1&2&3&4&5&_&6&U%7&U%U%U%U%U%U%U%U%i%i%U%U%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%O$O$_$_$:$:$`.z.A.", +"U%U%U%U%U%U%[&8&U%9&[&0&U%9&[&0&U%9&[&a&:&b&c&d&e&f&g&h&i&<&j&U%U%U%U%U%U%U%U%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%O$O$_$_$:$:$p+z.Y ", +"k&l&m&7&7&n&o&p&7&n&q&r&s&s&q&r&s&n&o&p&t&u&u&g&v&w&x&q&n&m&y&7&7&U%U%7&z&7&z&U%A&B&i%i%B&B&i%i%B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&i%B&O$O$_$_$:$:$`.z.A.", +"C&D&E&z&z&E&F&G&z&E&F&G&z&E&F&G&z&E&F&G&H&I&J&K&L&M&N&O&P&Q&z&z&z&z&z&z&z&z&z&z&z&z&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&O$O$_$_$:$:$p+z.Y ", +"z&z&z&z&R&S&T&U&R&S&T&U&R&S&T&U&R&S&T&U&V&V&W&X&Y&Z&`&C&R&z&z&z&z&z&z&z&z&z&z&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&O$O$_$_$:$:$^+z.A.", +"z& *.*+*@*#*$*%*@*#*$*%*@*#*$*%*@*#*$*%*&***=*-*;*>*k&P&+*z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&B&B&B&B&z&z&z&B&B&B&z&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&/$O$O$@@_$,*:$/ ^+z.Y ", +"'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*)*'*!*~*{*]*^*^*^*/*/*/*/*/*/*/*^*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*^*/*/*/*/*/*h h ^*h h ^*^*h h ^*^*^*^*h ^*^*^*^*h ^*^*^*(*_*_*_*_*_$:*:$<*`.z.} ", +"'*'*'*'*'*[*}*|*'*[*}*|*'*[*}*|*'*[*}*|*1*1*2*}*}*2*[*)*3*4*5*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*h h h h h h h h h h h h h h h h 6*7*_*_*_*_*^*:*:$: 8*z.Y } ", +"9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*( <*8*^+z.Y } 1 ", +"a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*8*b*8*b*8*b*8*b*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*8*8*8*b*8*`.z.A.Y | | ", +"c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*p+`.p+`.p+`.p+`.`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+^+`.^+^+z.z.Y Y | | 1 ", +"d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*A.Y A.Y A.Y A.Y Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y } } | | | | 1 1 ", +"e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*} | } | } | } | | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | | | | 1 | | | 1 1 1 "}; + + +static char * tabmiddle_xpm[] = { +"33 42 32 1", +" c None", +". c #CECFEF", +"+ c #CECBE7", +"@ c #C6C7E7", +"# c #C6CBE7", +"$ c #BDBEDE", +"% c #BDC3DE", +"& c #CECBEF", +"* c #B5B6D6", +"= c #ADAECE", +"- c #ADB2CE", +"; c #BDBAD6", +"> c #B5BAD6", +", c #C6C3DE", +"' c #ADAAC6", +") c #B5B2CE", +"! c #B5B6CE", +"~ c #A5A2BD", +"{ c #A5A6BD", +"] c #9C9EB5", +"^ c #9CA2BD", +"/ c #ADAEC6", +"( c #C6C3E7", +"_ c #9C9AB5", +": c #A5A6C6", +"< c #949AAD", +"[ c #A5AAC6", +"} c #9496AD", +"| c #BDBADE", +"1 c #BDBED6", +"2 c #9CA2B5", +"3 c #A5AABD", +"..........................+@.#.#.", +"........................$@%&#.#..", +"......................**$$@@&#.#.", +".....................=-;>,%+@.#..", +"....................'')!$$@@&#.#.", +"...................~{=)$$@@&#.#..", +"..................]^'/;;(%&#.#...", +"................._]:/*>,%&@.#.#..", +".................<{[)!$%+@.#.#...", +"................}~{=!$%@@.#......", +"................]^/-|$@@.#.......", +"................]'/*;@@&#........", +"...............<~[)>,%&#.#.......", +"...............]~=)$%+#.#........", +"...............]'/;1@@.#.........", +"...............~{)*,%&#..........", +"...............2/-$$@#...........", +"...............~[*>(@&#..........", +"...............^=)$%+#...........", +"...............{'*>(@.#..........", +"...............^=)$%+#...........", +"...............{'*>(@.#..........", +"...............^=)$%+#...........", +"...............{'*>(@.#..........", +"...............^=)$%+#...........", +"...............{'*>(@.#..........", +"...............^=)$%+#...........", +"...............{'*>@@.#..........", +"...............^=!$%&#...........", +"...............{/*;@@.#..........", +"...............{)!$%&#...........", +"..............]'/;1@@.#..........", +"..............23)>,%&#...........", +"..............~=-$$@@.#..........", +".............]{/*;@@.#...........", +"............<^[)>,%&#............", +"............]{/!$%@@.#...........", +"..........]^[-!$%@@.#............", +".........]^3/!>$@@.#.............", +".......<]^3/!>$@@&#..............", +".....<]2{[/!>$%@&#.#.............", +"}<<_]2{3/-!>$%@&#.#.............."}; + + +static char * tabselectedbeginn_xpm[] = { +"33 39 28 1", +" c None", +". c #CECFEF", +"+ c #EFF3EF", +"@ c #FFFBFF", +"# c #F7FBF7", +"$ c #FFFFFF", +"% c #EFEFEF", +"& c #F7F7F7", +"* c #DEDFDE", +"= c #E7E7E7", +"- c #D6D3D6", +"; c #DEE3DE", +"> c #EFEBEF", +", c #F7F3F7", +"' c #CECBCE", +") c #CECFCE", +"! c #D6D7D6", +"~ c #DEDBDE", +"{ c #E7EBE7", +"] c #C6C7C6", +"^ c #E7E3E7", +"/ c #BDC3BD", +"( c #CED3CE", +"_ c #BDBABD", +": c #C6C3C6", +"< c #C6CBC6", +"[ c #D6DBD6", +"} c #BDBEBD", +"..........................+@#$#$$", +"........................%%&&@#$#$", +"......................*==%%&&@#$$", +"....................--*;>%,&@#$#$", +"...................')!~={,+@#$#$$", +"...................]-!^=%%&&@#$#$", +"................../'(~;>%&&@#$#$$", +"................._])!*={,&@#$#$$$", +"................_])~*>%&&$#$$$$$$", +"................:%&&$#$$$$$$$$", +".............../)!^{,&@#$$$$$$$$$", +"...............](*^%+@#$$$$$$$$$$", +"...............]!~=%&&$$$$$$$$$$$", +"...............'(*=,+@#$$$$$$$$$$", +"...............%&&$$$$$$$$$$$", +"...............'-^=,+@#$$$$$$$$$$", +"...............%&#$$$$$$$$$$$", +"...............'-^=,+@#$$$$$$$$$$", +"...............%&#$$$$$$$$$$$", +"...............'-^=,+@#$$$$$$$$$$", +"...............%&#$$$$$$$$$$$", +"...............'-^=,+@#$$$$$$$$$$", +"...............%&#$$$$$$$$$$$", +"...............'!^=,&@#$$$$$$$$$$", +"...............<~*>%&#$$$$$$$$$$$", +"...............)!^{,&@#$$$$$$$$$$", +"..............])~;%+@#$$$$$$$$$$$", +"..............]-[={&&$#$$$$$$$$$$", +".............])!^=,&@#$$$$$$$$$$$", +"............:'-*^%+@#$$$$$$$$$$$$", +"............])~*>%&&$#$$$$$$$$$$$", +"...........:'!*={,&@#$$$$$$$$$$$$", +"..........:'-~^=,+@#$$$$$$$$$$$$$", +".......}]'-~^=%,&@#$$$$$$$$$$$$$$", +".....}:])-~^=%,+@#$#$$$$$$$$$$$$$", +"}}}:]')-!*^=%,&@#$#$$$$$$$$$$$$$$"}; + + +static char * tabselectedend_xpm[] = { +"33 42 33 1", +" c None", +". c #FFFFFF", +"+ c #CECBE7", +"@ c #C6C7E7", +"# c #CECFEF", +"$ c #C6CBE7", +"% c #BDBEDE", +"& c #BDC3DE", +"* c #CECBEF", +"= c #B5B6D6", +"- c #ADAECE", +"; c #ADB2CE", +"> c #BDBAD6", +", c #B5BAD6", +"' c #C6C3DE", +") c #ADAAC6", +"! c #B5B2CE", +"~ c #B5B6CE", +"{ c #A5A2BD", +"] c #A5A6BD", +"^ c #9C9EB5", +"/ c #9CA2BD", +"( c #ADAEC6", +"_ c #C6C3E7", +": c #9C9AB5", +"< c #A5A6C6", +"[ c #949AAD", +"} c #A5AAC6", +"| c #9496AD", +"1 c #BDBADE", +"2 c #BDBED6", +"3 c #9CA2B5", +"4 c #A5AABD", +"..........................+@#$#$#", +"........................%@&*$#$##", +"......................==%%@@*$#$#", +".....................-;>,'&+@#$##", +"....................))!~%%@@*$#$#", +"...................{]-!%%@@*$#$##", +"..................^/)(>>_&*$#$###", +".................:^<(=,'&*@#$#$##", +".................[]}!~%&+@#$#$###", +"................|{]-~%&@@#$######", +"................^/(;1%@@#$#######", +"................^)(=>@@*$########", +"...............[{}!,'&*$#$#######", +"...............^{-!%&+$#$########", +"...............^)(>2@@#$#########", +"...............{]!='&*$##########", +"...............3(;%%@$###########", +"...............{}=,_@*$##########", +".............../-!%&+$###########", +"...............])=,_@#$##########", +".............../-!%&+$###########", +"...............])=,_@#$##########", +".............../-!%&+$###########", +"...............])=,_@#$##########", +".............../-!%&+$###########", +"...............])=,_@#$##########", +".............../-!%&+$###########", +"...............])=,@@#$##########", +".............../-~%&*$###########", +"...............](=>@@#$##########", +"...............]!~%&*$###########", +"..............^)(>2@@#$##########", +"..............34!,'&*$###########", +"..............{-;%%@@#$##########", +".............^](=>@@#$###########", +"............[/}!,'&*$############", +"............^](~%&@@#$###########", +"..........^/};~%&@@#$############", +".........^/4(~,%@@#$#############", +".......[^/4(~,%@@*$##############", +".....[^3]}(~,%&@*$#$#############", +"|[[:^3]4(;~,%&@*$#$##############"}; + + +static char * tabend_xpm[] = { +"33 42 3 1", +" c None", +". c #CECFEF", +"+ c #FFFFFF", +"..........................+++++++", +"........................+++++++++", +"......................+++++++++++", +".....................++++++++++++", +"....................+++++++++++++", +"...................++++++++++++++", +"..................+++++++++++++++", +".................++++++++++++++++", +".................++++++++++++++++", +"................+++++++++++++++++", +"................+++++++++++++++++", +"................+++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"...............++++++++++++++++++", +"..............+++++++++++++++++++", +"..............+++++++++++++++++++", +"..............+++++++++++++++++++", +".............++++++++++++++++++++", +"............+++++++++++++++++++++", +"............+++++++++++++++++++++", +"..........+++++++++++++++++++++++", +".........++++++++++++++++++++++++", +".......++++++++++++++++++++++++++", +".....++++++++++++++++++++++++++++", +"+++++++++++++++++++++++++++++++++"}; + + + + +QColor fromHsl(QColor c) +{ + const qreal h = c.hueF(); + const qreal s = c.saturationF(); + const qreal l = c.valueF(); + + qreal ca[3] = {0, 0, 0}; + + if (s == 0 || h == 1) { + // achromatic case + ca[0] = ca[1] = ca[2] = l; + } else { + // chromatic case + qreal temp2; + if (l < qreal(0.5)) + temp2 = l * (qreal(1.0) + s); + else + temp2 = l + s - (l * s); + + const qreal temp1 = (qreal(2.0) * l) - temp2; + qreal temp3[3] = { h + (qreal(1.0) / qreal(3.0)), + h, + h - (qreal(1.0) / qreal(3.0)) }; + + for (int i = 0; i != 3; ++i) { + if (temp3[i] < qreal(0.0)) + temp3[i] += qreal(1.0); + else if (temp3[i] > qreal(1.0)) + temp3[i] -= qreal(1.0); + + const qreal sixtemp3 = temp3[i] * qreal(6.0); + + if (sixtemp3 < qreal(1.0)) + ca[i] = ((temp1 + (temp2 - temp1) * sixtemp3)); + else if ((temp3[i] * qreal(2.0)) < qreal(1.0)) + ca[i] = (temp2); + else if ((temp3[i] * qreal(3.0)) < qreal(2.0)) + ca[i] = temp1 + (temp2 -temp1) * (qreal(2.0) /qreal(3.0) - temp3[i]) * qreal(6.0); + else ca[i] = temp1; + } + } + + return QColor::fromRgbF(ca[0], ca[1], ca[2]); +} + +#define Q_MAX_3(a, b, c) ( ( a > b && a > c) ? a : (b > c ? b : c) ) +#define Q_MIN_3(a, b, c) ( ( a < b && a < c) ? a : (b < c ? b : c) ) + +QColor toHsl(QColor c) +{ + QColor color; + qreal h; + qreal s; + qreal l; + + const qreal r = c.redF(); + const qreal g = c.greenF(); + const qreal b = c.blueF(); + const qreal max = Q_MAX_3(r, g, b); + const qreal min = Q_MIN_3(r, g, b); + const qreal delta = max - min; + const qreal delta2 = max + min; + const qreal lightness = qreal(0.5) * delta2; + l = (lightness); + if (qFuzzyIsNull(delta)) { + // achromatic case, hue is undefined + h = 0; + s = 0; + } else { + // chromatic case + qreal hue = 0; + if (lightness < qreal(0.5)) + s = ((delta / delta2)); + else + s = ((delta / (qreal(2.0) - delta2))); + if (qFuzzyCompare(r, max)) { + hue = ((g - b) /delta); + } else if (qFuzzyCompare(g, max)) { + hue = (2.0 + (b - r) / delta); + } else if (qFuzzyCompare(b, max)) { + hue = (4.0 + (r - g) / delta); + } else { + Q_ASSERT_X(false, "QColor::toHsv", "internal error"); + } + hue *= 60.0; + if (hue < 0.0) + hue += 360.0; + h = (hue * 100); + } + + h = h / 36000; + + return QColor::fromHsvF(h, s, l); +} + +void tintColor(QColor &color, QColor tintColor, qreal _saturation) +{ + tintColor = toHsl(tintColor); + color = toHsl(color); + qreal hue = tintColor.hueF(); + + qreal saturation = color.saturationF(); + if (_saturation) + saturation = _saturation; + qreal lightness = color.valueF(); + color.setHsvF(hue, saturation, lightness); + + color = fromHsl(color); + color.toRgb(); +} + +void tintImagePal(QImage *image, QColor color, qreal saturation) +{ + QVector colorTable = image->colorTable(); + for (int i=2;i< colorTable.size();i++) { + QColor c(toHsl(colorTable.at(i))); + tintColor(c, color, saturation); + colorTable[i] = c.rgb(); + } + image->setColorTable(colorTable); +} + + +void tintImage(QImage *image, QColor color, qreal saturation) +{ + *image = image->convertToFormat(QImage::Format_RGB32); + + for (int x = 0; x < image->width(); x++) + for (int y = 0; y < image->height(); y++) { + QColor c(image->pixel(x,y)); + tintColor(c, color, saturation); + image->setPixel(x, y, c.rgb()); + } +} + +#endif //Q_WS_WINCE_WM + + +enum QSliderDirection { SliderUp, SliderDown, SliderLeft, SliderRight }; + +#ifdef Q_WS_WINCE_WM + +void QWindowsMobileStylePrivate::tintImagesButton(QColor color) +{ + if (currentTintButton == color) + return; + currentTintButton = color; + + imageTabEnd = QImage(tabend_xpm); + imageTabSelectedEnd = QImage(tabselectedend_xpm); + imageTabSelectedBegin = QImage(tabselectedbeginn_xpm); + imageTabMiddle = QImage(tabmiddle_xpm); + tintImage(&imageTabEnd, color, 0.0); + tintImage(&imageTabSelectedEnd, color, 0.0); + tintImage(&imageTabSelectedBegin, color, 0.0); + tintImage(&imageTabMiddle, color, 0.0); + + if (!doubleControls) { + int height = imageTabMiddle.height() / 2 + 1; + imageTabEnd = imageTabEnd.scaledToHeight(height); + imageTabMiddle = imageTabMiddle.scaledToHeight(height); + imageTabSelectedEnd = imageTabSelectedEnd.scaledToHeight(height); + imageTabSelectedBegin = imageTabSelectedBegin.scaledToHeight(height); + } +} + +void QWindowsMobileStylePrivate::tintImagesHigh(QColor color) +{ + if (currentTintHigh == color) + return; + currentTintHigh = color; + tintListViewHighlight(color); + imageScrollbarHandleUpHigh = imageScrollbarHandleUp; + imageScrollbarHandleDownHigh = imageScrollbarHandleDown; + tintImagePal(&imageScrollbarHandleDownHigh, color, qreal(0.8)); + tintImagePal(&imageScrollbarHandleUpHigh, color, qreal(0.8)); +} + +void QWindowsMobileStylePrivate::tintListViewHighlight(QColor color) +{ + imageListViewHighlightCornerRight = QImage(listviewhighcornerright_xpm); + tintImage(&imageListViewHighlightCornerRight, color, qreal(0.0)); + + imageListViewHighlightCornerLeft = QImage(listviewhighcornerleft_xpm); + tintImage(&imageListViewHighlightCornerLeft, color, qreal(0.0)); + + imageListViewHighlightMiddle = QImage(listviewhighmiddle_xpm); + tintImage(&imageListViewHighlightMiddle, color, qreal(0.0)); + + int height = imageListViewHighlightMiddle.height(); + if (!doubleControls) { + height = height / 2; + imageListViewHighlightCornerRight = imageListViewHighlightCornerRight.scaledToHeight(height); + imageListViewHighlightCornerLeft = imageListViewHighlightCornerLeft.scaledToHeight(height); + imageListViewHighlightMiddle = imageListViewHighlightMiddle.scaledToHeight(height); + } +} + +#endif //Q_WS_WINCE_WM + +void QWindowsMobileStylePrivate::setupWindowsMobileStyle65() +{ +#ifdef Q_WS_WINCE_WM + wm65 = qt_wince_is_windows_mobile_65(); + if (wm65) { + imageScrollbarHandleUp = QImage(sbhandleup_xpm); + imageScrollbarHandleDown = QImage(sbhandledown_xpm); + imageScrollbarGripUp = QImage(sbgripup_xpm); + imageScrollbarGripDown = QImage(sbgripdown_xpm); + imageScrollbarGripMiddle = QImage(sbgripmiddle_xpm); + + if (!doubleControls) { + imageScrollbarHandleUp = imageScrollbarHandleUp.scaledToHeight(imageScrollbarHandleUp.height() / 2); + imageScrollbarHandleDown = imageScrollbarHandleDown.scaledToHeight(imageScrollbarHandleDown.height() / 2); + imageScrollbarGripMiddle = imageScrollbarGripMiddle.scaledToHeight(imageScrollbarGripMiddle.height() / 2); + imageScrollbarGripUp = imageScrollbarGripUp.scaledToHeight(imageScrollbarGripUp.height() / 2); + imageScrollbarGripDown = imageScrollbarGripDown.scaledToHeight(imageScrollbarGripDown.height() / 2); + } else { + } + tintImagesHigh(Qt::blue); + } +#endif //Q_WS_WINCE_WM +} + +void QWindowsMobileStylePrivate::drawTabBarTab(QPainter *painter, const QStyleOptionTab *tab) +{ +#ifndef QT_NO_TABBAR +#ifdef Q_WS_WINCE_WM + if (wm65) { + tintImagesButton(tab->palette.button().color()); + QRect r; + r.setTopLeft(tab->rect.topRight() - QPoint(imageTabMiddle.width(), 0)); + r.setBottomRight(tab->rect.bottomRight()); + if (tab->state & QStyle::State_Selected) { + painter->fillRect(tab->rect, tab->palette.window()); + } else { + painter->fillRect(tab->rect, QColor(imageTabMiddle.pixel(0,0))); + } + if (tab->selectedPosition == QStyleOptionTab::NextIsSelected) { + painter->drawImage(r, imageTabSelectedBegin); + } else if (tab->position == QStyleOptionTab::End || + tab->position == QStyleOptionTab::OnlyOneTab) { + if (!(tab->state & QStyle::State_Selected)) { + painter->drawImage(r, imageTabEnd); + } + } else if (tab->state & QStyle::State_Selected) { + painter->drawImage(r, imageTabSelectedEnd); + } else { + painter->drawImage(r, imageTabMiddle); + } + if (tab->position == QStyleOptionTab::Beginning && ! (tab->state & QStyle::State_Selected)) { + painter->drawImage(tab->rect.topLeft() - QPoint(imageTabMiddle.width() * 0.60, 0), imageTabSelectedEnd); + } + //imageTabBarBig + return; + } +#endif //Q_WS_WINCE_WM + painter->save(); + painter->setPen(tab->palette.shadow().color()); + if (doubleControls) { + QPen pen = painter->pen(); + pen.setWidth(2); + pen.setCapStyle(Qt::FlatCap); + painter->setPen(pen); + } + if(tab->shape == QTabBar::RoundedNorth) { + if (tab->state & QStyle::State_Selected) { + painter->fillRect(tab->rect, tab->palette.light()); + painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight()); + } + else { + painter->fillRect(tab->rect, tab->palette.button()); + painter->drawLine(tab->rect.bottomLeft() , tab->rect.bottomRight()); + painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight()); + } + } + else if(tab->shape == QTabBar::RoundedSouth) { + if (tab->state & QStyle::State_Selected) { + painter->fillRect(tab->rect.adjusted(0,-2,0,0), tab->palette.light()); + painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight()); + } + else { + painter->fillRect(tab->rect, tab->palette.button()); + if (doubleControls) + painter->drawLine(tab->rect.topLeft() + QPoint(0,1), tab->rect.topRight() + QPoint(0,1)); + else + painter->drawLine(tab->rect.topLeft(), tab->rect.topRight()); + painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight()); + } + } + else if(tab->shape == QTabBar::RoundedEast) { + if (tab->state & QStyle::State_Selected) { + painter->fillRect(tab->rect, tab->palette.light()); + painter->drawLine(tab->rect.topLeft(), tab->rect.topRight()); + } + else { + painter->fillRect(tab->rect, tab->palette.button()); + painter->drawLine(tab->rect.topLeft(), tab->rect.bottomLeft()); + painter->drawLine(tab->rect.topLeft(), tab->rect.topRight()); + } + } + else if(tab->shape == QTabBar::RoundedWest) { + if (tab->state & QStyle::State_Selected) { + painter->fillRect(tab->rect, tab->palette.light()); + painter->drawLine(tab->rect.bottomLeft(), tab->rect.bottomRight()); + } + else { + painter->fillRect(tab->rect, tab->palette.button()); + painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight()); + painter->drawLine(tab->rect.bottomLeft(), tab->rect.bottomRight()); + } + } + painter->restore(); +#endif //QT_NO_TABBAR +} + +void QWindowsMobileStylePrivate::drawPanelItemViewSelected(QPainter *painter, const QStyleOptionViewItemV4 *option, QRect rect) +{ +#ifdef Q_WS_WINCE_WM + if (wm65) { + QRect r; + if (rect.isValid()) + r = rect; + else + r = option->rect; + tintImagesHigh(option->palette.highlight().color()); + + painter->setPen(QColor(Qt::lightGray)); + + if (option->viewItemPosition == QStyleOptionViewItemV4::Middle) { + painter->drawImage(r, imageListViewHighlightMiddle); + } else if (option->viewItemPosition == QStyleOptionViewItemV4::Beginning) { + painter->drawImage(r.adjusted(10, 0, 0, 0), imageListViewHighlightMiddle); + } else if (option->viewItemPosition == QStyleOptionViewItemV4::End) { + painter->drawImage(r.adjusted(0, 0, -10, 0), imageListViewHighlightMiddle); + } else { + painter->drawImage(r.adjusted(10, 0, -10, 0), imageListViewHighlightMiddle); + } + + QImage cornerLeft = imageListViewHighlightCornerLeft; + QImage cornerRight = imageListViewHighlightCornerRight; + + int width = r.width() > cornerRight.width() ? r.width() : cornerRight.width(); + + if ((width * 2) > r.width()) { + width = (r.width() - 5) / 2; + } + + cornerLeft = cornerLeft.scaled(width, r.height()); + cornerRight = cornerRight.scaled(width, r.height()); + + if ((option->viewItemPosition == QStyleOptionViewItemV4::Beginning) || (option->viewItemPosition == QStyleOptionViewItemV4::OnlyOne) || !option->viewItemPosition) { + painter->drawImage(r.topLeft(), cornerLeft); + } + if ((option->viewItemPosition == QStyleOptionViewItemV4::End) || (option->viewItemPosition == QStyleOptionViewItemV4::OnlyOne) || !option->viewItemPosition) { + painter->drawImage(r.topRight() - QPoint(cornerRight.width(),0), cornerRight); + } + return; + } +#endif //Q_WS_WINCE_WM + QPalette::ColorGroup cg = option->state & QStyle::State_Enabled + ? QPalette::Normal : QPalette::Disabled; + + if (rect.isValid()) + painter->fillRect(rect, option->palette.brush(cg, QPalette::Highlight)); + else + painter->fillRect(option->rect, option->palette.brush(cg, QPalette::Highlight)); +} + +void QWindowsMobileStylePrivate::drawScrollbarGrip(QPainter *p, QStyleOptionSlider *newScrollbar, const QStyleOptionComplex *option, bool drawCompleteFrame) +{ +#ifdef Q_WS_WINCE_WM + if (wm65) { + if (newScrollbar->orientation == Qt::Horizontal) { + QTransform transform; + transform.rotate(-90); + QRect r = newScrollbar->rect; + p->drawImage(r.adjusted(10, 0, -10, 0), imageScrollbarGripMiddle.transformed(transform)); + p->drawImage(r.topLeft(), imageScrollbarGripUp.transformed(transform)); + p->drawImage(r.topRight() - QPoint(imageScrollbarGripDown.height() - 1, 0), imageScrollbarGripDown.transformed(transform)); + } else { + QRect r = newScrollbar->rect; + p->drawImage(r.adjusted(0, 10, 0, -10), imageScrollbarGripMiddle); + p->drawImage(r.topLeft(), imageScrollbarGripUp); + p->drawImage(r.bottomLeft() - QPoint(0, imageScrollbarGripDown.height() - 1), imageScrollbarGripDown); + } + return ; + } +#endif + if (newScrollbar->orientation == Qt::Horizontal) { + p->fillRect(newScrollbar->rect,option->palette.button()); + QRect r = newScrollbar->rect; + p->drawLine(r.topLeft(), r.bottomLeft()); + p->drawLine(r.topRight(), r.bottomRight()); + if (smartphone) { + p->drawLine(r.topLeft(), r.topRight()); + p->drawLine(r.bottomLeft(), r.bottomRight()); + } + } + else { + p->fillRect(newScrollbar->rect,option->palette.button()); + QRect r = newScrollbar->rect; + p->drawLine(r.topLeft(), r.topRight()); + p->drawLine(r.bottomLeft(), r.bottomRight()); + if (smartphone) { + p->drawLine(r.topLeft(), r.bottomLeft()); + p->drawLine(r.topRight(), r.bottomRight()); + } + } + if (newScrollbar->state & QStyle::State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*newScrollbar); + fropt.rect.setRect(newScrollbar->rect.x() + 2, newScrollbar->rect.y() + 2, + newScrollbar->rect.width() - 5, + newScrollbar->rect.height() - 5); + } + int gripMargin = doubleControls ? 4 : 2; + int doubleLines = doubleControls ? 2 : 1; + //If there is a frame around the scrollbar (abstractScrollArea), + //then the margin is different, because of the missing frame + int gripMarginFrame = doubleControls ? 3 : 1; + if (drawCompleteFrame) + gripMarginFrame = 0; + //draw grips + if (!smartphone) + if (newScrollbar->orientation == Qt::Horizontal) { + for (int i = -3; i < 3; i += 2) { + p->drawLine( + QPoint(newScrollbar->rect.center().x() + i * doubleLines + 1, + newScrollbar->rect.top() + gripMargin +gripMarginFrame), + QPoint(newScrollbar->rect.center().x() + i * doubleLines + 1, + newScrollbar->rect.bottom() - gripMargin)); + } + } else { + for (int i = -2; i < 4 ; i += 2) { + p->drawLine( + QPoint(newScrollbar->rect.left() + gripMargin + gripMarginFrame , + newScrollbar->rect.center().y() + 1 + i * doubleLines - 1), + QPoint(newScrollbar->rect.right() - gripMargin, + newScrollbar->rect.center().y() + 1 + i * doubleLines - 1)); + } + } + if (!smartphone) { + QRect r; + if (doubleControls) + r = option->rect.adjusted(1, 1, -1, 0); + else + r = option->rect.adjusted(0, 0, -1, 0); + if (drawCompleteFrame && doubleControls) + r.adjust(0, 0, 0, -1); + //Check if the scrollbar is part of an abstractItemView and draw the frame according + if (drawCompleteFrame) + p->drawRect(r); + else + if (newScrollbar->orientation == Qt::Horizontal) + p->drawLine(r.topLeft(), r.topRight()); + else + p->drawLine(r.topLeft(), r.bottomLeft()); + } +} + +void QWindowsMobileStylePrivate::drawScrollbarHandleUp(QPainter *p, QStyleOptionSlider *opt, bool completeFrame, bool ) +{ +#ifdef Q_WS_WINCE_WM + if (wm65) { + tintImagesHigh(opt->palette.highlight().color()); + QRect r = opt->rect; + if (opt->orientation == Qt::Horizontal) { + QTransform transform; + transform.rotate(-90); + if (opt->state & QStyle::State_Sunken) + p->drawImage(r.topLeft(), imageScrollbarHandleUpHigh.transformed(transform)); + else + p->drawImage(r.topLeft(), imageScrollbarHandleUp.transformed(transform)); + } else { + if (opt->state & QStyle::State_Sunken) + p->drawImage(r.topLeft(), imageScrollbarHandleUpHigh); + else + p->drawImage(r.topLeft(), imageScrollbarHandleUp); + } + return ; + } +#endif //Q_WS_WINCE_WM + + QBrush fill = opt->palette.button(); + if (opt->state & QStyle::State_Sunken) + fill = opt->palette.shadow(); + + QStyleOption arrowOpt = *opt; + if (doubleControls) + arrowOpt.rect = opt->rect.adjusted(4, 6, -5, -3); + else + arrowOpt.rect = opt->rect.adjusted(5, 6, -4, -3); + + bool horizontal = (opt->orientation == Qt::Horizontal); + + if (horizontal) { + p->fillRect(opt->rect,fill); + QRect r = opt->rect.adjusted(0,0,1,0); + p->drawLine(r.topRight(), r.bottomRight()); + if (doubleControls) + arrowOpt.rect.adjust(0, -2 ,0, -2); + q_func()->proxy()->drawPrimitive(QStyle::PE_IndicatorArrowLeft, &arrowOpt, p, 0); + } else { + p->fillRect(opt->rect,fill); + QRect r = opt->rect.adjusted(0, 0, 0, 1); + p->drawLine(r.bottomLeft(), r.bottomRight()); + if (completeFrame) + arrowOpt.rect.adjust(-2, 0, -2, 0); + if (doubleControls) + arrowOpt.rect.adjust(0, -4 , 0, -4); + if (completeFrame && doubleControls) + arrowOpt.rect.adjust(2, 0, 2, 0); + q_func()->proxy()->drawPrimitive(QStyle::PE_IndicatorArrowUp, &arrowOpt, p, 0); + } +} + +void QWindowsMobileStylePrivate::drawScrollbarHandleDown(QPainter *p, QStyleOptionSlider *opt, bool completeFrame, bool secondScrollBar) +{ +#ifndef QT_NO_SCROLLBAR +#ifdef Q_WS_WINCE_WM + if (wm65) { + tintImagesHigh(opt->palette.highlight().color()); + QRect r = opt->rect; + if (opt->orientation == Qt::Horizontal) { + QTransform transform; + transform.rotate(-90); + if (opt->state & QStyle::State_Sunken) + p->drawImage(r.topLeft(), imageScrollbarHandleDownHigh.transformed(transform)); + else + p->drawImage(r.topLeft(), imageScrollbarHandleDown.transformed(transform)); + } else { + if (opt->state & QStyle::State_Sunken) + p->drawImage(r.topLeft(), imageScrollbarHandleDownHigh); + else + p->drawImage(r.topLeft(), imageScrollbarHandleDown); + } + return ; + } +#endif //Q_WS_WINCE_WM + + QBrush fill = opt->palette.button(); + if (opt->state & QStyle::State_Sunken) + fill = opt->palette.shadow(); + + QStyleOption arrowOpt = *opt; + if (doubleControls) + arrowOpt.rect = opt->rect.adjusted(4, 0, -5, 3); + else + arrowOpt.rect = opt->rect.adjusted(5, 6, -4, -3); + + bool horizontal = (opt->orientation == Qt::Horizontal); + + if (horizontal) { + p->fillRect(opt->rect,fill); + QRect r = opt->rect.adjusted(0, 0, 0, 0); + p->drawLine(r.topLeft(), r.bottomLeft()); + if (secondScrollBar) + p->drawLine(r.topRight(), r.bottomRight()); + if (doubleControls) + arrowOpt.rect.adjust(0, 4, 0, 4 ); + q_func()->proxy()->drawPrimitive(QStyle::PE_IndicatorArrowRight, &arrowOpt, p, 0); + } else { + p->fillRect(opt->rect,fill); + QRect r = opt->rect.adjusted(0, -1, 0, -1); + p->drawLine(r.topLeft(), r.topRight()); + if (secondScrollBar) + p->drawLine(r.bottomLeft() + QPoint(0,1), r.bottomRight() + QPoint(0, 1)); + if (completeFrame) + arrowOpt.rect.adjust(-2, 0, -2, 0); + if (doubleControls) + arrowOpt.rect.adjust(1, 0, 1, 0 ); + if (completeFrame && doubleControls) + arrowOpt.rect.adjust(1, 0, 1, 0); + q_func()->proxy()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &arrowOpt, p, 0); + } +#endif //QT_NO_SCROLLBAR +} + +void QWindowsMobileStylePrivate::drawScrollbarGroove(QPainter *p,const QStyleOptionSlider *opt) +{ +#ifndef QT_NO_SCROLLBAR +#ifdef Q_OS_WINCE_WM + if (wm65) { + p->fillRect(opt->rect, QColor(231, 231, 231)); + return ; + } +#endif + QBrush fill; + if (smartphone) { + fill = opt->palette.light(); + p->fillRect(opt->rect, fill); + fill = opt->palette.button(); + QImage image; +#ifndef QT_NO_IMAGEFORMAT_XPM + if (opt->orientation == Qt::Horizontal) + image = QImage(vertlines_xpm); + else + image = QImage(horlines_xpm); +#endif + image.setColor(1, opt->palette.button().color().rgb()); + fill.setTextureImage(image); + } + else { + fill = opt->palette.light(); + } + p->fillRect(opt->rect, fill); +#endif //QT_NO_SCROLLBAR +} + +QWindowsMobileStyle::QWindowsMobileStyle(QWindowsMobileStylePrivate &dd) : QWindowsStyle(dd) { + qApp->setEffectEnabled(Qt::UI_FadeMenu, false); + qApp->setEffectEnabled(Qt::UI_AnimateMenu, false); +} + +QWindowsMobileStyle::QWindowsMobileStyle() : QWindowsStyle(*new QWindowsMobileStylePrivate) { + qApp->setEffectEnabled(Qt::UI_FadeMenu, false); + qApp->setEffectEnabled(Qt::UI_AnimateMenu, false); +} + +QWindowsMobileStylePrivate::QWindowsMobileStylePrivate() :QWindowsStylePrivate() { + +#ifdef Q_WS_WINCE + doubleControls = qt_wince_is_high_dpi(); + smartphone = qt_wince_is_smartphone(); +#else + doubleControls = false; + smartphone = false; +#endif //Q_WS_WINCE + +#ifndef QT_NO_IMAGEFORMAT_XPM + + imageArrowDown = QImage(arrowdown_xpm); + imageArrowUp = QImage(arrowdown_xpm).mirrored(); + imageArrowLeft = QImage(arrowleft_xpm); + imageArrowRight = QImage(arrowleft_xpm).mirrored(true, false); + if (doubleControls) { + imageRadioButton = QImage(radiobutton_xpm); + imageRadioButtonChecked = QImage(radiochecked_xpm); + imageChecked = QImage(checkedlight_xpm); + imageCheckedBold = QImage(checkedbold_xpm); + imageRadioButtonHighlighted = QImage(highlightedradiobutton_xpm); + imageClose = QImage(cross_big_xpm); + imageMaximize = QImage(max_big_xpm); + imageMinimize = QImage(min_big_xpm); + imageNormalize = QImage(normal_big_xpm); + } else { + imageRadioButton = QImage(radiobutton_low_xpm); + imageRadioButtonChecked = QImage(radiochecked_low_xpm); + imageChecked = QImage(checkedlight_low_xpm); + imageCheckedBold = QImage(checkedbold_low_xpm); + imageRadioButtonHighlighted = QImage(highlightedradiobutton_low_xpm); + imageClose = QImage(cross_small_xpm); + imageMaximize = QImage(max_small_xpm); + imageMinimize = QImage(min_small_xpm); + imageNormalize = QImage(normal_small_xpm); + } + + setupWindowsMobileStyle65(); + + + imageArrowDownBig = QImage(arrowdown_big_xpm); + imageArrowUpBig = QImage(arrowdown_big_xpm).mirrored(); + imageArrowLeftBig = QImage(arrowleft_big_xpm); + imageArrowRightBig = QImage(arrowleft_big_xpm).mirrored(true, false); + +#endif +} + +void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const { + + QWindowsMobileStylePrivate *d = const_cast(d_func()); + + bool doRestore = false; + QRect rect = option->rect; + painter->setClipping(false); + + switch (element) { + case PE_PanelButtonTool: { + int penSize = 1; + if (d->doubleControls) + penSize = 2; + if (widget) + if (QWidget *parent = widget->parentWidget()) +#ifndef QT_NO_TABWIDGET + if (qobject_cast(parent->parentWidget())) { +#else + if (false) { +#endif //QT_NO_TABBAR + rect.adjust(0,2*penSize,0,-1*penSize); + qDrawPlainRect(painter, rect, option->palette.shadow().color(), penSize, &option->palette.light()); + if (option->state & (State_Sunken)) + qDrawPlainRect(painter, rect, option->palette.shadow().color(), penSize, &option->palette.shadow()); + } + else { + if (!(option->state & State_AutoRaise) || (option->state & (State_Sunken | State_On))) + qDrawPlainRect(painter,option->rect.adjusted(0, penSize, 0, -1 * penSize) , + option->palette.button().color(), 0, &option->palette.button()); + if (option->state & (State_Sunken)) { + qDrawPlainRect(painter, rect, option->palette.shadow().color(), penSize, &option->palette.light()); + } + if (option->state & (State_On)){ + QBrush fill = QBrush(option->palette.light().color()); + painter->fillRect(rect.adjusted(windowsItemFrame , windowsItemFrame , + -windowsItemFrame , -windowsItemFrame ), fill); + qDrawPlainRect(painter, rect, option->palette.shadow().color(), penSize, &option->palette.light()); + } + } + break; } + case PE_IndicatorButtonDropDown: + if (d->doubleControls) + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(), 2, &option->palette.button()); + else + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(), 1, &option->palette.button()); + break; +#ifndef QT_NO_TABBAR + case PE_IndicatorTabTear: + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { + bool rtl = tab->direction == Qt::RightToLeft; + QRect rect = tab->rect; + QPainterPath path; + rect.setTop(rect.top() + ((tab->state & State_Selected) ? 1 : 3)); + rect.setBottom(rect.bottom() - ((tab->state & State_Selected) ? 0 : 2)); + path.moveTo(QPoint(rtl ? rect.right() : rect.left(), rect.top())); + int count = 3; + for(int jags = 1; jags <= count; ++jags, rtl = !rtl) + path.lineTo(QPoint(rtl ? rect.left() : rect.right(), rect.top() + jags * rect.height()/count)); + painter->setPen(QPen(tab->palette.light(), qreal(.8))); + painter->setBrush(tab->palette.background()); + painter->setRenderHint(QPainter::Antialiasing); + painter->drawPath(path); + } + break; +#endif //QT_NO_TABBAR + +#ifndef QT_NO_TOOLBAR + case PE_IndicatorToolBarSeparator: { + painter->save(); + QPoint p1, p2; + if (option->state & State_Horizontal) { + p1 = QPoint(option->rect.width()/2, 0); + p2 = QPoint(p1.x(), option->rect.height()); + } else { + p1 = QPoint(0, option->rect.height()/2); + p2 = QPoint(option->rect.width(), p1.y()); + } + + + painter->setPen(option->palette.mid().color()); + if (d->doubleControls) { + QPen pen = painter->pen(); + pen.setWidth(2); + pen.setCapStyle(Qt::FlatCap); + painter->setPen(pen); + } + painter->drawLine(p1, p2); + painter->restore(); + break; } +#endif // QT_NO_TOOLBAR + case PE_IndicatorToolBarHandle: + painter->save(); + painter->translate(option->rect.x(), option->rect.y()); + if (option->state & State_Horizontal) { + int x = option->rect.width() / 2 - 4; + if (QApplication::layoutDirection() == Qt::RightToLeft) + x -= 2; + if (option->rect.height() > 4) { + qDrawWinButton(painter,x-1,0,7,option->rect.height(), option->palette, false, 0); + + qDrawShadePanel(painter, x, 1, 3, option->rect.height() - 1, + option->palette, false, 0); + qDrawShadePanel(painter, x + 3, 1, 3, option->rect.height() - 1, + option->palette, false, 0); + painter->setPen(option->palette.button().color()); + } + } else { + if (option->rect.width() > 4) { + int y = option->rect.height() / 2 - 4; + qDrawShadePanel(painter, 2, y, option->rect.width() - 2, 3, + option->palette, false, 0); + qDrawShadePanel(painter, 2, y + 3, option->rect.width() - 2, 3, + option->palette, false, 0); + } + } + painter->restore(); + break; + +#ifndef QT_NO_PROGRESSBAR + case PE_IndicatorProgressChunk: { + bool vertical = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(option)) + vertical = (pb2->orientation == Qt::Vertical); + if (!vertical) { + painter->fillRect(option->rect.x(), option->rect.y()+2, option->rect.width(), option->rect.height()-4, + option->palette.brush(QPalette::Highlight)); + } else { + painter->fillRect(option->rect.x()+2, option->rect.y(), option->rect.width()-4, option->rect.height(), + option->palette.brush(QPalette::Highlight)); + } + } + break; +#endif // QT_NO_PROGRESSBAR + + case PE_FrameButtonTool: { +#ifndef QT_NO_DOCKWIDGET + if (widget && widget->inherits("QDockWidgetTitleButton")) { + if (const QDockWidget *dw = qobject_cast(widget->parent())) + if (dw->isFloating()){ + qDrawPlainRect(painter,option->rect.adjusted(1, 1, 0, 0), + option->palette.shadow().color(),1,&option->palette.button()); + return; + } + } +#endif // QT_NO_DOCKWIDGET + QBrush fill; + bool stippled; + bool panel = (element == PE_PanelButtonTool); + if ((!(option->state & State_Sunken )) + && (!(option->state & State_Enabled) + || ((option->state & State_Enabled ) && !(option->state & State_MouseOver))) + && (option->state & State_On)) { + fill = QBrush(option->palette.light().color(), Qt::Dense4Pattern); + stippled = true; + } else { + fill = option->palette.brush(QPalette::Button); + stippled = false; + } + if (option->state & (State_Raised | State_Sunken | State_On)) { + if (option->state & State_AutoRaise) { + if(option->state & (State_Enabled | State_Sunken | State_On)){ + if (panel) + qDrawPlainRect(painter, option->rect,option->palette.shadow().color(),d->doubleControls, &fill); + else + qDrawPlainRect(painter, option->rect,option->palette.shadow().color(),d->doubleControls, &fill); + } + if (stippled) { + painter->setPen(option->palette.button().color()); + painter->drawRect(option->rect.adjusted(1, 1, -2, -2)); + } + } else { + qDrawPlainRect(painter, option->rect,option->palette.shadow().color(),d->doubleControls, &fill); + } + } else { + painter->fillRect(option->rect, fill); + } + break; } + + case PE_FrameFocusRect: + if (const QStyleOptionFocusRect *fropt = qstyleoption_cast(option)) { + //### check for d->alt_down + int penSize; + d->doubleControls ? penSize = 2 : penSize = 1; + bool alternateFocusStyle = false; + if (!widget) + alternateFocusStyle = true; +#ifndef QT_NO_COMBOBOX + if (qobject_cast(widget)) + alternateFocusStyle = true; +#endif + if (!(fropt->state & State_KeyboardFocusChange) && !styleHint(SH_UnderlineShortcut, option)) + return; + QRect r = option->rect; + painter->save(); + painter->setBackgroundMode(Qt::TransparentMode); + if (alternateFocusStyle) { + QColor bg_col = fropt->backgroundColor; + if (!bg_col.isValid()) + bg_col = painter->background().color(); + // Create an "XOR" color. + QColor patternCol((bg_col.red() ^ 0xff) & 0xff, + (bg_col.green() ^ 0xff) & 0xff, + (bg_col.blue() ^ 0xff) & 0xff); + painter->setBrush(QBrush(patternCol, Qt::Dense4Pattern)); + painter->setBrushOrigin(r.topLeft()); + } + else { + painter->setPen(option->palette.highlight().color()); + painter->setBrush(option->palette.highlight()); + } + painter->setPen(Qt::NoPen); + painter->setBrushOrigin(r.topLeft()); + painter->drawRect(r.left(), r.top(), r.width(), penSize); // Top + painter->drawRect(r.left(), r.bottom(), r.width() + penSize - 1, penSize); // Bottom + painter->drawRect(r.left(), r.top(), penSize, r.height()); // Left + painter->drawRect(r.right(), r.top(), penSize, r.height()); // Right + painter->restore(); + } + break; + + case PE_PanelButtonBevel: { + QBrush fill; + bool panel = element != PE_FrameButtonBevel; + painter->setBrushOrigin(option->rect.topLeft()); + if (!(option->state & State_Sunken) && (option->state & State_On)) + fill = QBrush(option->palette.light().color(), Qt::Dense4Pattern); + else + fill = option->palette.brush(QPalette::Button); + + if (option->state & (State_Raised | State_On | State_Sunken)) { + if (d->doubleControls) + qDrawPlainRect(painter, option->rect,option->palette.shadow().color(),2,&fill); + else + qDrawPlainRect(painter, option->rect,option->palette.shadow().color(),1,&fill); + } else { + if (panel) + painter->fillRect(option->rect, fill); + else + painter->drawRect(option->rect); + } + break; } + + case PE_FrameGroupBox: + if (const QStyleOptionFrame *frame = qstyleoption_cast(option)) { + + const QStyleOptionFrameV2 *frame2 = qstyleoption_cast(option); + if (frame2 && !(frame2->features & QStyleOptionFrameV2::Flat)) { + QPen oldPen = painter->pen(); + QRect r = frame->rect; + painter->setPen(frame->palette.shadow().color()); + painter->fillRect(r.x(), r.y(), r.x() + r.width()-1, + r.y() + r.height() - windowsMobileFrameGroupBoxOffset, + frame->palette.light()); + painter ->drawLine(r.topLeft() + QPoint(-2, 1), r.topRight()+ QPoint(0, 1)); + if (d->doubleControls) + painter ->drawLine(r.topLeft() + QPoint(-2, 2), r.topRight()+ QPoint(0, 2)); + painter->setPen(oldPen); + } + } + break; + + case PE_IndicatorCheckBox: { + QBrush fill; + QRect r = d->doubleControls ? option->rect.adjusted(0,1,0,-1) : option->rect; + if (option->state & State_NoChange) + fill = QBrush(option->palette.shadow().color(), Qt::Dense4Pattern); + else if (option->state & State_Sunken) + fill = option->palette.button(); + else if (option->state & State_Enabled) + fill = option->palette.base(); + else + fill = option->palette.background(); + painter->save(); + doRestore = true; + if (d->doubleControls && (option->state & State_NoChange)) + painter->fillRect(r, fill); + else + painter->fillRect(option->rect, fill); + painter->setPen(option->palette.shadow().color()); + painter->drawLine(r.topLeft(), r.topRight()); + painter->drawLine(r.topRight(), r.bottomRight()); + painter->drawLine(r.bottomLeft(), r.bottomRight()); + painter->drawLine(r.bottomLeft(), r.topLeft()); + if (d->doubleControls) { + QRect r0 = r.adjusted(1, 1, -1, -1); + painter->drawLine(r0.topLeft(), r0.topRight()); + painter->drawLine(r0.topRight(), r0.bottomRight()); + painter->drawLine(r0.bottomLeft(), r0.bottomRight()); + painter->drawLine(r0.bottomLeft(), r0.topLeft()); + } + if (option->state & State_HasFocus) { + painter->setPen(option->palette.highlight().color()); + QRect r2 = d->doubleControls ? r.adjusted(2, 2, -2, -2) : r.adjusted(1, 1, -1, -1); + painter->drawLine(r2.topLeft(), r2.topRight()); + painter->drawLine(r2.topRight(), r2.bottomRight()); + painter->drawLine(r2.bottomLeft(), r2.bottomRight()); + painter->drawLine(r2.bottomLeft(), r2.topLeft()); + if (d->doubleControls) { + QRect r3 = r2.adjusted(1, 1, -1, -1); + painter->drawLine(r3.topLeft(), r3.topRight()); + painter->drawLine(r3.topRight(), r3.bottomRight()); + painter->drawLine(r3.bottomLeft(), r3.bottomRight()); + painter->drawLine(r3.bottomLeft(), r3.topLeft()); + } + painter->setPen(option->palette.shadow().color()); + } + //fall through... + } + case PE_IndicatorViewItemCheck: + case PE_Q3CheckListIndicator: { + if (!doRestore) { + painter->save(); + doRestore = true; + } + if (element == PE_Q3CheckListIndicator || element == PE_IndicatorViewItemCheck) { + painter->setPen(option->palette.shadow().color()); + if (option->state & State_NoChange) + painter->setBrush(option->palette.brush(QPalette::Button)); + if (d->doubleControls) { + QRect r = QRect(option->rect.x(), option->rect.y(), windowsMobileitemViewCheckBoxSize * 2, windowsMobileitemViewCheckBoxSize * 2); + qDrawPlainRect(painter, r, option->palette.shadow().color(), 2); + } else { + QRect r = QRect(option->rect.x(), option->rect.y(), windowsMobileitemViewCheckBoxSize, windowsMobileitemViewCheckBoxSize); + qDrawPlainRect(painter, r, option->palette.shadow().color(), 1); + } + if (option->state & State_Enabled) + d->imageChecked.setColor(1, option->palette.shadow().color().rgba()); + else + d->imageChecked.setColor(1, option->palette.dark().color().rgba()); + if (!(option->state & State_Off)) { + if (d->doubleControls) + painter->drawImage(option->rect.x(), option->rect.y(), d->imageChecked); + else + painter->drawImage(option->rect.x() + 3, option->rect.y() + 3, d->imageChecked); + } + } + else { + if (option->state & State_NoChange) + d->imageCheckedBold.setColor(1, option->palette.dark().color().rgba()); + else if (option->state & State_Enabled) + d->imageCheckedBold.setColor(1, option->palette.shadow().color().rgba()); + else + d->imageCheckedBold.setColor(1, option->palette.dark().color().rgba()); + if (!(option->state & State_Off)) { + if (d->doubleControls) + painter->drawImage(option->rect.x() + 2, option->rect.y(), d->imageCheckedBold); + else + painter->drawImage(option->rect.x() + 3, option->rect.y() + 3, d->imageCheckedBold); + } + } + if (doRestore) + painter->restore(); + break; } + case PE_IndicatorRadioButton: { + painter->save(); + + if (option->state & State_HasFocus) { + d->imageRadioButtonHighlighted.setColor(1, option->palette.shadow().color().rgba()); + d->imageRadioButtonHighlighted.setColor(2, option->palette.highlight().color().rgba()); + painter->drawImage(option->rect.x(), option->rect.y(), d->imageRadioButtonHighlighted); + } + else { + d->imageRadioButton.setColor(1, option->palette.shadow().color().rgba()); + painter->drawImage(option->rect.x(), option->rect.y(), d->imageRadioButton); + } + if (option->state & (State_Sunken | State_On)) { + if (option->state & State_Enabled) + d->imageRadioButtonChecked.setColor(1, option->palette.shadow().color().rgba()); + else + d->imageRadioButtonChecked.setColor(1, option->palette.dark().color().rgba()); + + static const int offset = d->doubleControls ? 6 : 3; + painter->drawImage(option->rect.x() + offset, option->rect.y() + offset, d->imageRadioButtonChecked); + } + painter->restore(); + break; } + case PE_PanelButtonCommand: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + QBrush fill; + State flags = option->state; + QPalette pal = option->palette; + QRect r = option->rect; + if ((flags & State_Sunken || flags & State_On) ) + fill = pal.brush(QPalette::Shadow); + else + fill = pal.brush(QPalette::Button); + int singleLine = 1; + int doubleLine = 2; + if (d->doubleControls) { + singleLine = 2; + doubleLine = 4; + } + if (button->features & QStyleOptionButton::DefaultButton && flags & State_Sunken) { + if (d->doubleControls) { + qDrawPlainRect(painter, r, pal.shadow().color(), 1, &fill); + qDrawPlainRect(painter, r.adjusted(1, 1, -1, 1), pal.shadow().color(), 1, &fill); + } + else { + qDrawPlainRect(painter, r, pal.shadow().color(), 1, &fill); + } + } else if (flags & (State_Raised | State_Sunken | State_On | State_Sunken)) { + qDrawPlainRect(painter, r, pal.shadow().color(), singleLine, &fill); + } else { + painter->fillRect(r, fill); + } + } + break; + case PE_FrameDefaultButton: { + painter->save(); + painter->setPen(option->palette.shadow().color()); + QRect rect = option->rect; + if (d->doubleControls) { + rect.adjust(1, 1, -2, -2); + painter->drawRect(rect); + painter->drawRect(rect.adjusted(1, 1, -1, -1)); + } + + else { + rect.adjust(2, 2, -3, -3); + painter->drawRect(rect); + } + painter->restore(); + break; } + case PE_IndicatorSpinPlus: + case PE_IndicatorSpinMinus: { + QRect r = option->rect; + int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget)+2; + QRect br = r.adjusted(fw, fw, -fw, -fw); + int offset = (option->state & State_Sunken) ? 1 : 0; + int step = (br.width() + 4) / 5; + painter->fillRect(br.x() + offset, br.y() + offset +br.height() / 2 - step / 2, + br.width(), step, option->palette.buttonText()); + if (element == PE_IndicatorSpinPlus) + painter->fillRect(br.x() + br.width() / 2 - step / 2 + offset, br.y() + offset+4, + step, br.height() - 7, option->palette.buttonText()); + break; } + case PE_IndicatorSpinUp: + case PE_IndicatorSpinDown: { + painter->save(); + QPoint points[7]; + switch (element) { + case PE_IndicatorSpinUp: + points[0] = QPoint(-2, -4); + points[1] = QPoint(-2, 2); + points[2] = QPoint(-1, -3); + points[3] = QPoint(-1, 1); + points[4] = QPoint(0, -2); + points[5] = QPoint(0, 0); + points[6] = QPoint(1, -1); + break; + case PE_IndicatorSpinDown: + points[0] = QPoint(0, -4); + points[1] = QPoint(0, 2); + points[2] = QPoint(-1, -3); + points[3] = QPoint(-1, 1); + points[4] = QPoint(-2, -2); + points[5] = QPoint(-2, 0); + points[6] = QPoint(-3, -1); + break; + default: + break; + } + if (option->state & State_Sunken) + painter->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal), + proxy()->pixelMetric(PM_ButtonShiftVertical)); + if (option->state & State_Enabled) { + painter->translate(option->rect.x() + option->rect.width() / 2, + option->rect.y() + option->rect.height() / 2); + painter->setPen(option->palette.buttonText().color()); + painter->drawLine(points[0], points[1]); + painter->drawLine(points[2], points[3]); + painter->drawLine(points[4], points[5]); + painter->drawPoint(points[6]); + } else { + painter->translate(option->rect.x() + option->rect.width() / 2 + 1, + option->rect.y() + option->rect.height() / 2 + 1); + painter->setPen(option->palette.light().color()); + painter->drawLine(points[0], points[1]); + painter->drawLine(points[2], points[3]); + painter->drawLine(points[4], points[5]); + painter->drawPoint(points[6]); + painter->translate(-1, -1); + painter->setPen(option->palette.mid().color()); + painter->drawLine(points[0], points[1]); + painter->drawLine(points[2], points[3]); + painter->drawLine(points[4], points[5]); + painter->drawPoint(points[6]); + } + painter->restore(); + break; } + + case PE_IndicatorArrowUpBig: + case PE_IndicatorArrowDownBig: + case PE_IndicatorArrowLeftBig: + case PE_IndicatorArrowRightBig: + + case PE_IndicatorArrowUp: + case PE_IndicatorArrowDown: + case PE_IndicatorArrowRight: + case PE_IndicatorArrowLeft: { + painter->save(); + + if (d->doubleControls) { + QColor color; + if (option->state & State_Sunken) + color = option->palette.light().color(); + else + color = option->palette.buttonText().color(); + QImage image; + int xoffset, yoffset; + bool isTabBarArrow = widget && widget->parent() + && widget->inherits("QToolButton") + && widget->parent()->inherits("QTabBar"); + + switch (element) { + case PE_IndicatorArrowUp: + image = d->imageArrowUp; + xoffset = 1; + yoffset = 12; + break; + case PE_IndicatorArrowDown: + image = d->imageArrowDown; + xoffset = 1; + yoffset =12; + break; + case PE_IndicatorArrowLeft: + image = d->imageArrowLeft; + xoffset = 8; + yoffset = isTabBarArrow ? 12 : 2; + break; + case PE_IndicatorArrowRight: + image = d->imageArrowRight; + xoffset = 8; + yoffset = isTabBarArrow ? 12 : 2; + break; + case PE_IndicatorArrowUpBig: + image = d->imageArrowUpBig; + xoffset = 3; + yoffset = 12; + break; + case PE_IndicatorArrowDownBig: + image = d->imageArrowDownBig; + xoffset = 2; + yoffset =12; + break; + case PE_IndicatorArrowLeftBig: + image = d->imageArrowLeftBig; + xoffset = 8; + yoffset = 2; + break; + case PE_IndicatorArrowRightBig: + image = d->imageArrowRightBig; + xoffset = 8; + yoffset = 2; + break; + default: + break; + } + image.setColor(1, color.rgba()); + painter->drawImage(option->rect.x() + xoffset, option->rect.y() + yoffset, image); + } + else { + QPoint points[7]; + switch (element) { + case PE_IndicatorArrowUp: + case PE_IndicatorArrowUpBig: + points[0] = QPoint(-3, 1); + points[1] = QPoint(3, 1); + points[2] = QPoint(-2, 0); + points[3] = QPoint(2, 0); + points[4] = QPoint(-1, -1); + points[5] = QPoint(1, -1); + points[6] = QPoint(0, -2); + break; + case PE_IndicatorArrowDown: + case PE_IndicatorArrowDownBig: + points[0] = QPoint(-3, -1); + points[1] = QPoint(3, -1); + points[2] = QPoint(-2, 0); + points[3] = QPoint(2, 0); + points[4] = QPoint(-1, 1); + points[5] = QPoint(1, 1); + points[6] = QPoint(0, 2); + break; + case PE_IndicatorArrowRight: + case PE_IndicatorArrowRightBig: + points[0] = QPoint(-2, -3); + points[1] = QPoint(-2, 3); + points[2] = QPoint(-1, -2); + points[3] = QPoint(-1, 2); + points[4] = QPoint(0, -1); + points[5] = QPoint(0, 1); + points[6] = QPoint(1, 0); + break; + case PE_IndicatorArrowLeft: + case PE_IndicatorArrowLeftBig: + points[0] = QPoint(0, -3); + points[1] = QPoint(0, 3); + points[2] = QPoint(-1, -2); + points[3] = QPoint(-1, 2); + points[4] = QPoint(-2, -1); + points[5] = QPoint(-2, 1); + points[6] = QPoint(-3, 0); + break; + default: + break; + } + if (option->state & State_Sunken) + painter->setPen(option->palette.light().color()); + else + painter->setPen(option->palette.buttonText().color()); + if (option->state & State_Enabled) { + painter->translate(option->rect.x() + option->rect.width() / 2, + option->rect.y() + option->rect.height() / 2 - 1); + painter->drawLine(points[0], points[1]); + painter->drawLine(points[2], points[3]); + painter->drawLine(points[4], points[5]); + painter->drawPoint(points[6]); + } else { + painter->translate(option->rect.x() + option->rect.width() / 2, + option->rect.y() + option->rect.height() / 2 - 1); + painter->setPen(option->palette.mid().color()); + painter->drawLine(points[0], points[1]); + painter->drawLine(points[2], points[3]); + painter->drawLine(points[4], points[5]); + painter->drawPoint(points[6]); + } + } + painter->restore(); + break; } +#ifndef QT_NO_TABWIDGET + case PE_FrameTabWidget: + if (const QStyleOptionTabWidgetFrame *tab = qstyleoption_cast(option)) { + QRect rect = option->rect; + QPalette pal = option->palette; + painter->save(); + QBrush fill = pal.light(); + painter->fillRect(rect, fill); + painter->setPen(pal.shadow().color()); + if (d->doubleControls) { + QPen pen = painter->pen(); + pen.setWidth(2); + pen.setCapStyle(Qt::FlatCap); + painter->setPen(pen); + } + switch (tab->shape) { + case QTabBar::RoundedNorth: +#ifdef Q_WS_WINCE_WM + if (!d->wm65) +#endif + { + if (d->doubleControls) + painter->drawLine(rect.topLeft() + QPoint(0, 1), rect.topRight() + QPoint(0, 1)); + else + painter->drawLine(rect.topLeft(), rect.topRight()); + } + break; + case QTabBar::RoundedSouth: +#ifdef Q_WS_WINCE_WM + if (!d->wm65) +#endif + { + if (d->doubleControls) + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + else + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + } + break; + case QTabBar::RoundedEast: +#ifdef Q_WS_WINCE_WM + if (!d->wm65) +#endif + painter->drawLine(rect.topRight(), rect.bottomRight()); + break; + case QTabBar::RoundedWest: +#ifdef Q_WS_WINCE_WM + if (!d->wm65) +#endif + painter->drawLine(rect.topLeft(), rect.bottomLeft()); + break; + case QTabBar::TriangularWest: + case QTabBar::TriangularEast: + case QTabBar::TriangularSouth: + case QTabBar::TriangularNorth: + if (d->doubleControls) + qDrawPlainRect(painter, rect.adjusted(0,-2,0,0), option->palette.shadow().color(),2,&pal.light()); + else + qDrawPlainRect(painter, rect, option->palette.shadow().color(),1,&pal.light()); + break; + default: + break; + } + painter->restore(); + } + break; +#endif //QT_NO_TABBAR +#ifndef QT_NO_ITEMVIEWS + case PE_PanelItemViewRow: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(option)) { + QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled + ? QPalette::Normal : QPalette::Disabled; + if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active)) + cg = QPalette::Inactive; + + if ((vopt->state & QStyle::State_Selected) && proxy()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, option, widget)) + d->drawPanelItemViewSelected(painter, vopt); + else if (vopt->features & QStyleOptionViewItemV2::Alternate) + painter->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::AlternateBase)); + else if (!(vopt->state & QStyle::State_Enabled)) + painter->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::Base)); + } + break; + case PE_PanelItemViewItem: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(option)) { + QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled + ? QPalette::Normal : QPalette::Disabled; + if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active)) + cg = QPalette::Inactive; + + if (vopt->showDecorationSelected && (vopt->state & QStyle::State_Selected)) { + d->drawPanelItemViewSelected(painter, vopt); + } else { + if (vopt->backgroundBrush.style() != Qt::NoBrush) { + QPointF oldBO = painter->brushOrigin(); + painter->setBrushOrigin(vopt->rect.topLeft()); + painter->fillRect(vopt->rect, vopt->backgroundBrush); + painter->setBrushOrigin(oldBO); + } + + if (vopt->state & QStyle::State_Selected) { + QRect textRect = proxy()->subElementRect(QStyle::SE_ItemViewItemText, option, widget); + d->drawPanelItemViewSelected(painter, vopt, textRect); + } + } + } + break; +#endif //QT_NO_ITEMVIEWS + + case PE_FrameWindow: { + QPalette popupPal = option->palette; + popupPal.setColor(QPalette::Light, option->palette.background().color()); + popupPal.setColor(QPalette::Midlight, option->palette.light().color()); + if (d->doubleControls) + qDrawPlainRect(painter, option->rect, popupPal.shadow().color(),2,0); + else + qDrawPlainRect(painter, option->rect, popupPal.shadow().color(),1,0); + break; } + case PE_FrameTabBarBase: { + break; } + case PE_Widget: + break; + case PE_IndicatorMenuCheckMark: { + int markW = option->rect.width() > 7 ? 7 : option->rect.width(); + int markH = markW; + if (d->doubleControls) + markW*=2; + markH*=2; + int posX = option->rect.x() + (option->rect.width() - markW)/2 + 1; + int posY = option->rect.y() + (option->rect.height() - markH)/2; + + QVector a; + a.reserve(markH); + + int i, xx, yy; + xx = posX; + yy = 3 + posY; + for (i = 0; i < markW/2; ++i) { + a << QLineF(xx, yy, xx, yy + 2); + ++xx; + ++yy; + } + yy -= 2; + for (; i < markH; ++i) { + a << QLineF(xx, yy, xx, yy + 2); + ++xx; + --yy; + } + if (!(option->state & State_Enabled) && !(option->state & State_On)) { + int pnt; + painter->setPen(option->palette.highlightedText().color()); + QPoint offset(1, 1); + for (pnt = 0; pnt < a.size(); ++pnt) + a[pnt].translate(offset.x(), offset.y()); + painter->drawLines(a); + for (pnt = 0; pnt < a.size(); ++pnt) + a[pnt].translate(offset.x(), offset.y()); + } + painter->setPen(option->palette.text().color()); + painter->drawLines(a); + break; } + case PE_IndicatorBranch: { + // Copied from the Windows style. + static const int decoration_size = d->doubleControls ? 18 : 9; + static const int ofsA = d->doubleControls ? 4 : 2; + static const int ofsB = d->doubleControls ? 8 : 4; + static const int ofsC = d->doubleControls ? 12 : 6; + static const int ofsD = d->doubleControls ? 1 : 0; + int mid_h = option->rect.x() + option->rect.width() / 2; + int mid_v = option->rect.y() + option->rect.height() / 2; + int bef_h = mid_h; + int bef_v = mid_v; + int aft_h = mid_h; + int aft_v = mid_v; + if (option->state & State_Children) { + int delta = decoration_size / 2; + bef_h -= delta; + bef_v -= delta; + aft_h += delta; + aft_v += delta; + QPen oldPen = painter->pen(); + QPen crossPen = oldPen; + crossPen.setWidth(2); + painter->setPen(crossPen); + painter->drawLine(bef_h + ofsA + ofsD, bef_v + ofsB + ofsD, bef_h + ofsC + ofsD, bef_v + ofsB + ofsD); + if (!(option->state & State_Open)) + painter->drawLine(bef_h + ofsB + ofsD, bef_v + ofsA + ofsD, bef_h + ofsB + ofsD, bef_v + ofsC + ofsD); + painter->setPen(option->palette.dark().color()); + painter->drawRect(bef_h, bef_v, decoration_size - 1, decoration_size - 1); + if (d->doubleControls) + painter->drawRect(bef_h + 1, bef_v + 1, decoration_size - 3, decoration_size - 3); + painter->setPen(oldPen); + } + QBrush brush(option->palette.dark().color(), Qt::Dense4Pattern); + if (option->state & State_Item) { + if (option->direction == Qt::RightToLeft) + painter->fillRect(option->rect.left(), mid_v, bef_h - option->rect.left(), 1, brush); + else + painter->fillRect(aft_h, mid_v, option->rect.right() - aft_h + 1, 1, brush); + } + if (option->state & State_Sibling) + painter->fillRect(mid_h, aft_v, 1, option->rect.bottom() - aft_v + 1, brush); + if (option->state & (State_Open | State_Children | State_Item | State_Sibling)) + painter->fillRect(mid_h, option->rect.y(), 1, bef_v - option->rect.y(), brush); + break; } + case PE_Frame: + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(), + d->doubleControls ? 2 : 1, &option->palette.background()); + break; + case PE_FrameLineEdit: + case PE_FrameMenu: + if (d->doubleControls) + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(),2); + else + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(),1); + break; + case PE_FrameStatusBar: + if (d->doubleControls) + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(),2,0); + else + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(),1,0); + break; + + default: + QWindowsStyle::drawPrimitive(element, option, painter, widget); + break; + } +} + +void QWindowsMobileStyle::drawControl(ControlElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const { + + + QWindowsMobileStylePrivate *d = const_cast(d_func()); + + + painter->setClipping(false); + switch (element) { + case CE_MenuBarEmptyArea: + painter->setClipping(true); + QWindowsStyle::drawControl(element, option, painter, widget); + break; + case CE_PushButtonBevel: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + QRect br = button->rect; + int dbi = proxy()->pixelMetric(PM_ButtonDefaultIndicator, button, widget); + + if (button->features & QStyleOptionButton::AutoDefaultButton) + br.setCoords(br.left() + dbi, br.top() + dbi, br.right() - dbi, br.bottom() - dbi); + QStyleOptionButton tmpBtn = *button; + tmpBtn.rect = br; + proxy()->drawPrimitive(PE_PanelButtonCommand, &tmpBtn, painter, widget); + if (button->features & QStyleOptionButton::HasMenu) { + int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget); + QRect ir = button->rect; + QStyleOptionButton newButton = *button; + if (d->doubleControls) + newButton.rect = QRect(ir.right() - mbi, ir.height() - 30, mbi, ir.height() - 4); + else + newButton.rect = QRect(ir.right() - mbi, ir.height() - 20, mbi, ir.height() - 4); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &newButton, painter, widget); + } + if (button->features & QStyleOptionButton::DefaultButton) + proxy()->drawPrimitive(PE_FrameDefaultButton, option, painter, widget); + } + break; + case CE_RadioButton: + case CE_CheckBox: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + bool isRadio = (element == CE_RadioButton); + QStyleOptionButton subopt = *button; + subopt.rect = proxy()->subElementRect(isRadio ? SE_RadioButtonIndicator + : SE_CheckBoxIndicator, button, widget); + proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox, + &subopt, painter, widget); + subopt.rect = proxy()->subElementRect(isRadio ? SE_RadioButtonContents + : SE_CheckBoxContents, button, widget); + proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget); + if (button->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*button); + fropt.rect = proxy()->subElementRect(isRadio ? SE_RadioButtonFocusRect + : SE_CheckBoxFocusRect, button, widget); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + } + break; + case CE_RadioButtonLabel: + case CE_CheckBoxLabel: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + uint alignment = visualAlignment(button->direction, Qt::AlignLeft | Qt::AlignVCenter); + if (!styleHint(SH_UnderlineShortcut, button, widget)) + alignment |= Qt::TextHideMnemonic; + QPixmap pix; + QRect textRect = button->rect; + if (!button->icon.isNull()) { + pix = button->icon.pixmap(button->iconSize, button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled); + proxy()->drawItemPixmap(painter, button->rect, alignment, pix); + if (button->direction == Qt::RightToLeft) + textRect.setRight(textRect.right() - button->iconSize.width() - 4); + else + textRect.setLeft(textRect.left() + button->iconSize.width() + 4); + } + if (!button->text.isEmpty()){ + if (button->state & State_Enabled) + proxy()->drawItemText(painter, textRect, alignment | Qt::TextShowMnemonic, + button->palette, false, button->text, QPalette::WindowText); + else + proxy()->drawItemText(painter, textRect, alignment | Qt::TextShowMnemonic, + button->palette, false, button->text, QPalette::Mid); + } + } + break; +#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBarGroove: + if (d->doubleControls) + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(), 2, &option->palette.brush(QPalette::Window)); + else + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(), 1, &option->palette.brush(QPalette::Window)); + break; +#endif //QT_NO_PROGRESSBAR +#ifndef QT_NO_TABBAR + case CE_TabBarTab: + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { + proxy()->drawControl(CE_TabBarTabShape, tab, painter, widget); + proxy()->drawControl(CE_TabBarTabLabel, tab, painter, widget); + } + break; + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { + + if (tab->shape == QTabBar::RoundedNorth || tab->shape == QTabBar::RoundedEast || + tab->shape == QTabBar::RoundedSouth || tab->shape == QTabBar::RoundedWest) { + d->drawTabBarTab(painter, tab); + } else { + QCommonStyle::drawControl(element, option, painter, widget); + } + break; } + +#endif // QT_NO_TABBAR + +#ifndef QT_NO_TOOLBAR + case CE_ToolBar: + if (const QStyleOptionToolBar *toolBar = qstyleoption_cast(option)) { + QRect rect = option->rect; + painter->save(); + painter->setPen(option->palette.dark().color()); + painter->fillRect(rect,option->palette.button()); + if (d->doubleControls) { + QPen pen = painter->pen(); + pen.setWidth(4); + painter->setPen(pen); + } + if (toolBar->toolBarArea == Qt::TopToolBarArea) + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + else + painter->drawLine(rect.topLeft(), rect.topRight()); + painter->restore(); + break; } +#endif //QT_NO_TOOLBAR + case CE_Header: + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + QRegion clipRegion = painter->clipRegion(); + painter->setClipRect(option->rect); + proxy()->drawControl(CE_HeaderSection, header, painter, widget); + QStyleOptionHeader subopt = *header; + subopt.rect = proxy()->subElementRect(SE_HeaderLabel, header, widget); + if (header->state & State_Sunken) + subopt.palette.setColor(QPalette::ButtonText, header->palette.brightText().color()); + subopt.state |= QStyle::State_On; + if (subopt.rect.isValid()) + proxy()->drawControl(CE_HeaderLabel, &subopt, painter, widget); + if (header->sortIndicator != QStyleOptionHeader::None) { + subopt.rect = proxy()->subElementRect(SE_HeaderArrow, option, widget); + proxy()->drawPrimitive(PE_IndicatorHeaderArrow, &subopt, painter, widget); + } + painter->setClipRegion(clipRegion); + } + break; + + case CE_HeaderSection: + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + QBrush fill; + QColor color; + QRect rect = option->rect; + painter->setPen(option->palette.shadow().color()); + + int penSize = 1; + + if (d->doubleControls) { + penSize = 2; + QPen pen = painter->pen(); + pen.setWidth(2); + pen.setCapStyle(Qt::FlatCap); + painter->setPen(pen); + } + + //fix Frame + + if (header->position == QStyleOptionHeader::End + || (header->position == QStyleOptionHeader::OnlyOneSection + && !header->text.isEmpty())) + if (Qt::Horizontal == header->orientation ) + rect.adjust(0, 0, penSize, 0); + else + rect.adjust(0, 0, 0, penSize); + + if (option->state & State_Sunken) { + fill = option->palette.brush(QPalette::Shadow); + color = option->palette.light().color(); + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + painter->drawLine(rect.topRight(), rect.bottomRight()); + rect.adjust(0, 0, -penSize, -penSize); + } + else { + fill = option->palette.brush(QPalette::Button); + color = option->palette.shadow().color(); + if (Qt::Horizontal == header->orientation ) + rect.adjust(-penSize, 0, 0, 0); + else + rect.adjust(0, -penSize, 0, 0); + } + if (Qt::Horizontal == header->orientation ) + rect.adjust(0,-penSize,0,0); + else + rect.adjust(-penSize, 0, 0, 0); + + if (option->state & State_Sunken) { + qDrawPlainRect(painter, rect, color, penSize, &fill); + } else { + //Corner + rect.adjust(-penSize, 0, 0, 0); + qDrawPlainRect(painter, rect, color, penSize, &fill); + } + + //Hack to get rid of some double lines... StyleOptions need a clean flag for that + rect = option->rect; +#ifndef QT_NO_SCROLLAREA + if (const QAbstractScrollArea *abstractScrollArea = qobject_cast (widget) ) { + QRect rectScrollArea = abstractScrollArea->geometry(); + if (Qt::Horizontal == header->orientation ) + if ((rectScrollArea.right() - rect.right() ) > 1) + painter->drawLine(rect.topRight(), rect.bottomRight()); + else ; + else + if ((rectScrollArea.bottom() - rect.bottom() ) > 1) + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + } +#endif // QT_NO_SCROLLAREA + break; + } +#ifndef QT_NO_COMBOBOX + case CE_ComboBoxLabel: + // This is copied from qcommonstyle.cpp with the difference, that + // the editRect isn't adjusted when calling drawItemText. + if (const QStyleOptionComboBox *cb = qstyleoption_cast(option)) { + QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget); + painter->save(); + painter->setClipRect(editRect); + if (!cb->currentIcon.isNull()) { + QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal + : QIcon::Disabled; + QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode); + QRect iconRect(editRect); + iconRect.setWidth(cb->iconSize.width() + 4); + iconRect = alignedRect(cb->direction, + Qt::AlignLeft | Qt::AlignVCenter, + iconRect.size(), editRect); + if (cb->editable) + painter->fillRect(iconRect, option->palette.brush(QPalette::Base)); + proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); + + if (cb->direction == Qt::RightToLeft) + editRect.translate(-4 - cb->iconSize.width(), 0); + else + editRect.translate(cb->iconSize.width() + 4, 0); + } + if (!cb->currentText.isEmpty() && !cb->editable) { + proxy()->drawItemText(painter, editRect, + visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter), + cb->palette, cb->state & State_Enabled, cb->currentText); + } + painter->restore(); + } + break; +#endif // QT_NO_COMBOBOX +#ifndef QT_NO_DOCKWIDGET + case CE_DockWidgetTitle: + if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast(option)) { + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(option); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + + QRect rect = dwOpt->rect; + QRect r = rect; + + if (verticalTitleBar) { + QSize s = r.size(); + s.transpose(); + r.setSize(s); + + painter->save(); + painter->translate(r.left(), r.top() + r.width()); + painter->rotate(-90); + painter->translate(-r.left(), -r.top()); + } + + bool floating = false; + bool active = dwOpt->state & State_Active; + int menuOffset = 0; //used to center text when floated + QColor inactiveCaptionTextColor = option->palette.highlightedText().color(); + if (dwOpt->movable) { + QColor left, right; + + //Titlebar gradient + if (widget && widget->isWindow()) { + floating = true; + if (active) { + right = option->palette.highlight().color(); + left = right.lighter(125); + } else { + left = option->palette.highlight().color().lighter(125); + right = QColor(0xff, 0xff, 0xff); + } + menuOffset = 2; + QBrush fillBrush(left); + if (left != right) { + QPoint p1(r.x(), r.top() + r.height()/2); + QPoint p2(rect.right(), r.top() + r.height()/2); + QLinearGradient lg(p1, p2); + lg.setColorAt(0, left); + lg.setColorAt(1, right); + fillBrush = lg; + } + painter->fillRect(r.adjusted(0, 0, 0, -3), fillBrush); + } else { + painter->fillRect(r.adjusted(0, 0, 0, -3), option->palette.button().color()); + } + painter->setPen(dwOpt->palette.color(QPalette::Light)); + if (!widget || !widget->isWindow()) { + painter->drawLine(r.topLeft(), r.topRight()); + painter->setPen(dwOpt->palette.color(QPalette::Dark)); + painter->drawLine(r.bottomLeft(), r.bottomRight()); } + } + if (!dwOpt->title.isEmpty()) { + QFont oldFont = painter->font(); + QFont newFont = oldFont; + if (newFont.pointSize() > 2) + newFont.setPointSize(newFont.pointSize() - 2); + if (floating) + newFont.setBold(true); + painter->setFont(newFont); + QPalette palette = dwOpt->palette; + palette.setColor(QPalette::Window, inactiveCaptionTextColor); + QRect titleRect = proxy()->subElementRect(SE_DockWidgetTitleBarText, option, widget); + if (verticalTitleBar) { + titleRect = QRect(r.left() + rect.bottom() + - titleRect.bottom(), + r.top() + titleRect.left() - rect.left(), + titleRect.height(), titleRect.width()); + } + proxy()->drawItemText(painter, titleRect, + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, palette, + dwOpt->state & State_Enabled, dwOpt->title, + floating ? (active ? QPalette::BrightText : QPalette::Window) : QPalette::WindowText); + painter->setFont(oldFont); + } + if (verticalTitleBar) + painter->restore(); + } + return; +#endif // QT_NO_DOCKWIDGET + + case CE_PushButtonLabel: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + painter->save(); + QRect ir = button->rect; + QPalette::ColorRole colorRole; + uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic; + if (!styleHint(SH_UnderlineShortcut, button, widget)) + tf |= Qt::TextHideMnemonic; + + if (button->state & (State_On | State_Sunken)) + colorRole = QPalette::Light; + else + colorRole = QPalette::ButtonText; + + if (!button->icon.isNull()) { + QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal + : QIcon::Disabled; + if (mode == QIcon::Normal && button->state & State_HasFocus) + mode = QIcon::Active; + QIcon::State state = QIcon::Off; + if (button->state & State_On) + state = QIcon::On; + QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + //Center the icon if there is no text + + QPoint point; + if (button->text.isEmpty()) { + point = QPoint(ir.x() + ir.width() / 2 - pixw / 2, + ir.y() + ir.height() / 2 - pixh / 2); + } else { + point = QPoint(ir.x() + 2, ir.y() + ir.height() / 2 - pixh / 2); + } + if (button->direction == Qt::RightToLeft) + point.rx() += pixw; + + if ((button->state & (State_On | State_Sunken)) && button->direction == Qt::RightToLeft) + point.rx() -= proxy()->pixelMetric(PM_ButtonShiftHorizontal, option, widget) * 2; + + painter->drawPixmap(visualPos(button->direction, button->rect, point), pixmap); + + if (button->direction == Qt::RightToLeft) + ir.translate(-4, 0); + else + ir.translate(pixw + 4, 0); + ir.setWidth(ir.width() - (pixw + 4)); + // left-align text if there is + if (!button->text.isEmpty()) + tf |= Qt::AlignLeft; + } else { + tf |= Qt::AlignHCenter; + } + if (button->state & State_Enabled) + proxy()->drawItemText(painter, ir, tf, button->palette, true, button->text, colorRole); + else + proxy()->drawItemText(painter, ir, tf, button->palette, true, button->text, QPalette::Mid); + painter->restore(); + } + break; + default: + QWindowsStyle::drawControl(element, option, painter, widget); + break; + } +} + +void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const { + + painter->setClipping(false); + QWindowsMobileStylePrivate *d = const_cast(d_func()); + + switch (control) { +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget); + int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); + int ticks = slider->tickPosition; + QRect groove = proxy()->subControlRect(CC_Slider, slider, SC_SliderGroove, widget); + QRect handle = proxy()->subControlRect(CC_Slider, slider, SC_SliderHandle, widget); + + if ((slider->subControls & SC_SliderGroove) && groove.isValid()) { + int mid = thickness / 2; + if (ticks & QSlider::TicksAbove) + mid += len / 8; + if (ticks & QSlider::TicksBelow) + mid -= len / 8; + + painter->setPen(slider->palette.shadow().color()); + if (slider->orientation == Qt::Horizontal) { + qDrawPlainRect(painter, groove.x(), groove.y() + mid - 2, + groove.width(), 4, option->palette.shadow().color(),1,0); + } else { + qDrawPlainRect(painter, groove.x()+mid-2, groove.y(), + 4, groove.height(), option->palette.shadow().color(),1,0); + } + } + if (slider->subControls & SC_SliderTickmarks) { + QStyleOptionSlider tmpSlider = *slider; + tmpSlider.subControls = SC_SliderTickmarks; + QCommonStyle::drawComplexControl(control, &tmpSlider, painter, widget); + } + + if (slider->subControls & SC_SliderHandle) { + const QColor c0 = slider->palette.shadow().color(); + const QColor c1 = slider->palette.dark().color(); + const QColor c3 = slider->palette.midlight().color(); + const QColor c4 = slider->palette.dark().color(); + QBrush handleBrush; + + if (slider->state & State_Enabled) { + handleBrush = slider->palette.color(QPalette::Light); + } else { + handleBrush = QBrush(slider->palette.color(QPalette::Shadow), + Qt::Dense4Pattern); + } + int x = handle.x(), y = handle.y(), + wi = handle.width(), he = handle.height(); + int x1 = x; + int x2 = x+wi-1; + int y1 = y; + int y2 = y+he-1; + + Qt::Orientation orient = slider->orientation; + bool tickAbove = slider->tickPosition == QSlider::TicksAbove; + bool tickBelow = slider->tickPosition == QSlider::TicksBelow; + + if (slider->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*slider); + fropt.rect = proxy()->subElementRect(SE_SliderFocusRect, slider, widget); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + if ((tickAbove && tickBelow) || (!tickAbove && !tickBelow)) { + Qt::BGMode oldMode = painter->backgroundMode(); + painter->setBackgroundMode(Qt::OpaqueMode); + qDrawPlainRect(painter, QRect(x, y, wi, he) + ,slider->palette.shadow().color(),1,&handleBrush); + painter->setBackgroundMode(oldMode); + QBrush fill = QBrush(option->palette.light().color(), Qt::Dense4Pattern); + if (slider->state & State_Sunken) + painter->fillRect(QRectF(x1 + 2, y1 + 2, x2 - x1 - 3, y2 - y1 - 3),fill); + return; + } + QSliderDirection dir; + if (orient == Qt::Horizontal) + if (tickAbove) + dir = SliderUp; + else + dir = SliderDown; + else + if (tickAbove) + dir = SliderLeft; + else + dir = SliderRight; + QPolygon polygon; + int d = 0; + switch (dir) { + case SliderUp: + x2++; + y1 = y1 + wi / 2; + d = (wi + 1) / 2 - 1; + polygon.setPoints(5, x1, y1, x1, y2, x2, y2, x2, y1, x1 + d,y1 - d); + break; + case SliderDown: + x2++; + y2 = y2 - wi/2; + d = (wi + 1) / 2 - 1; + polygon.setPoints(5, x1, y1, x1, y2, x1 + d,y2 + d, x2, y2, x2, y1); + break; + case SliderLeft: + d = (he + 1) / 2 - 1; + x1 = x1 + he/2; + polygon.setPoints(5, x1, y1, x1 - d, y1 + d, x1,y2, x2, y2, x2, y1); + y1--; + break; + case SliderRight: + d = (he + 1) / 2 - 1; + x2 = x2 - he/2; + polygon.setPoints(5, x1, y1, x1, y2, x2,y2, x2 + d, y1 + d, x2, y1); + y1--; + break; + } + QBrush oldBrush = painter->brush(); + painter->setPen(Qt::NoPen); + painter->setBrush(handleBrush); + Qt::BGMode oldMode = painter->backgroundMode(); + painter->setBackgroundMode(Qt::OpaqueMode); + painter->drawRect(x1, y1, x2-x1+1, y2-y1+1); + painter->drawPolygon(polygon); + QBrush fill = QBrush(option->palette.button().color(), Qt::Dense4Pattern); + painter->setBrush(oldBrush); + painter->setBackgroundMode(oldMode); + if (slider->state & State_Sunken) + painter->fillRect(QRectF(x1, y1, x2 - x1 + 1, y2 - y1 + 1),fill); + + if (dir != SliderUp) { + painter->setPen(c0); + painter->drawLine(x1, y1, x2, y1); + } + if (dir != SliderLeft) { + painter->setPen(c0); + painter->drawLine(x1, y1, x1, y2); + } + if (dir != SliderRight) { + painter->setPen(c0); + painter->drawLine(x2, y1, x2, y2); + } + if (dir != SliderDown) { + painter->setPen(c0); + painter->drawLine(x1, y2, x2, y2); + } + switch (dir) { + case SliderUp: + if (slider->state & State_Sunken) + painter->fillRect(QRectF(x1 + 3, y1 - d + 2, x2 - x1 - 4, y1),fill); + painter->setPen(c0); + painter->drawLine(x1, y1, x1 + d, y1 - d); + d = wi - d - 1; + painter->drawLine(x2, y1, x2 -d , y1 -d ); + d--; + break; + case SliderDown: + if (slider->state & State_Sunken) + painter->fillRect(QRectF(x1+3, y2 - d, x2 - x1 -4,y2 - 8),fill); + painter->setPen(c0); + painter->drawLine(x1, y2, x1 + d, y2 + d); + d = wi - d - 1; + painter->drawLine(x2, y2, x2 - d, y2 + d); + d--; + break; + case SliderLeft: + if (slider->state & State_Sunken) + painter->fillRect(QRectF(x1 - d + 2, y1 + 2, x1, y2 - y1 - 3),fill); + painter->setPen(c0); + painter->drawLine(x1, y1, x1 - d, y1 + d); + d = he - d - 1; + painter->drawLine(x1, y2, x1 - d, y2 - d); + d--; + break; + case SliderRight: + if (slider->state & State_Sunken) + painter->fillRect(QRectF(x2 - d - 4, y1 + 2, x2 - 4, y2 - y1 - 3),fill); + painter->setPen(c0); + painter->drawLine(x2, y1, x2 + d, y1 + d); + painter->setPen(c0); + d = he - d - 1; + painter->drawLine(x2, y2, x2 + d, y2 - d); + d--; + break; + } + } + } + break; +#endif //QT_NO_SLIDER +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + painter->save(); + painter->setPen(option->palette.shadow().color()); + if (d->doubleControls) { + QPen pen = painter->pen(); + pen.setWidth(2); + pen.setCapStyle(Qt::SquareCap); + painter->setPen(pen); + } + if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(option)) { + d->drawScrollbarGroove(painter, scrollbar); + // Make a copy here and reset it for each primitive. + QStyleOptionSlider newScrollbar = *scrollbar; + State saveFlags = scrollbar->state; + //Check if the scrollbar is part of an abstractItemView and draw the frame according + bool drawCompleteFrame = true; + bool secondScrollBar = false; + if (widget) + if (QWidget *parent = widget->parentWidget()) { + if (QAbstractScrollArea *abstractScrollArea = qobject_cast(parent->parentWidget())) { + drawCompleteFrame = (abstractScrollArea->frameStyle() == QFrame::NoFrame) || (abstractScrollArea->frameStyle() == QFrame::StyledPanel); + secondScrollBar = (abstractScrollArea->horizontalScrollBar()->isVisible() + && abstractScrollArea->verticalScrollBar()->isVisible()) ; + } +#ifndef QT_NO_LISTVIEW + if (QListView *listView = qobject_cast(parent->parentWidget())) + drawCompleteFrame = false; +#endif + } + if (scrollbar->minimum == scrollbar->maximum) + saveFlags |= State_Enabled; + if (scrollbar->subControls & SC_ScrollBarSubLine) { + newScrollbar.state = saveFlags; + newScrollbar.rect = proxy()->subControlRect(control, &newScrollbar, SC_ScrollBarSubLine, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarSubLine)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + d->drawScrollbarHandleUp(painter, &newScrollbar, drawCompleteFrame, secondScrollBar); + } + } + if (scrollbar->subControls & SC_ScrollBarAddLine) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = proxy()->subControlRect(control, &newScrollbar, SC_ScrollBarAddLine, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarAddLine)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + d->drawScrollbarHandleDown(painter, &newScrollbar, drawCompleteFrame, secondScrollBar); + } + } + if (scrollbar->subControls & SC_ScrollBarSlider) { + + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = proxy()->subControlRect(control, &newScrollbar, SC_ScrollBarSlider, widget); + + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarSlider)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + d->drawScrollbarGrip(painter, &newScrollbar, option, drawCompleteFrame); + } + } + } + painter->restore(); + break; +#endif // QT_NO_SCROLLBAR + case CC_ToolButton: + if (const QStyleOptionToolButton *toolbutton + = qstyleoption_cast(option)) { + QRect button, menuarea; + bool isTabWidget = false; +#ifndef QT_NO_TABWIDGET + if (widget) + if (QWidget *parent = widget->parentWidget()) + isTabWidget = (qobject_cast(parent->parentWidget())); +#endif //QT_NO_TABWIDGET + + button = proxy()->subControlRect(control, toolbutton, SC_ToolButton, widget); + menuarea = proxy()->subControlRect(control, toolbutton, SC_ToolButtonMenu, widget); + State buttonFlags = toolbutton->state; + if (buttonFlags & State_AutoRaise) { + if (!(buttonFlags & State_MouseOver)) { + buttonFlags &= ~State_Raised; + } + } + State menuFlags = buttonFlags; + if (toolbutton->activeSubControls & SC_ToolButton) + buttonFlags |= State_Sunken; + if (toolbutton->activeSubControls & SC_ToolButtonMenu) + menuFlags |= State_On; + QStyleOption tool(0); + tool.palette = toolbutton->palette; + if (toolbutton->subControls & SC_ToolButton) { + tool.rect = button; + tool.state = buttonFlags; + proxy()->drawPrimitive(PE_PanelButtonTool, &tool, painter, widget); + } + if (toolbutton->subControls & SC_ToolButtonMenu) { + tool.rect = menuarea; + tool.state = buttonFlags & State_Enabled; + QStyleOption toolMenu(0); + toolMenu = *toolbutton; + toolMenu.state = menuFlags; + if (buttonFlags & State_Sunken) + proxy()->drawPrimitive(PE_PanelButtonTool, &toolMenu, painter, widget); + QStyleOption arrowOpt(0); + arrowOpt.rect = tool.rect; + arrowOpt.palette = tool.palette; + State flags = State_None; + if (menuFlags & State_Enabled) + flags |= State_Enabled; + if ((menuFlags & State_On) && !(buttonFlags & State_Sunken)) { + flags |= State_Sunken; + painter->fillRect(menuarea, option->palette.shadow()); + } + arrowOpt.state = flags; + proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget); + } + if (toolbutton->state & State_HasFocus) { + QStyleOptionFocusRect focusRect; + focusRect.QStyleOption::operator=(*toolbutton); + focusRect.rect.adjust(3, 3, -3, -3); + if (toolbutton->features & QStyleOptionToolButton::Menu) + focusRect.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, + toolbutton, widget), 0); + proxy()->drawPrimitive(PE_FrameFocusRect, &focusRect, painter, widget); + } + QStyleOptionToolButton label = *toolbutton; + if (isTabWidget) + label.state = toolbutton->state; + else + label.state = toolbutton->state & State_Enabled; + int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget); + label.rect = button.adjusted(fw, fw, -fw, -fw); + proxy()->drawControl(CE_ToolButtonLabel, &label, painter, widget); + } + break; + +#ifndef QT_NO_GROUPBOX + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(option)) { + // Draw frame + painter->save(); + QFont font = painter->font(); + font.setBold(true); + painter->setFont(font); + QStyleOptionGroupBox groupBoxFont = *groupBox; + groupBoxFont.fontMetrics = QFontMetrics(font); + QRect textRect = proxy()->subControlRect(CC_GroupBox, &groupBoxFont, SC_GroupBoxLabel, widget); + QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget).adjusted(0,0,0,0); + if (groupBox->subControls & QStyle::SC_GroupBoxFrame) { + QStyleOptionFrameV2 frame; + frame.QStyleOption::operator=(*groupBox); + frame.features = groupBox->features; + frame.lineWidth = groupBox->lineWidth; + frame.midLineWidth = groupBox->midLineWidth; + frame.rect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget); + painter->save(); + QRegion region(groupBox->rect); + if (!groupBox->text.isEmpty()) { + bool ltr = groupBox->direction == Qt::LeftToRight; + QRect finalRect = checkBoxRect.united(textRect); + if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) + finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0); + region -= finalRect; + } + proxy()->drawPrimitive(PE_FrameGroupBox, &frame, painter, widget); + painter->restore(); + } + // Draw checkbox + if (groupBox->subControls & SC_GroupBoxCheckBox) { + QStyleOptionButton box; + box.QStyleOption::operator=(*groupBox); + box.rect = checkBoxRect; + proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget); + } + // Draw title + if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) { + QColor textColor = groupBox->textColor; + if (textColor.isValid()) + painter->setPen(textColor); + else + painter->setPen(groupBox->palette.link().color()); + painter->setPen(groupBox->palette.link().color()); + + int alignment = int(groupBox->textAlignment); + if (!styleHint(QStyle::SH_UnderlineShortcut, option, widget)) + alignment |= Qt::TextHideMnemonic; + + if (groupBox->state & State_Enabled) + proxy()->drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment, + groupBox->palette, true, groupBox->text, + textColor.isValid() ? QPalette::NoRole : QPalette::Link); + else + proxy()->drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment, + groupBox->palette, true, groupBox->text, QPalette::Mid); + if (groupBox->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*groupBox); + fropt.rect = textRect; + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + } + painter->restore(); + } + break; +#endif //QT_NO_GROUPBOX + +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) { + QBrush editBrush = cmb->palette.brush(QPalette::Base); + if ((cmb->subControls & SC_ComboBoxFrame) && cmb->frame) + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(), proxy()->pixelMetric(PM_ComboBoxFrameWidth, option, widget), &editBrush); + else + painter->fillRect(option->rect, editBrush); + State flags = State_None; + QRect ar = proxy()->subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget); + if ((option->state & State_On)) { + painter->fillRect(ar.adjusted(0, 0, 1, 1),cmb->palette.brush(QPalette::Shadow)); + } + if (d->doubleControls) + ar.adjust(5, 0, 5, 0); + else + ar.adjust(2, 0, -2, 0); + if (option->state & State_Enabled) + flags |= State_Enabled; + if (option->state & State_On) + flags |= State_Sunken; + QStyleOption arrowOpt(0); + arrowOpt.rect = ar; + arrowOpt.palette = cmb->palette; + arrowOpt.state = flags; + proxy()->drawPrimitive(PrimitiveElement(PE_IndicatorArrowDownBig), &arrowOpt, painter, widget); + if (cmb->subControls & SC_ComboBoxEditField) { + QRect re = proxy()->subControlRect(CC_ComboBox, cmb, SC_ComboBoxEditField, widget); + if (cmb->state & State_HasFocus && !cmb->editable) + painter->fillRect(re.x(), re.y(), re.width(), re.height(), + cmb->palette.brush(QPalette::Highlight)); + if (cmb->state & State_HasFocus) { + painter->setPen(cmb->palette.highlightedText().color()); + painter->setBackground(cmb->palette.highlight()); + } else { + painter->setPen(cmb->palette.text().color()); + painter->setBackground(cmb->palette.background()); + } + if (cmb->state & State_HasFocus && !cmb->editable) { + QStyleOptionFocusRect focus; + focus.QStyleOption::operator=(*cmb); + focus.rect = proxy()->subElementRect(SE_ComboBoxFocusRect, cmb, widget); + focus.state |= State_FocusAtBorder; + focus.backgroundColor = cmb->palette.highlight().color(); + if ((option->state & State_On)) + proxy()->drawPrimitive(PE_FrameFocusRect, &focus, painter, widget); + } + } + } + break; +#endif // QT_NO_COMBOBOX + + +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { + QStyleOptionSpinBox copy = *spinBox; + //PrimitiveElement primitiveElement; + int primitiveElement; + + if (spinBox->frame && (spinBox->subControls & SC_SpinBoxFrame)) { + QRect r = proxy()->subControlRect(CC_SpinBox, spinBox, SC_SpinBoxFrame, widget); + qDrawPlainRect(painter, r, option->palette.shadow().color(), proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget),0); + } + QPalette shadePal(option->palette); + shadePal.setColor(QPalette::Button, option->palette.light().color()); + shadePal.setColor(QPalette::Light, option->palette.base().color()); + if (spinBox->subControls & SC_SpinBoxUp) { + copy.subControls = SC_SpinBoxUp; + QPalette pal2 = spinBox->palette; + if (!(spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled)) { + pal2.setCurrentColorGroup(QPalette::Disabled); + copy.state &= ~State_Enabled; + } + copy.palette = pal2; + if (spinBox->activeSubControls == SC_SpinBoxUp && (spinBox->state & State_Sunken)) { + copy.state |= State_On; + copy.state |= State_Sunken; + } else { + copy.state |= State_Raised; + copy.state &= ~State_Sunken; + } + primitiveElement = (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorArrowUpBig + : PE_IndicatorArrowUpBig); + copy.rect = proxy()->subControlRect(CC_SpinBox, spinBox, SC_SpinBoxUp, widget); + if (copy.state & (State_Sunken | State_On)) + qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(), proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), ©.palette.brush(QPalette::Shadow)); + else + qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(), proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), ©.palette.brush(QPalette::Base)); + copy.rect.adjust(proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), 0, -pixelMetric(PM_SpinBoxFrameWidth, option, widget), 0); + proxy()->drawPrimitive(PrimitiveElement(primitiveElement), ©, painter, widget); + } + if (spinBox->subControls & SC_SpinBoxDown) { + copy.subControls = SC_SpinBoxDown; + copy.state = spinBox->state; + QPalette pal2 = spinBox->palette; + if (!(spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled)) { + pal2.setCurrentColorGroup(QPalette::Disabled); + copy.state &= ~State_Enabled; + } + copy.palette = pal2; + if (spinBox->activeSubControls == SC_SpinBoxDown && (spinBox->state & State_Sunken)) { + copy.state |= State_On; + copy.state |= State_Sunken; + } else { + copy.state |= State_Raised; + copy.state &= ~State_Sunken; + } + primitiveElement = (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorArrowDownBig + : PE_IndicatorArrowDownBig); + copy.rect = proxy()->subControlRect(CC_SpinBox, spinBox, SC_SpinBoxDown, widget); + qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(), proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), ©.palette.brush(QPalette::Base)); + if (copy.state & (State_Sunken | State_On)) + qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(), proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), ©.palette.brush(QPalette::Shadow)); + else + qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(), proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), ©.palette.brush(QPalette::Base)); + copy.rect.adjust(3, 0, -4, 0); + if (primitiveElement == PE_IndicatorArrowUp || primitiveElement == PE_IndicatorArrowDown) { + int frameWidth = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget); + copy.rect = copy.rect.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth); + proxy()->drawPrimitive(PrimitiveElement(primitiveElement), ©, painter, widget); + } + else { + proxy()->drawPrimitive(PrimitiveElement(primitiveElement), ©, painter, widget); + } + if (spinBox->frame && (spinBox->subControls & SC_SpinBoxFrame)) { + QRect r = proxy()->subControlRect(CC_SpinBox, spinBox, SC_SpinBoxEditField, widget); + } + } + } + break; +#endif // QT_NO_SPINBOX + + default: + QWindowsStyle::drawComplexControl(control, option, painter, widget); + break; + } +} + +QSize QWindowsMobileStyle::sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const { + + QSize newSize = QWindowsStyle::sizeFromContents(type, option, size, widget); + switch (type) { + case CT_PushButton: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + newSize = QCommonStyle::sizeFromContents(type, option, size, widget); + int w = newSize.width(), + h = newSize.height(); + int defwidth = 0; + if (button->features & QStyleOptionButton::AutoDefaultButton) + defwidth = 2 * proxy()->pixelMetric(PM_ButtonDefaultIndicator, button, widget); + + int minwidth = int(QStyleHelper::dpiScaled(55.0f)); + int minheight = int(QStyleHelper::dpiScaled(19.0f)); + + if (w < minwidth + defwidth && button->icon.isNull()) + w = minwidth + defwidth; + if (h < minheight + defwidth) + h = minheight + defwidth; + newSize = QSize(w + 4, h + 4); + } + break; + +#ifndef QT_NO_GROUPBOX + case CT_GroupBox: + if (const QGroupBox *grb = static_cast(widget)) { + newSize = size + QSize(!grb->isFlat() ? 16 : 0, !grb->isFlat() ? 16 : 0); + } + break; +#endif // QT_NO_GROUPBOX + + case CT_RadioButton: + case CT_CheckBox: + newSize = size; + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + bool isRadio = (type == CT_RadioButton); + QRect irect = visualRect(button->direction, button->rect, + proxy()->subElementRect(isRadio ? SE_RadioButtonIndicator + : SE_CheckBoxIndicator, button, widget)); + int h = proxy()->pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight + : PM_IndicatorHeight, button, widget); + int margins = (!button->icon.isNull() && button->text.isEmpty()) ? 0 : 10; + if (d_func()->doubleControls) + margins *= 2; + newSize += QSize(irect.right() + margins, 1); + newSize.setHeight(qMax(newSize.height(), h)); + } + break; +#ifndef QT_NO_COMBOBOX + case CT_ComboBox: + if (const QStyleOptionComboBox *comboBox = qstyleoption_cast(option)) { + int fw = comboBox->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, option, widget) * 2 : 0; + newSize = QSize(newSize.width() + fw + 9, newSize.height() + fw); //Nine is a magic Number - See CommonStyle for real magic (23) + } + break; +#endif +#ifndef QT_NO_SPINBOX + case CT_SpinBox: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { + int fw = spinBox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget) * 2 : 0; + newSize = QSize(newSize.width() + fw-5, newSize.height() + fw-6); + } + break; +#endif +#ifndef QT_NO_LINEEDIT + case CT_LineEdit: + newSize += QSize(0,1); + break; +#endif + case CT_ToolButton: + newSize = QSize(newSize.width() + 1, newSize.height()); + break; + case CT_TabBarTab: + if (d_func()->doubleControls) + newSize = QSize(newSize.width(), 42); + else + newSize = QSize(newSize.width(), 21); + break; + case CT_HeaderSection: + newSize += QSize(4, 2); + break; +#ifndef QT_NO_ITEMVIEWS +#ifdef Q_WS_WINCE_WM + case CT_ItemViewItem: + if (d_func()->wm65) + if (d_func()->doubleControls) + newSize.setHeight(46); + else + newSize.setHeight(23); + break; +#endif //Q_WS_WINCE_WM +#endif //QT_NO_ITEMVIEWS + default: + break; + } + return newSize; +} + +QRect QWindowsMobileStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const { + + QWindowsMobileStylePrivate *d = const_cast(d_func()); + QRect rect = QWindowsStyle::subElementRect(element, option, widget); + switch (element) { +#ifndef QT_NO_TABWIDGET + case SE_TabWidgetTabBar: + if (d->doubleControls) + rect.adjust(-2, 0, 2, 0); + else + rect.adjust(-2, 0, 2, 0); + break; +#endif //QT_NO_TABWIDGET + case SE_CheckBoxFocusRect: + rect.adjust(1,0,-2,-1); + break; + case SE_RadioButtonFocusRect: + rect.adjust(1,1,-2,-2); + break; + default: + break; +#ifndef QT_NO_SLIDER + case SE_SliderFocusRect: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + rect = slider->rect; + } + break; + case SE_PushButtonFocusRect: + if (d->doubleControls) + rect.adjust(-1, -1, 0, 0); + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_ITEMVIEWS + case SE_ItemViewItemFocusRect: +#ifdef Q_WS_WINCE_WM + if (d->wm65) + rect = QRect(); +#endif + break; +#endif //QT_NO_ITEMVIEWS + } + return rect; +} + +QRect QWindowsMobileStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, + SubControl subControl, const QWidget *widget) const { + + QWindowsMobileStylePrivate *d = const_cast(d_func()); + + QRect rect = QCommonStyle::subControlRect(control, option, subControl, widget); + switch (control) { + +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(option)) { + int sliderButtonExtent = proxy()->pixelMetric(PM_ScrollBarExtent, scrollbar, widget); + float stretchFactor = 1.4f; + int sliderButtonExtentDir = int (sliderButtonExtent * stretchFactor); + +#ifdef Q_WS_WINCE_WM + if (d->wm65) + { + sliderButtonExtent = d->imageScrollbarHandleUp.width(); + sliderButtonExtentDir = d->imageScrollbarHandleUp.height(); + } +#endif //Q_WS_WINCE_WM + + int sliderlen; + int maxlen = ((scrollbar->orientation == Qt::Horizontal) ? + scrollbar->rect.width() : scrollbar->rect.height()) - (sliderButtonExtentDir * 2); + // calculate slider length + if (scrollbar->maximum != scrollbar->minimum) { + uint range = scrollbar->maximum - scrollbar->minimum; + sliderlen = (qint64(scrollbar->pageStep) * maxlen) / (range + scrollbar->pageStep); + + int slidermin = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollbar, widget); + if (sliderlen < slidermin || range > INT_MAX / 2) + sliderlen = slidermin; + if (sliderlen > maxlen) + sliderlen = maxlen; + } else { + sliderlen = maxlen; + } + int sliderstart = sliderButtonExtentDir + sliderPositionFromValue(scrollbar->minimum, + scrollbar->maximum, + scrollbar->sliderPosition, + maxlen - sliderlen, + scrollbar->upsideDown); + if (d->smartphone) { + sliderstart -= sliderButtonExtentDir; + sliderlen += 2*sliderButtonExtent; + } + switch (subControl) { + case SC_ScrollBarSubLine: // top/left button + if (scrollbar->orientation == Qt::Horizontal) { + int buttonWidth = qMin(scrollbar->rect.width() / 2, sliderButtonExtentDir ); + rect.setRect(0, 0, buttonWidth, sliderButtonExtent); + } else { + int buttonHeight = qMin(scrollbar->rect.height() / 2, sliderButtonExtentDir); + rect.setRect(0, 0, sliderButtonExtent, buttonHeight); + } + if (d->smartphone) + rect.setRect(0, 0, 0, 0); + break; + case SC_ScrollBarAddLine: // bottom/right button + if (scrollbar->orientation == Qt::Horizontal) { + int buttonWidth = qMin(scrollbar->rect.width()/2, sliderButtonExtentDir); + rect.setRect(scrollbar->rect.width() - buttonWidth, 0, buttonWidth, sliderButtonExtent); + } else { + int buttonHeight = qMin(scrollbar->rect.height()/2, sliderButtonExtentDir ); + rect.setRect(0, scrollbar->rect.height() - buttonHeight, sliderButtonExtent, buttonHeight); + } + if (d->smartphone) + rect.setRect(0, 0, 0, 0); + break; + case SC_ScrollBarSubPage: // between top/left button and slider + if (scrollbar->orientation == Qt::Horizontal) + if (d->smartphone) + rect.setRect(0, 0, sliderstart, sliderButtonExtent); + else + rect.setRect(sliderButtonExtent, 0, sliderstart - sliderButtonExtent, sliderButtonExtent); + else + if (d->smartphone) + rect.setRect(0, 0, sliderButtonExtent, sliderstart); + else + rect.setRect(0, sliderButtonExtent, sliderButtonExtent, sliderstart - sliderButtonExtent); + break; + case SC_ScrollBarAddPage: // between bottom/right button and slider + if (scrollbar->orientation == Qt::Horizontal) + if (d->smartphone) + rect.setRect(sliderstart + sliderlen, 0, + maxlen - sliderstart - sliderlen + 2*sliderButtonExtent, sliderButtonExtent); + else + rect.setRect(sliderstart + sliderlen, 0, + maxlen - sliderstart - sliderlen + sliderButtonExtent, sliderButtonExtent); + else + if (d->smartphone) + rect.setRect(0, sliderstart + sliderlen, sliderButtonExtent, + maxlen - sliderstart - sliderlen + 2*sliderButtonExtent); + else + rect.setRect(0, sliderstart + sliderlen, sliderButtonExtent, + maxlen - sliderstart - sliderlen + sliderButtonExtent); + break; + case SC_ScrollBarGroove: + if (scrollbar->orientation == Qt::Horizontal) + rect.setRect(sliderButtonExtent, 0, scrollbar->rect.width() - sliderButtonExtent * 2, + scrollbar->rect.height()); + else + rect.setRect(0, sliderButtonExtent, scrollbar->rect.width(), + scrollbar->rect.height() - sliderButtonExtent * 2); + break; + case SC_ScrollBarSlider: + if (scrollbar->orientation == Qt::Horizontal) + rect.setRect(sliderstart, 0, sliderlen, sliderButtonExtent); + else + rect.setRect(0, sliderstart, sliderButtonExtent, sliderlen); + break; + default: + break; + } + rect = visualRect(scrollbar->direction, scrollbar->rect, rect); + } + break; +#endif // QT_NO_SCROLLBAR + + + +#ifndef QT_NO_TOOLBUTTON + case CC_ToolButton: + if (const QStyleOptionToolButton *toolButton = qstyleoption_cast(option)) { + int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolButton, widget); + rect = toolButton->rect; + switch (subControl) { + case SC_ToolButton: + if ((toolButton->features + & (QStyleOptionToolButton::Menu | QStyleOptionToolButton::PopupDelay)) + == QStyleOptionToolButton::Menu) + rect.adjust(0, 0, -mbi, 0); + break; + case SC_ToolButtonMenu: + if ((toolButton->features + & (QStyleOptionToolButton::Menu | QStyleOptionToolButton::PopupDelay)) + == QStyleOptionToolButton::Menu) + rect.adjust(rect.width() - mbi, 1, 0, 1); + break; + default: + break; + } + rect = visualRect(toolButton->direction, toolButton->rect, rect); + } + break; +#endif // QT_NO_TOOLBUTTON + +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget); + int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget); + switch (subControl) { + case SC_SliderHandle: { + int sliderPos = 0; + int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); + bool horizontal = slider->orientation == Qt::Horizontal; + sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum, + slider->sliderPosition, + (horizontal ? slider->rect.width() + : slider->rect.height()) - len, + slider->upsideDown); + if (horizontal) + rect.setRect(slider->rect.x() + sliderPos, slider->rect.y() + tickOffset, len, thickness); + else + rect.setRect(slider->rect.x() + tickOffset, slider->rect.y() + sliderPos, thickness, len); + break; } + default: + break; + } + rect = visualRect(slider->direction, slider->rect, rect); + } + break; +#endif //QT_NO_SLIDER +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *comboBox = qstyleoption_cast(option)) { + int x = comboBox->rect.x(), + y = comboBox->rect.y(), + wi = comboBox->rect.width(), + he = comboBox->rect.height(); + int xpos = x; + int margin = comboBox->frame ? (d->doubleControls ? 2 : 1) : 0; + int bmarg = comboBox->frame ? (d->doubleControls ? 2 : 1) : 0; + if (subControl == SC_ComboBoxArrow) + xpos += wi - int((he - 2*bmarg)*0.9) - bmarg; + else + xpos += wi - (he - 2*bmarg) - bmarg; + switch (subControl) { + case SC_ComboBoxArrow: + rect.setRect(xpos, y + bmarg, he - 2*bmarg, he - 2*bmarg); + break; + case SC_ComboBoxEditField: + rect.setRect(x + margin, y + margin, wi - 2 * margin - int((he - 2*bmarg) * 0.84f), he - 2 * margin); + if (d->doubleControls) { + if (comboBox->editable) + rect.adjust(2, 0, 0, 0); + else + rect.adjust(4, 2, 0, -2); + } else if (!comboBox->editable) { + rect.adjust(2, 1, 0, -1); + } + break; + case SC_ComboBoxFrame: + rect = comboBox->rect; + break; + default: + break; + } + } +#endif //QT_NO_COMBOBOX +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { + QSize bs; + int fw = spinBox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinBox, widget) : 0; + bs.setHeight(qMax(d->doubleControls ? 28 : 14, (spinBox->rect.height()))); + // 1.6 -approximate golden mean + bs.setWidth(qMax(d->doubleControls ? 28 : 14, qMin((bs.height()*7/8), (spinBox->rect.width() / 8)))); + bs = bs.expandedTo(QApplication::globalStrut()); + int x, lx, rx; + x = spinBox->rect.width() - bs.width()*2; + lx = fw; + rx = x - fw; + switch (subControl) { + case SC_SpinBoxUp: + rect = QRect(x + proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), 0 , bs.width(), bs.height()); + break; + case SC_SpinBoxDown: + rect = QRect(x + bs.width(), 0, bs.width(), bs.height()); + break; + case SC_SpinBoxEditField: + if (spinBox->buttonSymbols == QAbstractSpinBox::NoButtons) { + rect = QRect(lx, fw, spinBox->rect.width() - 2*fw - 2, spinBox->rect.height() - 2*fw); + } else { + rect = QRect(lx, fw, rx-2, spinBox->rect.height() - 2*fw); + } + break; + case SC_SpinBoxFrame: + rect = spinBox->rect; + default: + break; + } + rect = visualRect(spinBox->direction, spinBox->rect, rect); + } + break; +#endif // Qt_NO_SPINBOX +#ifndef QT_NO_GROUPBOX + case CC_GroupBox: { + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(option)) { + switch (subControl) { + case SC_GroupBoxFrame: + // FALL THROUGH + case SC_GroupBoxContents: { + int topMargin = 0; + int topHeight = 0; + int bottomMargin = 0; + int labelMargin = 2; + + QRect frameRect = groupBox->rect; + int verticalAlignment = styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget); + if (groupBox->text.size()) { + topHeight = groupBox->fontMetrics.height(); + if (verticalAlignment & Qt::AlignVCenter) + topMargin = topHeight+5; + else if (verticalAlignment & Qt::AlignTop) + topMargin = -topHeight+5; + } + if (subControl == SC_GroupBoxFrame) { + frameRect.setTop(topMargin); + frameRect.setBottom(frameRect.height() + bottomMargin); + rect = frameRect; + break; + } + int frameWidth = 0; + if (groupBox->text.size()) { + frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth, groupBox, widget); + rect = frameRect.adjusted(frameWidth, frameWidth + topHeight + labelMargin, -frameWidth, -frameWidth); + } + else { + rect = groupBox->rect; + } + break; + } + case SC_GroupBoxCheckBox: + // FALL THROUGH + case SC_GroupBoxLabel: { + QFontMetrics fontMetrics = groupBox->fontMetrics; + int h = fontMetrics.height(); + int textWidth = fontMetrics.size(Qt::TextShowMnemonic, groupBox->text + QLatin1Char(' ')).width(); + int margX = (groupBox->features & QStyleOptionFrameV2::Flat) ? 0 : 2; + int margY = (groupBox->features & QStyleOptionFrameV2::Flat) ? 0 : 2; + rect = groupBox->rect.adjusted(margX, margY, -margX, 0); + if (groupBox->text.size()) + rect.setHeight(h); + else + rect.setHeight(0); + int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget); + int indicatorSpace = proxy()->pixelMetric(PM_CheckBoxLabelSpacing, option, widget) - 1; + bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox; + int checkBoxSize = hasCheckBox ? (indicatorWidth + indicatorSpace) : 0; + + // Adjusted rect for label + indicatorWidth + indicatorSpace + QRect totalRect = alignedRect(groupBox->direction, groupBox->textAlignment, + QSize(textWidth + checkBoxSize, h), rect); + + // Adjust totalRect if checkbox is set + if (hasCheckBox) { + bool ltr = groupBox->direction == Qt::LeftToRight; + int left = 2; + // Adjust for check box + if (subControl == SC_GroupBoxCheckBox) { + int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget); + left = ltr ? totalRect.left() : (totalRect.right() - indicatorWidth); + int top = totalRect.top() + (fontMetrics.height() - indicatorHeight) / 2; + totalRect.setRect(left, top, indicatorWidth, indicatorHeight); + // Adjust for label + } else { + left = ltr ? (totalRect.left() + checkBoxSize - 2) : totalRect.left(); + totalRect.setRect(left, totalRect.top(), + totalRect.width() - checkBoxSize, totalRect.height()); + } + } + if ((subControl== SC_GroupBoxLabel)) + totalRect.adjust(-2,0,6,0); + rect = totalRect; + break; + } + default: + break; + } + } + break; + } +#endif // QT_NO_GROUPBOX + default: + break; + } + return rect; +} + +QPalette QWindowsMobileStyle::standardPalette() const { + QPalette palette (Qt::black,QColor(198, 195, 198), QColor(222, 223, 222 ), + QColor(132, 130, 132), QColor(198, 195, 198), Qt::black, Qt::white, Qt::white, QColor(198, 195, 198)); + palette.setColor(QPalette::Window, QColor(206, 223, 239)); + palette.setColor(QPalette::Link, QColor(8,77,123)); //Alternate TextColor for labels... + palette.setColor(QPalette::Base, Qt::white); + palette.setColor(QPalette::Button, QColor(206, 223, 239)); + palette.setColor(QPalette::Highlight, QColor(49, 146, 214)); + palette.setColor(QPalette::Light, Qt::white); + palette.setColor(QPalette::Text, Qt::black); + palette.setColor(QPalette::ButtonText, Qt::black); + palette.setColor(QPalette::Midlight, QColor(222, 223, 222 )); + palette.setColor(QPalette::Dark, QColor(132, 130, 132)); + palette.setColor(QPalette::Mid, QColor(189, 190, 189)); + palette.setColor(QPalette::Shadow, QColor(0, 0, 0)); + palette.setColor(QPalette::BrightText, QColor(33, 162, 33)); //color for ItemView checked indicator (arrow) + return palette; +} + + +/*! \reimp */ +void QWindowsMobileStyle::polish(QApplication *application) { + QWindowsStyle::polish(application); +} + +/*! \reimp */ +void QWindowsMobileStyle::polish(QWidget *widget) { + +#ifndef QT_NO_TOOLBAR + if (QToolBar *toolBar = qobject_cast(widget)) { + QPalette pal = toolBar->palette(); + pal.setColor(QPalette::Background, pal.button().color()); + toolBar->setPalette(pal); + } + else +#endif //QT_NO_TOOLBAR + + QWindowsStyle::polish(widget); +} + +void QWindowsMobileStyle::unpolish(QWidget *widget) +{ + QWindowsStyle::unpolish(widget); +} + +void QWindowsMobileStyle::unpolish(QApplication *app) +{ + QWindowsStyle::unpolish(app); +} + +/*! \reimp */ +void QWindowsMobileStyle::polish(QPalette &palette) { + QWindowsStyle::polish(palette); +} + +int QWindowsMobileStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWidget *widget) const { + + QWindowsMobileStylePrivate *d = const_cast(d_func()); + int ret; + + switch (pm) { + case PM_DefaultTopLevelMargin: + ret =0; + break; + case PM_DefaultLayoutSpacing: + d->doubleControls ? ret = 8 : ret = 4; + break; + case PM_HeaderMargin: + d->doubleControls ? ret = 2 : ret = 1; + break; + case PM_DefaultChildMargin: + d->doubleControls ? ret = 10 : ret = 5; + break; + case PM_ToolBarSeparatorExtent: + d->doubleControls ? ret = 6 : ret = 3; + break; + case PM_DefaultFrameWidth: + d->doubleControls ? ret = 2 : ret = 1; + break; + case PM_MenuVMargin: + ret = 1; + break; + case PM_MenuHMargin: + ret = 1; + break; + case PM_MenuButtonIndicator: + ret = d->doubleControls ? 24 : 14; + break; + case PM_ComboBoxFrameWidth: + d->doubleControls ? ret = 2 : ret = 1; + break; + case PM_SpinBoxFrameWidth: + d->doubleControls ? ret = 2 : ret = 1; + break; + case PM_ButtonDefaultIndicator: + case PM_ButtonShiftHorizontal: + case PM_ButtonShiftVertical: + d->doubleControls ? ret = 2 : ret = 1; + break; +#ifndef QT_NO_TABBAR + case PM_TabBarTabShiftHorizontal: + ret = 0; + break; + case PM_TabBarTabShiftVertical: + ret = 0; + break; +#endif + case PM_MaximumDragDistance: + ret = 60; + break; + case PM_TabBarTabVSpace: + ret = d->doubleControls ? 12 : 6; + break; + case PM_TabBarBaseHeight: + ret = 0; + break; + case PM_IndicatorWidth: + ret = d->doubleControls ? windowsMobileIndicatorSize * 2 : windowsMobileIndicatorSize; + break; + case PM_IndicatorHeight: + ret = d->doubleControls ? windowsMobileIndicatorSize * 2 : windowsMobileIndicatorSize; + break; + case PM_ExclusiveIndicatorWidth: + ret = d->doubleControls ? windowsMobileExclusiveIndicatorSize * 2 + 4: windowsMobileExclusiveIndicatorSize + 2; + break; + case PM_ExclusiveIndicatorHeight: + ret = d->doubleControls ? windowsMobileExclusiveIndicatorSize * 2 + 4: windowsMobileExclusiveIndicatorSize + 2; + break; +#ifndef QT_NO_SLIDER + case PM_SliderLength: + ret = d->doubleControls ? 16 : 8; + break; + case PM_FocusFrameHMargin: + ret = d->doubleControls ? 1 : 2; + break; + case PM_SliderThickness: + ret = d->doubleControls ? windowsMobileSliderThickness * 2: windowsMobileSliderThickness; + break; + case PM_TabBarScrollButtonWidth: + ret = d->doubleControls ? 14 * 2 : 18; + break; + case PM_CheckBoxLabelSpacing: + case PM_RadioButtonLabelSpacing: + ret = d->doubleControls ? 6 * 2 : 6; + break; + // Returns the number of pixels to use for the business part of the + // slider (i.e., the non-tickmark portion). The remaining space is shared + // equally between the tickmark regions. + case PM_SliderControlThickness: + if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { + int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height() : sl->rect.width(); + int ticks = sl->tickPosition; + int n = 0; + if (ticks & QSlider::TicksAbove) + ++n; + if (ticks & QSlider::TicksBelow) + ++n; + if (!n) { + ret = space; + break; + } + int thick = 8; + if (ticks != QSlider::TicksBothSides && ticks != QSlider::NoTicks) + thick += proxy()->pixelMetric(PM_SliderLength, sl, widget) / 4; + + space -= thick; + if (space > 0) + thick += (space * 2) / (n + 2); + ret = thick; + } else { + ret = 0; + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_MENU + case PM_SmallIconSize: + d->doubleControls ? ret = windowsMobileIconSize * 2 : ret = windowsMobileIconSize; + break; + case PM_ButtonMargin: + d->doubleControls ? ret = 8 : ret = 4; + break; + case PM_LargeIconSize: + d->doubleControls ? ret = 64 : ret = 32; + break; + case PM_IconViewIconSize: + ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget); + break; + case PM_ToolBarIconSize: + d->doubleControls ? ret = 2 * windowsMobileIconSize : ret = windowsMobileIconSize; + break; + case PM_DockWidgetTitleMargin: + ret = 2; + break; +#if defined(Q_WS_WIN) +#else + case PM_DockWidgetFrameWidth: + ret = 4; + break; +#endif // Q_WS_WIN + break; +#endif // QT_NO_MENU + + case PM_TitleBarHeight: + d->doubleControls ? ret = 42 : ret = 21; + break; + case PM_ScrollBarSliderMin: +#ifdef Q_WS_WINCE_WM + if (d->wm65) +#else + if (false) +#endif + { + d->doubleControls ? ret = 68 : ret = 34; + } else { + d->doubleControls ? ret = 36 : ret = 18; + } + break; + case PM_ScrollBarExtent: { + + if (d->smartphone) + ret = 9; + else + d->doubleControls ? ret = 25 : ret = 13; + +#ifdef Q_WS_WINCE_WM + if (d->wm65) +#else + if (false) +#endif + { + d->doubleControls ? ret = 26 : ret = 13; + break; + } + +#ifndef QT_NO_SCROLLAREA + //Check if the scrollbar is part of an abstractItemView and set size according + if (widget) + if (QWidget *parent = widget->parentWidget()) + if (qobject_cast(parent->parentWidget())) + if (d->smartphone) + ret = 8; + else + d->doubleControls ? ret = 24 : ret = 12; +#endif + } + break; + case PM_SplitterWidth: + ret = qMax(4, QApplication::globalStrut().width()); + break; + +#if defined(Q_WS_WIN) + case PM_MDIFrameWidth: + ret = 1; + break; +#endif + case PM_ToolBarExtensionExtent: + d->doubleControls ? ret = 32 : ret = 16; + break; + case PM_ToolBarItemMargin: + d->doubleControls ? ret = 2 : ret = 1; + break; + case PM_ToolBarItemSpacing: + d->doubleControls ? ret = 2 : ret = 1; + break; + case PM_ToolBarHandleExtent: + d->doubleControls ? ret = 16 : ret = 8; + break; + case PM_ButtonIconSize: + d->doubleControls ? ret = 32 : ret = 16; + break; + case PM_TextCursorWidth: + ret = 2; + break; + case PM_TabBar_ScrollButtonOverlap: + ret = 0; + break; + default: + ret = QWindowsStyle::pixelMetric(pm, opt, widget); + break; + } + return ret; +} + +int QWindowsMobileStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWidget *widget, + QStyleHintReturn *returnData) const { + + int ret; + switch (hint) { + case SH_Menu_MouseTracking: + case SH_ComboBox_ListMouseTracking: + case SH_EtchDisabledText: + ret = 0; + break; + case SH_DitherDisabledText: + ret = 0; + break; + case SH_ItemView_ShowDecorationSelected: + ret = 0; + break; +#ifndef QT_NO_TABWIDGET + case SH_TabWidget_DefaultTabPosition: + ret = QTabWidget::South; + break; +#endif + case SH_ToolBar_Movable: + ret = false; + break; + case SH_ScrollBar_ContextMenu: + ret = false; + break; + case SH_MenuBar_AltKeyNavigation: + ret = false; + break; + case SH_RequestSoftwareInputPanel: + ret = RSIP_OnMouseClick; + break; + default: + ret = QWindowsStyle::styleHint(hint, opt, widget, returnData); + break; + } + return ret; +} + +QPixmap QWindowsMobileStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, + const QWidget *widget) const { + + QWindowsMobileStylePrivate *d = const_cast(d_func()); + switch (sp) { +#ifndef QT_NO_IMAGEFORMAT_XPM + case SP_ToolBarHorizontalExtensionButton: { + QPixmap pixmap = QCommonStyle::standardPixmap(sp, option, widget); + if (d->doubleControls) + return pixmap.scaledToHeight(pixmap.height() * 2); + else + return pixmap; + } + case SP_TitleBarMaxButton: + case SP_TitleBarCloseButton: + case SP_TitleBarNormalButton: + case SP_TitleBarMinButton: { + QImage image; + switch (sp) { + case SP_TitleBarMaxButton: + image = d->imageMaximize; + break; + case SP_TitleBarCloseButton: + image = d->imageClose; + break; + case SP_TitleBarNormalButton: + image = d->imageNormalize; + break; + case SP_TitleBarMinButton: + image = d->imageMinimize; + break; + default: + break; + } + if (option) { + image.setColor(0, option->palette.shadow().color().rgba()); + image.setColor(1, option->palette.highlight().color().rgba()); + image.setColor(2, option->palette.highlight().color().lighter(150).rgba()); + image.setColor(3, option->palette.highlightedText().color().rgba()); + } + + return QPixmap::fromImage(image); + } + +#endif + default: + return QWindowsStyle::standardPixmap(sp, option, widget); + } +} + +QPixmap QWindowsMobileStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *option) const { + + switch (iconMode) { + case QIcon::Selected: { +#ifdef Q_WS_WINCE_WM + if (d_func()->wm65) + return pixmap; +#endif //Q_WS_WINCE_WM + QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); + int imgh = img.height(); + int imgw = img.width(); + for (int y = 0; y < imgh; y += 2) { + for (int x = 0; x < imgw; x += 2) { + QColor c = option->palette.highlight().color().rgb(); + c.setAlpha( qAlpha(img.pixel(x, y))); + QRgb pixel = c.rgba(); + img.setPixel(x, y, pixel); + } + } + return QPixmap::fromImage(img); + } + default: + break; + } + return QWindowsStyle::generatedIconPixmap(iconMode, pixmap, option); +} + + +bool QWindowsMobileStyle::doubleControls() const { + + QWindowsMobileStylePrivate *d = const_cast(d_func()); + + return d->doubleControls; +} + +void QWindowsMobileStyle::setDoubleControls(bool doubleControls) { + + QWindowsMobileStylePrivate *d = const_cast(d_func()); + + d->doubleControls = doubleControls; +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_WINDOWSMOBILE + diff --git a/src/widgets/styles/qwindowsmobilestyle.h b/src/widgets/styles/qwindowsmobilestyle.h new file mode 100644 index 0000000000..6ac1af1c35 --- /dev/null +++ b/src/widgets/styles/qwindowsmobilestyle.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSMOBILESTYLE_H +#define QWINDOWSMOBILESTYLE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_STYLE_WINDOWSMOBILE) + +class QWindowsMobileStylePrivate; + +class Q_GUI_EXPORT QWindowsMobileStyle : public QWindowsStyle +{ + Q_OBJECT +public: + QWindowsMobileStyle(); + + void drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget = 0) const; + + void drawControl(ControlElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const; + + void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const; + + QSize sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const; + + QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const; + + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, + SubControl sc, const QWidget *widget) const; + + QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *option) const; + + QPixmap standardPixmap(StandardPixmap sp, const QStyleOption *option, + const QWidget *widget) const; + + int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const; + + int styleHint(StyleHint hint, const QStyleOption *opt = 0, const QWidget *widget = 0, + QStyleHintReturn *returnData = 0) const; + + void polish(QApplication*); + void unpolish(QApplication*); + void polish(QWidget *widget); + void unpolish(QWidget *widget); + void polish(QPalette &); + + QPalette standardPalette() const; + + bool doubleControls() const; + + void setDoubleControls(bool); + +protected: + QWindowsMobileStyle(QWindowsMobileStylePrivate &dd); + +private: + Q_DECLARE_PRIVATE(QWindowsMobileStyle) +}; + +#endif // QT_NO_STYLE_WINDOWSMOBILE + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif //QWINDOWSMOBILESTYLE_H diff --git a/src/widgets/styles/qwindowsmobilestyle_p.h b/src/widgets/styles/qwindowsmobilestyle_p.h new file mode 100644 index 0000000000..cfc6aea1c6 --- /dev/null +++ b/src/widgets/styles/qwindowsmobilestyle_p.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSMOBILESTYLE_P_H +#define QWINDOWSMOBILESTYLE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qwindowsmobilestyle.h" +#include "qwindowsstyle_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_STYLE_WINDOWSMOBILE + +class QStyleOptionTab; +class QStyleOptionSlider; +class QStyleOptionViewItemV4; + +class QWindowsMobileStylePrivate : public QWindowsStylePrivate +{ + Q_DECLARE_PUBLIC(QWindowsMobileStyle) +public: + QWindowsMobileStylePrivate(); + bool doubleControls; + bool smartphone; +#ifdef Q_WS_WINCE_WM + bool wm65; +#endif + + QImage imageRadioButton; + QImage imageRadioButtonChecked; + QImage imageRadioButtonHighlighted; + QImage imageChecked; + QImage imageCheckedBold; + QImage imageArrowDown; + QImage imageArrowUp; + QImage imageArrowLeft; + QImage imageArrowRight; + QImage imageArrowDownBig; + QImage imageArrowUpBig; + QImage imageArrowLeftBig; + QImage imageArrowRightBig; + QImage imageClose; + QImage imageMaximize; + QImage imageNormalize; + QImage imageMinimize; + + void setupWindowsMobileStyle65(); + +#ifdef Q_WS_WINCE_WM + //Windows Mobile 6.5 images + QImage imageScrollbarHandleUp; + QImage imageScrollbarHandleDown; + QImage imageScrollbarHandleUpHigh; + QImage imageScrollbarHandleDownHigh; + QImage imageScrollbarGripUp; + QImage imageScrollbarGripDown; + QImage imageScrollbarGripMiddle; + QImage imageListViewHighlightCornerLeft; + QImage imageListViewHighlightCornerRight; + QImage imageListViewHighlightMiddle; + QImage imageTabEnd; + QImage imageTabSelectedEnd; + QImage imageTabSelectedBegin; + QImage imageTabMiddle; + + QColor currentTintHigh; + QColor currentTintButton; + + void tintImagesHigh(QColor color); + void tintImagesButton(QColor color); + void tintListViewHighlight(QColor color); + +#endif //Q_WS_WINCE_WM + + void drawScrollbarHandleUp(QPainter *p, QStyleOptionSlider *opt, bool completeFrame = false, bool secondScrollBar = false); + void drawScrollbarHandleDown(QPainter *p, QStyleOptionSlider *opt, bool completeFrame = false, bool secondScrollBar = false); + void drawScrollbarGroove(QPainter *p, const QStyleOptionSlider *opt); + void drawScrollbarGrip(QPainter *p, QStyleOptionSlider *newScrollbar, const QStyleOptionComplex *option, bool drawCompleteFrame); + void drawTabBarTab(QPainter *p, const QStyleOptionTab *tab); + void drawPanelItemViewSelected(QPainter *painter, const QStyleOptionViewItemV4 *option, QRect rect = QRect()); + +}; + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_WINDOWSMOBILE +#endif //QWINDOWSMOBILESTYLE_P_H diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp new file mode 100644 index 0000000000..44f3f92d8b --- /dev/null +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -0,0 +1,3392 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsstyle.h" +#include "qwindowsstyle_p.h" + +#if !defined(QT_NO_STYLE_WINDOWS) || defined(QT_PLUGIN) + +#include +#include "qapplication.h" +#include "qbitmap.h" +#include "qdrawutil.h" // for now +#include "qevent.h" +#include "qmenu.h" +#include "qmenubar.h" +#include +#include "qpaintengine.h" +#include "qpainter.h" +#include "qprogressbar.h" +#include "qrubberband.h" +#include "qstyleoption.h" +#include "qtabbar.h" +#include "qwidget.h" +#include "qdebug.h" +#include "qmainwindow.h" +#include "qfile.h" +#include "qtextstream.h" +#include "qpixmapcache.h" +#include "qwizard.h" +#include "qlistview.h" +#include +#include + +#ifdef Q_WS_X11 +#include "qfileinfo.h" +#include "qdir.h" +#include +#endif + +#include + +QT_BEGIN_NAMESPACE + +#if defined(Q_WS_WIN) + +QT_BEGIN_INCLUDE_NAMESPACE +#include "qt_windows.h" +QT_END_INCLUDE_NAMESPACE +# ifndef COLOR_GRADIENTACTIVECAPTION +# define COLOR_GRADIENTACTIVECAPTION 27 +# endif +# ifndef COLOR_GRADIENTINACTIVECAPTION +# define COLOR_GRADIENTINACTIVECAPTION 28 +# endif + + +typedef struct +{ + DWORD cbSize; + HICON hIcon; + int iSysImageIndex; + int iIcon; + WCHAR szPath[MAX_PATH]; +} QSHSTOCKICONINFO; + +#define _SHGFI_SMALLICON 0x000000001 +#define _SHGFI_LARGEICON 0x000000000 +#define _SHGFI_ICON 0x000000100 +#define _SIID_SHIELD 77 + +typedef HRESULT (WINAPI *PtrSHGetStockIconInfo)(int siid, int uFlags, QSHSTOCKICONINFO *psii); +static PtrSHGetStockIconInfo pSHGetStockIconInfo = 0; + +#endif //Q_WS_WIN + +QT_BEGIN_INCLUDE_NAMESPACE +#include +QT_END_INCLUDE_NAMESPACE + +enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight }; + +/* + \internal +*/ +QWindowsStylePrivate::QWindowsStylePrivate() + : alt_down(false), menuBarTimer(0), animationFps(10), animateTimer(0), animateStep(0) +{ +#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) + if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA + && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) { + QSystemLibrary shellLib(QLatin1String("shell32")); + pSHGetStockIconInfo = (PtrSHGetStockIconInfo)shellLib.resolve("SHGetStockIconInfo"); + } +#endif + startTime.start(); +} + +// Returns true if the toplevel parent of \a widget has seen the Alt-key +bool QWindowsStylePrivate::hasSeenAlt(const QWidget *widget) const +{ + widget = widget->window(); + return seenAlt.contains(widget); +} + +/*! + \reimp +*/ +void QWindowsStyle::timerEvent(QTimerEvent *event) +{ +#ifndef QT_NO_PROGRESSBAR + Q_D(QWindowsStyle); + if (event->timerId() == d->animateTimer) { + Q_ASSERT(d->animationFps> 0); + d->animateStep = d->startTime.elapsed() / (1000 / d->animationFps); + foreach (QProgressBar *bar, d->bars) { + if ((bar->minimum() == 0 && bar->maximum() == 0)) + bar->update(); + } + } +#endif // QT_NO_PROGRESSBAR + event->ignore(); +} + +/*! + \reimp +*/ +bool QWindowsStyle::eventFilter(QObject *o, QEvent *e) +{ + // Records Alt- and Focus events + if (!o->isWidgetType()) + return QObject::eventFilter(o, e); + + QWidget *widget = qobject_cast(o); + Q_D(QWindowsStyle); + switch(e->type()) { + case QEvent::KeyPress: + if (static_cast(e)->key() == Qt::Key_Alt) { + widget = widget->window(); + + // Alt has been pressed - find all widgets that care + QList l = widget->findChildren(); + for (int pos=0 ; pos < l.size() ; ++pos) { + QWidget *w = l.at(pos); + if (w->isWindow() || !w->isVisible() || + w->style()->styleHint(SH_UnderlineShortcut, 0, w)) + l.removeAt(pos); + } + // Update states before repainting + d->seenAlt.append(widget); + d->alt_down = true; + + // Repaint all relevant widgets + for (int pos = 0; pos < l.size(); ++pos) + l.at(pos)->update(); + } + break; + case QEvent::KeyRelease: + if (static_cast(e)->key() == Qt::Key_Alt) { + widget = widget->window(); + + // Update state and repaint the menu bars. + d->alt_down = false; +#ifndef QT_NO_MENUBAR + QList l = widget->findChildren(); + for (int i = 0; i < l.size(); ++i) + l.at(i)->update(); +#endif + } + break; + case QEvent::Close: + // Reset widget when closing + d->seenAlt.removeAll(widget); + d->seenAlt.removeAll(widget->window()); + break; +#ifndef QT_NO_PROGRESSBAR + case QEvent::StyleChange: + case QEvent::Show: + if (QProgressBar *bar = qobject_cast(o)) { + if (!d->bars.contains(bar)) { + d->bars << bar; + if (d->bars.size() == 1) { + Q_ASSERT(d->animationFps> 0); + d->animateTimer = startTimer(1000 / d->animationFps); + } + } + } + break; + case QEvent::Destroy: + case QEvent::Hide: + // reinterpret_cast because there is no type info when getting + // the destroy event. We know that it is a QProgressBar. + if (QProgressBar *bar = reinterpret_cast(o)) { + d->bars.removeAll(bar); + if (d->bars.isEmpty() && d->animateTimer) { + killTimer(d->animateTimer); + d->animateTimer = 0; + } + } + break; +#endif // QT_NO_PROGRESSBAR + default: + break; + } + return QCommonStyle::eventFilter(o, e); +} + +/*! + \class QWindowsStyle + \brief The QWindowsStyle class provides a Microsoft Windows-like look and feel. + + \ingroup appearance + + This style is Qt's default GUI style on Windows. + + \img qwindowsstyle.png + \sa QWindowsXPStyle, QMacStyle, QPlastiqueStyle, QCDEStyle, QMotifStyle +*/ + +/*! + Constructs a QWindowsStyle object. +*/ +QWindowsStyle::QWindowsStyle() : QCommonStyle(*new QWindowsStylePrivate) +{ +} + +/*! + \internal + + Constructs a QWindowsStyle object. +*/ +QWindowsStyle::QWindowsStyle(QWindowsStylePrivate &dd) : QCommonStyle(dd) +{ +} + + +/*! Destroys the QWindowsStyle object. */ +QWindowsStyle::~QWindowsStyle() +{ +} + +#ifdef Q_WS_WIN +static inline QRgb colorref2qrgb(COLORREF col) +{ + return qRgb(GetRValue(col), GetGValue(col), GetBValue(col)); +} +#endif + +/*! \reimp */ +void QWindowsStyle::polish(QApplication *app) +{ + QCommonStyle::polish(app); + QWindowsStylePrivate *d = const_cast(d_func()); + // We only need the overhead when shortcuts are sometimes hidden + if (!proxy()->styleHint(SH_UnderlineShortcut, 0) && app) + app->installEventFilter(this); + + d->activeCaptionColor = app->palette().highlight().color(); + d->activeGradientCaptionColor = app->palette().highlight() .color(); + d->inactiveCaptionColor = app->palette().dark().color(); + d->inactiveGradientCaptionColor = app->palette().dark().color(); + d->inactiveCaptionText = app->palette().background().color(); + +#if defined(Q_WS_WIN) //fetch native title bar colors + if(app->desktopSettingsAware()){ + DWORD activeCaption = GetSysColor(COLOR_ACTIVECAPTION); + DWORD gradientActiveCaption = GetSysColor(COLOR_GRADIENTACTIVECAPTION); + DWORD inactiveCaption = GetSysColor(COLOR_INACTIVECAPTION); + DWORD gradientInactiveCaption = GetSysColor(COLOR_GRADIENTINACTIVECAPTION); + DWORD inactiveCaptionText = GetSysColor(COLOR_INACTIVECAPTIONTEXT); + d->activeCaptionColor = colorref2qrgb(activeCaption); + d->activeGradientCaptionColor = colorref2qrgb(gradientActiveCaption); + d->inactiveCaptionColor = colorref2qrgb(inactiveCaption); + d->inactiveGradientCaptionColor = colorref2qrgb(gradientInactiveCaption); + d->inactiveCaptionText = colorref2qrgb(inactiveCaptionText); + } +#endif +} + +/*! \reimp */ +void QWindowsStyle::unpolish(QApplication *app) +{ + QCommonStyle::unpolish(app); + app->removeEventFilter(this); +} + +/*! \reimp */ +void QWindowsStyle::polish(QWidget *widget) +{ + QCommonStyle::polish(widget); +#ifndef QT_NO_PROGRESSBAR + if (qobject_cast(widget)) + widget->installEventFilter(this); +#endif +} + +/*! \reimp */ +void QWindowsStyle::unpolish(QWidget *widget) +{ + QCommonStyle::unpolish(widget); +#ifndef QT_NO_PROGRESSBAR + if (QProgressBar *bar=qobject_cast(widget)) { + Q_D(QWindowsStyle); + widget->removeEventFilter(this); + d->bars.removeAll(bar); + } +#endif +} + +/*! + \reimp +*/ +void QWindowsStyle::polish(QPalette &pal) +{ + QCommonStyle::polish(pal); +} + +/*! + \reimp +*/ +int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWidget *widget) const +{ + int ret; + + switch (pm) { + case PM_ButtonDefaultIndicator: + case PM_ButtonShiftHorizontal: + case PM_ButtonShiftVertical: + case PM_MenuHMargin: + case PM_MenuVMargin: + ret = 1; + break; +#ifndef QT_NO_TABBAR + case PM_TabBarTabShiftHorizontal: + ret = 0; + break; + case PM_TabBarTabShiftVertical: + ret = 2; + break; +#endif + case PM_MaximumDragDistance: +#if defined(Q_WS_WIN) + { + HDC hdcScreen = GetDC(0); + int dpi = GetDeviceCaps(hdcScreen, LOGPIXELSX); + ReleaseDC(0, hdcScreen); + ret = (int)(dpi * 1.375); + } +#else + ret = 60; +#endif + break; + +#ifndef QT_NO_SLIDER + case PM_SliderLength: + ret = int(QStyleHelper::dpiScaled(11.)); + break; + + // Returns the number of pixels to use for the business part of the + // slider (i.e., the non-tickmark portion). The remaining space is shared + // equally between the tickmark regions. + case PM_SliderControlThickness: + if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { + int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height() : sl->rect.width(); + int ticks = sl->tickPosition; + int n = 0; + if (ticks & QSlider::TicksAbove) + ++n; + if (ticks & QSlider::TicksBelow) + ++n; + if (!n) { + ret = space; + break; + } + + int thick = 6; // Magic constant to get 5 + 16 + 5 + if (ticks != QSlider::TicksBothSides && ticks != QSlider::NoTicks) + thick += proxy()->pixelMetric(PM_SliderLength, sl, widget) / 4; + + space -= thick; + if (space > 0) + thick += (space * 2) / (n + 2); + ret = thick; + } else { + ret = 0; + } + break; +#endif // QT_NO_SLIDER + +#ifndef QT_NO_MENU + case PM_MenuBarHMargin: + ret = 0; + break; + + case PM_MenuBarVMargin: + ret = 0; + break; + + case PM_MenuBarPanelWidth: + ret = 0; + break; + + case PM_SmallIconSize: + ret = int(QStyleHelper::dpiScaled(16.)); + break; + + case PM_LargeIconSize: + ret = int(QStyleHelper::dpiScaled(32.)); + break; + + case PM_IconViewIconSize: + ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget); + break; + + case PM_DockWidgetTitleMargin: + ret = int(QStyleHelper::dpiScaled(2.)); + break; + case PM_DockWidgetTitleBarButtonMargin: + ret = int(QStyleHelper::dpiScaled(4.)); + break; +#if defined(Q_WS_WIN) + case PM_DockWidgetFrameWidth: +#if defined(Q_OS_WINCE) + ret = GetSystemMetrics(SM_CXDLGFRAME); +#else + ret = GetSystemMetrics(SM_CXFRAME); +#endif + break; +#else + case PM_DockWidgetFrameWidth: + ret = 4; + break; +#endif // Q_WS_WIN + break; + +#endif // QT_NO_MENU + + +#if defined(Q_WS_WIN) + case PM_TitleBarHeight: +#ifdef QT3_SUPPORT + // qt3 dockwindow height should be equal to tool windows + if (widget && widget->inherits("Q3DockWindowTitleBar")) { + ret = GetSystemMetrics(SM_CYSMCAPTION) - 1; + } else +#endif + if (widget && (widget->windowType() == Qt::Tool)) { + // MS always use one less than they say +#if defined(Q_OS_WINCE) + ret = GetSystemMetrics(SM_CYCAPTION) - 1; +#else + ret = GetSystemMetrics(SM_CYSMCAPTION) - 1; +#endif + } else { + ret = GetSystemMetrics(SM_CYCAPTION) - 1; + } + + break; + + case PM_ScrollBarExtent: + { +#ifndef Q_OS_WINCE + NONCLIENTMETRICS ncm; + ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); + if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) + ret = qMax(ncm.iScrollHeight, ncm.iScrollWidth); + else +#endif + ret = QCommonStyle::pixelMetric(pm, opt, widget); + } + break; +#endif // Q_WS_WIN + + case PM_SplitterWidth: + ret = qMax(4, QApplication::globalStrut().width()); + break; + +#if defined(Q_WS_WIN) + case PM_MdiSubWindowFrameWidth: +#if defined(Q_OS_WINCE) + ret = GetSystemMetrics(SM_CYDLGFRAME); +#else + ret = GetSystemMetrics(SM_CYFRAME); +#endif + break; + case PM_TextCursorWidth: { + DWORD caretWidth = 1; +#if defined(SPI_GETCARETWIDTH) + SystemParametersInfo(SPI_GETCARETWIDTH, 0, &caretWidth, 0); +#endif + ret = (int)caretWidth; + break; } +#endif + case PM_ToolBarItemMargin: + ret = 1; + break; + case PM_ToolBarItemSpacing: + ret = 0; + break; + case PM_ToolBarHandleExtent: + ret = int(QStyleHelper::dpiScaled(10.)); + break; + default: + ret = QCommonStyle::pixelMetric(pm, opt, widget); + break; + } + + return ret; +} + +#ifndef QT_NO_IMAGEFORMAT_XPM + +/* XPM */ +static const char * const qt_menu_xpm[] = { +"16 16 72 1", +" c None", +". c #65AF36", +"+ c #66B036", +"@ c #77B94C", +"# c #A7D28C", +"$ c #BADBA4", +"% c #A4D088", +"& c #72B646", +"* c #9ACB7A", +"= c #7FBD56", +"- c #85C05F", +"; c #F4F9F0", +"> c #FFFFFF", +", c #E5F1DC", +"' c #ECF5E7", +") c #7ABA50", +"! c #83BF5C", +"~ c #AED595", +"{ c #D7EACA", +"] c #A9D28D", +"^ c #BCDDA8", +"/ c #C4E0B1", +"( c #81BE59", +"_ c #D0E7C2", +": c #D4E9C6", +"< c #6FB542", +"[ c #6EB440", +"} c #88C162", +"| c #98CA78", +"1 c #F4F9F1", +"2 c #8FC56C", +"3 c #F1F8EC", +"4 c #E8F3E1", +"5 c #D4E9C7", +"6 c #74B748", +"7 c #80BE59", +"8 c #73B747", +"9 c #6DB43F", +"0 c #CBE4BA", +"a c #80BD58", +"b c #6DB33F", +"c c #FEFFFE", +"d c #68B138", +"e c #F9FCF7", +"f c #91C66F", +"g c #E8F3E0", +"h c #DCEDD0", +"i c #91C66E", +"j c #A3CF86", +"k c #C9E3B8", +"l c #B0D697", +"m c #E3F0DA", +"n c #95C873", +"o c #E6F2DE", +"p c #9ECD80", +"q c #BEDEAA", +"r c #C7E2B6", +"s c #79BA4F", +"t c #6EB441", +"u c #BCDCA7", +"v c #FAFCF8", +"w c #F6FAF3", +"x c #84BF5D", +"y c #EDF6E7", +"z c #FAFDF9", +"A c #88C263", +"B c #98CA77", +"C c #CDE5BE", +"D c #67B037", +"E c #D9EBCD", +"F c #6AB23C", +"G c #77B94D", +" .++++++++++++++", +".+++++++++++++++", +"+++@#$%&+++*=+++", +"++-;>,>')+!>~+++", +"++{>]+^>/(_>:~<+", +"+[>>}+|>123>456+", +"+7>>8+->>90>~+++", +"+a>>b+a>c[0>~+++", +"+de>=+f>g+0>~+++", +"++h>i+j>k+0>~+++", +"++l>mno>p+q>rst+", +"++duv>wl++xy>zA+", +"++++B>Cb++++&D++", +"+++++0zE++++++++", +"++++++FG+++++++.", +"++++++++++++++. "}; + +static const char * const qt_close_xpm[] = { +"10 10 2 1", +"# c #000000", +". c None", +"..........", +".##....##.", +"..##..##..", +"...####...", +"....##....", +"...####...", +"..##..##..", +".##....##.", +"..........", +".........."}; + +static const char * const qt_maximize_xpm[]={ +"10 10 2 1", +"# c #000000", +". c None", +"#########.", +"#########.", +"#.......#.", +"#.......#.", +"#.......#.", +"#.......#.", +"#.......#.", +"#.......#.", +"#########.", +".........."}; + +static const char * const qt_minimize_xpm[] = { +"10 10 2 1", +"# c #000000", +". c None", +"..........", +"..........", +"..........", +"..........", +"..........", +"..........", +"..........", +".#######..", +".#######..", +".........."}; + +static const char * const qt_normalizeup_xpm[] = { +"10 10 2 1", +"# c #000000", +". c None", +"...######.", +"...######.", +"...#....#.", +".######.#.", +".######.#.", +".#....###.", +".#....#...", +".#....#...", +".######...", +".........."}; + +static const char * const qt_help_xpm[] = { +"10 10 2 1", +". c None", +"# c #000000", +"..........", +"..######..", +".##....##.", +"......##..", +".....##...", +"....##....", +"....##....", +"..........", +"....##....", +".........."}; + +static const char * const qt_shade_xpm[] = { +"10 10 2 1", +"# c #000000", +". c None", +"..........", +"..........", +"..........", +"..........", +"....#.....", +"...###....", +"..#####...", +".#######..", +"..........", +".........."}; + +static const char * const qt_unshade_xpm[] = { +"10 10 2 1", +"# c #000000", +". c None", +"..........", +"..........", +"..........", +".#######..", +"..#####...", +"...###....", +"....#.....", +"..........", +"..........", +".........."}; + +static const char * dock_widget_close_xpm[] = { +"8 8 2 1", +"# c #000000", +". c None", +"........", +".##..##.", +"..####..", +"...##...", +"..####..", +".##..##.", +"........", +"........"}; + +/* XPM */ +static const char * const information_xpm[]={ +"32 32 5 1", +". c None", +"c c #000000", +"* c #999999", +"a c #ffffff", +"b c #0000ff", +"...........********.............", +"........***aaaaaaaa***..........", +"......**aaaaaaaaaaaaaa**........", +".....*aaaaaaaaaaaaaaaaaa*.......", +"....*aaaaaaaabbbbaaaaaaaac......", +"...*aaaaaaaabbbbbbaaaaaaaac.....", +"..*aaaaaaaaabbbbbbaaaaaaaaac....", +".*aaaaaaaaaaabbbbaaaaaaaaaaac...", +".*aaaaaaaaaaaaaaaaaaaaaaaaaac*..", +"*aaaaaaaaaaaaaaaaaaaaaaaaaaaac*.", +"*aaaaaaaaaabbbbbbbaaaaaaaaaaac*.", +"*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", +"*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", +"*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", +"*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", +"*aaaaaaaaaaaabbbbbaaaaaaaaaaac**", +".*aaaaaaaaaaabbbbbaaaaaaaaaac***", +".*aaaaaaaaaaabbbbbaaaaaaaaaac***", +"..*aaaaaaaaaabbbbbaaaaaaaaac***.", +"...caaaaaaabbbbbbbbbaaaaaac****.", +"....caaaaaaaaaaaaaaaaaaaac****..", +".....caaaaaaaaaaaaaaaaaac****...", +"......ccaaaaaaaaaaaaaacc****....", +".......*cccaaaaaaaaccc*****.....", +"........***cccaaaac*******......", +"..........****caaac*****........", +".............*caaac**...........", +"...............caac**...........", +"................cac**...........", +".................cc**...........", +"..................***...........", +"...................**..........."}; +/* XPM */ +static const char* const warning_xpm[]={ +"32 32 4 1", +". c None", +"a c #ffff00", +"* c #000000", +"b c #999999", +".............***................", +"............*aaa*...............", +"...........*aaaaa*b.............", +"...........*aaaaa*bb............", +"..........*aaaaaaa*bb...........", +"..........*aaaaaaa*bb...........", +".........*aaaaaaaaa*bb..........", +".........*aaaaaaaaa*bb..........", +"........*aaaaaaaaaaa*bb.........", +"........*aaaa***aaaa*bb.........", +".......*aaaa*****aaaa*bb........", +".......*aaaa*****aaaa*bb........", +"......*aaaaa*****aaaaa*bb.......", +"......*aaaaa*****aaaaa*bb.......", +".....*aaaaaa*****aaaaaa*bb......", +".....*aaaaaa*****aaaaaa*bb......", +"....*aaaaaaaa***aaaaaaaa*bb.....", +"....*aaaaaaaa***aaaaaaaa*bb.....", +"...*aaaaaaaaa***aaaaaaaaa*bb....", +"...*aaaaaaaaaa*aaaaaaaaaa*bb....", +"..*aaaaaaaaaaa*aaaaaaaaaaa*bb...", +"..*aaaaaaaaaaaaaaaaaaaaaaa*bb...", +".*aaaaaaaaaaaa**aaaaaaaaaaa*bb..", +".*aaaaaaaaaaa****aaaaaaaaaa*bb..", +"*aaaaaaaaaaaa****aaaaaaaaaaa*bb.", +"*aaaaaaaaaaaaa**aaaaaaaaaaaa*bb.", +"*aaaaaaaaaaaaaaaaaaaaaaaaaaa*bbb", +"*aaaaaaaaaaaaaaaaaaaaaaaaaaa*bbb", +".*aaaaaaaaaaaaaaaaaaaaaaaaa*bbbb", +"..*************************bbbbb", +"....bbbbbbbbbbbbbbbbbbbbbbbbbbb.", +".....bbbbbbbbbbbbbbbbbbbbbbbbb.."}; +/* XPM */ +static const char* const critical_xpm[]={ +"32 32 4 1", +". c None", +"a c #999999", +"* c #ff0000", +"b c #ffffff", +"...........********.............", +".........************...........", +".......****************.........", +"......******************........", +".....********************a......", +"....**********************a.....", +"...************************a....", +"..*******b**********b*******a...", +"..******bbb********bbb******a...", +".******bbbbb******bbbbb******a..", +".*******bbbbb****bbbbb*******a..", +"*********bbbbb**bbbbb*********a.", +"**********bbbbbbbbbb**********a.", +"***********bbbbbbbb***********aa", +"************bbbbbb************aa", +"************bbbbbb************aa", +"***********bbbbbbbb***********aa", +"**********bbbbbbbbbb**********aa", +"*********bbbbb**bbbbb*********aa", +".*******bbbbb****bbbbb*******aa.", +".******bbbbb******bbbbb******aa.", +"..******bbb********bbb******aaa.", +"..*******b**********b*******aa..", +"...************************aaa..", +"....**********************aaa...", +"....a********************aaa....", +".....a******************aaa.....", +"......a****************aaa......", +".......aa************aaaa.......", +".........aa********aaaaa........", +"...........aaaaaaaaaaa..........", +".............aaaaaaa............"}; +/* XPM */ +static const char *const question_xpm[] = { +"32 32 5 1", +". c None", +"c c #000000", +"* c #999999", +"a c #ffffff", +"b c #0000ff", +"...........********.............", +"........***aaaaaaaa***..........", +"......**aaaaaaaaaaaaaa**........", +".....*aaaaaaaaaaaaaaaaaa*.......", +"....*aaaaaaaaaaaaaaaaaaaac......", +"...*aaaaaaaabbbbbbaaaaaaaac.....", +"..*aaaaaaaabaaabbbbaaaaaaaac....", +".*aaaaaaaabbaaaabbbbaaaaaaaac...", +".*aaaaaaaabbbbaabbbbaaaaaaaac*..", +"*aaaaaaaaabbbbaabbbbaaaaaaaaac*.", +"*aaaaaaaaaabbaabbbbaaaaaaaaaac*.", +"*aaaaaaaaaaaaabbbbaaaaaaaaaaac**", +"*aaaaaaaaaaaaabbbaaaaaaaaaaaac**", +"*aaaaaaaaaaaaabbaaaaaaaaaaaaac**", +"*aaaaaaaaaaaaabbaaaaaaaaaaaaac**", +"*aaaaaaaaaaaaaaaaaaaaaaaaaaaac**", +".*aaaaaaaaaaaabbaaaaaaaaaaaac***", +".*aaaaaaaaaaabbbbaaaaaaaaaaac***", +"..*aaaaaaaaaabbbbaaaaaaaaaac***.", +"...caaaaaaaaaabbaaaaaaaaaac****.", +"....caaaaaaaaaaaaaaaaaaaac****..", +".....caaaaaaaaaaaaaaaaaac****...", +"......ccaaaaaaaaaaaaaacc****....", +".......*cccaaaaaaaaccc*****.....", +"........***cccaaaac*******......", +"..........****caaac*****........", +".............*caaac**...........", +"...............caac**...........", +"................cac**...........", +".................cc**...........", +"..................***...........", +"...................**..........."}; + +#endif //QT_NO_IMAGEFORMAT_XPM + +#ifdef Q_OS_WIN +static QPixmap loadIconFromShell32( int resourceId, int size ) +{ +#ifdef Q_OS_WINCE + HMODULE hmod = LoadLibrary(L"ceshell"); +#else + HMODULE hmod = QSystemLibrary::load(L"shell32"); +#endif + if( hmod ) { + HICON iconHandle = (HICON)LoadImage(hmod, MAKEINTRESOURCE(resourceId), IMAGE_ICON, size, size, 0); + if( iconHandle ) { + QPixmap iconpixmap = QPixmap::fromWinHICON( iconHandle ); + DestroyIcon(iconHandle); + return iconpixmap; + } + } + return QPixmap(); +} +#endif + +/*! + \reimp + */ +QPixmap QWindowsStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget) const +{ +#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) + QPixmap desktopIcon; + switch(standardPixmap) { + case SP_DriveCDIcon: + case SP_DriveDVDIcon: + { + desktopIcon = loadIconFromShell32(12, 16); + break; + } + case SP_DriveNetIcon: + { + desktopIcon = loadIconFromShell32(10, 16); + break; + } + case SP_DriveHDIcon: + { + desktopIcon = loadIconFromShell32(9, 16); + break; + } + case SP_DriveFDIcon: + { + desktopIcon = loadIconFromShell32(7, 16); + break; + } + case SP_FileIcon: + { + desktopIcon = loadIconFromShell32(1, 16); + break; + } + case SP_FileLinkIcon: + { + desktopIcon = loadIconFromShell32(1, 16); + QPainter painter(&desktopIcon); + QPixmap link = loadIconFromShell32(30, 16); + painter.drawPixmap(0, 0, 16, 16, link); + break; + } + case SP_DirLinkIcon: + { + desktopIcon = loadIconFromShell32(4, 16); + QPainter painter(&desktopIcon); + QPixmap link = loadIconFromShell32(30, 16); + painter.drawPixmap(0, 0, 16, 16, link); + break; + } + case SP_DirClosedIcon: + { + desktopIcon = loadIconFromShell32(4, 16); + break; + } + case SP_DesktopIcon: + { + desktopIcon = loadIconFromShell32(35, 16); + break; + } + case SP_ComputerIcon: + { + desktopIcon = loadIconFromShell32(16, 16); + break; + } + case SP_DirOpenIcon: + { + desktopIcon = loadIconFromShell32(5, 16); + break; + } + case SP_FileDialogNewFolder: + { + desktopIcon = loadIconFromShell32(319, 16); + break; + } + case SP_DirHomeIcon: + { + desktopIcon = loadIconFromShell32(235, 16); + break; + } + case SP_TrashIcon: + { + desktopIcon = loadIconFromShell32(191, 16); + break; + } + case SP_MessageBoxInformation: + { + HICON iconHandle = LoadIcon(NULL, IDI_INFORMATION); + desktopIcon = QPixmap::fromWinHICON( iconHandle ); + DestroyIcon(iconHandle); + break; + } + case SP_MessageBoxWarning: + { + HICON iconHandle = LoadIcon(NULL, IDI_WARNING); + desktopIcon = QPixmap::fromWinHICON( iconHandle ); + DestroyIcon(iconHandle); + break; + } + case SP_MessageBoxCritical: + { + HICON iconHandle = LoadIcon(NULL, IDI_ERROR); + desktopIcon = QPixmap::fromWinHICON( iconHandle ); + DestroyIcon(iconHandle); + break; + } + case SP_MessageBoxQuestion: + { + HICON iconHandle = LoadIcon(NULL, IDI_QUESTION); + desktopIcon = QPixmap::fromWinHICON( iconHandle ); + DestroyIcon(iconHandle); + break; + } + case SP_VistaShield: + { + if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA + && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based + && pSHGetStockIconInfo) + { + QPixmap pixmap; + QSHSTOCKICONINFO iconInfo; + memset(&iconInfo, 0, sizeof(iconInfo)); + iconInfo.cbSize = sizeof(iconInfo); + if (pSHGetStockIconInfo(_SIID_SHIELD, _SHGFI_ICON | _SHGFI_SMALLICON, &iconInfo) == S_OK) { + pixmap = QPixmap::fromWinHICON(iconInfo.hIcon); + DestroyIcon(iconInfo.hIcon); + return pixmap; + } + } + } + break; + default: + break; + } + if (!desktopIcon.isNull()) { + return desktopIcon; + } +#endif +#ifndef QT_NO_IMAGEFORMAT_XPM + switch (standardPixmap) { + case SP_TitleBarMenuButton: + return QPixmap(qt_menu_xpm); + case SP_TitleBarShadeButton: + return QPixmap(qt_shade_xpm); + case SP_TitleBarUnshadeButton: + return QPixmap(qt_unshade_xpm); + case SP_TitleBarNormalButton: + return QPixmap(qt_normalizeup_xpm); + case SP_TitleBarMinButton: + return QPixmap(qt_minimize_xpm); + case SP_TitleBarMaxButton: + return QPixmap(qt_maximize_xpm); + case SP_TitleBarCloseButton: + return QPixmap(qt_close_xpm); + case SP_TitleBarContextHelpButton: + return QPixmap(qt_help_xpm); + case SP_DockWidgetCloseButton: + return QPixmap(dock_widget_close_xpm); + case SP_MessageBoxInformation: + return QPixmap(information_xpm); + case SP_MessageBoxWarning: + return QPixmap(warning_xpm); + case SP_MessageBoxCritical: + return QPixmap(critical_xpm); + case SP_MessageBoxQuestion: + return QPixmap(question_xpm); + default: + break; + } +#endif //QT_NO_IMAGEFORMAT_XPM + return QCommonStyle::standardPixmap(standardPixmap, opt, widget); +} + +/*! \reimp */ +int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWidget *widget, + QStyleHintReturn *returnData) const +{ + int ret = 0; + + switch (hint) { + case SH_EtchDisabledText: + case SH_Slider_SnapToValue: + case SH_PrintDialog_RightAlignButtons: + case SH_FontDialog_SelectAssociatedText: + case SH_Menu_AllowActiveAndDisabled: + case SH_MenuBar_AltKeyNavigation: + case SH_MenuBar_MouseTracking: + case SH_Menu_MouseTracking: + case SH_ComboBox_ListMouseTracking: + case SH_ScrollBar_StopMouseOverSlider: + case SH_MainWindow_SpaceBelowMenuBar: + ret = 1; + + break; + case SH_ItemView_ShowDecorationSelected: +#ifndef QT_NO_LISTVIEW + if (qobject_cast(widget)) + ret = 1; +#endif + break; + case SH_ItemView_ChangeHighlightOnFocus: + ret = 1; + break; + case SH_ToolBox_SelectedPageTitleBold: + ret = 0; + break; + +#if defined(Q_WS_WIN) + case SH_UnderlineShortcut: + { + ret = 1; + BOOL cues = false; + SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &cues, 0); + ret = int(cues); + // Do nothing if we always paint underlines + Q_D(const QWindowsStyle); + if (!ret && widget && d) { +#ifndef QT_NO_MENUBAR + const QMenuBar *menuBar = qobject_cast(widget); + if (!menuBar && qobject_cast(widget)) { + QWidget *w = QApplication::activeWindow(); + if (w && w != widget) + menuBar = w->findChild(); + } + // If we paint a menu bar draw underlines if is in the keyboardState + if (menuBar) { + if (menuBar->d_func()->keyboardState || d->altDown()) + ret = 1; + // Otherwise draw underlines if the toplevel widget has seen an alt-press + } else +#endif // QT_NO_MENUBAR + if (d->hasSeenAlt(widget)) { + ret = 1; + } + } + break; + } +#endif +#ifndef QT_NO_RUBBERBAND + case SH_RubberBand_Mask: + if (const QStyleOptionRubberBand *rbOpt = qstyleoption_cast(opt)) { + ret = 0; + if (rbOpt->shape == QRubberBand::Rectangle) { + ret = true; + if(QStyleHintReturnMask *mask = qstyleoption_cast(returnData)) { + mask->region = opt->rect; + int size = 1; + if (widget && widget->isWindow()) + size = 4; + mask->region -= opt->rect.adjusted(size, size, -size, -size); + } + } + } + break; +#endif // QT_NO_RUBBERBAND + case SH_LineEdit_PasswordCharacter: + { +#ifdef Q_WS_WIN + if (widget && (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) { + const QFontMetrics &fm = widget->fontMetrics(); + if (fm.inFont(QChar(0x25CF))) + ret = 0x25CF; + else if (fm.inFont(QChar(0x2022))) + ret = 0x2022; + } +#endif + if (!ret) + ret = '*'; + } + break; +#ifndef QT_NO_WIZARD + case SH_WizardStyle: + ret = QWizard::ModernStyle; + break; +#endif + case SH_ItemView_ArrowKeysNavigateIntoChildren: + ret = true; + break; + case SH_DialogButtonBox_ButtonsHaveIcons: + ret = 0; + break; + default: + ret = QCommonStyle::styleHint(hint, opt, widget, returnData); + break; + } + return ret; +} + +/*! \reimp */ +void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *w) const +{ + // Used to restore across fallthrough cases. Currently only used in PE_IndicatorCheckBox + bool doRestore = false; + + switch (pe) { +#ifndef QT_NO_TOOLBAR + case PE_IndicatorToolBarSeparator: + { + QRect rect = opt->rect; + const int margin = 2; + QPen oldPen = p->pen(); + if(opt->state & State_Horizontal){ + const int offset = rect.width()/2; + p->setPen(QPen(opt->palette.dark().color())); + p->drawLine(rect.bottomLeft().x() + offset, + rect.bottomLeft().y() - margin, + rect.topLeft().x() + offset, + rect.topLeft().y() + margin); + p->setPen(QPen(opt->palette.light().color())); + p->drawLine(rect.bottomLeft().x() + offset + 1, + rect.bottomLeft().y() - margin, + rect.topLeft().x() + offset + 1, + rect.topLeft().y() + margin); + } + else{ //Draw vertical separator + const int offset = rect.height()/2; + p->setPen(QPen(opt->palette.dark().color())); + p->drawLine(rect.topLeft().x() + margin , + rect.topLeft().y() + offset, + rect.topRight().x() - margin, + rect.topRight().y() + offset); + p->setPen(QPen(opt->palette.light().color())); + p->drawLine(rect.topLeft().x() + margin , + rect.topLeft().y() + offset + 1, + rect.topRight().x() - margin, + rect.topRight().y() + offset + 1); + } + p->setPen(oldPen); + } + break; + case PE_IndicatorToolBarHandle: + p->save(); + p->translate(opt->rect.x(), opt->rect.y()); + if (opt->state & State_Horizontal) { + int x = opt->rect.width() / 2 - 4; + if (opt->direction == Qt::RightToLeft) + x -= 2; + if (opt->rect.height() > 4) { + qDrawShadePanel(p, x, 2, 3, opt->rect.height() - 4, + opt->palette, false, 1, 0); + qDrawShadePanel(p, x + 3, 2, 3, opt->rect.height() - 4, + opt->palette, false, 1, 0); + } + } else { + if (opt->rect.width() > 4) { + int y = opt->rect.height() / 2 - 4; + qDrawShadePanel(p, 2, y, opt->rect.width() - 4, 3, + opt->palette, false, 1, 0); + qDrawShadePanel(p, 2, y + 3, opt->rect.width() - 4, 3, + opt->palette, false, 1, 0); + } + } + p->restore(); + break; + +#endif // QT_NO_TOOLBAR + case PE_FrameButtonTool: + case PE_PanelButtonTool: { + QPen oldPen = p->pen(); +#ifndef QT_NO_DOCKWIDGET + if (w && w->inherits("QDockWidgetTitleButton")) { + if (const QWidget *dw = w->parentWidget()) + if (dw->isWindow()){ + qDrawWinButton(p, opt->rect.adjusted(1, 1, 0, 0), opt->palette, opt->state & (State_Sunken | State_On), + &opt->palette.button()); + + return; + } + } +#endif // QT_NO_DOCKWIDGET + QBrush fill; + bool stippled; + bool panel = (pe == PE_PanelButtonTool); + if ((!(opt->state & State_Sunken )) + && (!(opt->state & State_Enabled) + || !(opt->state & State_MouseOver && opt->state & State_AutoRaise)) + && (opt->state & State_On)) { + fill = QBrush(opt->palette.light().color(), Qt::Dense4Pattern); + stippled = true; + } else { + fill = opt->palette.brush(QPalette::Button); + stippled = false; + } + + if (opt->state & (State_Raised | State_Sunken | State_On)) { + if (opt->state & State_AutoRaise) { + if(opt->state & (State_Enabled | State_Sunken | State_On)){ + if (panel) + qDrawShadePanel(p, opt->rect, opt->palette, + opt->state & (State_Sunken | State_On), 1, &fill); + else + qDrawShadeRect(p, opt->rect, opt->palette, + opt->state & (State_Sunken | State_On), 1); + } + if (stippled) { + p->setPen(opt->palette.button().color()); + p->drawRect(opt->rect.adjusted(1,1,-2,-2)); + } + } else { + qDrawWinButton(p, opt->rect, opt->palette, + opt->state & (State_Sunken | State_On), panel ? &fill : 0); + } + } else { + p->fillRect(opt->rect, fill); + } + p->setPen(oldPen); + break; } + case PE_PanelButtonCommand: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + QBrush fill; + State flags = opt->state; + QPalette pal = opt->palette; + QRect r = opt->rect; + if (! (flags & State_Sunken) && (flags & State_On)) + fill = QBrush(pal.light().color(), Qt::Dense4Pattern); + else + fill = pal.brush(QPalette::Button); + + if (btn->features & QStyleOptionButton::DefaultButton && flags & State_Sunken) { + p->setPen(pal.dark().color()); + p->setBrush(fill); + p->drawRect(r.adjusted(0, 0, -1, -1)); + } else if (flags & (State_Raised | State_Sunken | State_On | State_Sunken)) { + qDrawWinButton(p, r, pal, flags & (State_Sunken | State_On), + &fill); + } else { + p->fillRect(r, fill); + } + } + break; + case PE_FrameDefaultButton: { + QPen oldPen = p->pen(); + p->setPen(opt->palette.shadow().color()); + QRect rect = opt->rect; + rect.adjust(0, 0, -1, -1); + p->drawRect(rect); + p->setPen(oldPen); + break; + } + case PE_IndicatorArrowUp: + case PE_IndicatorArrowDown: + case PE_IndicatorArrowRight: + case PE_IndicatorArrowLeft: + { + if (opt->rect.width() <= 1 || opt->rect.height() <= 1) + break; + QRect r = opt->rect; + int size = qMin(r.height(), r.width()); + QPixmap pixmap; + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("$qt_ia-") + % QLatin1String(metaObject()->className()), opt, QSize(size, size)) + % HexString(pe); + if (!QPixmapCache::find(pixmapName, pixmap)) { + int border = size/5; + int sqsize = 2*(size/2); + QImage image(sqsize, sqsize, QImage::Format_ARGB32_Premultiplied); + image.fill(0); + QPainter imagePainter(&image); + + QPolygon a; + switch (pe) { + case PE_IndicatorArrowUp: + a.setPoints(3, border, sqsize/2, sqsize/2, border, sqsize - border, sqsize/2); + break; + case PE_IndicatorArrowDown: + a.setPoints(3, border, sqsize/2, sqsize/2, sqsize - border, sqsize - border, sqsize/2); + break; + case PE_IndicatorArrowRight: + a.setPoints(3, sqsize - border, sqsize/2, sqsize/2, border, sqsize/2, sqsize - border); + break; + case PE_IndicatorArrowLeft: + a.setPoints(3, border, sqsize/2, sqsize/2, border, sqsize/2, sqsize - border); + break; + default: + break; + } + + int bsx = 0; + int bsy = 0; + + if (opt->state & State_Sunken) { + bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, w); + bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt, w); + } + + QRect bounds = a.boundingRect(); + int sx = sqsize / 2 - bounds.center().x() - 1; + int sy = sqsize / 2 - bounds.center().y() - 1; + imagePainter.translate(sx + bsx, sy + bsy); + imagePainter.setPen(opt->palette.buttonText().color()); + imagePainter.setBrush(opt->palette.buttonText()); + + if (!(opt->state & State_Enabled)) { + imagePainter.translate(1, 1); + imagePainter.setBrush(opt->palette.light().color()); + imagePainter.setPen(opt->palette.light().color()); + imagePainter.drawPolygon(a); + imagePainter.translate(-1, -1); + imagePainter.setBrush(opt->palette.mid().color()); + imagePainter.setPen(opt->palette.mid().color()); + } + + imagePainter.drawPolygon(a); + imagePainter.end(); + pixmap = QPixmap::fromImage(image); + QPixmapCache::insert(pixmapName, pixmap); + } + int xOffset = r.x() + (r.width() - size)/2; + int yOffset = r.y() + (r.height() - size)/2; + p->drawPixmap(xOffset, yOffset, pixmap); + } + break; + case PE_IndicatorCheckBox: { + QBrush fill; + if (opt->state & State_NoChange) + fill = QBrush(opt->palette.base().color(), Qt::Dense4Pattern); + else if (opt->state & State_Sunken) + fill = opt->palette.button(); + else if (opt->state & State_Enabled) + fill = opt->palette.base(); + else + fill = opt->palette.background(); + p->save(); + doRestore = true; + qDrawWinPanel(p, opt->rect, opt->palette, true, &fill); + if (opt->state & State_NoChange) + p->setPen(opt->palette.dark().color()); + else + p->setPen(opt->palette.text().color()); + } // Fall through! + case PE_IndicatorViewItemCheck: + case PE_Q3CheckListIndicator: + if (!doRestore) { + p->save(); + doRestore = true; + } + if (pe == PE_Q3CheckListIndicator || pe == PE_IndicatorViewItemCheck) { + const QStyleOptionViewItem *itemViewOpt = qstyleoption_cast(opt); + p->setPen(itemViewOpt + && itemViewOpt->showDecorationSelected + && opt->state & State_Selected + ? opt->palette.highlightedText().color() + : opt->palette.text().color()); + if (opt->state & State_NoChange) + p->setBrush(opt->palette.brush(QPalette::Button)); + p->drawRect(opt->rect.x() + 1, opt->rect.y() + 1, 11, 11); + } + if (!(opt->state & State_Off)) { + QLineF lines[7]; + int i, xx, yy; + xx = opt->rect.x() + 3; + yy = opt->rect.y() + 5; + for (i = 0; i < 3; ++i) { + lines[i] = QLineF(xx, yy, xx, yy + 2); + ++xx; + ++yy; + } + yy -= 2; + for (i = 3; i < 7; ++i) { + lines[i] = QLineF(xx, yy, xx, yy + 2); + ++xx; + --yy; + } + p->drawLines(lines, 7); + } + if (doRestore) + p->restore(); + break; + case PE_FrameFocusRect: + if (const QStyleOptionFocusRect *fropt = qstyleoption_cast(opt)) { + //### check for d->alt_down + if (!(fropt->state & State_KeyboardFocusChange) && !proxy()->styleHint(SH_UnderlineShortcut, opt)) + return; + QRect r = opt->rect; + p->save(); + p->setBackgroundMode(Qt::TransparentMode); + QColor bg_col = fropt->backgroundColor; + if (!bg_col.isValid()) + bg_col = p->background().color(); + // Create an "XOR" color. + QColor patternCol((bg_col.red() ^ 0xff) & 0xff, + (bg_col.green() ^ 0xff) & 0xff, + (bg_col.blue() ^ 0xff) & 0xff); + p->setBrush(QBrush(patternCol, Qt::Dense4Pattern)); + p->setBrushOrigin(r.topLeft()); + p->setPen(Qt::NoPen); + p->drawRect(r.left(), r.top(), r.width(), 1); // Top + p->drawRect(r.left(), r.bottom(), r.width(), 1); // Bottom + p->drawRect(r.left(), r.top(), 1, r.height()); // Left + p->drawRect(r.right(), r.top(), 1, r.height()); // Right + p->restore(); + } + break; + case PE_IndicatorRadioButton: + { +#define PTSARRLEN(x) sizeof(x)/(sizeof(QPoint)) + static const QPoint pts1[] = { // dark lines + QPoint(1, 9), QPoint(1, 8), QPoint(0, 7), QPoint(0, 4), QPoint(1, 3), QPoint(1, 2), + QPoint(2, 1), QPoint(3, 1), QPoint(4, 0), QPoint(7, 0), QPoint(8, 1), QPoint(9, 1) + }; + static const QPoint pts2[] = { // black lines + QPoint(2, 8), QPoint(1, 7), QPoint(1, 4), QPoint(2, 3), QPoint(2, 2), QPoint(3, 2), + QPoint(4, 1), QPoint(7, 1), QPoint(8, 2), QPoint(9, 2) + }; + static const QPoint pts3[] = { // background lines + QPoint(2, 9), QPoint(3, 9), QPoint(4, 10), QPoint(7, 10), QPoint(8, 9), QPoint(9, 9), + QPoint(9, 8), QPoint(10, 7), QPoint(10, 4), QPoint(9, 3) + }; + static const QPoint pts4[] = { // white lines + QPoint(2, 10), QPoint(3, 10), QPoint(4, 11), QPoint(7, 11), QPoint(8, 10), + QPoint(9, 10), QPoint(10, 9), QPoint(10, 8), QPoint(11, 7), QPoint(11, 4), + QPoint(10, 3), QPoint(10, 2) + }; + static const QPoint pts5[] = { // inner fill + QPoint(4, 2), QPoint(7, 2), QPoint(9, 4), QPoint(9, 7), QPoint(7, 9), QPoint(4, 9), + QPoint(2, 7), QPoint(2, 4) + }; + + // make sure the indicator is square + QRect ir = opt->rect; + + if (opt->rect.width() < opt->rect.height()) { + ir.setTop(opt->rect.top() + (opt->rect.height() - opt->rect.width()) / 2); + ir.setHeight(opt->rect.width()); + } else if (opt->rect.height() < opt->rect.width()) { + ir.setLeft(opt->rect.left() + (opt->rect.width() - opt->rect.height()) / 2); + ir.setWidth(opt->rect.height()); + } + + p->save(); + bool down = opt->state & State_Sunken; + bool enabled = opt->state & State_Enabled; + bool on = opt->state & State_On; + QPolygon a; + + //center when rect is larger than indicator size + int xOffset = 0; + int yOffset = 0; + int indicatorWidth = proxy()->pixelMetric(PM_ExclusiveIndicatorWidth); + int indicatorHeight = proxy()->pixelMetric(PM_ExclusiveIndicatorWidth); + if (ir.width() > indicatorWidth) + xOffset += (ir.width() - indicatorWidth)/2; + if (ir.height() > indicatorHeight) + yOffset += (ir.height() - indicatorHeight)/2; + p->translate(xOffset, yOffset); + + p->translate(ir.x(), ir.y()); + + p->setPen(opt->palette.dark().color()); + p->drawPolyline(pts1, PTSARRLEN(pts1)); + + p->setPen(opt->palette.shadow().color()); + p->drawPolyline(pts2, PTSARRLEN(pts2)); + + p->setPen(opt->palette.midlight().color()); + p->drawPolyline(pts3, PTSARRLEN(pts3)); + + p->setPen(opt->palette.light().color()); + p->drawPolyline(pts4, PTSARRLEN(pts4)); + + QColor fillColor = (down || !enabled) + ? opt->palette.button().color() + : opt->palette.base().color(); + p->setPen(fillColor); + p->setBrush(fillColor) ; + p->drawPolygon(pts5, PTSARRLEN(pts5)); + + p->translate(-ir.x(), -ir.y()); // restore translate + + if (on) { + p->setPen(Qt::NoPen); + p->setBrush(opt->palette.text()); + p->drawRect(ir.x() + 5, ir.y() + 4, 2, 4); + p->drawRect(ir.x() + 4, ir.y() + 5, 4, 2); + } + p->restore(); + break; + } +#ifndef QT_NO_FRAME + case PE_Frame: + case PE_FrameMenu: + if (const QStyleOptionFrame *frame = qstyleoption_cast(opt)) { + if (frame->lineWidth == 2 || pe == PE_Frame) { + QPalette popupPal = frame->palette; + if (pe == PE_FrameMenu) { + popupPal.setColor(QPalette::Light, frame->palette.background().color()); + popupPal.setColor(QPalette::Midlight, frame->palette.light().color()); + } + if (pe == PE_Frame && (frame->state & State_Raised)) + qDrawWinButton(p, frame->rect, popupPal, frame->state & State_Sunken); + else if (pe == PE_Frame && (frame->state & State_Sunken)) + { + popupPal.setColor(QPalette::Midlight, frame->palette.background().color()); + qDrawWinPanel(p, frame->rect, popupPal, frame->state & State_Sunken); + } + else + qDrawWinPanel(p, frame->rect, popupPal, frame->state & State_Sunken); + } else { + QCommonStyle::drawPrimitive(pe, opt, p, w); + } + } else { + QPalette popupPal = opt->palette; + popupPal.setColor(QPalette::Light, opt->palette.background().color()); + popupPal.setColor(QPalette::Midlight, opt->palette.light().color()); + qDrawWinPanel(p, opt->rect, popupPal, opt->state & State_Sunken); + } + break; +#endif // QT_NO_FRAME + case PE_IndicatorBranch: { + // This is _way_ too similar to the common style. + static const int decoration_size = 9; + int mid_h = opt->rect.x() + opt->rect.width() / 2; + int mid_v = opt->rect.y() + opt->rect.height() / 2; + int bef_h = mid_h; + int bef_v = mid_v; + int aft_h = mid_h; + int aft_v = mid_v; + if (opt->state & State_Children) { + int delta = decoration_size / 2; + bef_h -= delta; + bef_v -= delta; + aft_h += delta; + aft_v += delta; + p->drawLine(bef_h + 2, bef_v + 4, bef_h + 6, bef_v + 4); + if (!(opt->state & State_Open)) + p->drawLine(bef_h + 4, bef_v + 2, bef_h + 4, bef_v + 6); + QPen oldPen = p->pen(); + p->setPen(opt->palette.dark().color()); + p->drawRect(bef_h, bef_v, decoration_size - 1, decoration_size - 1); + p->setPen(oldPen); + } + QBrush brush(opt->palette.dark().color(), Qt::Dense4Pattern); + if (opt->state & State_Item) { + if (opt->direction == Qt::RightToLeft) + p->fillRect(opt->rect.left(), mid_v, bef_h - opt->rect.left(), 1, brush); + else + p->fillRect(aft_h, mid_v, opt->rect.right() - aft_h + 1, 1, brush); + } + if (opt->state & State_Sibling) + p->fillRect(mid_h, aft_v, 1, opt->rect.bottom() - aft_v + 1, brush); + if (opt->state & (State_Open | State_Children | State_Item | State_Sibling)) + p->fillRect(mid_h, opt->rect.y(), 1, bef_v - opt->rect.y(), brush); + break; } + case PE_FrameButtonBevel: + case PE_PanelButtonBevel: { + QBrush fill; + bool panel = pe != PE_FrameButtonBevel; + p->setBrushOrigin(opt->rect.topLeft()); + if (!(opt->state & State_Sunken) && (opt->state & State_On)) + fill = QBrush(opt->palette.light().color(), Qt::Dense4Pattern); + else + fill = opt->palette.brush(QPalette::Button); + + if (opt->state & (State_Raised | State_On | State_Sunken)) { + qDrawWinButton(p, opt->rect, opt->palette, opt->state & (State_Sunken | State_On), + panel ? &fill : 0); + } else { + if (panel) + p->fillRect(opt->rect, fill); + else + p->drawRect(opt->rect); + } + break; } + case PE_FrameWindow: { + QPalette popupPal = opt->palette; + popupPal.setColor(QPalette::Light, opt->palette.background().color()); + popupPal.setColor(QPalette::Midlight, opt->palette.light().color()); + qDrawWinPanel(p, opt->rect, popupPal, opt->state & State_Sunken); + break; } +#ifndef QT_NO_DOCKWIDGET + case PE_IndicatorDockWidgetResizeHandle: { + QPen oldPen = p->pen(); + p->setPen(opt->palette.light().color()); + if (opt->state & State_Horizontal) { + p->drawLine(opt->rect.left(), opt->rect.top(), + opt->rect.right(), opt->rect.top()); + p->setPen(opt->palette.dark().color()); + p->drawLine(opt->rect.left(), opt->rect.bottom() - 1, + opt->rect.right(), opt->rect.bottom() - 1); + p->setPen(opt->palette.shadow().color()); + p->drawLine(opt->rect.left(), opt->rect.bottom(), + opt->rect.right(), opt->rect.bottom()); + } else { + p->drawLine(opt->rect.left(), opt->rect.top(), + opt->rect.left(), opt->rect.bottom()); + p->setPen(opt->palette.dark().color()); + p->drawLine(opt->rect.right() - 1, opt->rect.top(), + opt->rect.right() - 1, opt->rect.bottom()); + p->setPen(opt->palette.shadow().color()); + p->drawLine(opt->rect.right(), opt->rect.top(), + opt->rect.right(), opt->rect.bottom()); + } + p->setPen(oldPen); + break; } +case PE_FrameDockWidget: + if (qstyleoption_cast(opt)) { + proxy()->drawPrimitive(QStyle::PE_FrameWindow, opt, p, w); + } + break; +#endif // QT_NO_DOCKWIDGET + + case PE_FrameStatusBarItem: + qDrawShadePanel(p, opt->rect, opt->palette, true, 1, 0); + break; + +#ifndef QT_NO_PROGRESSBAR + case PE_IndicatorProgressChunk: + { + bool vertical = false, inverted = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt)) { + vertical = (pb2->orientation == Qt::Vertical); + inverted = pb2->invertedAppearance; + } + + int space = 2; + int chunksize = proxy()->pixelMetric(PM_ProgressBarChunkWidth, opt, w) - space; + if (!vertical) { + if (opt->rect.width() <= chunksize) + space = 0; + + if (inverted) + p->fillRect(opt->rect.x() + space, opt->rect.y(), opt->rect.width() - space, opt->rect.height(), + opt->palette.brush(QPalette::Highlight)); + else + p->fillRect(opt->rect.x(), opt->rect.y(), opt->rect.width() - space, opt->rect.height(), + opt->palette.brush(QPalette::Highlight)); + } else { + if (opt->rect.height() <= chunksize) + space = 0; + + if (inverted) + p->fillRect(opt->rect.x(), opt->rect.y(), opt->rect.width(), opt->rect.height() - space, + opt->palette.brush(QPalette::Highlight)); + else + p->fillRect(opt->rect.x(), opt->rect.y() + space, opt->rect.width(), opt->rect.height() - space, + opt->palette.brush(QPalette::Highlight)); + } + } + break; +#endif // QT_NO_PROGRESSBAR + + case PE_FrameTabWidget: { + qDrawWinButton(p, opt->rect, opt->palette, false, 0); + break; + } + default: + QCommonStyle::drawPrimitive(pe, opt, p, w); + } +} + +/*! \reimp */ +void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p, + const QWidget *widget) const +{ + switch (ce) { +#ifndef QT_NO_RUBBERBAND + case CE_RubberBand: + if (qstyleoption_cast(opt)) { + // ### workaround for slow general painter path + QPixmap tiledPixmap(16, 16); + QPainter pixmapPainter(&tiledPixmap); + pixmapPainter.setPen(Qt::NoPen); + pixmapPainter.setBrush(Qt::Dense4Pattern); + pixmapPainter.setBackground(Qt::white); + pixmapPainter.setBackgroundMode(Qt::OpaqueMode); + pixmapPainter.drawRect(0, 0, tiledPixmap.width(), tiledPixmap.height()); + pixmapPainter.end(); + tiledPixmap = QPixmap::fromImage(tiledPixmap.toImage()); + p->save(); + QRect r = opt->rect; + QStyleHintReturnMask mask; + if (proxy()->styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask)) + p->setClipRegion(mask.region); + p->drawTiledPixmap(r.x(), r.y(), r.width(), r.height(), tiledPixmap); + p->restore(); + return; + } + break; +#endif // QT_NO_RUBBERBAND + +#if !defined(QT_NO_MENU) && !defined(QT_NO_MAINWINDOW) + case CE_MenuBarEmptyArea: + if (widget && qobject_cast(widget->parentWidget())) { + p->fillRect(opt->rect, opt->palette.button()); + QPen oldPen = p->pen(); + p->setPen(QPen(opt->palette.dark().color())); + p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight()); + p->setPen(oldPen); + } + break; +#endif +#ifndef QT_NO_MENU + case CE_MenuItem: + if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(opt)) { + int x, y, w, h; + menuitem->rect.getRect(&x, &y, &w, &h); + int tab = menuitem->tabWidth; + bool dis = !(menuitem->state & State_Enabled); + bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable + ? menuitem->checked : false; + bool act = menuitem->state & State_Selected; + + // windows always has a check column, regardless whether we have an icon or not + int checkcol = qMax(menuitem->maxIconWidth, QWindowsStylePrivate::windowsCheckMarkWidth); + + QBrush fill = menuitem->palette.brush(act ? QPalette::Highlight : QPalette::Button); + p->fillRect(menuitem->rect.adjusted(0, 0, -1, 0), fill); + + if (menuitem->menuItemType == QStyleOptionMenuItem::Separator){ + int yoff = y-1 + h / 2; + p->setPen(menuitem->palette.dark().color()); + p->drawLine(x + 2, yoff, x + w - 4, yoff); + p->setPen(menuitem->palette.light().color()); + p->drawLine(x + 2, yoff + 1, x + w - 4, yoff + 1); + return; + } + + QRect vCheckRect = visualRect(opt->direction, menuitem->rect, QRect(menuitem->rect.x(), menuitem->rect.y(), checkcol, menuitem->rect.height())); + if (checked) { + if (act && !dis) { + qDrawShadePanel(p, vCheckRect, + menuitem->palette, true, 1, + &menuitem->palette.brush(QPalette::Button)); + } else { + QBrush fill(menuitem->palette.light().color(), Qt::Dense4Pattern); + qDrawShadePanel(p, vCheckRect, menuitem->palette, true, 1, &fill); + } + } else if (!act) { + p->fillRect(vCheckRect, menuitem->palette.brush(QPalette::Button)); + } + + // On Windows Style, if we have a checkable item and an icon we + // draw the icon recessed to indicate an item is checked. If we + // have no icon, we draw a checkmark instead. + if (!menuitem->icon.isNull()) { + QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; + if (act && !dis) + mode = QIcon::Active; + QPixmap pixmap; + if (checked) + pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, opt, widget), mode, QIcon::On); + else + pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, opt, widget), mode); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + if (act && !dis && !checked) + qDrawShadePanel(p, vCheckRect, menuitem->palette, false, 1, + &menuitem->palette.brush(QPalette::Button)); + QRect pmr(0, 0, pixw, pixh); + pmr.moveCenter(vCheckRect.center()); + p->setPen(menuitem->palette.text().color()); + p->drawPixmap(pmr.topLeft(), pixmap); + } else if (checked) { + QStyleOptionMenuItem newMi = *menuitem; + newMi.state = State_None; + if (!dis) + newMi.state |= State_Enabled; + if (act) + newMi.state |= State_On; + newMi.rect = visualRect(opt->direction, menuitem->rect, QRect(menuitem->rect.x() + QWindowsStylePrivate::windowsItemFrame, + menuitem->rect.y() + QWindowsStylePrivate::windowsItemFrame, + checkcol - 2 * QWindowsStylePrivate::windowsItemFrame, + menuitem->rect.height() - 2 * QWindowsStylePrivate::windowsItemFrame)); + proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget); + } + p->setPen(act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color()); + + QColor discol; + if (dis) { + discol = menuitem->palette.text().color(); + p->setPen(discol); + } + + int xm = int(QWindowsStylePrivate::windowsItemFrame) + checkcol + int(QWindowsStylePrivate::windowsItemHMargin); + int xpos = menuitem->rect.x() + xm; + QRect textRect(xpos, y + QWindowsStylePrivate::windowsItemVMargin, + w - xm - QWindowsStylePrivate::windowsRightBorder - tab + 1, h - 2 * QWindowsStylePrivate::windowsItemVMargin); + QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect); + QString s = menuitem->text; + if (!s.isEmpty()) { // draw text + p->save(); + int t = s.indexOf(QLatin1Char('\t')); + int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget)) + text_flags |= Qt::TextHideMnemonic; + text_flags |= Qt::AlignLeft; + if (t >= 0) { + QRect vShortcutRect = visualRect(opt->direction, menuitem->rect, + QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom()))); + if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, opt, widget)) { + p->setPen(menuitem->palette.light().color()); + p->drawText(vShortcutRect.adjusted(1,1,1,1), text_flags, s.mid(t + 1)); + p->setPen(discol); + } + p->drawText(vShortcutRect, text_flags, s.mid(t + 1)); + s = s.left(t); + } + QFont font = menuitem->font; + if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) + font.setBold(true); + p->setFont(font); + if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, opt, widget)) { + p->setPen(menuitem->palette.light().color()); + p->drawText(vTextRect.adjusted(1,1,1,1), text_flags, s.left(t)); + p->setPen(discol); + } + p->drawText(vTextRect, text_flags, s.left(t)); + p->restore(); + } + if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow + int dim = (h - 2 * QWindowsStylePrivate::windowsItemFrame) / 2; + PrimitiveElement arrow; + arrow = (opt->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; + xpos = x + w - QWindowsStylePrivate::windowsArrowHMargin - QWindowsStylePrivate::windowsItemFrame - dim; + QRect vSubMenuRect = visualRect(opt->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim)); + QStyleOptionMenuItem newMI = *menuitem; + newMI.rect = vSubMenuRect; + newMI.state = dis ? State_None : State_Enabled; + if (act) + newMI.palette.setColor(QPalette::ButtonText, + newMI.palette.highlightedText().color()); + proxy()->drawPrimitive(arrow, &newMI, p, widget); + } + + } + break; +#endif // QT_NO_MENU +#ifndef QT_NO_MENUBAR + case CE_MenuBarItem: + if (const QStyleOptionMenuItem *mbi = qstyleoption_cast(opt)) { + bool active = mbi->state & State_Selected; + bool hasFocus = mbi->state & State_HasFocus; + bool down = mbi->state & State_Sunken; + QStyleOptionMenuItem newMbi = *mbi; + p->fillRect(mbi->rect, mbi->palette.brush(QPalette::Button)); + if (active || hasFocus) { + QBrush b = mbi->palette.brush(QPalette::Button); + if (active && down) + p->setBrushOrigin(p->brushOrigin() + QPoint(1, 1)); + if (active && hasFocus) + qDrawShadeRect(p, mbi->rect.x(), mbi->rect.y(), mbi->rect.width(), + mbi->rect.height(), mbi->palette, active && down, 1, 0, &b); + if (active && down) { + newMbi.rect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, mbi, widget), + proxy()->pixelMetric(PM_ButtonShiftVertical, mbi, widget)); + p->setBrushOrigin(p->brushOrigin() - QPoint(1, 1)); + } + } + QCommonStyle::drawControl(ce, &newMbi, p, widget); + } + break; +#endif // QT_NO_MENUBAR +#ifndef QT_NO_TABBAR + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + bool rtlHorTabs = (tab->direction == Qt::RightToLeft + && (tab->shape == QTabBar::RoundedNorth + || tab->shape == QTabBar::RoundedSouth)); + bool selected = tab->state & State_Selected; + bool lastTab = ((!rtlHorTabs && tab->position == QStyleOptionTab::End) + || (rtlHorTabs + && tab->position == QStyleOptionTab::Beginning)); + bool firstTab = ((!rtlHorTabs + && tab->position == QStyleOptionTab::Beginning) + || (rtlHorTabs + && tab->position == QStyleOptionTab::End)); + bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab; + bool previousSelected = + ((!rtlHorTabs + && tab->selectedPosition == QStyleOptionTab::PreviousIsSelected) + || (rtlHorTabs + && tab->selectedPosition == QStyleOptionTab::NextIsSelected)); + bool nextSelected = + ((!rtlHorTabs + && tab->selectedPosition == QStyleOptionTab::NextIsSelected) + || (rtlHorTabs + && tab->selectedPosition + == QStyleOptionTab::PreviousIsSelected)); + int tabBarAlignment = proxy()->styleHint(SH_TabBar_Alignment, tab, widget); + bool leftAligned = (!rtlHorTabs && tabBarAlignment == Qt::AlignLeft) + || (rtlHorTabs + && tabBarAlignment == Qt::AlignRight); + + bool rightAligned = (!rtlHorTabs && tabBarAlignment == Qt::AlignRight) + || (rtlHorTabs + && tabBarAlignment == Qt::AlignLeft); + + QColor light = tab->palette.light().color(); + QColor midlight = tab->palette.midlight().color(); + QColor dark = tab->palette.dark().color(); + QColor shadow = tab->palette.shadow().color(); + QColor background = tab->palette.background().color(); + int borderThinkness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget); + if (selected) + borderThinkness /= 2; + QRect r2(opt->rect); + int x1 = r2.left(); + int x2 = r2.right(); + int y1 = r2.top(); + int y2 = r2.bottom(); + switch (tab->shape) { + default: + QCommonStyle::drawControl(ce, tab, p, widget); + break; + case QTabBar::RoundedNorth: { + if (!selected) { + y1 += 2; + x1 += onlyOne || firstTab ? borderThinkness : 0; + x2 -= onlyOne || lastTab ? borderThinkness : 0; + } + + p->fillRect(QRect(x1 + 1, y1 + 1, (x2 - x1) - 1, (y2 - y1) - 2), tab->palette.background()); + + // Delete border + if (selected) { + p->fillRect(QRect(x1,y2-1,x2-x1,1), tab->palette.background()); + p->fillRect(QRect(x1,y2,x2-x1,1), tab->palette.background()); + } + // Left + if (firstTab || selected || onlyOne || !previousSelected) { + p->setPen(light); + p->drawLine(x1, y1 + 2, x1, y2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness)); + p->drawPoint(x1 + 1, y1 + 1); + } + // Top + { + int beg = x1 + (previousSelected ? 0 : 2); + int end = x2 - (nextSelected ? 0 : 2); + p->setPen(light); + p->drawLine(beg, y1, end, y1); + } + // Right + if (lastTab || selected || onlyOne || !nextSelected) { + p->setPen(shadow); + p->drawLine(x2, y1 + 2, x2, y2 - ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness)); + p->drawPoint(x2 - 1, y1 + 1); + p->setPen(dark); + p->drawLine(x2 - 1, y1 + 2, x2 - 1, y2 - ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness)); + } + break; } + case QTabBar::RoundedSouth: { + if (!selected) { + y2 -= 2; + x1 += firstTab ? borderThinkness : 0; + x2 -= lastTab ? borderThinkness : 0; + } + + p->fillRect(QRect(x1 + 1, y1 + 2, (x2 - x1) - 1, (y2 - y1) - 1), tab->palette.background()); + + // Delete border + if (selected) { + p->fillRect(QRect(x1, y1 + 1, (x2 - 1)-x1, 1), tab->palette.background()); + p->fillRect(QRect(x1, y1, (x2 - 1)-x1, 1), tab->palette.background()); + } + // Left + if (firstTab || selected || onlyOne || !previousSelected) { + p->setPen(light); + p->drawLine(x1, y2 - 2, x1, y1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness)); + p->drawPoint(x1 + 1, y2 - 1); + } + // Bottom + { + int beg = x1 + (previousSelected ? 0 : 2); + int end = x2 - (nextSelected ? 0 : 2); + p->setPen(shadow); + p->drawLine(beg, y2, end, y2); + p->setPen(dark); + p->drawLine(beg, y2 - 1, end, y2 - 1); + } + // Right + if (lastTab || selected || onlyOne || !nextSelected) { + p->setPen(shadow); + p->drawLine(x2, y2 - 2, x2, y1 + ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness)); + p->drawPoint(x2 - 1, y2 - 1); + p->setPen(dark); + p->drawLine(x2 - 1, y2 - 2, x2 - 1, y1 + ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness)); + } + break; } + case QTabBar::RoundedWest: { + if (!selected) { + x1 += 2; + y1 += firstTab ? borderThinkness : 0; + y2 -= lastTab ? borderThinkness : 0; + } + + p->fillRect(QRect(x1 + 1, y1 + 1, (x2 - x1) - 2, (y2 - y1) - 1), tab->palette.background()); + + // Delete border + if (selected) { + p->fillRect(QRect(x2 - 1, y1, 1, y2-y1), tab->palette.background()); + p->fillRect(QRect(x2, y1, 1, y2-y1), tab->palette.background()); + } + // Top + if (firstTab || selected || onlyOne || !previousSelected) { + p->setPen(light); + p->drawLine(x1 + 2, y1, x2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1); + p->drawPoint(x1 + 1, y1 + 1); + } + // Left + { + int beg = y1 + (previousSelected ? 0 : 2); + int end = y2 - (nextSelected ? 0 : 2); + p->setPen(light); + p->drawLine(x1, beg, x1, end); + } + // Bottom + if (lastTab || selected || onlyOne || !nextSelected) { + p->setPen(shadow); + p->drawLine(x1 + 3, y2, x2 - ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness), y2); + p->drawPoint(x1 + 2, y2 - 1); + p->setPen(dark); + p->drawLine(x1 + 3, y2 - 1, x2 - ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness), y2 - 1); + p->drawPoint(x1 + 1, y2 - 1); + p->drawPoint(x1 + 2, y2); + } + break; } + case QTabBar::RoundedEast: { + if (!selected) { + x2 -= 2; + y1 += firstTab ? borderThinkness : 0; + y2 -= lastTab ? borderThinkness : 0; + } + + p->fillRect(QRect(x1 + 2, y1 + 1, (x2 - x1) - 1, (y2 - y1) - 1), tab->palette.background()); + + // Delete border + if (selected) { + p->fillRect(QRect(x1 + 1, y1, 1, (y2 - 1)-y1),tab->palette.background()); + p->fillRect(QRect(x1, y1, 1, (y2-1)-y1), tab->palette.background()); + } + // Top + if (firstTab || selected || onlyOne || !previousSelected) { + p->setPen(light); + p->drawLine(x2 - 2, y1, x1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1); + p->drawPoint(x2 - 1, y1 + 1); + } + // Right + { + int beg = y1 + (previousSelected ? 0 : 2); + int end = y2 - (nextSelected ? 0 : 2); + p->setPen(shadow); + p->drawLine(x2, beg, x2, end); + p->setPen(dark); + p->drawLine(x2 - 1, beg, x2 - 1, end); + } + // Bottom + if (lastTab || selected || onlyOne || !nextSelected) { + p->setPen(shadow); + p->drawLine(x2 - 2, y2, x1 + ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness), y2); + p->drawPoint(x2 - 1, y2 - 1); + p->setPen(dark); + p->drawLine(x2 - 2, y2 - 1, x1 + ((onlyOne || lastTab) && selected && rightAligned ? 0 : borderThinkness), y2 - 1); + } + break; } + } + } + break; +#endif // QT_NO_TABBAR + case CE_ToolBoxTabShape: + qDrawShadePanel(p, opt->rect, opt->palette, + opt->state & (State_Sunken | State_On), 1, + &opt->palette.brush(QPalette::Button)); + break; +#ifndef QT_NO_SPLITTER + case CE_Splitter: + p->eraseRect(opt->rect); + break; +#endif // QT_NO_SPLITTER +#ifndef QT_NO_SCROLLBAR + case CE_ScrollBarSubLine: + case CE_ScrollBarAddLine: { + if ((opt->state & State_Sunken)) { + p->setPen(opt->palette.dark().color()); + p->setBrush(opt->palette.brush(QPalette::Button)); + p->drawRect(opt->rect.adjusted(0, 0, -1, -1)); + } else { + QStyleOption buttonOpt = *opt; + if (!(buttonOpt.state & State_Sunken)) + buttonOpt.state |= State_Raised; + QPalette pal(opt->palette); + pal.setColor(QPalette::Button, opt->palette.light().color()); + pal.setColor(QPalette::Light, opt->palette.button().color()); + qDrawWinButton(p, opt->rect, pal, opt->state & (State_Sunken | State_On), + &opt->palette.brush(QPalette::Button)); + } + PrimitiveElement arrow; + if (opt->state & State_Horizontal) { + if (ce == CE_ScrollBarAddLine) + arrow = opt->direction == Qt::LeftToRight ? PE_IndicatorArrowRight : PE_IndicatorArrowLeft; + else + arrow = opt->direction == Qt::LeftToRight ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; + } else { + if (ce == CE_ScrollBarAddLine) + arrow = PE_IndicatorArrowDown; + else + arrow = PE_IndicatorArrowUp; + } + QStyleOption arrowOpt = *opt; + arrowOpt.rect = opt->rect.adjusted(4, 4, -4, -4); + proxy()->drawPrimitive(arrow, &arrowOpt, p, widget); + break; } + case CE_ScrollBarAddPage: + case CE_ScrollBarSubPage: { + QBrush br; + QBrush bg = p->background(); + Qt::BGMode bg_mode = p->backgroundMode(); + p->setPen(Qt::NoPen); + p->setBackgroundMode(Qt::OpaqueMode); + + if (opt->state & State_Sunken) { + br = QBrush(opt->palette.shadow().color(), Qt::Dense4Pattern); + p->setBackground(opt->palette.dark().color()); + p->setBrush(br); + } else { + QPixmap pm = opt->palette.brush(QPalette::Light).texture(); + br = !pm.isNull() ? QBrush(pm) : QBrush(opt->palette.light().color(), Qt::Dense4Pattern); + p->setBackground(opt->palette.background().color()); + p->setBrush(br); + } + p->drawRect(opt->rect); + p->setBackground(bg); + p->setBackgroundMode(bg_mode); + break; } + case CE_ScrollBarSlider: + if (!(opt->state & State_Enabled)) { + QPixmap pm = opt->palette.brush(QPalette::Light).texture(); + QBrush br = !pm.isNull() ? QBrush(pm) : QBrush(opt->palette.light().color(), Qt::Dense4Pattern); + p->setPen(Qt::NoPen); + p->setBrush(br); + p->setBackgroundMode(Qt::OpaqueMode); + p->drawRect(opt->rect); + } else { + QStyleOptionButton buttonOpt; + buttonOpt.QStyleOption::operator=(*opt); + buttonOpt.state = State_Enabled | State_Raised; + + QPalette pal(opt->palette); + pal.setColor(QPalette::Button, opt->palette.light().color()); + pal.setColor(QPalette::Light, opt->palette.button().color()); + qDrawWinButton(p, opt->rect, pal, false, &opt->palette.brush(QPalette::Button)); + } + break; +#endif // QT_NO_SCROLLBAR + case CE_HeaderSection: { + QBrush fill; + if (opt->state & State_On) + fill = QBrush(opt->palette.light().color(), Qt::Dense4Pattern); + else + fill = opt->palette.brush(QPalette::Button); + + if (opt->state & (State_Raised | State_Sunken)) { + qDrawWinButton(p, opt->rect, opt->palette, opt->state & State_Sunken, &fill); + } else { + p->fillRect(opt->rect, fill); + } + break; } +#ifndef QT_NO_TOOLBAR + case CE_ToolBar: + if (const QStyleOptionToolBar *toolbar = qstyleoption_cast(opt)) { + QRect rect = opt->rect; + + bool paintLeftBorder = true; + bool paintRightBorder = true; + bool paintBottomBorder = true; + + switch (toolbar->toolBarArea){ + case Qt::BottomToolBarArea : + switch(toolbar->positionOfLine){ + case QStyleOptionToolBar::Beginning: + case QStyleOptionToolBar::OnlyOne: + paintBottomBorder = false; + default: + break; + } + case Qt::TopToolBarArea : + switch(toolbar->positionWithinLine){ + case QStyleOptionToolBar::Beginning: + paintLeftBorder = false; + break; + case QStyleOptionToolBar::End: + paintRightBorder = false; + break; + case QStyleOptionToolBar::OnlyOne: + paintRightBorder = false; + paintLeftBorder = false; + default: + break; + } + if(opt->direction == Qt::RightToLeft){ //reverse layout changes the order of Beginning/end + bool tmp = paintLeftBorder; + paintRightBorder=paintLeftBorder; + paintLeftBorder=tmp; + } + break; + case Qt::RightToolBarArea : + switch (toolbar->positionOfLine){ + case QStyleOptionToolBar::Beginning: + case QStyleOptionToolBar::OnlyOne: + paintRightBorder = false; + break; + default: + break; + } + break; + case Qt::LeftToolBarArea : + switch (toolbar->positionOfLine){ + case QStyleOptionToolBar::Beginning: + case QStyleOptionToolBar::OnlyOne: + paintLeftBorder = false; + break; + default: + break; + } + break; + default: + break; + } + + + //draw top border + p->setPen(QPen(opt->palette.light().color())); + p->drawLine(rect.topLeft().x(), + rect.topLeft().y(), + rect.topRight().x(), + rect.topRight().y()); + + if (paintLeftBorder){ + p->setPen(QPen(opt->palette.light().color())); + p->drawLine(rect.topLeft().x(), + rect.topLeft().y(), + rect.bottomLeft().x(), + rect.bottomLeft().y()); + } + + if (paintRightBorder){ + p->setPen(QPen(opt->palette.dark().color())); + p->drawLine(rect.topRight().x(), + rect.topRight().y(), + rect.bottomRight().x(), + rect.bottomRight().y()); + } + + if (paintBottomBorder){ + p->setPen(QPen(opt->palette.dark().color())); + p->drawLine(rect.bottomLeft().x(), + rect.bottomLeft().y(), + rect.bottomRight().x(), + rect.bottomRight().y()); + } + } + break; + + +#endif // QT_NO_TOOLBAR +#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBarContents: + if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { + QRect rect = pb->rect; + if (!rect.isValid()) + return; + + bool vertical = false; + bool inverted = false; + + // Get extra style options if version 2 + const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(opt); + if (pb2) { + vertical = (pb2->orientation == Qt::Vertical); + inverted = pb2->invertedAppearance; + } + QMatrix m; + if (vertical) { + rect = QRect(rect.y(), rect.x(), rect.height(), rect.width()); // flip width and height + m.rotate(90); + m.translate(0, -(rect.height() + rect.y()*2)); + } + QPalette pal2 = pb->palette; + // Correct the highlight color if it is the same as the background + if (pal2.highlight() == pal2.background()) + pal2.setColor(QPalette::Highlight, pb->palette.color(QPalette::Active, + QPalette::Highlight)); + bool reverse = ((!vertical && (pb->direction == Qt::RightToLeft)) || vertical); + if (inverted) + reverse = !reverse; + int w = rect.width(); + if (pb->minimum == 0 && pb->maximum == 0) { + Q_D(const QWindowsStyle); + const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, pb, widget); + QStyleOptionProgressBarV2 pbBits = *pb; + Q_ASSERT(unit_width >0); + + pbBits.rect = rect; + pbBits.palette = pal2; + + int chunkCount = w / unit_width + 1; + int step = d->animateStep%chunkCount; + int chunksInRow = 5; + int myY = pbBits.rect.y(); + int myHeight = pbBits.rect.height(); + int chunksToDraw = chunksInRow; + + if(step > chunkCount - 5)chunksToDraw = (chunkCount - step); + p->save(); + p->setClipRect(m.mapRect(QRectF(rect)).toRect()); + + int x0 = reverse ? rect.left() + rect.width() - unit_width*(step) - unit_width : rect.left() + unit_width * step; + int x = 0; + + for (int i = 0; i < chunksToDraw ; ++i) { + pbBits.rect.setRect(x0 + x, myY, unit_width, myHeight); + pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect(); + proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget); + x += reverse ? -unit_width : unit_width; + } + //Draw wrap-around chunks + if( step > chunkCount-5){ + x0 = reverse ? rect.left() + rect.width() - unit_width : rect.left() ; + x = 0; + int chunksToDraw = step - (chunkCount - chunksInRow); + for (int i = 0; i < chunksToDraw ; ++i) { + pbBits.rect.setRect(x0 + x, myY, unit_width, myHeight); + pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect(); + proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget); + x += reverse ? -unit_width : unit_width; + } + } + p->restore(); //restore state + } + else { + QCommonStyle::drawControl(ce, opt, p, widget); + } + } + break; +#endif // QT_NO_PROGRESSBAR + +#ifndef QT_NO_DOCKWIDGET + case CE_DockWidgetTitle: + + if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast(opt)) { + Q_D(const QWindowsStyle); + + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(opt); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + + QRect rect = dwOpt->rect; + QRect r = rect; + + if (verticalTitleBar) { + QSize s = r.size(); + s.transpose(); + r.setSize(s); + + p->save(); + p->translate(r.left(), r.top() + r.width()); + p->rotate(-90); + p->translate(-r.left(), -r.top()); + } + + bool floating = false; + bool active = dwOpt->state & State_Active; + QColor inactiveCaptionTextColor = d->inactiveCaptionText; + if (dwOpt->movable) { + QColor left, right; + + //Titlebar gradient + if (widget && widget->isWindow()) { + floating = true; + if (active) { + left = d->activeCaptionColor; + right = d->activeGradientCaptionColor; + } else { + left = d->inactiveCaptionColor; + right = d->inactiveGradientCaptionColor; + } + QBrush fillBrush(left); + if (left != right) { + QPoint p1(r.x(), r.top() + r.height()/2); + QPoint p2(rect.right(), r.top() + r.height()/2); + QLinearGradient lg(p1, p2); + lg.setColorAt(0, left); + lg.setColorAt(1, right); + fillBrush = lg; + } + p->fillRect(r.adjusted(0, 0, 0, -3), fillBrush); + } + p->setPen(dwOpt->palette.color(QPalette::Light)); + if (!widget || !widget->isWindow()) { + p->drawLine(r.topLeft(), r.topRight()); + p->setPen(dwOpt->palette.color(QPalette::Dark)); + p->drawLine(r.bottomLeft(), r.bottomRight()); } + } + if (!dwOpt->title.isEmpty()) { + QFont oldFont = p->font(); + if (floating) { + QFont font = oldFont; + font.setBold(true); + p->setFont(font); + } + QPalette palette = dwOpt->palette; + palette.setColor(QPalette::Window, inactiveCaptionTextColor); + QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, opt, widget); + if (verticalTitleBar) { + titleRect = QRect(r.left() + rect.bottom() + - titleRect.bottom(), + r.top() + titleRect.left() - rect.left(), + titleRect.height(), titleRect.width()); + } + proxy()->drawItemText(p, titleRect, + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, palette, + dwOpt->state & State_Enabled, dwOpt->title, + floating ? (active ? QPalette::BrightText : QPalette::Window) : QPalette::WindowText); + p->setFont(oldFont); + } + if (verticalTitleBar) + p->restore(); + } + return; +#endif // QT_NO_DOCKWIDGET + default: + QCommonStyle::drawControl(ce, opt, p, widget); + } +} + +/*! \reimp */ +QRect QWindowsStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *w) const +{ + QRect r; + switch (sr) { + case SE_SliderFocusRect: + case SE_ToolBoxTabContents: + r = visualRect(opt->direction, opt->rect, opt->rect); + break; + case SE_DockWidgetTitleBarText: { + r = QCommonStyle::subElementRect(sr, opt, w); + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(opt); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + int m = proxy()->pixelMetric(PM_DockWidgetTitleMargin, opt, w); + if (verticalTitleBar) { + r.adjust(0, 0, 0, -m); + } else { + if (opt->direction == Qt::LeftToRight) + r.adjust(m, 0, 0, 0); + else + r.adjust(0, 0, -m, 0); + } + break; + } + case SE_ProgressBarContents: + r = QCommonStyle::subElementRect(SE_ProgressBarGroove, opt, w); + r.adjust(3, 3, -3, -3); + break; + default: + r = QCommonStyle::subElementRect(sr, opt, w); + } + return r; +} + +#ifdef QT3_SUPPORT +Q_GLOBAL_STATIC_WITH_ARGS(QBitmap, globalVerticalLine, (1, 129)) +Q_GLOBAL_STATIC_WITH_ARGS(QBitmap, globalHorizontalLine, (128, 1)) +#endif + +/*! \reimp */ +void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + QPainter *p, const QWidget *widget) const +{ + switch (cc) { +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget); + int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); + int ticks = slider->tickPosition; + QRect groove = proxy()->subControlRect(CC_Slider, slider, SC_SliderGroove, widget); + QRect handle = proxy()->subControlRect(CC_Slider, slider, SC_SliderHandle, widget); + + if ((slider->subControls & SC_SliderGroove) && groove.isValid()) { + int mid = thickness / 2; + + if (ticks & QSlider::TicksAbove) + mid += len / 8; + if (ticks & QSlider::TicksBelow) + mid -= len / 8; + + p->setPen(slider->palette.shadow().color()); + if (slider->orientation == Qt::Horizontal) { + qDrawWinPanel(p, groove.x(), groove.y() + mid - 2, + groove.width(), 4, slider->palette, true); + p->drawLine(groove.x() + 1, groove.y() + mid - 1, + groove.x() + groove.width() - 3, groove.y() + mid - 1); + } else { + qDrawWinPanel(p, groove.x() + mid - 2, groove.y(), + 4, groove.height(), slider->palette, true); + p->drawLine(groove.x() + mid - 1, groove.y() + 1, + groove.x() + mid - 1, groove.y() + groove.height() - 3); + } + } + + if (slider->subControls & SC_SliderTickmarks) { + QStyleOptionSlider tmpSlider = *slider; + tmpSlider.subControls = SC_SliderTickmarks; + QCommonStyle::drawComplexControl(cc, &tmpSlider, p, widget); + } + + if (slider->subControls & SC_SliderHandle) { + // 4444440 + // 4333310 + // 4322210 + // 4322210 + // 4322210 + // 4322210 + // *43210* + // **410** + // ***0*** + const QColor c0 = slider->palette.shadow().color(); + const QColor c1 = slider->palette.dark().color(); + // const QColor c2 = g.button(); + const QColor c3 = slider->palette.midlight().color(); + const QColor c4 = slider->palette.light().color(); + QBrush handleBrush; + + if (slider->state & State_Enabled) { + handleBrush = slider->palette.color(QPalette::Button); + } else { + handleBrush = QBrush(slider->palette.color(QPalette::Button), + Qt::Dense4Pattern); + } + + + int x = handle.x(), y = handle.y(), + wi = handle.width(), he = handle.height(); + + int x1 = x; + int x2 = x+wi-1; + int y1 = y; + int y2 = y+he-1; + + Qt::Orientation orient = slider->orientation; + bool tickAbove = slider->tickPosition == QSlider::TicksAbove; + bool tickBelow = slider->tickPosition == QSlider::TicksBelow; + + if (slider->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*slider); + fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + + if ((tickAbove && tickBelow) || (!tickAbove && !tickBelow)) { + Qt::BGMode oldMode = p->backgroundMode(); + p->setBackgroundMode(Qt::OpaqueMode); + qDrawWinButton(p, QRect(x, y, wi, he), slider->palette, false, + &handleBrush); + p->setBackgroundMode(oldMode); + return; + } + + QSliderDirection dir; + + if (orient == Qt::Horizontal) + if (tickAbove) + dir = SlUp; + else + dir = SlDown; + else + if (tickAbove) + dir = SlLeft; + else + dir = SlRight; + + QPolygon a; + + int d = 0; + switch (dir) { + case SlUp: + y1 = y1 + wi/2; + d = (wi + 1) / 2 - 1; + a.setPoints(5, x1,y1, x1,y2, x2,y2, x2,y1, x1+d,y1-d); + break; + case SlDown: + y2 = y2 - wi/2; + d = (wi + 1) / 2 - 1; + a.setPoints(5, x1,y1, x1,y2, x1+d,y2+d, x2,y2, x2,y1); + break; + case SlLeft: + d = (he + 1) / 2 - 1; + x1 = x1 + he/2; + a.setPoints(5, x1,y1, x1-d,y1+d, x1,y2, x2,y2, x2,y1); + break; + case SlRight: + d = (he + 1) / 2 - 1; + x2 = x2 - he/2; + a.setPoints(5, x1,y1, x1,y2, x2,y2, x2+d,y1+d, x2,y1); + break; + } + + QBrush oldBrush = p->brush(); + p->setPen(Qt::NoPen); + p->setBrush(handleBrush); + Qt::BGMode oldMode = p->backgroundMode(); + p->setBackgroundMode(Qt::OpaqueMode); + p->drawRect(x1, y1, x2-x1+1, y2-y1+1); + p->drawPolygon(a); + p->setBrush(oldBrush); + p->setBackgroundMode(oldMode); + + if (dir != SlUp) { + p->setPen(c4); + p->drawLine(x1, y1, x2, y1); + p->setPen(c3); + p->drawLine(x1, y1+1, x2, y1+1); + } + if (dir != SlLeft) { + p->setPen(c3); + p->drawLine(x1+1, y1+1, x1+1, y2); + p->setPen(c4); + p->drawLine(x1, y1, x1, y2); + } + if (dir != SlRight) { + p->setPen(c0); + p->drawLine(x2, y1, x2, y2); + p->setPen(c1); + p->drawLine(x2-1, y1+1, x2-1, y2-1); + } + if (dir != SlDown) { + p->setPen(c0); + p->drawLine(x1, y2, x2, y2); + p->setPen(c1); + p->drawLine(x1+1, y2-1, x2-1, y2-1); + } + + switch (dir) { + case SlUp: + p->setPen(c4); + p->drawLine(x1, y1, x1+d, y1-d); + p->setPen(c0); + d = wi - d - 1; + p->drawLine(x2, y1, x2-d, y1-d); + d--; + p->setPen(c3); + p->drawLine(x1+1, y1, x1+1+d, y1-d); + p->setPen(c1); + p->drawLine(x2-1, y1, x2-1-d, y1-d); + break; + case SlDown: + p->setPen(c4); + p->drawLine(x1, y2, x1+d, y2+d); + p->setPen(c0); + d = wi - d - 1; + p->drawLine(x2, y2, x2-d, y2+d); + d--; + p->setPen(c3); + p->drawLine(x1+1, y2, x1+1+d, y2+d); + p->setPen(c1); + p->drawLine(x2-1, y2, x2-1-d, y2+d); + break; + case SlLeft: + p->setPen(c4); + p->drawLine(x1, y1, x1-d, y1+d); + p->setPen(c0); + d = he - d - 1; + p->drawLine(x1, y2, x1-d, y2-d); + d--; + p->setPen(c3); + p->drawLine(x1, y1+1, x1-d, y1+1+d); + p->setPen(c1); + p->drawLine(x1, y2-1, x1-d, y2-1-d); + break; + case SlRight: + p->setPen(c4); + p->drawLine(x2, y1, x2+d, y1+d); + p->setPen(c0); + d = he - d - 1; + p->drawLine(x2, y2, x2+d, y2-d); + d--; + p->setPen(c3); + p->drawLine(x2, y1+1, x2+d, y1+1+d); + p->setPen(c1); + p->drawLine(x2, y2-1, x2+d, y2-1-d); + break; + } + } + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_SCROLLBAR + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(opt)) { + QStyleOptionSlider newScrollbar = *scrollbar; + if (scrollbar->minimum == scrollbar->maximum) + newScrollbar.state &= ~State_Enabled; //do not draw the slider. + QCommonStyle::drawComplexControl(cc, &newScrollbar, p, widget); + } + break; +#endif // QT_NO_SCROLLBAR +#ifdef QT3_SUPPORT + case CC_Q3ListView: + if (const QStyleOptionQ3ListView *lv = qstyleoption_cast(opt)) { + int i; + if (lv->subControls & SC_Q3ListView) + QCommonStyle::drawComplexControl(cc, lv, p, widget); + if (lv->subControls & (SC_Q3ListViewBranch | SC_Q3ListViewExpand)) { + if (lv->items.isEmpty()) + break; + QStyleOptionQ3ListViewItem item = lv->items.at(0); + int y = lv->rect.y(); + int c; + int dotoffset = 0; + QPolygon dotlines; + if ((lv->activeSubControls & SC_All) && (lv->subControls & SC_Q3ListViewExpand)) { + c = 2; + dotlines.resize(2); + dotlines[0] = QPoint(lv->rect.right(), lv->rect.top()); + dotlines[1] = QPoint(lv->rect.right(), lv->rect.bottom()); + } else { + int linetop = 0, linebot = 0; + // each branch needs at most two lines, ie. four end points + dotoffset = (item.itemY + item.height - y) % 2; + dotlines.resize(item.childCount * 4); + c = 0; + + // skip the stuff above the exposed rectangle + for (i = 1; i < lv->items.size(); ++i) { + QStyleOptionQ3ListViewItem child = lv->items.at(i); + if (child.height + y > 0) + break; + y += child.totalHeight; + } + int bx = lv->rect.width() / 2; + + // paint stuff in the magical area + while (i < lv->items.size() && y < lv->rect.height()) { + QStyleOptionQ3ListViewItem child = lv->items.at(i); + if (child.features & QStyleOptionQ3ListViewItem::Visible) { + int lh; + if (!(item.features & QStyleOptionQ3ListViewItem::MultiLine)) + lh = child.height; + else + lh = p->fontMetrics().height() + 2 * lv->itemMargin; + lh = qMax(lh, QApplication::globalStrut().height()); + if (lh % 2 > 0) + ++lh; + linebot = y + lh / 2; + if (child.features & QStyleOptionQ3ListViewItem::Expandable + || (child.childCount > 0 && child.height > 0)) { + // needs a box + p->setPen(lv->palette.mid().color()); + p->drawRect(bx - 4, linebot - 4, 8, 8); + // plus or minus + p->setPen(lv->palette.text().color()); + p->drawLine(bx - 2, linebot, bx + 2, linebot); + if (!(child.state & State_Open)) + p->drawLine(bx, linebot - 2, bx, linebot + 2); + // dotlinery + p->setPen(lv->palette.mid().color()); + dotlines[c++] = QPoint(bx, linetop); + dotlines[c++] = QPoint(bx, linebot - 4); + dotlines[c++] = QPoint(bx + 5, linebot); + dotlines[c++] = QPoint(lv->rect.width(), linebot); + linetop = linebot + 5; + } else { + // just dotlinery + dotlines[c++] = QPoint(bx+1, linebot -1); + dotlines[c++] = QPoint(lv->rect.width(), linebot -1); + } + y += child.totalHeight; + } + ++i; + } + + // Expand line height to edge of rectangle if there's any + // visible child below + while (i < lv->items.size() && lv->items.at(i).height <= 0) + ++i; + if (i < lv->items.size()) + linebot = lv->rect.height(); + + if (linetop < linebot) { + dotlines[c++] = QPoint(bx, linetop); + dotlines[c++] = QPoint(bx, linebot); + } + } + p->setPen(lv->palette.text().color()); + QBitmap *verticalLine = globalVerticalLine(); + QBitmap *horizontalLine = globalHorizontalLine(); + static bool isInit = false; + if (!isInit) { + isInit = true; + // make 128*1 and 1*128 bitmaps that can be used for + // drawing the right sort of lines. + verticalLine->clear(); + horizontalLine->clear(); + QPolygon a(64); + QPainter p; + p.begin(verticalLine); + for(i = 0; i < 64; ++i) + a.setPoint(i, 0, i * 2 + 1); + p.setPen(Qt::color1); + p.drawPoints(a); + p.end(); + QApplication::flush(); + verticalLine->setMask(*verticalLine); + p.begin(horizontalLine); + for(i = 0; i < 64; ++i) + a.setPoint(i, i * 2 + 1, 0); + p.setPen(Qt::color1); + p.drawPoints(a); + p.end(); + QApplication::flush(); + horizontalLine->setMask(*horizontalLine); + } + + int line; // index into dotlines + if (lv->subControls & SC_Q3ListViewBranch) for(line = 0; line < c; line += 2) { + // assumptions here: lines are horizontal or vertical. + // lines always start with the numerically lowest + // coordinate. + + // point ... relevant coordinate of current point + // end ..... same coordinate of the end of the current line + // other ... the other coordinate of the current point/line + if (dotlines[line].y() == dotlines[line+1].y()) { + int end = dotlines[line + 1].x(); + int point = dotlines[line].x(); + int other = dotlines[line].y(); + while (point < end) { + int i = 128; + if (i + point > end) + i = end-point; + p->drawPixmap(point, other, *horizontalLine, 0, 0, i, 1); + point += i; + } + } else { + int end = dotlines[line + 1].y(); + int point = dotlines[line].y(); + int other = dotlines[line].x(); + int pixmapoffset = ((point & 1) != dotoffset) ? 1 : 0; + while(point < end) { + int i = 128; + if (i + point > end) + i = end-point; + p->drawPixmap(other, point, *verticalLine, 0, pixmapoffset, 1, i); + point += i; + } + } + } + } + } + break; +#endif // QT3_SUPPORT +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(opt)) { + QBrush editBrush = cmb->palette.brush(QPalette::Base); + if ((cmb->subControls & SC_ComboBoxFrame)) { + if (cmb->frame) { + QPalette shadePal = opt->palette; + shadePal.setColor(QPalette::Midlight, shadePal.button().color()); + qDrawWinPanel(p, opt->rect, shadePal, true, &editBrush); + } + else { + p->fillRect(opt->rect, editBrush); + } + } + if (cmb->subControls & SC_ComboBoxArrow) { + State flags = State_None; + + QRect ar = proxy()->subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget); + bool sunkenArrow = cmb->activeSubControls == SC_ComboBoxArrow + && cmb->state & State_Sunken; + if (sunkenArrow) { + p->setPen(cmb->palette.dark().color()); + p->setBrush(cmb->palette.brush(QPalette::Button)); + p->drawRect(ar.adjusted(0,0,-1,-1)); + } else { + // Make qDrawWinButton use the right colors for drawing the shade of the button + QPalette pal(cmb->palette); + pal.setColor(QPalette::Button, cmb->palette.light().color()); + pal.setColor(QPalette::Light, cmb->palette.button().color()); + qDrawWinButton(p, ar, pal, false, + &cmb->palette.brush(QPalette::Button)); + } + + ar.adjust(2, 2, -2, -2); + if (opt->state & State_Enabled) + flags |= State_Enabled; + if (opt->state & State_HasFocus) + flags |= State_HasFocus; + + if (sunkenArrow) + flags |= State_Sunken; + QStyleOption arrowOpt(0); + arrowOpt.rect = ar.adjusted(1, 1, -1, -1); + arrowOpt.palette = cmb->palette; + arrowOpt.state = flags; + proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); + } + + if (cmb->subControls & SC_ComboBoxEditField) { + QRect re = proxy()->subControlRect(CC_ComboBox, cmb, SC_ComboBoxEditField, widget); + if (cmb->state & State_HasFocus && !cmb->editable) + p->fillRect(re.x(), re.y(), re.width(), re.height(), + cmb->palette.brush(QPalette::Highlight)); + + if (cmb->state & State_HasFocus) { + p->setPen(cmb->palette.highlightedText().color()); + p->setBackground(cmb->palette.highlight()); + + } else { + p->setPen(cmb->palette.text().color()); + p->setBackground(cmb->palette.background()); + } + + if (cmb->state & State_HasFocus && !cmb->editable) { + QStyleOptionFocusRect focus; + focus.QStyleOption::operator=(*cmb); + focus.rect = subElementRect(SE_ComboBoxFocusRect, cmb, widget); + focus.state |= State_FocusAtBorder; + focus.backgroundColor = cmb->palette.highlight().color(); + proxy()->drawPrimitive(PE_FrameFocusRect, &focus, p, widget); + } + } + } + break; +#endif // QT_NO_COMBOBOX +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *sb = qstyleoption_cast(opt)) { + QStyleOptionSpinBox copy = *sb; + PrimitiveElement pe; + bool enabled = opt->state & State_Enabled; + if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) { + QBrush editBrush = sb->palette.brush(QPalette::Base); + QRect r = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget); + QPalette shadePal = sb->palette; + shadePal.setColor(QPalette::Midlight, shadePal.button().color()); + qDrawWinPanel(p, r, shadePal, true, &editBrush); + } + + QPalette shadePal(opt->palette); + shadePal.setColor(QPalette::Button, opt->palette.light().color()); + shadePal.setColor(QPalette::Light, opt->palette.button().color()); + + if (sb->subControls & SC_SpinBoxUp) { + copy.subControls = SC_SpinBoxUp; + QPalette pal2 = sb->palette; + if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled)) { + pal2.setCurrentColorGroup(QPalette::Disabled); + copy.state &= ~State_Enabled; + } + + copy.palette = pal2; + + if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken)) { + copy.state |= State_On; + copy.state |= State_Sunken; + } else { + copy.state |= State_Raised; + copy.state &= ~State_Sunken; + } + pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus + : PE_IndicatorSpinUp); + + copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget); + qDrawWinButton(p, copy.rect, shadePal, copy.state & (State_Sunken | State_On), + ©.palette.brush(QPalette::Button)); + copy.rect.adjust(4, 1, -5, -1); + if ((!enabled || !(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled)) + && proxy()->styleHint(SH_EtchDisabledText, opt, widget) ) + { + QStyleOptionSpinBox lightCopy = copy; + lightCopy.rect.adjust(1, 1, 1, 1); + lightCopy.palette.setBrush(QPalette::ButtonText, copy.palette.light()); + proxy()->drawPrimitive(pe, &lightCopy, p, widget); + } + proxy()->drawPrimitive(pe, ©, p, widget); + } + + if (sb->subControls & SC_SpinBoxDown) { + copy.subControls = SC_SpinBoxDown; + copy.state = sb->state; + QPalette pal2 = sb->palette; + if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled)) { + pal2.setCurrentColorGroup(QPalette::Disabled); + copy.state &= ~State_Enabled; + } + copy.palette = pal2; + + if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken)) { + copy.state |= State_On; + copy.state |= State_Sunken; + } else { + copy.state |= State_Raised; + copy.state &= ~State_Sunken; + } + pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus + : PE_IndicatorSpinDown); + + copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget); + qDrawWinButton(p, copy.rect, shadePal, copy.state & (State_Sunken | State_On), + ©.palette.brush(QPalette::Button)); + copy.rect.adjust(4, 0, -5, -1); + if ((!enabled || !(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled)) + && proxy()->styleHint(SH_EtchDisabledText, opt, widget) ) + { + QStyleOptionSpinBox lightCopy = copy; + lightCopy.rect.adjust(1, 1, 1, 1); + lightCopy.palette.setBrush(QPalette::ButtonText, copy.palette.light()); + proxy()->drawPrimitive(pe, &lightCopy, p, widget); + } + proxy()->drawPrimitive(pe, ©, p, widget); + } + } + break; +#endif // QT_NO_SPINBOX + + default: + QCommonStyle::drawComplexControl(cc, opt, p, widget); + } +} + +/*! \reimp */ +QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, + const QSize &csz, const QWidget *widget) const +{ + QSize sz(csz); + switch (ct) { + case CT_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { + sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); + int w = sz.width(), + h = sz.height(); + int defwidth = 0; + if (btn->features & QStyleOptionButton::AutoDefaultButton) + defwidth = 2 * proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget); + int minwidth = int(QStyleHelper::dpiScaled(75.)); + int minheight = int(QStyleHelper::dpiScaled(23.)); + +#ifndef QT_QWS_SMALL_PUSHBUTTON + if (w < minwidth + defwidth && !btn->text.isEmpty()) + w = minwidth + defwidth; + if (h < minheight + defwidth) + h = minheight + defwidth; +#endif + sz = QSize(w, h); + } + break; +#ifndef QT_NO_MENU + case CT_MenuItem: + if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { + int w = sz.width(); + sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); + + if (mi->menuItemType == QStyleOptionMenuItem::Separator) { + sz = QSize(10, QWindowsStylePrivate::windowsSepHeight); + } + else if (mi->icon.isNull()) { + sz.setHeight(sz.height() - 2); + w -= 6; + } + + if (mi->menuItemType != QStyleOptionMenuItem::Separator && !mi->icon.isNull()) { + int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); + sz.setHeight(qMax(sz.height(), + mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + + 2 * QWindowsStylePrivate::windowsItemFrame)); + } + int maxpmw = mi->maxIconWidth; + int tabSpacing = 20; + if (mi->text.contains(QLatin1Char('\t'))) + w += tabSpacing; + else if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) + w += 2 * QWindowsStylePrivate::windowsArrowHMargin; + else if (mi->menuItemType == QStyleOptionMenuItem::DefaultItem) { + // adjust the font and add the difference in size. + // it would be better if the font could be adjusted in the initStyleOption qmenu func!! + QFontMetrics fm(mi->font); + QFont fontBold = mi->font; + fontBold.setBold(true); + QFontMetrics fmBold(fontBold); + w += fmBold.width(mi->text) - fm.width(mi->text); + } + + int checkcol = qMax(maxpmw, QWindowsStylePrivate::windowsCheckMarkWidth); // Windows always shows a check column + w += checkcol; + w += int(QWindowsStylePrivate::windowsRightBorder) + 10; + sz.setWidth(w); + } + break; +#endif // QT_NO_MENU +#ifndef QT_NO_MENUBAR + case CT_MenuBarItem: + if (!sz.isEmpty()) + sz += QSize(QWindowsStylePrivate::windowsItemHMargin * 4, QWindowsStylePrivate::windowsItemVMargin * 2); + break; +#endif + // Otherwise, fall through + case CT_ToolButton: + if (qstyleoption_cast(opt)) + return sz += QSize(7, 6); + // Otherwise, fall through + + default: + sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); + } + return sz; +} + +/*! + \internal +*/ +QIcon QWindowsStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget) const +{ + QIcon icon; + QPixmap pixmap; +#ifdef Q_OS_WIN + switch (standardIcon) { + case SP_FileDialogNewFolder: + { + for (int size = 16 ; size <= 32 ; size += 16) { + pixmap = loadIconFromShell32(319, size); + icon.addPixmap(pixmap, QIcon::Normal); + } + break; + } + case SP_DirHomeIcon: + { + for (int size = 16 ; size <= 32 ; size += 16) { + pixmap = loadIconFromShell32(235, size); + icon.addPixmap(pixmap, QIcon::Normal); + } + break; + } + case SP_DirIcon: + for (int size = 16 ; size <= 32 ; size += 16) { + pixmap = loadIconFromShell32(4, size); + icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off); + pixmap = loadIconFromShell32(5, size); + icon.addPixmap(pixmap, QIcon::Normal, QIcon::On); + } + break; + case SP_DirLinkIcon: + for (int size = 16 ; size <= 32 ; size += 16) { + QPixmap link = loadIconFromShell32(30, size); + pixmap = loadIconFromShell32(4, size); + if (!pixmap.isNull() && !link.isNull()) { + QPainter painter(&pixmap); + painter.drawPixmap(0, 0, size, size, link); + icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off); + } + link = loadIconFromShell32(30, size); + pixmap = loadIconFromShell32(5, size); + if (!pixmap.isNull() && !link.isNull()) { + QPainter painter(&pixmap); + painter.drawPixmap(0, 0, size, size, link); + icon.addPixmap(pixmap, QIcon::Normal, QIcon::On); + } + } + break; + case SP_FileIcon: + for (int size = 16 ; size <= 32 ; size += 16) { + pixmap = loadIconFromShell32(1, size); + icon.addPixmap(pixmap, QIcon::Normal); + } + break; + case SP_ComputerIcon: + for (int size = 16 ; size <= 32 ; size += 16) { + pixmap = loadIconFromShell32(16, size); + icon.addPixmap(pixmap, QIcon::Normal); + } + break; + + case SP_DesktopIcon: + for (int size = 16 ; size <= 32 ; size += 16) { + pixmap = loadIconFromShell32(35, size); + icon.addPixmap(pixmap, QIcon::Normal); + } + break; + case SP_DriveCDIcon: + case SP_DriveDVDIcon: + for (int size = 16 ; size <= 32 ; size += 16) { + pixmap = loadIconFromShell32(12, size); + icon.addPixmap(pixmap, QIcon::Normal); + } + break; + case SP_DriveNetIcon: + for (int size = 16 ; size <= 32 ; size += 16) { + pixmap = loadIconFromShell32(10, size); + icon.addPixmap(pixmap, QIcon::Normal); + } + break; + case SP_DriveHDIcon: + for (int size = 16 ; size <= 32 ; size += 16) { + pixmap = loadIconFromShell32(9, size); + icon.addPixmap(pixmap, QIcon::Normal); + } + break; + case SP_DriveFDIcon: + for (int size = 16 ; size <= 32 ; size += 16) { + pixmap = loadIconFromShell32(7, size); + icon.addPixmap(pixmap, QIcon::Normal); + } + break; + case SP_FileLinkIcon: + for (int size = 16 ; size <= 32 ; size += 16) { + QPixmap link; + link = loadIconFromShell32(30, size); + pixmap = loadIconFromShell32(1, size); + if (!pixmap.isNull() && !link.isNull()) { + QPainter painter(&pixmap); + painter.drawPixmap(0, 0, size, size, link); + icon.addPixmap(pixmap, QIcon::Normal); + } + } + break; + case SP_VistaShield: + { + if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA + && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based + && pSHGetStockIconInfo) + { + icon.addPixmap(proxy()->standardPixmap(SP_VistaShield, option, widget)); //fetches small icon + QSHSTOCKICONINFO iconInfo; //append large icon + memset(&iconInfo, 0, sizeof(iconInfo)); + iconInfo.cbSize = sizeof(iconInfo); + if (pSHGetStockIconInfo(_SIID_SHIELD, _SHGFI_ICON | _SHGFI_LARGEICON, &iconInfo) == S_OK) { + icon.addPixmap(QPixmap::fromWinHICON(iconInfo.hIcon)); + DestroyIcon(iconInfo.hIcon); + } + } + } + break; + default: + break; + } +#endif + + if (icon.isNull()) + icon = QCommonStyle::standardIconImplementation(standardIcon, option, widget); + return icon; +} + + + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_WINDOWS diff --git a/src/widgets/styles/qwindowsstyle.h b/src/widgets/styles/qwindowsstyle.h new file mode 100644 index 0000000000..99f64fcb05 --- /dev/null +++ b/src/widgets/styles/qwindowsstyle.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSSTYLE_H +#define QWINDOWSSTYLE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_STYLE_WINDOWS) + +class QWindowsStylePrivate; + +class Q_GUI_EXPORT QWindowsStyle : public QCommonStyle +{ + Q_OBJECT +public: + QWindowsStyle(); + ~QWindowsStyle(); + + void polish(QApplication*); + void unpolish(QApplication*); + + void polish(QWidget*); + void unpolish(QWidget*); + + void polish(QPalette &); + + void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const; + void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, + const QWidget *w = 0) const; + QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const; + void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, + const QWidget *w = 0) const; + QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, + const QSize &contentsSize, const QWidget *widget = 0) const; + + int pixelMetric(PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0) const; + + int styleHint(StyleHint hint, const QStyleOption *opt = 0, const QWidget *widget = 0, + QStyleHintReturn *returnData = 0) const; + + QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget = 0) const; + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget = 0) const; + +protected: + bool eventFilter(QObject *o, QEvent *e); + void timerEvent(QTimerEvent *event); + QWindowsStyle(QWindowsStylePrivate &dd); + +private: + Q_DISABLE_COPY(QWindowsStyle) + Q_DECLARE_PRIVATE(QWindowsStyle) + void *reserved; +}; + +#endif // QT_NO_STYLE_WINDOWS + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QWINDOWSSTYLE_H diff --git a/src/widgets/styles/qwindowsstyle_p.h b/src/widgets/styles/qwindowsstyle_p.h new file mode 100644 index 0000000000..a10f2baffd --- /dev/null +++ b/src/widgets/styles/qwindowsstyle_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSSTYLE_P_H +#define QWINDOWSSTYLE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qwindowsstyle.h" +#include "qcommonstyle_p.h" + +#ifndef QT_NO_STYLE_WINDOWS +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QTime; +class QProgressBar; + +class QWindowsStylePrivate : public QCommonStylePrivate +{ + Q_DECLARE_PUBLIC(QWindowsStyle) +public: + QWindowsStylePrivate(); + bool hasSeenAlt(const QWidget *widget) const; + bool altDown() const { return alt_down; } + bool alt_down; + QList seenAlt; + int menuBarTimer; + + QList bars; + int animationFps; + int animateTimer; + QElapsedTimer startTime; + int animateStep; + QColor inactiveCaptionText; + QColor activeCaptionColor; + QColor activeGradientCaptionColor; + QColor inactiveCaptionColor; + QColor inactiveGradientCaptionColor; + + enum { + windowsItemFrame = 2, // menu item frame width + windowsSepHeight = 9, // separator item height + windowsItemHMargin = 3, // menu item hor text margin + windowsItemVMargin = 2, // menu item ver text margin + windowsArrowHMargin = 6, // arrow horizontal margin + windowsRightBorder = 15, // right border on windows + windowsCheckMarkWidth = 12 // checkmarks width on windows + }; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_WINDOWS + +#endif //QWINDOWSSTYLE_P_H diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp new file mode 100644 index 0000000000..7f1a3ab678 --- /dev/null +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -0,0 +1,2670 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsvistastyle.h" +#include "qwindowsvistastyle_p.h" +#include +#include + +#if !defined(QT_NO_STYLE_WINDOWSVISTA) || defined(QT_PLUGIN) + +QT_BEGIN_NAMESPACE + +static const int windowsItemFrame = 2; // menu item frame width +static const int windowsItemHMargin = 3; // menu item hor text margin +static const int windowsItemVMargin = 4; // menu item ver text margin +static const int windowsArrowHMargin = 6; // arrow horizontal margin +static const int windowsRightBorder = 15; // right border on windows + +#ifndef TMT_CONTENTMARGINS +# define TMT_CONTENTMARGINS 3602 +#endif +#ifndef TMT_SIZINGMARGINS +# define TMT_SIZINGMARGINS 3601 +#endif +#ifndef LISS_NORMAL +# define LISS_NORMAL 1 +# define LISS_HOT 2 +# define LISS_SELECTED 3 +# define LISS_DISABLED 4 +# define LISS_SELECTEDNOTFOCUS 5 +# define LISS_HOTSELECTED 6 +#endif +#ifndef BP_COMMANDLINK +# define BP_COMMANDLINK 6 +# define BP_COMMANDLINKGLYPH 7 +# define CMDLGS_NORMAL 1 +# define CMDLGS_HOT 2 +# define CMDLGS_PRESSED 3 +# define CMDLGS_DISABLED 4 +#endif + +// Runtime resolved theme engine function calls + + +typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); +typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); +typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); +typedef HRESULT (WINAPI *PtrCloseThemeData)(HTHEME hTheme); +typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); +typedef HRESULT (WINAPI *PtrDrawThemeBackgroundEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions); +typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars); +typedef HRESULT (WINAPI *PtrGetThemeBool)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT BOOL *pfVal); +typedef HRESULT (WINAPI *PtrGetThemeColor)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor); +typedef HRESULT (WINAPI *PtrGetThemeEnumValue)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); +typedef HRESULT (WINAPI *PtrGetThemeFilename)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars); +typedef HRESULT (WINAPI *PtrGetThemeFont)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT LOGFONT *pFont); +typedef HRESULT (WINAPI *PtrGetThemeInt)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); +typedef HRESULT (WINAPI *PtrGetThemeIntList)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT INTLIST *pIntList); +typedef HRESULT (WINAPI *PtrGetThemeMargins)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins); +typedef HRESULT (WINAPI *PtrGetThemeMetric)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT int *piVal); +typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); +typedef HRESULT (WINAPI *PtrGetThemePosition)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT POINT *pPoint); +typedef HRESULT (WINAPI *PtrGetThemeRect)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT RECT *pRect); +typedef HRESULT (WINAPI *PtrGetThemeString)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars); +typedef HRESULT (WINAPI *PtrGetThemeTransitionDuration)(HTHEME hTheme, int iPartId, int iStateFromId, int iStateToId, int iPropId, int *pDuration); +typedef HRESULT (WINAPI *PtrIsThemePartDefined)(HTHEME hTheme, int iPartId, int iStateId); +typedef HRESULT (WINAPI *PtrSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); +typedef HRESULT (WINAPI *PtrGetThemePropertyOrigin)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin); + +static PtrIsThemePartDefined pIsThemePartDefined = 0; +static PtrOpenThemeData pOpenThemeData = 0; +static PtrCloseThemeData pCloseThemeData = 0; +static PtrDrawThemeBackground pDrawThemeBackground = 0; +static PtrDrawThemeBackgroundEx pDrawThemeBackgroundEx = 0; +static PtrGetCurrentThemeName pGetCurrentThemeName = 0; +static PtrGetThemeBool pGetThemeBool = 0; +static PtrGetThemeColor pGetThemeColor = 0; +static PtrGetThemeEnumValue pGetThemeEnumValue = 0; +static PtrGetThemeFilename pGetThemeFilename = 0; +static PtrGetThemeFont pGetThemeFont = 0; +static PtrGetThemeInt pGetThemeInt = 0; +static PtrGetThemeIntList pGetThemeIntList = 0; +static PtrGetThemeMargins pGetThemeMargins = 0; +static PtrGetThemeMetric pGetThemeMetric = 0; +static PtrGetThemePartSize pGetThemePartSize = 0; +static PtrGetThemePosition pGetThemePosition = 0; +static PtrGetThemeRect pGetThemeRect = 0; +static PtrGetThemeString pGetThemeString = 0; +static PtrGetThemeTransitionDuration pGetThemeTransitionDuration= 0; +static PtrSetWindowTheme pSetWindowTheme = 0; +static PtrGetThemePropertyOrigin pGetThemePropertyOrigin = 0; + +/* \internal + Checks if we should use Vista style , or if we should + fall back to Windows style. +*/ +bool QWindowsVistaStylePrivate::useVista() +{ + return (QWindowsVistaStylePrivate::useXP() && + (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && + QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)); +} + +/*! + \class QWindowsVistaStyle + \brief The QWindowsVistaStyle class provides a look and feel suitable for applications on Microsoft Windows Vista. + \since 4.3 + \ingroup appearance + + \warning This style is only available on the Windows Vista platform + because it makes use of Windows Vista's style engine. + + \sa QMacStyle, QWindowsXPStyle, QPlastiqueStyle, QCleanlooksStyle, QMotifStyle +*/ + +/*! + Constructs a QWindowsVistaStyle object. +*/ +QWindowsVistaStyle::QWindowsVistaStyle() + : QWindowsXPStyle(*new QWindowsVistaStylePrivate) +{ +} + +//convert Qt state flags to uxtheme button states +static int buttonStateId(int flags, int partId) +{ + int stateId = 0; + if (partId == BP_RADIOBUTTON || partId == BP_CHECKBOX) { + if (!(flags & QStyle::State_Enabled)) + stateId = RBS_UNCHECKEDDISABLED; + else if (flags & QStyle::State_Sunken) + stateId = RBS_UNCHECKEDPRESSED; + else if (flags & QStyle::State_MouseOver) + stateId = RBS_UNCHECKEDHOT; + else + stateId = RBS_UNCHECKEDNORMAL; + + if (flags & QStyle::State_On) + stateId += RBS_CHECKEDNORMAL-1; + + } else if (partId == BP_PUSHBUTTON) { + if (!(flags & QStyle::State_Enabled)) + stateId = PBS_DISABLED; + else if (flags & (QStyle::State_Sunken | QStyle::State_On)) + stateId = PBS_PRESSED; + else if (flags & QStyle::State_MouseOver) + stateId = PBS_HOT; + else + stateId = PBS_NORMAL; + } else { + Q_ASSERT(1); + } + return stateId; +} + +void QWindowsVistaAnimation::paint(QPainter *painter, const QStyleOption *option) +{ + Q_UNUSED(option); + Q_UNUSED(painter); +} + +/*! \internal + + Helperfunction to paint the current transition state between two + animation frames. + + The result is a blended image consisting of ((alpha)*_primaryImage) + + ((1-alpha)*_secondaryImage) + +*/ +void QWindowsVistaAnimation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) { + if (_secondaryImage.isNull() || _primaryImage.isNull()) + return; + + if (_tempImage.isNull()) + _tempImage = _secondaryImage; + + const int a = qRound(alpha*256); + const int ia = 256 - a; + const int sw = _primaryImage.width(); + const int sh = _primaryImage.height(); + const int bpl = _primaryImage.bytesPerLine(); + switch(_primaryImage.depth()) { + case 32: + { + uchar *mixed_data = _tempImage.bits(); + const uchar *back_data = _primaryImage.bits(); + const uchar *front_data = _secondaryImage.bits(); + for (int sy = 0; sy < sh; sy++) { + quint32* mixed = (quint32*)mixed_data; + const quint32* back = (const quint32*)back_data; + const quint32* front = (const quint32*)front_data; + for (int sx = 0; sx < sw; sx++) { + quint32 bp = back[sx]; + quint32 fp = front[sx]; + mixed[sx] = qRgba ((qRed(bp)*ia + qRed(fp)*a)>>8, + (qGreen(bp)*ia + qGreen(fp)*a)>>8, + (qBlue(bp)*ia + qBlue(fp)*a)>>8, + (qAlpha(bp)*ia + qAlpha(fp)*a)>>8); + } + mixed_data += bpl; + back_data += bpl; + front_data += bpl; + } + } + default: + break; + } + painter->drawImage(rect, _tempImage); +} + +/*! \internal + Paints a transition state. The result will be a mix between the + initial and final state of the transition, depending on the time + difference between _startTime and current time. +*/ +void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *option) +{ + float alpha = 1.0; + if (_duration > 0) { + QTime current = QTime::currentTime(); + + if (_startTime > current) + _startTime = current; + + int timeDiff = _startTime.msecsTo(current); + alpha = timeDiff/(float)_duration; + if (timeDiff > _duration) { + _running = false; + alpha = 1.0; + } + } + else { + _running = false; + } + drawBlendedImage(painter, option->rect, alpha); +} + +/*! \internal + Paints a pulse. The result will be a mix between the primary and + secondary pulse images depending on the time difference between + _startTime and current time. +*/ +void QWindowsVistaPulse::paint(QPainter *painter, const QStyleOption *option) +{ + float alpha = 1.0; + if (_duration > 0) { + QTime current = QTime::currentTime(); + + if (_startTime > current) + _startTime = current; + + int timeDiff = _startTime.msecsTo(current) % _duration*2; + if (timeDiff > _duration) + timeDiff = _duration*2 - timeDiff; + alpha = timeDiff/(float)_duration; + } else { + _running = false; + } + drawBlendedImage(painter, option->rect, alpha); +} + + +/*! + \internal + + Animations are used for some state transitions on specific widgets. + + Only one running animation can exist for a widget at any specific + time. Animations can be added through + QWindowsVistaStylePrivate::startAnimation(Animation *) and any + existing animation on a widget can be retrieved with + QWindowsVistaStylePrivate::widgetAnimation(Widget *). + + Once an animation has been started, + QWindowsVistaStylePrivate::timerEvent(QTimerEvent *) will + continuously call update() on the widget until it is stopped, + meaning that drawPrimitive will be called many times until the + transition has completed. During this time, the result will be + retrieved by the Animation::paint(...) function and not by the style + itself. + + To determine if a transition should occur, the style needs to know + the previous state of the widget as well as the current one. This is + solved by updating dynamic properties on the widget every time the + function is called. + + Transitions interrupting existing transitions should always be + smooth, so whenever a hover-transition is started on a pulsating + button, it uses the current frame of the pulse-animation as the + starting image for the hover transition. + + */ +void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const +{ + QWindowsVistaStylePrivate *d = const_cast(d_func()); + + int state = option->state; + if (!QWindowsVistaStylePrivate::useVista()) { + QWindowsStyle::drawPrimitive(element, option, painter, widget); + return; + } + + QRect oldRect; + QRect newRect; + + if (widget && d->transitionsEnabled()) + { + /* all widgets that supports state transitions : */ + if ( +#ifndef QT_NO_LINEEDIT + (qobject_cast(widget) && element == PE_FrameLineEdit) || +#endif // QT_NO_LINEEDIT + (qobject_cast(widget)&& element == PE_IndicatorRadioButton) || + (qobject_cast(widget) && element == PE_IndicatorCheckBox) || + (qobject_cast(widget)&& element == PE_IndicatorCheckBox) || + (qobject_cast(widget) && element == PE_PanelButtonBevel) + ) + { + // Retrieve and update the dynamic properties tracking + // the previous state of the widget: + QWidget *w = const_cast (widget); + int oldState = w->property("_q_stylestate").toInt(); + oldRect = w->property("_q_stylerect").toRect(); + newRect = w->rect(); + w->setProperty("_q_stylestate", (int)option->state); + w->setProperty("_q_stylerect", w->rect()); + + bool doTransition = oldState && + ((state & State_Sunken) != (oldState & State_Sunken) || + (state & State_On) != (oldState & State_On) || + (state & State_MouseOver) != (oldState & State_MouseOver)); + + if (oldRect != newRect || + (state & State_Enabled) != (oldState & State_Enabled) || + (state & State_Active) != (oldState & State_Active)) + d->stopAnimation(widget); + +#ifndef QT_NO_LINEEDIT + if (const QLineEdit *edit = qobject_cast(widget)) + if (edit->isReadOnly() && element == PE_FrameLineEdit) // Do not animate read only line edits + doTransition = false; +#endif // QT_NO_LINEEDIT + + if (doTransition) { + + // We create separate images for the initial and final transition states and store them in the + // Transition object. + QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); + QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); + QStyleOption opt = *option; + + opt.rect.setRect(0, 0, option->rect.width(), option->rect.height()); + opt.state = (QStyle::State)oldState; + startImage.fill(0); + QPainter startPainter(&startImage); + + QWindowsVistaAnimation *anim = d->widgetAnimation(widget); + QWindowsVistaTransition *t = new QWindowsVistaTransition; + t->setWidget(w); + + // If we have a running animation on the widget already, we will use that to paint the initial + // state of the new transition, this ensures a smooth transition from a current animation such as a + // pulsating default button into the intended target state. + + if (!anim) + proxy()->drawPrimitive(element, &opt, &startPainter, 0); // Note that the widget pointer is intentionally 0 + else // this ensures that we do not recurse in the animation logic above + anim->paint(&startPainter, &opt); + + d->startAnimation(t); + t->setStartImage(startImage); + + // The end state of the transition is simply the result we would have painted + // if the style was not animated. + + QPainter endPainter(&endImage); + endImage.fill(0); + QStyleOption opt2 = opt; + opt2.state = option->state; + proxy()->drawPrimitive(element, &opt2, &endPainter, 0); // Note that the widget pointer is intentionally 0 + // this ensures that we do not recurse in the animation logic above + t->setEndImage(endImage); + + HTHEME theme; + int partId; + int duration; + int fromState = 0; + int toState = 0; + + //translate state flags to UXTHEME states : + if (element == PE_FrameLineEdit) { + theme = pOpenThemeData(0, L"Edit"); + partId = EP_EDITBORDER_NOSCROLL; + + if (oldState & State_MouseOver) + fromState = ETS_HOT; + else if (oldState & State_HasFocus) + fromState = ETS_FOCUSED; + else + fromState = ETS_NORMAL; + + if (state & State_MouseOver) + toState = ETS_HOT; + else if (state & State_HasFocus) + toState = ETS_FOCUSED; + else + toState = ETS_NORMAL; + + } else { + theme = pOpenThemeData(0, L"Button"); + if (element == PE_IndicatorRadioButton) + partId = BP_RADIOBUTTON; + else if (element == PE_IndicatorCheckBox) + partId = BP_CHECKBOX; + else + partId = BP_PUSHBUTTON; + + fromState = buttonStateId(oldState, partId); + toState = buttonStateId(option->state, partId); + } + + // Retrieve the transition time between the states from the system. + if (theme && pGetThemeTransitionDuration(theme, partId, fromState, toState, + TMT_TRANSITIONDURATIONS, &duration) == S_OK) + { + t->setDuration(duration); + } + t->setStartTime(QTime::currentTime()); + } + } + } // End of animation part + + + QRect rect = option->rect; + + switch (element) { + case PE_IndicatorHeaderArrow: + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + int stateId = HSAS_SORTEDDOWN; + if (header->sortIndicator & QStyleOptionHeader::SortDown) + stateId = HSAS_SORTEDUP; //note that the uxtheme sort down indicator is the inverse of ours + XPThemeData theme(widget, painter, QLatin1String("HEADER"), HP_HEADERSORTARROW, stateId, option->rect); + d->drawBackground(theme); + } + break; + + case PE_IndicatorBranch: + { + XPThemeData theme(d->treeViewHelper(), painter, QLatin1String("TREEVIEW")); + static int decoration_size = 0; + if (theme.isValid() && !decoration_size) { + SIZE size; + pGetThemePartSize(theme.handle(), 0, TVP_HOTGLYPH, GLPS_OPENED, 0, TS_TRUE, &size); + decoration_size = qMax(size.cx, size.cy); + } + int mid_h = option->rect.x() + option->rect.width() / 2; + int mid_v = option->rect.y() + option->rect.height() / 2; + int bef_h = mid_h; + int bef_v = mid_v; + int aft_h = mid_h; + int aft_v = mid_v; + if (option->state & State_Children) { + int delta = decoration_size / 2; + theme.rect = QRect(bef_h - delta, bef_v - delta, decoration_size, decoration_size); + theme.partId = option->state & State_MouseOver ? TVP_HOTGLYPH : TVP_GLYPH; + theme.stateId = option->state & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED; + if (option->direction == Qt::RightToLeft) + theme.mirrorHorizontally = true; + d->drawBackground(theme); + bef_h -= delta + 2; + bef_v -= delta + 2; + aft_h += delta - 2; + aft_v += delta - 2; + } +#if 0 + QBrush brush(option->palette.dark().color(), Qt::Dense4Pattern); + if (option->state & State_Item) { + if (option->direction == Qt::RightToLeft) + painter->fillRect(option->rect.left(), mid_v, bef_h - option->rect.left(), 1, brush); + else + painter->fillRect(aft_h, mid_v, option->rect.right() - aft_h + 1, 1, brush); + } + if (option->state & State_Sibling && option->rect.bottom() > aft_v) + painter->fillRect(mid_h, aft_v, 1, option->rect.bottom() - aft_v + 1, brush); + if (option->state & (State_Open | State_Children | State_Item | State_Sibling) && (bef_v > option->rect.y())) + painter->fillRect(mid_h, option->rect.y(), 1, bef_v - option->rect.y(), brush); +#endif + } + break; + + case PE_PanelButtonBevel: + case PE_IndicatorCheckBox: + case PE_IndicatorRadioButton: + { + if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) { + a->paint(painter, option); + } else { + QWindowsXPStyle::drawPrimitive(element, option, painter, widget); + } + } + break; + + case PE_FrameMenu: + { + int stateId = option->state & State_Active ? MB_ACTIVE : MB_INACTIVE; + XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_POPUPBORDERS, stateId, option->rect); + d->drawBackground(theme); + } + break; + case PE_Frame: +#ifndef QT_NO_TEXTEDIT + if (const QTextEdit *edit = qobject_cast(widget)) { + painter->save(); + int stateId = ETS_NORMAL; + if (!(state & State_Enabled)) + stateId = ETS_DISABLED; + else if (edit->isReadOnly()) + stateId = ETS_READONLY; + else if (state & State_HasFocus) + stateId = ETS_SELECTED; + XPThemeData theme(widget, painter, QLatin1String("EDIT"), EP_EDITBORDER_HVSCROLL, stateId, option->rect); + uint resolve_mask = option->palette.resolve(); + if (resolve_mask & (1 << QPalette::Base)) { + // Since EP_EDITBORDER_HVSCROLL does not us borderfill, theme.noContent cannot be used for clipping + int borderSize = 1; + pGetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize); + QRegion clipRegion = option->rect; + QRegion content = option->rect.adjusted(borderSize, borderSize, -borderSize, -borderSize); + clipRegion ^= content; + painter->setClipRegion(clipRegion); + } + d->drawBackground(theme); + painter->restore(); + } else +#endif // QT_NO_TEXTEDIT + QWindowsXPStyle::drawPrimitive(element, option, painter, widget); + break; + + case PE_PanelLineEdit: + if (const QStyleOptionFrame *panel = qstyleoption_cast(option)) { + QBrush bg; + bool usePalette = false; + bool isEnabled = option->state & State_Enabled; + uint resolve_mask = panel->palette.resolve(); + if (widget) { + //Since spin box and combo box includes a line edit we need to resolve the palette on the parent instead +#ifndef QT_NO_SPINBOX + if (QAbstractSpinBox *spinbox = qobject_cast(widget->parentWidget())) + resolve_mask = spinbox->palette().resolve(); +#endif // QT_NO_SPINBOX + } + if (resolve_mask & (1 << QPalette::Base)) { + // Base color is set for this widget, so use it + bg = panel->palette.brush(QPalette::Base); + usePalette = true; + } + if (usePalette) { + painter->fillRect(panel->rect, bg); + } else { + int partId = EP_BACKGROUND; + int stateId = EBS_NORMAL; + if (!isEnabled) + stateId = EBS_DISABLED; + else if (state & State_ReadOnly) + stateId = EBS_READONLY; + else if (state & State_MouseOver) + stateId = EBS_HOT; + + XPThemeData theme(0, painter, QLatin1String("EDIT"), partId, stateId, rect); + if (!theme.isValid()) { + QWindowsStyle::drawPrimitive(element, option, painter, widget); + return; + } + int bgType; + pGetThemeEnumValue( theme.handle(), + partId, + stateId, + TMT_BGTYPE, + &bgType); + if( bgType == BT_IMAGEFILE ) { + d->drawBackground(theme); + } else { + QBrush fillColor = option->palette.brush(QPalette::Base); + if (!isEnabled) { + PROPERTYORIGIN origin = PO_NOTFOUND; + pGetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin); + // Use only if the fill property comes from our part + if ((origin == PO_PART || origin == PO_STATE)) { + COLORREF bgRef; + pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); + fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef))); + } + } + painter->fillRect(option->rect, fillColor); + } + } + if (panel->lineWidth > 0) + proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget); + return; + } + break; + + case PE_FrameLineEdit: + if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) { + anim->paint(painter, option); + } else { + QPainter *p = painter; + QWidget *parentWidget = 0; + if (widget) { + parentWidget = widget->parentWidget(); + if (parentWidget) + parentWidget = parentWidget->parentWidget(); + } + if (widget && widget->inherits("QLineEdit") + && parentWidget && parentWidget->inherits("QAbstractItemView")) { + // we try to check if this lineedit is a delegate on a QAbstractItemView-derived class. + QPen oldPen = p->pen(); + // Inner white border + p->setPen(QPen(option->palette.base().color(), 1)); + p->drawRect(option->rect.adjusted(1, 1, -2, -2)); + // Outer dark border + p->setPen(QPen(option->palette.shadow().color(), 1)); + p->drawRect(option->rect.adjusted(0, 0, -1, -1)); + p->setPen(oldPen); + return; + } else { + int stateId = ETS_NORMAL; + if (!(state & State_Enabled)) + stateId = ETS_DISABLED; + else if (state & State_ReadOnly) + stateId = ETS_READONLY; + else if (state & State_MouseOver) + stateId = ETS_HOT; + else if (state & State_HasFocus) + stateId = ETS_SELECTED; + XPThemeData theme(widget, painter, QLatin1String("EDIT"), EP_EDITBORDER_NOSCROLL, stateId, option->rect); + painter->save(); + QRegion clipRegion = option->rect; + clipRegion -= option->rect.adjusted(2, 2, -2, -2); + painter->setClipRegion(clipRegion); + d->drawBackground(theme); + painter->restore(); + } + } + break; + + case PE_IndicatorToolBarHandle: + { + XPThemeData theme; + QRect rect; + if (option->state & State_Horizontal) { + theme = XPThemeData(widget, painter, QLatin1String("REBAR"), RP_GRIPPER, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2)); + rect = option->rect.adjusted(0, 1, 0, -2); + rect.setWidth(4); + } else { + theme = XPThemeData(widget, painter, QLatin1String("REBAR"), RP_GRIPPERVERT, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2)); + rect = option->rect.adjusted(1, 0, -1, 0); + rect.setHeight(4); + } + theme.rect = rect; + d->drawBackground(theme); + } + break; + + case PE_IndicatorToolBarSeparator: + { + QPen pen = painter->pen(); + int margin = 3; + painter->setPen(option->palette.background().color().darker(114)); + if (option->state & State_Horizontal) { + int x1 = option->rect.center().x(); + painter->drawLine(QPoint(x1, option->rect.top() + margin), QPoint(x1, option->rect.bottom() - margin)); + } else { + int y1 = option->rect.center().y(); + painter->drawLine(QPoint(option->rect.left() + margin, y1), QPoint(option->rect.right() - margin, y1)); + } + painter->setPen(pen); + } + break; + + case PE_PanelTipLabel: { + XPThemeData theme(widget, painter, QLatin1String("TOOLTIP"), TTP_STANDARD, TTSS_NORMAL, option->rect); + d->drawBackground(theme); + break; + } + + case PE_PanelItemViewItem: + { + const QStyleOptionViewItemV4 *vopt; + const QAbstractItemView *view = qobject_cast(widget); + bool newStyle = true; + + if (qobject_cast(widget)) + newStyle = false; + + if (newStyle && view && (vopt = qstyleoption_cast(option))) { + bool selected = vopt->state & QStyle::State_Selected; + bool hover = vopt->state & QStyle::State_MouseOver; + bool active = vopt->state & QStyle::State_Active; + + if (vopt->features & QStyleOptionViewItemV2::Alternate) + painter->fillRect(vopt->rect, vopt->palette.alternateBase()); + + QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled + ? QPalette::Normal : QPalette::Disabled; + if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active)) + cg = QPalette::Inactive; + + QRect textRect = subElementRect(QStyle::SE_ItemViewItemText, option, widget); + QRect itemRect = subElementRect(QStyle::SE_ItemViewItemFocusRect, option, widget).adjusted(-1, 0, 1, 0); + itemRect.setTop(vopt->rect.top()); + itemRect.setBottom(vopt->rect.bottom()); + + QSize sectionSize = itemRect.size(); + if (vopt->showDecorationSelected) + sectionSize = vopt->rect.size(); + + if (view->selectionBehavior() == QAbstractItemView::SelectRows) + sectionSize.setWidth(vopt->rect.width()); + if (view->selectionMode() == QAbstractItemView::NoSelection) + hover = false; + QPixmap pixmap; + + if (vopt->backgroundBrush.style() != Qt::NoBrush) { + QPointF oldBO = painter->brushOrigin(); + painter->setBrushOrigin(vopt->rect.topLeft()); + painter->fillRect(vopt->rect, vopt->backgroundBrush); + } + + if (hover || selected) { + QString key = QString::fromLatin1("qvdelegate-%1-%2-%3-%4-%5").arg(sectionSize.width()) + .arg(sectionSize.height()).arg(selected).arg(active).arg(hover); + if (!QPixmapCache::find(key, pixmap)) { + pixmap = QPixmap(sectionSize); + pixmap.fill(Qt::transparent); + + int state; + if (selected && hover) + state = LISS_HOTSELECTED; + else if (selected && !active) + state = LISS_SELECTEDNOTFOCUS; + else if (selected) + state = LISS_SELECTED; + else + state = LISS_HOT; + + QPainter pixmapPainter(&pixmap); + XPThemeData theme(d->treeViewHelper(), &pixmapPainter, QLatin1String("TREEVIEW"), + LVP_LISTITEM, state, QRect(0, 0, sectionSize.width(), sectionSize.height())); + if (theme.isValid()) { + d->drawBackground(theme); + } else { + QWindowsXPStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget); + break;; + } + QPixmapCache::insert(key, pixmap); + } + + if (vopt->showDecorationSelected) { + const int frame = 2; //Assumes a 2 pixel pixmap border + QRect srcRect = QRect(0, 0, sectionSize.width(), sectionSize.height()); + QRect pixmapRect = vopt->rect; + bool reverse = vopt->direction == Qt::RightToLeft; + bool leftSection = vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning; + bool rightSection = vopt->viewItemPosition == QStyleOptionViewItemV4::End; + if (vopt->viewItemPosition == QStyleOptionViewItemV4::OnlyOne + || vopt->viewItemPosition == QStyleOptionViewItemV4::Invalid) + painter->drawPixmap(pixmapRect.topLeft(), pixmap); + else if (reverse ? rightSection : leftSection){ + painter->drawPixmap(QRect(pixmapRect.topLeft(), + QSize(frame, pixmapRect.height())), pixmap, + QRect(QPoint(0, 0), QSize(frame, pixmapRect.height()))); + painter->drawPixmap(pixmapRect.adjusted(frame, 0, 0, 0), + pixmap, srcRect.adjusted(frame, 0, -frame, 0)); + } else if (reverse ? leftSection : rightSection) { + painter->drawPixmap(QRect(pixmapRect.topRight() - QPoint(frame - 1, 0), + QSize(frame, pixmapRect.height())), pixmap, + QRect(QPoint(pixmapRect.width() - frame, 0), + QSize(frame, pixmapRect.height()))); + painter->drawPixmap(pixmapRect.adjusted(0, 0, -frame, 0), + pixmap, srcRect.adjusted(frame, 0, -frame, 0)); + } else if (vopt->viewItemPosition == QStyleOptionViewItemV4::Middle) + painter->drawPixmap(pixmapRect, pixmap, + srcRect.adjusted(frame, 0, -frame, 0)); + } else { + if (vopt->text.isEmpty() && vopt->icon.isNull()) + break; + painter->drawPixmap(itemRect.topLeft(), pixmap); + } + } + } else { + QWindowsXPStyle::drawPrimitive(element, option, painter, widget); + } + break; + } + case PE_Widget: + { + const QDialogButtonBox *buttonBox = 0; + + if (qobject_cast (widget)) + buttonBox = widget->findChild(QLatin1String("qt_msgbox_buttonbox")); +#ifndef QT_NO_INPUTDIALOG + else if (qobject_cast (widget)) + buttonBox = widget->findChild(QLatin1String("qt_inputdlg_buttonbox")); +#endif // QT_NO_INPUTDIALOG + + if (buttonBox) { + //draw white panel part + XPThemeData theme(widget, painter, QLatin1String("TASKDIALOG"), TDLG_PRIMARYPANEL, 0, option->rect); + QRect toprect = option->rect; + toprect.setBottom(buttonBox->geometry().top()); + theme.rect = toprect; + d->drawBackground(theme); + + //draw bottom panel part + QRect buttonRect = option->rect; + buttonRect.setTop(buttonBox->geometry().top()); + theme.rect = buttonRect; + theme.partId = TDLG_SECONDARYPANEL; + d->drawBackground(theme); + } + } + break; + default: + QWindowsXPStyle::drawPrimitive(element, option, painter, widget); + break; + } +} + + +/*! + \internal + + see drawPrimitive for comments on the animation support + */ +void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const +{ + QWindowsVistaStylePrivate *d = const_cast(d_func()); + + if (!QWindowsVistaStylePrivate::useVista()) { + QWindowsStyle::drawControl(element, option, painter, widget); + return; + } + + bool selected = option->state & State_Selected; + bool pressed = option->state & State_Sunken; + bool disabled = !(option->state & State_Enabled); + + int state = option->state; + QString name; + + QRect rect(option->rect); + State flags = option->state; + int partId = 0; + int stateId = 0; + + QRect oldRect; + QRect newRect; + + if (d->transitionsEnabled() && widget) { + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + if ((qobject_cast(widget) && element == CE_PushButtonBevel)) + { + QWidget *w = const_cast (widget); + int oldState = w->property("_q_stylestate").toInt(); + oldRect = w->property("_q_stylerect").toRect(); + newRect = w->rect(); + w->setProperty("_q_stylestate", (int)option->state); + w->setProperty("_q_stylerect", w->rect()); + + bool wasDefault = w->property("_q_isdefault").toBool(); + bool isDefault = button->features & QStyleOptionButton::DefaultButton; + w->setProperty("_q_isdefault", isDefault); + + bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) || + (state & State_On) != (oldState & State_On) || + (state & State_MouseOver) != (oldState & State_MouseOver)); + + if (oldRect != newRect || (wasDefault && !isDefault)) + { + doTransition = false; + d->stopAnimation(widget); + } + + if (doTransition) { + QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); + QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); + QWindowsVistaAnimation *anim = d->widgetAnimation(widget); + + QStyleOptionButton opt = *button; + opt.state = (QStyle::State)oldState; + + startImage.fill(0); + QWindowsVistaTransition *t = new QWindowsVistaTransition; + t->setWidget(w); + QPainter startPainter(&startImage); + + if (!anim) { + proxy()->drawControl(element, &opt, &startPainter, 0 /* Intentional */); + } else { + anim->paint(&startPainter, &opt); + d->stopAnimation(widget); + } + + t->setStartImage(startImage); + d->startAnimation(t); + + endImage.fill(0); + QPainter endPainter(&endImage); + proxy()->drawControl(element, option, &endPainter, 0 /* Intentional */); + t->setEndImage(endImage); + int duration = 0; + HTHEME theme = pOpenThemeData(0, L"Button"); + + int fromState = buttonStateId(oldState, BP_PUSHBUTTON); + int toState = buttonStateId(option->state, BP_PUSHBUTTON); + if (pGetThemeTransitionDuration(theme, BP_PUSHBUTTON, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK) + t->setDuration(duration); + else + t->setDuration(0); + t->setStartTime(QTime::currentTime()); + } + } + } + } + switch (element) { + case CE_PushButtonBevel: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) + { + + if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) { + anim->paint(painter, option); + } else { + name = QLatin1String("BUTTON"); + partId = BP_PUSHBUTTON; + if (btn->features & QStyleOptionButton::CommandLinkButton) + partId = BP_COMMANDLINK; + bool justFlat = (btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken)); + if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat)) + stateId = PBS_DISABLED; + else if (justFlat) + ; + else if (flags & (State_Sunken | State_On)) + stateId = PBS_PRESSED; + else if (flags & State_MouseOver) + stateId = PBS_HOT; + else if (btn->features & QStyleOptionButton::DefaultButton && (state & State_Active)) + stateId = PBS_DEFAULTED; + else + stateId = PBS_NORMAL; + + if (!justFlat) { + + if (widget && d->transitionsEnabled() && (btn->features & QStyleOptionButton::DefaultButton) && + !(state & (State_Sunken | State_On)) && !(state & State_MouseOver) && + (state & State_Enabled) && (state & State_Active)) + { + QWindowsVistaAnimation *anim = d->widgetAnimation(widget); + if (!anim && widget) { + QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); + startImage.fill(0); + QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); + alternateImage.fill(0); + + QWindowsVistaPulse *pulse = new QWindowsVistaPulse; + pulse->setWidget(const_cast(widget)); + + QPainter startPainter(&startImage); + stateId = PBS_DEFAULTED; + XPThemeData theme(widget, &startPainter, name, partId, stateId, rect); + d->drawBackground(theme); + + QPainter alternatePainter(&alternateImage); + theme.stateId = PBS_DEFAULTED_ANIMATING; + theme.painter = &alternatePainter; + d->drawBackground(theme); + pulse->setPrimaryImage(startImage); + pulse->setAlternateImage(alternateImage); + pulse->setStartTime(QTime::currentTime()); + pulse->setDuration(2000); + d->startAnimation(pulse); + anim = pulse; + } + + if (anim) + anim->paint(painter, option); + else { + XPThemeData theme(widget, painter, name, partId, stateId, rect); + d->drawBackground(theme); + } + } + else { + d->stopAnimation(widget); + XPThemeData theme(widget, painter, name, partId, stateId, rect); + d->drawBackground(theme); + } + } + } + if (btn->features & QStyleOptionButton::HasMenu) { + int mbiw = 0, mbih = 0; + XPThemeData theme(widget, 0, QLatin1String("TOOLBAR"), TP_DROPDOWNBUTTON); + if (theme.isValid()) { + SIZE size; + if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { + mbiw = size.cx; + mbih = size.cy; + } + } + QRect ir = subElementRect(SE_PushButtonContents, option, 0); + QStyleOptionButton newBtn = *btn; + newBtn.rect = QStyle::visualRect(option->direction, option->rect, + QRect(ir.right() - mbiw - 2, + option->rect.top() + (option->rect.height()/2) - (mbih/2), + mbiw + 1, mbih + 1)); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget); + } + return; + } + break; +#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBarContents: + if (const QStyleOptionProgressBar *bar + = qstyleoption_cast(option)) { + int stateId = MBI_NORMAL; + if (disabled) + stateId = MBI_DISABLED; + bool isIndeterminate = (bar->minimum == 0 && bar->maximum == 0); + bool vertical = false; + bool inverted = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(option)) { + vertical = (pb2->orientation == Qt::Vertical); + inverted = pb2->invertedAppearance; + } + + if (const QProgressBar *progressbar = qobject_cast(widget)) { + if (((progressbar->value() > 0 && d->transitionsEnabled()) || isIndeterminate)) { + if (!d->widgetAnimation(progressbar) && progressbar->value() < progressbar->maximum()) { + QWindowsVistaAnimation *a = new QWindowsVistaAnimation; + a->setWidget(const_cast(widget)); + a->setStartTime(QTime::currentTime()); + d->startAnimation(a); + } + } else { + d->stopAnimation(progressbar); + } + } + + XPThemeData theme(widget, painter, QLatin1String("PROGRESS"), vertical ? PP_FILLVERT : PP_FILL); + theme.rect = option->rect; + bool reverse = (bar->direction == Qt::LeftToRight && inverted) || (bar->direction == Qt::RightToLeft && !inverted); + QTime current = QTime::currentTime(); + + if (isIndeterminate) { + if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) { + int glowSize = 120; + int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width()); + int animOffset = a->startTime().msecsTo(current) / 4; + if (animOffset > animationWidth) + a->setStartTime(QTime::currentTime()); + painter->save(); + painter->setClipRect(theme.rect); + QRect animRect; + QSize pixmapSize(14, 14); + if (vertical) { + animRect = QRect(theme.rect.left(), + inverted ? rect.top() - glowSize + animOffset : + rect.bottom() + glowSize - animOffset, + rect.width(), glowSize); + pixmapSize.setHeight(animRect.height()); + } else { + animRect = QRect(rect.left() - glowSize + animOffset, + rect.top(), glowSize, rect.height()); + animRect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight, + option->rect, animRect); + pixmapSize.setWidth(animRect.width()); + } + QString name = QString::fromLatin1("qiprogress-%1-%2").arg(pixmapSize.width()).arg(pixmapSize.height()); + QPixmap pixmap; + if (!QPixmapCache::find(name, pixmap)) { + QImage image(pixmapSize, QImage::Format_ARGB32); + image.fill(Qt::transparent); + QPainter imagePainter(&image); + theme.painter = &imagePainter; + theme.partId = vertical ? PP_FILLVERT : PP_FILL; + theme.rect = QRect(QPoint(0,0), theme.rect.size()); + QLinearGradient alphaGradient(0, 0, vertical ? 0 : image.width(), + vertical ? image.height() : 0); + alphaGradient.setColorAt(0, QColor(0, 0, 0, 0)); + alphaGradient.setColorAt(0.5, QColor(0, 0, 0, 220)); + alphaGradient.setColorAt(1, QColor(0, 0, 0, 0)); + imagePainter.fillRect(image.rect(), alphaGradient); + imagePainter.setCompositionMode(QPainter::CompositionMode_SourceIn); + d->drawBackground(theme); + imagePainter.end(); + pixmap = QPixmap::fromImage(image); + QPixmapCache::insert(name, pixmap); + } + painter->drawPixmap(animRect, pixmap); + painter->restore(); + } + } + else { + qint64 progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar + + if (vertical) { + int maxHeight = option->rect.height(); + int minHeight = 0; + double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxHeight); + int height = isIndeterminate ? maxHeight: qMax(int(vc6_workaround), minHeight); + theme.rect.setHeight(height); + if (!inverted) + theme.rect.moveTop(rect.height() - theme.rect.height()); + } else { + int maxWidth = option->rect.width(); + int minWidth = 0; + double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxWidth); + int width = isIndeterminate ? maxWidth : qMax(int(vc6_workaround), minWidth); + theme.rect.setWidth(width); + theme.rect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight, + option->rect, theme.rect); + } + d->drawBackground(theme); + + if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) { + int glowSize = 140; + int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width()); + int animOffset = a->startTime().msecsTo(current) / 4; + theme.partId = vertical ? PP_MOVEOVERLAYVERT : PP_MOVEOVERLAY; + if (animOffset > animationWidth) { + if (bar->progress < bar->maximum) + a->setStartTime(QTime::currentTime()); + else + d->stopAnimation(widget); //we stop the glow motion only after it has + //moved out of view + } + painter->save(); + painter->setClipRect(theme.rect); + if (vertical) { + theme.rect = QRect(theme.rect.left(), + inverted ? rect.top() - glowSize + animOffset : + rect.bottom() + glowSize - animOffset, + rect.width(), glowSize); + } else { + theme.rect = QRect(rect.left() - glowSize + animOffset,rect.top(), glowSize, rect.height()); + theme.rect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight, option->rect, theme.rect); + } + d->drawBackground(theme); + painter->restore(); + } + } + } + break; +#endif // QT_NO_PROGRESSBAR + case CE_MenuBarItem: + { + + if (const QStyleOptionMenuItem *mbi = qstyleoption_cast(option)) + { + if (mbi->menuItemType == QStyleOptionMenuItem::DefaultItem) + break; + + QPalette::ColorRole textRole = disabled ? QPalette::Text : QPalette::ButtonText; + QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal); + + uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget)) + alignment |= Qt::TextHideMnemonic; + + //The rect adjustment is a workaround for the menu not really filling its background. + XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_BARBACKGROUND, 0, option->rect.adjusted(-1, 0, 2, 1)); + d->drawBackground(theme); + + int stateId = MBI_NORMAL; + if (disabled) + stateId = MBI_DISABLED; + else if (pressed) + stateId = MBI_PUSHED; + else if (selected) + stateId = MBI_HOT; + + XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_BARITEM, stateId, option->rect); + d->drawBackground(theme2); + + if (!pix.isNull()) + drawItemPixmap(painter, mbi->rect, alignment, pix); + else + drawItemText(painter, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole); + } + } + break; +#ifndef QT_NO_MENU + case CE_MenuItem: + if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) { + // windows always has a check column, regardless whether we have an icon or not + int checkcol = 28; + { + SIZE size; + MARGINS margins; + XPThemeData theme(widget, 0, QLatin1String("MENU"), MENU_POPUPCHECKBACKGROUND, MBI_HOT); + pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); + pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); + checkcol = qMax(menuitem->maxIconWidth, int(6 + size.cx + margins.cxLeftWidth + margins.cxRightWidth)); + } + QColor darkLine = option->palette.background().color().darker(108); + QColor lightLine = option->palette.background().color().lighter(107); + QRect rect = option->rect; + QStyleOptionMenuItem mbiCopy = *menuitem; + + //draw vertical menu line + QPoint p1 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.top())); + QPoint p2 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.bottom())); + QRect gutterRect(p1.x(), p1.y(), 3, p2.y() - p1.y() + 1); + XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_POPUPGUTTER, stateId, gutterRect); + d->drawBackground(theme2); + + int x, y, w, h; + menuitem->rect.getRect(&x, &y, &w, &h); + int tab = menuitem->tabWidth; + bool dis = !(menuitem->state & State_Enabled); + bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable + ? menuitem->checked : false; + bool act = menuitem->state & State_Selected; + + if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) { + int yoff = y-2 + h / 2; + QPoint p1 = QPoint(x + checkcol, yoff); + QPoint p2 = QPoint(x + w + 6 , yoff); + stateId = MBI_HOT; + QRect subRect(p1.x(), p1.y(), p2.x() - p1.x(), 6); + subRect = QStyle::visualRect(option->direction, option->rect, subRect ); + XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_POPUPSEPARATOR, stateId, subRect); + d->drawBackground(theme2); + return; + } + + QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(), + menuitem->rect.y(), checkcol - 6, menuitem->rect.height())); + + if (act) { + stateId = MBI_HOT; + XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_POPUPITEM, stateId, option->rect); + d->drawBackground(theme2); + } + + if (checked) { + XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_POPUPCHECKBACKGROUND, + menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect); + SIZE size; + MARGINS margins; + pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); + pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, + TMT_CONTENTMARGINS, NULL, &margins); + QRect checkRect(0, 0, size.cx + margins.cxLeftWidth + margins.cxRightWidth , + size.cy + margins.cyBottomHeight + margins.cyTopHeight); + checkRect.moveCenter(vCheckRect.center()); + theme.rect = checkRect; + + d->drawBackground(theme); + + if (menuitem->icon.isNull()) { + checkRect = QRect(0, 0, size.cx, size.cy); + checkRect.moveCenter(theme.rect.center()); + theme.rect = checkRect; + + theme.partId = MENU_POPUPCHECK; + bool bullet = menuitem->checkType & QStyleOptionMenuItem::Exclusive; + if (dis) + theme.stateId = bullet ? MC_BULLETDISABLED: MC_CHECKMARKDISABLED; + else + theme.stateId = bullet ? MC_BULLETNORMAL: MC_CHECKMARKNORMAL; + d->drawBackground(theme); + } + } + + if (!menuitem->icon.isNull()) { + QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; + if (act && !dis) + mode = QIcon::Active; + QPixmap pixmap; + if (checked) + pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On); + else + pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + QRect pmr(0, 0, pixw, pixh); + pmr.moveCenter(vCheckRect.center()); + painter->setPen(menuitem->palette.text().color()); + painter->drawPixmap(pmr.topLeft(), pixmap); + } + + painter->setPen(menuitem->palette.buttonText().color()); + + QColor discol; + if (dis) { + discol = menuitem->palette.text().color(); + painter->setPen(discol); + } + + int xm = windowsItemFrame + checkcol + windowsItemHMargin; + int xpos = menuitem->rect.x() + xm; + QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); + QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect); + QString s = menuitem->text; + if (!s.isEmpty()) { // draw text + painter->save(); + int t = s.indexOf(QLatin1Char('\t')); + int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget)) + text_flags |= Qt::TextHideMnemonic; + text_flags |= Qt::AlignLeft; + if (t >= 0) { + QRect vShortcutRect = visualRect(option->direction, menuitem->rect, + QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom()))); + painter->drawText(vShortcutRect, text_flags, s.mid(t + 1)); + s = s.left(t); + } + QFont font = menuitem->font; + if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) + font.setBold(true); + painter->setFont(font); + painter->setPen(discol); + painter->drawText(vTextRect, text_flags, s.left(t)); + painter->restore(); + } + if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow + int dim = (h - 2 * windowsItemFrame) / 2; + PrimitiveElement arrow; + arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; + xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim; + QRect vSubMenuRect = visualRect(option->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim)); + QStyleOptionMenuItem newMI = *menuitem; + newMI.rect = vSubMenuRect; + newMI.state = dis ? State_None : State_Enabled; + proxy()->drawPrimitive(arrow, &newMI, painter, widget); + } + } + break; +#endif // QT_NO_MENU + case CE_HeaderSection: + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + name = QLatin1String("HEADER"); + partId = HP_HEADERITEM; + if (flags & State_Sunken) + stateId = HIS_PRESSED; + else if (flags & State_MouseOver) + stateId = HIS_HOT; + else + stateId = HIS_NORMAL; + + if (header->sortIndicator != QStyleOptionHeader::None) + stateId += 3; + + XPThemeData theme(widget, painter, name, partId, stateId, option->rect); + d->drawBackground(theme); + } + break; + case CE_MenuBarEmptyArea: + { + stateId = MBI_NORMAL; + if (!(state & State_Enabled)) + stateId = MBI_DISABLED; + XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_BARBACKGROUND, stateId, option->rect); + d->drawBackground(theme); + } + break; + case CE_ToolBar: + if (const QStyleOptionToolBar *toolbar = qstyleoption_cast(option)) { + QPalette pal = option->palette; + pal.setColor(QPalette::Dark, option->palette.background().color().darker(130)); + QStyleOptionToolBar copyOpt = *toolbar; + copyOpt.palette = pal; + QWindowsStyle::drawControl(element, ©Opt, painter, widget); + } + break; + case CE_DockWidgetTitle: + if (const QDockWidget *dockWidget = qobject_cast(widget)) { + QRect rect = option->rect; + if (dockWidget->isFloating()) { + QWindowsXPStyle::drawControl(element, option, painter, widget); + break; //otherwise fall through + } + + if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast(option)) { + + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(dwOpt); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + + if (verticalTitleBar) { + QSize s = rect.size(); + s.transpose(); + rect.setSize(s); + + painter->translate(rect.left() - 1, rect.top() + rect.width()); + painter->rotate(-90); + painter->translate(-rect.left() + 1, -rect.top()); + } + + painter->setBrush(option->palette.background().color().darker(110)); + painter->setPen(option->palette.background().color().darker(130)); + painter->drawRect(rect.adjusted(0, 1, -1, -3)); + + int buttonMargin = 4; + int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget); + int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget); + const QDockWidget *dw = qobject_cast(widget); + bool isFloating = dw != 0 && dw->isFloating(); + + QRect r = option->rect.adjusted(0, 2, -1, -3); + QRect titleRect = r; + + if (dwOpt->closable) { + QSize sz = standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10)); + titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0); + } + + if (dwOpt->floatable) { + QSize sz = standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10)); + titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0); + } + + if (isFloating) { + titleRect.adjust(0, -fw, 0, 0); + if (widget != 0 && widget->windowIcon().cacheKey() != QApplication::windowIcon().cacheKey()) + titleRect.adjust(titleRect.height() + mw, 0, 0, 0); + } else { + titleRect.adjust(mw, 0, 0, 0); + if (!dwOpt->floatable && !dwOpt->closable) + titleRect.adjust(0, 0, -mw, 0); + } + if (!verticalTitleBar) + titleRect = visualRect(dwOpt->direction, r, titleRect); + + if (!dwOpt->title.isEmpty()) { + QString titleText = painter->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, + verticalTitleBar ? titleRect.height() : titleRect.width()); + const int indent = painter->fontMetrics().descent(); + drawItemText(painter, rect.adjusted(indent + 1, 1, -indent - 1, -1), + Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette, + dwOpt->state & State_Enabled, titleText, + QPalette::WindowText); + } + } + break; + } +#ifndef QT_NO_ITEMVIEWS + case CE_ItemViewItem: + { + const QStyleOptionViewItemV4 *vopt; + const QAbstractItemView *view = qobject_cast(widget); + bool newStyle = true; + + if (qobject_cast(widget)) + newStyle = false; + + if (newStyle && view && (vopt = qstyleoption_cast(option))) { + /* + // We cannot currently get the correct selection color for "explorer style" views + COLORREF cref = 0; + XPThemeData theme(d->treeViewHelper(), 0, QLatin1String("LISTVIEW"), 0, 0); + unsigned int res = pGetThemeColor(theme.handle(), LVP_LISTITEM, LISS_SELECTED, TMT_TEXTCOLOR, &cref); + QColor textColor(GetRValue(cref), GetGValue(cref), GetBValue(cref)); + */ + QPalette palette = vopt->palette; + palette.setColor(QPalette::All, QPalette::HighlightedText, palette.color(QPalette::Active, QPalette::Text)); + // Note that setting a saturated color here results in ugly XOR colors in the focus rect + palette.setColor(QPalette::All, QPalette::Highlight, palette.base().color().darker(108)); + QStyleOptionViewItemV4 adjustedOption = *vopt; + adjustedOption.palette = palette; + // We hide the focusrect in singleselection as it is not required + if ((view->selectionMode() == QAbstractItemView::SingleSelection) + && !(vopt->state & State_KeyboardFocusChange)) + adjustedOption.state &= ~State_HasFocus; + QWindowsXPStyle::drawControl(element, &adjustedOption, painter, widget); + } else { + QWindowsXPStyle::drawControl(element, option, painter, widget); + } + break; + } +#endif // QT_NO_ITEMVIEWS + + default: + QWindowsXPStyle::drawControl(element, option, painter, widget); + break; + } +} + +/*! + \internal + + see drawPrimitive for comments on the animation support + + */ +void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const +{ + QWindowsVistaStylePrivate *d = const_cast(d_func()); + if (!QWindowsVistaStylePrivate::useVista()) { + QWindowsStyle::drawComplexControl(control, option, painter, widget); + return; + } + + State state = option->state; + SubControls sub = option->subControls; + QRect r = option->rect; + + int partId = 0; + int stateId = 0; + + State flags = option->state; + if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow()) + flags |= State_MouseOver; + + if (d->transitionsEnabled() && widget) { + if ((qobject_cast(widget) && control == CC_ScrollBar) +#ifndef QT_NO_SPINBOX + || (qobject_cast(widget) && control == CC_SpinBox) +#endif // QT_NO_SPINBOX +#ifndef QT_NO_COMBOBOX + || (qobject_cast(widget) && control == CC_ComboBox) +#endif // QT_NO_COMBOBOX + ) + { + QWidget *w = const_cast (widget); + + int oldState = w->property("_q_stylestate").toInt(); + int oldActiveControls = w->property("_q_stylecontrols").toInt(); + QRect oldRect = w->property("_q_stylerect").toRect(); + w->setProperty("_q_stylestate", (int)option->state); + w->setProperty("_q_stylecontrols", (int)option->activeSubControls); + w->setProperty("_q_stylerect", w->rect()); + + bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) || + (state & State_On) != (oldState & State_On) || + (state & State_MouseOver) != (oldState & State_MouseOver) || + oldActiveControls != option->activeSubControls); + + + if (qstyleoption_cast(option)) { + QRect oldSliderPos = w->property("_q_stylesliderpos").toRect(); + QRect currentPos = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); + w->setProperty("_q_stylesliderpos", currentPos); + if (oldSliderPos != currentPos) { + doTransition = false; + d->stopAnimation(widget); + } + } else if (control == CC_SpinBox) { + //spinboxes have a transition when focus changes + if (!doTransition) + doTransition = (state & State_HasFocus) != (oldState & State_HasFocus); + } + + if (oldRect != option->rect) { + doTransition = false; + d->stopAnimation(widget); + } + + if (doTransition) { + QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); + QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); + QWindowsVistaAnimation *anim = d->widgetAnimation(widget); + QWindowsVistaTransition *t = new QWindowsVistaTransition; + t->setWidget(w); + if (!anim) { + if (const QStyleOptionComboBox *combo = qstyleoption_cast(option)) { + //Combo boxes are special cased to avoid cleartype issues + startImage.fill(0); + QPainter startPainter(&startImage); + QStyleOptionComboBox startCombo = *combo; + startCombo.state = (QStyle::State)oldState; + startCombo.activeSubControls = (QStyle::SubControl)oldActiveControls; + proxy()->drawComplexControl(control, &startCombo, &startPainter, 0 /* Intentional */); + t->setStartImage(startImage); + } else if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + //This is a workaround for the direct3d engine as it currently has some issues with grabWindow + startImage.fill(0); + QPainter startPainter(&startImage); + QStyleOptionSlider startSlider = *slider; + startSlider.state = (QStyle::State)oldState; + startSlider.activeSubControls = (QStyle::SubControl)oldActiveControls; + proxy()->drawComplexControl(control, &startSlider, &startPainter, 0 /* Intentional */); + t->setStartImage(startImage); + } else { + QPoint offset(0, 0); + if (!widget->internalWinId()) + offset = widget->mapTo(widget->nativeParentWidget(), offset); + t->setStartImage(QPixmap::grabWindow(widget->effectiveWinId(), offset.x(), offset.y(), + option->rect.width(), option->rect.height()).toImage()); + } + } else { + startImage.fill(0); + QPainter startPainter(&startImage); + anim->paint(&startPainter, option); + t->setStartImage(startImage); + } + d->startAnimation(t); + endImage.fill(0); + QPainter endPainter(&endImage); + proxy()->drawComplexControl(control, option, &endPainter, 0 /* Intentional */); + t->setEndImage(endImage); + t->setStartTime(QTime::currentTime()); + + if (option->state & State_MouseOver || option->state & State_Sunken) + t->setDuration(150); + else + t->setDuration(500); + } + + if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) { + anim->paint(painter, option); + return; + } + + } + } + + switch (control) { + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) + { + if (cmb->editable) { + if (sub & SC_ComboBoxEditField) { + partId = EP_EDITBORDER_NOSCROLL; + if (!(flags & State_Enabled)) + stateId = ETS_DISABLED; + else if (flags & State_MouseOver) + stateId = ETS_HOT; + else if (flags & State_HasFocus) + stateId = ETS_FOCUSED; + else + stateId = ETS_NORMAL; + + XPThemeData theme(widget, painter, QLatin1String("EDIT"), partId, stateId, r); + + d->drawBackground(theme); + } + if (sub & SC_ComboBoxArrow) { + QRect subRect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget); + XPThemeData theme(widget, painter, QLatin1String("COMBOBOX")); + theme.rect = subRect; + partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT; + + if (!(cmb->state & State_Enabled)) + stateId = CBXS_DISABLED; + else if (cmb->state & State_Sunken || cmb->state & State_On) + stateId = CBXS_PRESSED; + else if (cmb->state & State_MouseOver && option->activeSubControls & SC_ComboBoxArrow) + stateId = CBXS_HOT; + else + stateId = CBXS_NORMAL; + + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + + } else { + if (sub & SC_ComboBoxFrame) { + QStyleOptionButton btn; + btn.QStyleOption::operator=(*option); + btn.rect = option->rect.adjusted(-1, -1, 1, 1); + if (sub & SC_ComboBoxArrow) + btn.features = QStyleOptionButton::HasMenu; + proxy()->drawControl(QStyle::CE_PushButton, &btn, painter, widget); + } + } + } + break; + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(option)) + { + XPThemeData theme(widget, painter, QLatin1String("SCROLLBAR")); + + bool maxedOut = (scrollbar->maximum == scrollbar->minimum); + if (maxedOut) + flags &= ~State_Enabled; + + bool isHorz = flags & State_Horizontal; + bool isRTL = option->direction == Qt::RightToLeft; + if (sub & SC_ScrollBarAddLine) { + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget); + partId = SBP_ARROWBTN; + if (!(flags & State_Enabled)) + stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED); + else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_Sunken)) + stateId = (isHorz ? (isRTL ? ABS_LEFTPRESSED : ABS_RIGHTPRESSED) : ABS_DOWNPRESSED); + else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_MouseOver)) + stateId = (isHorz ? (isRTL ? ABS_LEFTHOT : ABS_RIGHTHOT) : ABS_DOWNHOT); + else if (scrollbar->state & State_MouseOver) + stateId = (isHorz ? (isRTL ? ABS_LEFTHOVER : ABS_RIGHTHOVER) : ABS_DOWNHOVER); + else + stateId = (isHorz ? (isRTL ? ABS_LEFTNORMAL : ABS_RIGHTNORMAL) : ABS_DOWNNORMAL); + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_ScrollBarSubLine) { + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget); + partId = SBP_ARROWBTN; + if (!(flags & State_Enabled)) + stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED); + else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_Sunken)) + stateId = (isHorz ? (isRTL ? ABS_RIGHTPRESSED : ABS_LEFTPRESSED) : ABS_UPPRESSED); + else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_MouseOver)) + stateId = (isHorz ? (isRTL ? ABS_RIGHTHOT : ABS_LEFTHOT) : ABS_UPHOT); + else if (scrollbar->state & State_MouseOver) + stateId = (isHorz ? (isRTL ? ABS_RIGHTHOVER : ABS_LEFTHOVER) : ABS_UPHOVER); + else + stateId = (isHorz ? (isRTL ? ABS_RIGHTNORMAL : ABS_LEFTNORMAL) : ABS_UPNORMAL); + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (maxedOut) { + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); + theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget)); + theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget)); + partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; + stateId = SCRBS_DISABLED; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } else { + if (sub & SC_ScrollBarSubPage) { + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget); + partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT; + if (!(flags & State_Enabled)) + stateId = SCRBS_DISABLED; + else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_Sunken)) + stateId = SCRBS_PRESSED; + else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_MouseOver)) + stateId = SCRBS_HOT; + else + stateId = SCRBS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_ScrollBarAddPage) { + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget); + partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; + if (!(flags & State_Enabled)) + stateId = SCRBS_DISABLED; + else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_Sunken)) + stateId = SCRBS_PRESSED; + else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_MouseOver)) + stateId = SCRBS_HOT; + else + stateId = SCRBS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_ScrollBarSlider) { + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); + if (!(flags & State_Enabled)) + stateId = SCRBS_DISABLED; + else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken)) + stateId = SCRBS_PRESSED; + else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_MouseOver)) + stateId = SCRBS_HOT; + else if (option->state & State_MouseOver) + stateId = SCRBS_HOVER; + else + stateId = SCRBS_NORMAL; + + // Draw handle + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); + theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT; + theme.stateId = stateId; + d->drawBackground(theme); + + // Calculate rect of gripper + const int swidth = theme.rect.width(); + const int sheight = theme.rect.height(); + + MARGINS contentsMargin; + RECT rect = theme.toRECT(theme.rect); + pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); + + SIZE size; + theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; + pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + int gw = size.cx, gh = size.cy; + + + QRect gripperBounds; + if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) { + gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); + gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); + gripperBounds.setWidth(gw); + gripperBounds.setHeight(gh); + } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) { + gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); + gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); + gripperBounds.setWidth(gw); + gripperBounds.setHeight(gh); + } + + // Draw gripper if there is enough space + if (!gripperBounds.isEmpty() && flags & State_Enabled) { + painter->save(); + XPThemeData grippBackground = theme; + grippBackground.partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; + theme.rect = gripperBounds; + painter->setClipRegion(d->region(theme));// Only change inside the region of the gripper + d->drawBackground(grippBackground);// The gutter is the grippers background + d->drawBackground(theme); // Transparent gripper ontop of background + painter->restore(); + } + } + } + } + break; +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *sb = qstyleoption_cast(option)) + { + XPThemeData theme(widget, painter, QLatin1String("SPIN")); + if (sb->frame && (sub & SC_SpinBoxFrame)) { + partId = EP_EDITBORDER_NOSCROLL; + if (!(flags & State_Enabled)) + stateId = ETS_DISABLED; + else if (flags & State_MouseOver) + stateId = ETS_HOT; + else if (flags & State_HasFocus) + stateId = ETS_SELECTED; + else + stateId = ETS_NORMAL; + + XPThemeData ftheme(widget, painter, QLatin1String("EDIT"), partId, stateId, r); + ftheme.noContent = true; + d->drawBackground(ftheme); + } + if (sub & SC_SpinBoxUp) { + theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget).adjusted(0, 0, 0, 1); + partId = SPNP_UP; + if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled)) + stateId = UPS_DISABLED; + else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken)) + stateId = UPS_PRESSED; + else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_MouseOver)) + stateId = UPS_HOT; + else + stateId = UPS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_SpinBoxDown) { + theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget); + partId = SPNP_DOWN; + if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled)) + stateId = DNS_DISABLED; + else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken)) + stateId = DNS_PRESSED; + else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_MouseOver)) + stateId = DNS_HOT; + else + stateId = DNS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + } + break; +#endif // QT_NO_SPINBOX + default: + QWindowsXPStyle::drawComplexControl(control, option, painter, widget); + break; + } +} + +/*! + \internal + */ +QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const +{ + if (!QWindowsVistaStylePrivate::useVista()) + return QWindowsStyle::sizeFromContents(type, option, size, widget); + + QSize sz(size); + switch (type) { + case CT_MenuItem: + sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget); + int minimumHeight; + { + SIZE size; + MARGINS margins; + XPThemeData theme(widget, 0, QLatin1String("MENU"), MENU_POPUPCHECKBACKGROUND, MBI_HOT); + pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); + pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); + minimumHeight = qMax(size.cy + margins.cyBottomHeight+ margins.cyTopHeight, sz.height()); + sz.rwidth() += size.cx + margins.cxLeftWidth + margins.cxRightWidth; + } + + if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) { + if (menuitem->menuItemType != QStyleOptionMenuItem::Separator) + sz.setHeight(minimumHeight); + } + return sz; +#ifndef QT_NO_MENUBAR + case CT_MenuBarItem: + if (!sz.isEmpty()) + sz += QSize(windowsItemHMargin * 5 + 1, 5); + return sz; + break; +#endif + case CT_ItemViewItem: + sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget); + sz.rheight() += 2; + return sz; + case CT_SpinBox: + { + //Spinbox adds frame twice + sz = QWindowsStyle::sizeFromContents(type, option, size, widget); + int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget); + sz -= QSize(2*border, 2*border); + } + return sz; + default: + break; + } + return QWindowsXPStyle::sizeFromContents(type, option, size, widget); +} + +/*! + \internal + */ +QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const +{ + if (!QWindowsVistaStylePrivate::useVista()) + return QWindowsStyle::subElementRect(element, option, widget); + + QRect rect = QWindowsXPStyle::subElementRect(element, option, widget); + switch (element) { + + case SE_PushButtonContents: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + MARGINS borderSize; + HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"Button"); + if (theme) { + int stateId = PBS_NORMAL; + if (!(option->state & State_Enabled)) + stateId = PBS_DISABLED; + else if (option->state & State_Sunken) + stateId = PBS_PRESSED; + else if (option->state & State_MouseOver) + stateId = PBS_HOT; + else if (btn->features & QStyleOptionButton::DefaultButton) + stateId = PBS_DEFAULTED; + + int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget); + rect = option->rect.adjusted(border, border, -border, -border); + + int result = pGetThemeMargins(theme, + NULL, + BP_PUSHBUTTON, + stateId, + TMT_CONTENTMARGINS, + NULL, + &borderSize); + + if (result == S_OK) { + rect.adjust(borderSize.cxLeftWidth, borderSize.cyTopHeight, + -borderSize.cxRightWidth, -borderSize.cyBottomHeight); + rect = visualRect(option->direction, option->rect, rect); + } + } + } + break; + + case SE_HeaderArrow: + { + QRect r = rect; + int h = option->rect.height(); + int w = option->rect.width(); + int x = option->rect.x(); + int y = option->rect.y(); + int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget); + + XPThemeData theme(widget, 0, QLatin1String("HEADER"), HP_HEADERSORTARROW, HSAS_SORTEDDOWN, option->rect); + + int arrowWidth = 13; + int arrowHeight = 5; + if (theme.isValid()) { + SIZE size; + if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { + arrowWidth = size.cx; + arrowHeight = size.cy; + } + } + if (option->state & State_Horizontal) { + r.setRect(x + w/2 - arrowWidth/2, y , arrowWidth, arrowHeight); + } else { + int vert_size = w / 2; + r.setRect(x + 5, y + h - margin * 2 - vert_size, + w - margin * 2 - 5, vert_size); + } + rect = visualRect(option->direction, option->rect, r); + } + break; + + case SE_HeaderLabel: + { + int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget); + QRect r = option->rect; + r.setRect(option->rect.x() + margin, option->rect.y() + margin, + option->rect.width() - margin * 2, option->rect.height() - margin * 2); + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + // Subtract width needed for arrow, if there is one + if (header->sortIndicator != QStyleOptionHeader::None) { + if (!(option->state & State_Horizontal)) //horizontal arrows are positioned on top + r.setHeight(r.height() - (option->rect.width() / 2) - (margin * 2)); + } + } + rect = visualRect(option->direction, option->rect, r); + } + break; + case SE_ProgressBarContents: + rect = QCommonStyle::subElementRect(SE_ProgressBarGroove, option, widget); + break; + case SE_ItemViewItemDecoration: + if (qstyleoption_cast(option)) + rect.adjust(-2, 0, 2, 0); + break; + case SE_ItemViewItemFocusRect: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast(option)) { + QRect textRect = subElementRect(QStyle::SE_ItemViewItemText, option, widget); + QRect displayRect = subElementRect(QStyle::SE_ItemViewItemDecoration, option, widget); + if (!vopt->icon.isNull()) + rect = textRect.united(displayRect); + else + rect = textRect; + rect = rect.adjusted(1, 0, -1, 0); + } + break; + default: + break; + } + return rect; +} + + +/* + This function is used by subControlRect to check if a button + should be drawn for the given subControl given a set of window flags. +*/ +static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBar *tb){ + + bool isMinimized = tb->titleBarState & Qt::WindowMinimized; + bool isMaximized = tb->titleBarState & Qt::WindowMaximized; + const uint flags = tb->titleBarFlags; + bool retVal = false; + switch (sc) { + case QStyle::SC_TitleBarContextHelpButton: + if (flags & Qt::WindowContextHelpButtonHint) + retVal = true; + break; + case QStyle::SC_TitleBarMinButton: + if (!isMinimized && (flags & Qt::WindowMinimizeButtonHint)) + retVal = true; + break; + case QStyle::SC_TitleBarNormalButton: + if (isMinimized && (flags & Qt::WindowMinimizeButtonHint)) + retVal = true; + else if (isMaximized && (flags & Qt::WindowMaximizeButtonHint)) + retVal = true; + break; + case QStyle::SC_TitleBarMaxButton: + if (!isMaximized && (flags & Qt::WindowMaximizeButtonHint)) + retVal = true; + break; + case QStyle::SC_TitleBarShadeButton: + if (!isMinimized && flags & Qt::WindowShadeButtonHint) + retVal = true; + break; + case QStyle::SC_TitleBarUnshadeButton: + if (isMinimized && flags & Qt::WindowShadeButtonHint) + retVal = true; + break; + case QStyle::SC_TitleBarCloseButton: + if (flags & Qt::WindowSystemMenuHint) + retVal = true; + break; + case QStyle::SC_TitleBarSysMenu: + if (flags & Qt::WindowSystemMenuHint) + retVal = true; + break; + default : + retVal = true; + } + return retVal; +} + + +/*! \internal */ +int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, + QStyleHintReturn *returnData) const +{ + QWindowsVistaStylePrivate *d = const_cast(d_func()); + int ret = 0; + switch (hint) { + case SH_MessageBox_CenterButtons: + ret = false; + break; + case SH_ToolTip_Mask: + if (option) { + if (QStyleHintReturnMask *mask = qstyleoption_cast(returnData)) { + ret = true; + XPThemeData themeData(widget, 0, QLatin1String("TOOLTIP"), TTP_STANDARD, TTSS_NORMAL, option->rect); + mask->region = d->region(themeData); + } + } + break; + case SH_Table_GridLineColor: + if (option) + ret = option->palette.color(QPalette::Base).darker(118).rgb(); + else + ret = -1; + break; + default: + ret = QWindowsXPStyle::styleHint(hint, option, widget, returnData); + break; + } + return ret; +} + + +/*! + \internal + */ +QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, + SubControl subControl, const QWidget *widget) const +{ + if (!QWindowsVistaStylePrivate::useVista()) + return QWindowsStyle::subControlRect(control, option, subControl, widget); + + QRect rect = QWindowsXPStyle::subControlRect(control, option, subControl, widget); + switch (control) { +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(option)) { + int x = cb->rect.x(), + y = cb->rect.y(), + wi = cb->rect.width(), + he = cb->rect.height(); + int xpos = x; + int margin = cb->frame ? 3 : 0; + int bmarg = cb->frame ? 2 : 0; + int arrowButtonWidth = bmarg + 16; + xpos += wi - arrowButtonWidth; + + switch (subControl) { + case SC_ComboBoxFrame: + rect = cb->rect; + break; + case SC_ComboBoxArrow: + rect.setRect(xpos, y , arrowButtonWidth, he); + break; + case SC_ComboBoxEditField: + rect.setRect(x + margin, y + margin, wi - 2 * margin - 16, he - 2 * margin); + break; + case SC_ComboBoxListBoxPopup: + rect = cb->rect; + break; + default: + break; + } + rect = visualRect(cb->direction, cb->rect, rect); + return rect; + } +#endif // QT_NO_COMBOBOX + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(option)) { + if (!buttonVisible(subControl, tb)) + return rect; + const bool isToolTitle = false; + const int height = tb->rect.height(); + const int width = tb->rect.width(); + int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4; + + const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); + const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0; + const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0; + const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0; + const bool contextHint = (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) != 0; + const bool shadeHint = (tb->titleBarFlags & Qt::WindowShadeButtonHint) != 0; + + switch (subControl) { + case SC_TitleBarLabel: + rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height); + if (isToolTitle) { + if (sysmenuHint) { + rect.adjust(0, 0, -buttonWidth - 3, 0); + } + if (minimizeHint || maximizeHint) + rect.adjust(0, 0, -buttonWidth - 2, 0); + } else { + if (sysmenuHint) { + const int leftOffset = height - 8; + rect.adjust(leftOffset, 0, 0, 4); + } + if (minimizeHint) + rect.adjust(0, 0, -buttonWidth - 2, 0); + if (maximizeHint) + rect.adjust(0, 0, -buttonWidth - 2, 0); + if (contextHint) + rect.adjust(0, 0, -buttonWidth - 2, 0); + if (shadeHint) + rect.adjust(0, 0, -buttonWidth - 2, 0); + } + rect.translate(0, 2); + rect = visualRect(option->direction, option->rect, rect); + break; + case SC_TitleBarSysMenu: + { + const int controlTop = 6; + const int controlHeight = height - controlTop - 3; + int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); + QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent)); + if (tb->icon.isNull()) + iconSize = QSize(controlHeight, controlHeight); + int hPad = (controlHeight - iconSize.height())/2; + int vPad = (controlHeight - iconSize.width())/2; + rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height()); + rect.translate(0, 3); + rect = visualRect(option->direction, option->rect, rect); + } + break; + default: + break; + } + } + break; + default: + break; + } + return rect; +} + +/*! + \internal + */ +bool QWindowsVistaStyle::event(QEvent *e) +{ + Q_D(QWindowsVistaStyle); + switch (e->type()) { + case QEvent::Timer: + { + QTimerEvent *timerEvent = (QTimerEvent *)e; + if (d->animationTimer.timerId() == timerEvent->timerId()) { + d->timerEvent(); + e->accept(); + return true; + } + } + break; + default: + break; + } + return QWindowsXPStyle::event(e); +} + +/*! + \internal + */ +QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, + const QPoint &pos, const QWidget *widget) const +{ + if (!QWindowsVistaStylePrivate::useVista()) { + return QWindowsStyle::hitTestComplexControl(control, option, pos, widget); + } + return QWindowsXPStyle::hitTestComplexControl(control, option, pos, widget); +} + +/*! + \internal + */ +int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const +{ + if (!QWindowsVistaStylePrivate::useVista()) { + return QWindowsStyle::pixelMetric(metric, option, widget); + } + switch (metric) { + + case PM_DockWidgetTitleBarButtonMargin: + return int(QStyleHelper::dpiScaled(5.)); + case PM_ScrollBarSliderMin: + return int(QStyleHelper::dpiScaled(18.)); + case PM_MenuHMargin: + case PM_MenuVMargin: + return 0; + case PM_MenuPanelWidth: + return 3; + default: + break; + } + return QWindowsXPStyle::pixelMetric(metric, option, widget); +} + +/*! + \internal + */ +QPalette QWindowsVistaStyle::standardPalette() const +{ + return QWindowsXPStyle::standardPalette(); +} + +/*! + \internal + */ +void QWindowsVistaStyle::polish(QApplication *app) +{ + QWindowsXPStyle::polish(app); +} + +/*! + \internal + */ +void QWindowsVistaStyle::polish(QWidget *widget) +{ + QWindowsXPStyle::polish(widget); +#ifndef QT_NO_LINEEDIT + if (qobject_cast(widget)) + widget->setAttribute(Qt::WA_Hover); + else +#endif // QT_NO_LINEEDIT + if (qobject_cast(widget)) + widget->setAttribute(Qt::WA_Hover); + else if (qobject_cast(widget)) { + QFont buttonFont = widget->font(); + buttonFont.setFamily(QLatin1String("Segoe UI")); + widget->setFont(buttonFont); + } + else if (widget->inherits("QTipLabel")){ + //note that since tooltips are not reused + //we do not have to care about unpolishing + widget->setContentsMargins(3, 0, 4, 0); + COLORREF bgRef; + HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"TOOLTIP"); + if (theme) { + if (pGetThemeColor(theme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &bgRef) == S_OK) { + QColor textColor = QColor::fromRgb(bgRef); + QPalette pal; + pal.setColor(QPalette::All, QPalette::ToolTipText, textColor); + widget->setPalette(pal); + } + } + } else if (qobject_cast (widget)) { + widget->setAttribute(Qt::WA_StyledBackground); + QDialogButtonBox *buttonBox = widget->findChild(QLatin1String("qt_msgbox_buttonbox")); + if (buttonBox) + buttonBox->setContentsMargins(0, 9, 0, 0); + } +#ifndef QT_NO_INPUTDIALOG + else if (qobject_cast (widget)) { + widget->setAttribute(Qt::WA_StyledBackground); + QDialogButtonBox *buttonBox = widget->findChild(QLatin1String("qt_inputdlg_buttonbox")); + if (buttonBox) + buttonBox->setContentsMargins(0, 9, 0, 0); + } +#endif // QT_NO_INPUTDIALOG + else if (QTreeView *tree = qobject_cast (widget)) { + tree->viewport()->setAttribute(Qt::WA_Hover); + } + else if (QListView *list = qobject_cast (widget)) { + list->viewport()->setAttribute(Qt::WA_Hover); + } +} + +/*! + \internal + */ +void QWindowsVistaStyle::unpolish(QWidget *widget) +{ + QWindowsXPStyle::unpolish(widget); + + QWindowsVistaStylePrivate *d = const_cast(d_func()); + d->stopAnimation(widget); + +#ifndef QT_NO_LINEEDIT + if (qobject_cast(widget)) + widget->setAttribute(Qt::WA_Hover, false); + else +#endif // QT_NO_LINEEDIT + if (qobject_cast(widget)) + widget->setAttribute(Qt::WA_Hover, false); + else if (qobject_cast (widget)) { + widget->setAttribute(Qt::WA_StyledBackground, false); + QDialogButtonBox *buttonBox = widget->findChild(QLatin1String("qt_msgbox_buttonbox")); + if (buttonBox) + buttonBox->setContentsMargins(0, 0, 0, 0); + } +#ifndef QT_NO_INPUTDIALOG + else if (qobject_cast (widget)) { + widget->setAttribute(Qt::WA_StyledBackground, false); + QDialogButtonBox *buttonBox = widget->findChild(QLatin1String("qt_inputdlg_buttonbox")); + if (buttonBox) + buttonBox->setContentsMargins(0, 0, 0, 0); + } +#endif // QT_NO_INPUTDIALOG + else if (QTreeView *tree = qobject_cast (widget)) { + tree->viewport()->setAttribute(Qt::WA_Hover, false); + } else if (qobject_cast(widget)) { + QFont font = QApplication::font("QCommandLinkButton"); + QFont widgetFont = widget->font(); + widgetFont.setFamily(font.family()); //Only family set by polish + widget->setFont(widgetFont); + } +} + + +/*! + \internal + */ +void QWindowsVistaStyle::unpolish(QApplication *app) +{ + QWindowsXPStyle::unpolish(app); +} + +/*! + \internal + */ +void QWindowsVistaStyle::polish(QPalette &pal) +{ + QWindowsStyle::polish(pal); + pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(104)); +} + +/*! + \internal + */ +QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option, + const QWidget *widget) const +{ + if (!QWindowsVistaStylePrivate::useVista()) { + return QWindowsStyle::standardPixmap(standardPixmap, option, widget); + } + return QWindowsXPStyle::standardPixmap(standardPixmap, option, widget); +} + +QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() : + QWindowsXPStylePrivate(), m_treeViewHelper(0) +{ + resolveSymbols(); +} + +QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate() +{ + delete m_treeViewHelper; +} + +void QWindowsVistaStylePrivate::timerEvent() +{ + for (int i = animations.size() - 1 ; i >= 0 ; --i) { + + if (animations[i]->widget()) + animations[i]->widget()->update(); + + if (!animations[i]->widget() || + !animations[i]->widget()->isEnabled() || + !animations[i]->widget()->isVisible() || + animations[i]->widget()->window()->isMinimized() || + !animations[i]->running() || + !QWindowsVistaStylePrivate::useVista()) + { + QWindowsVistaAnimation *a = animations.takeAt(i); + delete a; + } + } + if (animations.size() == 0 && animationTimer.isActive()) { + animationTimer.stop(); + } +} + +void QWindowsVistaStylePrivate::stopAnimation(const QWidget *w) +{ + for (int i = animations.size() - 1 ; i >= 0 ; --i) { + if (animations[i]->widget() == w) { + QWindowsVistaAnimation *a = animations.takeAt(i); + delete a; + break; + } + } +} + +void QWindowsVistaStylePrivate::startAnimation(QWindowsVistaAnimation *t) +{ + Q_Q(QWindowsVistaStyle); + stopAnimation(t->widget()); + animations.append(t); + if (animations.size() > 0 && !animationTimer.isActive()) { + animationTimer.start(45, q); + } +} + +bool QWindowsVistaStylePrivate::transitionsEnabled() const +{ + BOOL animEnabled = false; + if (SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0)) + { + if (animEnabled) + return true; + } + return false; +} + + +QWindowsVistaAnimation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const +{ + if (!widget) + return 0; + foreach (QWindowsVistaAnimation *a, animations) { + if (a->widget() == widget) + return a; + } + return 0; +} + + +/*! \internal + Returns true if all the necessary theme engine symbols were + resolved. +*/ +bool QWindowsVistaStylePrivate::resolveSymbols() +{ + static bool tried = false; + if (!tried) { + tried = true; + QSystemLibrary themeLib(QLatin1String("uxtheme")); + pSetWindowTheme = (PtrSetWindowTheme )themeLib.resolve("SetWindowTheme"); + pIsThemePartDefined = (PtrIsThemePartDefined )themeLib.resolve("IsThemePartDefined"); + pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); + pOpenThemeData = (PtrOpenThemeData )themeLib.resolve("OpenThemeData"); + pCloseThemeData = (PtrCloseThemeData )themeLib.resolve("CloseThemeData"); + pDrawThemeBackground = (PtrDrawThemeBackground )themeLib.resolve("DrawThemeBackground"); + pDrawThemeBackgroundEx = (PtrDrawThemeBackgroundEx )themeLib.resolve("DrawThemeBackgroundEx"); + pGetCurrentThemeName = (PtrGetCurrentThemeName )themeLib.resolve("GetCurrentThemeName"); + pGetThemeBool = (PtrGetThemeBool )themeLib.resolve("GetThemeBool"); + pGetThemeColor = (PtrGetThemeColor )themeLib.resolve("GetThemeColor"); + pGetThemeEnumValue = (PtrGetThemeEnumValue )themeLib.resolve("GetThemeEnumValue"); + pGetThemeFilename = (PtrGetThemeFilename )themeLib.resolve("GetThemeFilename"); + pGetThemeFont = (PtrGetThemeFont )themeLib.resolve("GetThemeFont"); + pGetThemeInt = (PtrGetThemeInt )themeLib.resolve("GetThemeInt"); + pGetThemeIntList = (PtrGetThemeIntList )themeLib.resolve("GetThemeIntList"); + pGetThemeMargins = (PtrGetThemeMargins )themeLib.resolve("GetThemeMargins"); + pGetThemeMetric = (PtrGetThemeMetric )themeLib.resolve("GetThemeMetric"); + pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); + pGetThemePosition = (PtrGetThemePosition )themeLib.resolve("GetThemePosition"); + pGetThemeRect = (PtrGetThemeRect )themeLib.resolve("GetThemeRect"); + pGetThemeString = (PtrGetThemeString )themeLib.resolve("GetThemeString"); + pGetThemeTransitionDuration = (PtrGetThemeTransitionDuration)themeLib.resolve("GetThemeTransitionDuration"); + pGetThemePropertyOrigin = (PtrGetThemePropertyOrigin)themeLib.resolve("GetThemePropertyOrigin"); + } + return pGetThemeTransitionDuration != 0; +} + +/* + * We need to set the windows explorer theme explicitly on a native widget + * in order to get Vista-style item view themes + */ +QWidget *QWindowsVistaStylePrivate::treeViewHelper() +{ + if (!m_treeViewHelper) { + m_treeViewHelper = new QWidget(0); + pSetWindowTheme(m_treeViewHelper->winId(), L"explorer", NULL); + } + return m_treeViewHelper; +} + + +/*! +\internal +*/ +QIcon QWindowsVistaStyle::standardIconImplementation(StandardPixmap standardIcon, + const QStyleOption *option, + const QWidget *widget) const +{ + if (!QWindowsVistaStylePrivate::useVista()) { + return QWindowsStyle::standardIconImplementation(standardIcon, option, widget); + } + + QWindowsVistaStylePrivate *d = const_cast(d_func()); + switch(standardIcon) { + case SP_CommandLink: + { + XPThemeData theme(0, 0, QLatin1String("BUTTON"), BP_COMMANDLINKGLYPH, CMDLGS_NORMAL); + if (theme.isValid()) { + SIZE size; + pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + QIcon linkGlyph; + QPixmap pm = QPixmap(size.cx, size.cy); + pm.fill(Qt::transparent); + QPainter p(&pm); + theme.painter = &p; + theme.rect = QRect(0, 0, size.cx, size.cy); + d->drawBackground(theme); + linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal + pm.fill(Qt::transparent); + + theme.stateId = CMDLGS_PRESSED; + d->drawBackground(theme); + linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed + pm.fill(Qt::transparent); + + theme.stateId = CMDLGS_HOT; + d->drawBackground(theme); + linkGlyph.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover + pm.fill(Qt::transparent); + + theme.stateId = CMDLGS_DISABLED; + d->drawBackground(theme); + linkGlyph.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled + return linkGlyph; + } + } + break; + default: + break; + } + return QWindowsXPStyle::standardIconImplementation(standardIcon, option, widget); +} + +QT_END_NAMESPACE + +#endif //QT_NO_WINDOWSVISTA diff --git a/src/widgets/styles/qwindowsvistastyle.h b/src/widgets/styles/qwindowsvistastyle.h new file mode 100644 index 0000000000..c13dccf28b --- /dev/null +++ b/src/widgets/styles/qwindowsvistastyle.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSVISTASTYLE_H +#define QWINDOWSVISTASTYLE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_STYLE_WINDOWSVISTA) + +class QWindowsVistaStylePrivate; +class Q_GUI_EXPORT QWindowsVistaStyle : public QWindowsXPStyle +{ + Q_OBJECT +public: + QWindowsVistaStyle(); + + void drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget = 0) const; + void drawControl(ControlElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const; + void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const; + QSize sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const; + + QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const; + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, + SubControl sc, const QWidget *widget) const; + + SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, + const QPoint &pos, const QWidget *widget = 0) const; + + QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget = 0) const; + int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const; + int styleHint(StyleHint hint, const QStyleOption *opt = 0, const QWidget *widget = 0, + QStyleHintReturn *returnData = 0) const; + + + void polish(QWidget *widget); + void unpolish(QWidget *widget); + void polish(QPalette &pal); + void polish(QApplication *app); + void unpolish(QApplication *app); + bool event(QEvent *event); + QPalette standardPalette() const; + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget = 0) const; + +private: + Q_DISABLE_COPY(QWindowsVistaStyle) + Q_DECLARE_PRIVATE(QWindowsVistaStyle) + friend class QStyleFactory; +}; +#endif //QT_NO_STYLE_WINDOWSVISTA + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif //QWINDOWSVISTASTYLE_H diff --git a/src/widgets/styles/qwindowsvistastyle_p.h b/src/widgets/styles/qwindowsvistastyle_p.h new file mode 100644 index 0000000000..ba653880c9 --- /dev/null +++ b/src/widgets/styles/qwindowsvistastyle_p.h @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSVISTASTYLE_P_H +#define QWINDOWSVISTASTYLE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qwindowsvistastyle.h" + +#if !defined(QT_NO_STYLE_WINDOWSVISTA) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +#if !defined(SCHEMA_VERIFY_VSSYM32) +#define TMT_ANIMATIONDURATION 5006 +#define TMT_TRANSITIONDURATIONS 6000 +#define EP_EDITBORDER_NOSCROLL 6 +#define EP_EDITBORDER_HVSCROLL 9 +#define EP_BACKGROUND 3 +#define EBS_NORMAL 1 +#define EBS_HOT 2 +#define EBS_DISABLED 3 +#define EBS_READONLY 5 +#define PBS_DEFAULTED_ANIMATING 6 +#define MBI_NORMAL 1 +#define MBI_HOT 2 +#define MBI_PUSHED 3 +#define MBI_DISABLED 4 +#define MB_ACTIVE 1 +#define MB_INACTIVE 2 +#define PP_FILL 5 +#define PP_FILLVERT 6 +#define PP_MOVEOVERLAY 8 +#define PP_MOVEOVERLAYVERT 10 +#define MENU_BARBACKGROUND 7 +#define MENU_BARITEM 8 +#define MENU_POPUPCHECK 11 +#define MENU_POPUPCHECKBACKGROUND 12 +#define MENU_POPUPGUTTER 13 +#define MENU_POPUPITEM 14 +#define MENU_POPUPBORDERS 10 +#define MENU_POPUPSEPARATOR 15 +#define MC_CHECKMARKNORMAL 1 +#define MC_CHECKMARKDISABLED 2 +#define MC_BULLETNORMAL 3 +#define MC_BULLETDISABLED 4 +#define ABS_UPHOVER 17 +#define ABS_DOWNHOVER 18 +#define ABS_LEFTHOVER 19 +#define ABS_RIGHTHOVER 20 +#define CP_DROPDOWNBUTTONRIGHT 6 +#define CP_DROPDOWNBUTTONLEFT 7 +#define SCRBS_HOVER 5 +#define TVP_HOTGLYPH 4 +#define SPI_GETCLIENTAREAANIMATION 0x1042 +#define TDLG_PRIMARYPANEL 1 +#define TDLG_SECONDARYPANEL 8 +#endif + +class QWindowsVistaAnimation +{ +public : + QWindowsVistaAnimation() : _running(true) { } + virtual ~QWindowsVistaAnimation() { } + QWidget * widget() const { return _widget; } + bool running() const { return _running; } + const QTime &startTime() const { return _startTime; } + void setRunning(bool val) { _running = val; } + void setWidget(QWidget *widget) { _widget = widget; } + void setStartTime(const QTime &startTime) { _startTime = startTime; } + virtual void paint(QPainter *painter, const QStyleOption *option); + +protected: + void drawBlendedImage(QPainter *painter, QRect rect, float value); + QTime _startTime; + QPointer _widget; + QImage _primaryImage; + QImage _secondaryImage; + QImage _tempImage; + bool _running; +}; + + +// Handles state transition animations +class QWindowsVistaTransition : public QWindowsVistaAnimation +{ +public : + QWindowsVistaTransition() : QWindowsVistaAnimation() {} + virtual ~QWindowsVistaTransition() { } + void setDuration(int duration) { _duration = duration; } + void setStartImage(const QImage &image) { _primaryImage = image; } + void setEndImage(const QImage &image) { _secondaryImage = image; } + virtual void paint(QPainter *painter, const QStyleOption *option); + int duration() const { return _duration; } + int _duration; //set time in ms to complete a state transition +}; + + +// Handles pulse animations (default buttons) +class QWindowsVistaPulse: public QWindowsVistaAnimation +{ +public : + QWindowsVistaPulse() : QWindowsVistaAnimation() {} + virtual ~QWindowsVistaPulse() { } + void setDuration(int duration) { _duration = duration; } + void setPrimaryImage(const QImage &image) { _primaryImage = image; } + void setAlternateImage(const QImage &image) { _secondaryImage = image; } + virtual void paint(QPainter *painter, const QStyleOption *option); + int duration() const { return _duration; } + int _duration; //time in ms to complete a pulse cycle +}; + + +class QWindowsVistaStylePrivate : public QWindowsXPStylePrivate +{ + Q_DECLARE_PUBLIC(QWindowsVistaStyle) + +public: + QWindowsVistaStylePrivate(); + ~QWindowsVistaStylePrivate(); + static bool resolveSymbols(); + static inline bool useVista(); + void startAnimation(QWindowsVistaAnimation *); + void stopAnimation(const QWidget *); + QWindowsVistaAnimation* widgetAnimation(const QWidget *) const; + void timerEvent(); + bool transitionsEnabled() const; + QWidget *treeViewHelper(); + +private: + QList animations; + QBasicTimer animationTimer; + QWidget *m_treeViewHelper; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_WINDOWSVISTA + +#endif // QWINDOWSVISTASTYLE_P_H diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp new file mode 100644 index 0000000000..74a20fce29 --- /dev/null +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -0,0 +1,4271 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qwindowsxpstyle.h" +#include "qwindowsxpstyle_p.h" + +#if !defined(QT_NO_STYLE_WINDOWSXP) || defined(QT_PLUGIN) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// Runtime resolved theme engine function calls +typedef bool (WINAPI *PtrIsAppThemed)(); +typedef bool (WINAPI *PtrIsThemeActive)(); +typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); +typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); +typedef HRESULT (WINAPI *PtrCloseThemeData)(HTHEME hTheme); +typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); +typedef HRESULT (WINAPI *PtrDrawThemeBackgroundEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions); +typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars); +typedef HRESULT (WINAPI *PtrGetThemeDocumentationProperty)(LPCWSTR pszThemeName, LPCWSTR pszPropertyName, OUT LPWSTR pszValueBuff, int cchMaxValChars); +typedef HRESULT (WINAPI *PtrGetThemeBool)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT BOOL *pfVal); +typedef HRESULT (WINAPI *PtrGetThemeColor)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor); +typedef HRESULT (WINAPI *PtrGetThemeEnumValue)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); +typedef HRESULT (WINAPI *PtrGetThemeFilename)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars); +typedef HRESULT (WINAPI *PtrGetThemeFont)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT LOGFONT *pFont); +typedef HRESULT (WINAPI *PtrGetThemeInt)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); +typedef HRESULT (WINAPI *PtrGetThemeIntList)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT INTLIST *pIntList); +typedef HRESULT (WINAPI *PtrGetThemeMargins)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins); +typedef HRESULT (WINAPI *PtrGetThemeMetric)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT int *piVal); +typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); +typedef HRESULT (WINAPI *PtrGetThemePosition)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT POINT *pPoint); +typedef HRESULT (WINAPI *PtrGetThemePropertyOrigin)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin); +typedef HRESULT (WINAPI *PtrGetThemeRect)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT RECT *pRect); +typedef HRESULT (WINAPI *PtrGetThemeString)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars); +typedef HRESULT (WINAPI *PtrGetThemeBackgroundRegion)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, const RECT *pRect, OUT HRGN *pRegion); +typedef BOOL (WINAPI *PtrIsThemeBackgroundPartiallyTransparent)(HTHEME hTheme, int iPartId, int iStateId); + +static PtrIsAppThemed pIsAppThemed = 0; +static PtrIsThemeActive pIsThemeActive = 0; +static PtrOpenThemeData pOpenThemeData = 0; +static PtrCloseThemeData pCloseThemeData = 0; +static PtrDrawThemeBackground pDrawThemeBackground = 0; +static PtrDrawThemeBackgroundEx pDrawThemeBackgroundEx = 0; +static PtrGetCurrentThemeName pGetCurrentThemeName = 0; +static PtrGetThemeBool pGetThemeBool = 0; +static PtrGetThemeColor pGetThemeColor = 0; +static PtrGetThemeEnumValue pGetThemeEnumValue = 0; +static PtrGetThemeFilename pGetThemeFilename = 0; +static PtrGetThemeFont pGetThemeFont = 0; +static PtrGetThemeInt pGetThemeInt = 0; +static PtrGetThemeIntList pGetThemeIntList = 0; +static PtrGetThemeMargins pGetThemeMargins = 0; +static PtrGetThemeMetric pGetThemeMetric = 0; +static PtrGetThemePartSize pGetThemePartSize = 0; +static PtrGetThemePosition pGetThemePosition = 0; +static PtrGetThemePropertyOrigin pGetThemePropertyOrigin = 0; +static PtrGetThemeRect pGetThemeRect = 0; +static PtrGetThemeString pGetThemeString = 0; +static PtrGetThemeBackgroundRegion pGetThemeBackgroundRegion = 0; +static PtrGetThemeDocumentationProperty pGetThemeDocumentationProperty = 0; +static PtrIsThemeBackgroundPartiallyTransparent pIsThemeBackgroundPartiallyTransparent = 0; + +// General const values +static const int windowsItemFrame = 2; // menu item frame width +static const int windowsItemHMargin = 3; // menu item hor text margin +static const int windowsItemVMargin = 0; // menu item ver text margin +static const int windowsArrowHMargin = 6; // arrow horizontal margin +static const int windowsRightBorder = 12; // right border on windows + +// External function calls +extern Q_GUI_EXPORT HDC qt_win_display_dc(); +extern QRegion qt_region_from_HRGN(HRGN rgn); + + + +// Theme data helper ------------------------------------------------------------------------------ +/* \internal + Returns true if the themedata is valid for use. +*/ +bool XPThemeData::isValid() +{ + return QWindowsXPStylePrivate::useXP() && name.size() && handle(); +} + + +/* \internal + Returns the theme engine handle to the specific class. + If the handle hasn't been opened before, it opens the data, and + adds it to a static map, for caching. +*/ +HTHEME XPThemeData::handle() +{ + if (!QWindowsXPStylePrivate::useXP()) + return 0; + + if (!htheme && QWindowsXPStylePrivate::handleMap) + htheme = QWindowsXPStylePrivate::handleMap->operator[](name); + + if (!htheme) { + htheme = pOpenThemeData(QWindowsXPStylePrivate::winId(widget), (wchar_t*)name.utf16()); + if (htheme) { + if (!QWindowsXPStylePrivate::handleMap) + QWindowsXPStylePrivate::handleMap = new QMap; + QWindowsXPStylePrivate::handleMap->operator[](name) = htheme; + } + } + + return htheme; +} + +/* \internal + Converts a QRect to the native RECT structure. +*/ +RECT XPThemeData::toRECT(const QRect &qr) +{ + RECT r; + r.left = qr.x(); + r.right = qr.x() + qr.width(); + r.top = qr.y(); + r.bottom = qr.y() + qr.height(); + return r; +} + +/* \internal + Returns the native region of a part, if the part is considered + transparent. The region is scaled to the parts size (rect). +*/ +HRGN XPThemeData::mask() +{ + if (!pIsThemeBackgroundPartiallyTransparent(handle(), partId, stateId)) + return 0; + + HRGN hrgn; + HDC dc = painter == 0 ? 0 : painter->paintEngine()->getDC(); + RECT nativeRect = toRECT(rect); + pGetThemeBackgroundRegion(handle(), dc, partId, stateId, &nativeRect, &hrgn); + if (dc) + painter->paintEngine()->releaseDC(dc); + return hrgn; +} + +// QWindowsXPStylePrivate ------------------------------------------------------------------------- +// Static initializations +QWidget *QWindowsXPStylePrivate::limboWidget = 0; +QPixmap *QWindowsXPStylePrivate::tabbody = 0; +QMap *QWindowsXPStylePrivate::handleMap = 0; +bool QWindowsXPStylePrivate::use_xp = false; +QBasicAtomicInt QWindowsXPStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting + +/* \internal + Checks if the theme engine can/should be used, or if we should + fall back to Windows style. +*/ +bool QWindowsXPStylePrivate::useXP(bool update) +{ + if (!update) + return use_xp; + return (use_xp = resolveSymbols() && pIsThemeActive() + && (pIsAppThemed() || !QApplication::instance())); +} + +/* \internal + Handles refcounting, and queries the theme engine for usage. +*/ +void QWindowsXPStylePrivate::init(bool force) +{ + if (ref.ref() && !force) + return; + if (!force) // -1 based atomic refcounting + ref.ref(); + + useXP(true); +} + +/* \internal + Cleans up all static data. +*/ +void QWindowsXPStylePrivate::cleanup(bool force) +{ + if(bufferBitmap) { + if (bufferDC && nullBitmap) + SelectObject(bufferDC, nullBitmap); + DeleteObject(bufferBitmap); + bufferBitmap = 0; + } + + if(bufferDC) + DeleteDC(bufferDC); + bufferDC = 0; + + if (ref.deref() && !force) + return; + if (!force) // -1 based atomic refcounting + ref.deref(); + + use_xp = false; + cleanupHandleMap(); + if (limboWidget) { + if (QApplication::closingDown()) + delete limboWidget; + else + limboWidget->deleteLater(); + } + delete tabbody; + limboWidget = 0; + tabbody = 0; +} + +/* \internal + Closes all open theme data handles to ensure that we don't leak + resources, and that we don't refere to old handles when for + example the user changes the theme style. +*/ +void QWindowsXPStylePrivate::cleanupHandleMap() +{ + if (!handleMap) + return; + + QMap::Iterator it; + for (it = handleMap->begin(); it != handleMap->end(); ++it) + pCloseThemeData(it.value()); + delete handleMap; + handleMap = 0; +} + +/*! \internal + This function will always return a valid window handle, and might + create a limbo widget to do so. + We often need a window handle to for example open theme data, so + this function ensures that we get one. +*/ +HWND QWindowsXPStylePrivate::winId(const QWidget *widget) +{ + if (widget && widget->internalWinId()) + return widget->internalWinId(); + + if (!limboWidget) { + limboWidget = new QWidget(0); + limboWidget->createWinId(); + limboWidget->setObjectName(QLatin1String("xp_limbo_widget")); + // We don't need this internal widget to appear in QApplication::topLevelWidgets() + if (QWidgetPrivate::allWidgets) + QWidgetPrivate::allWidgets->remove(limboWidget); + } + + return limboWidget->winId(); +} + +/*! \internal + Returns the pointer to a tab widgets body pixmap, scaled to the + height of the screen. This way the theme engine doesn't need to + scale the body for every time we ask for it. (Speed optimization) +*/ +const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *) +{ + if (!tabbody) { + SIZE sz; + XPThemeData theme(0, 0, QLatin1String("TAB"), TABP_BODY); + pGetThemePartSize(theme.handle(), qt_win_display_dc(), TABP_BODY, 0, 0, TS_TRUE, &sz); + + tabbody = new QPixmap(sz.cx, QApplication::desktop()->screenGeometry().height()); + QPainter painter(tabbody); + theme.rect = QRect(0, 0, sz.cx, sz.cy); + drawBackground(theme); + // We fill with the last line of the themedata, that + // way we don't get a tiled pixmap inside big tabs + QPixmap temp(sz.cx, 1); + painter.drawPixmap(0, 0, temp, 0, sz.cy-1, -1, -1); + painter.drawTiledPixmap(0, sz.cy, sz.cx, tabbody->height()-sz.cy, temp); + } + return tabbody; +} + +/*! \internal + Returns true if all the necessary theme engine symbols were + resolved. +*/ +bool QWindowsXPStylePrivate::resolveSymbols() +{ + static bool tried = false; + if (!tried) { + tried = true; + QSystemLibrary themeLib(QLatin1String("uxtheme")); + pIsAppThemed = (PtrIsAppThemed)themeLib.resolve("IsAppThemed"); + if (pIsAppThemed) { + pIsThemeActive = (PtrIsThemeActive )themeLib.resolve("IsThemeActive"); + pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); + pOpenThemeData = (PtrOpenThemeData )themeLib.resolve("OpenThemeData"); + pCloseThemeData = (PtrCloseThemeData )themeLib.resolve("CloseThemeData"); + pDrawThemeBackground = (PtrDrawThemeBackground )themeLib.resolve("DrawThemeBackground"); + pDrawThemeBackgroundEx = (PtrDrawThemeBackgroundEx )themeLib.resolve("DrawThemeBackgroundEx"); + pGetCurrentThemeName = (PtrGetCurrentThemeName )themeLib.resolve("GetCurrentThemeName"); + pGetThemeBool = (PtrGetThemeBool )themeLib.resolve("GetThemeBool"); + pGetThemeColor = (PtrGetThemeColor )themeLib.resolve("GetThemeColor"); + pGetThemeEnumValue = (PtrGetThemeEnumValue )themeLib.resolve("GetThemeEnumValue"); + pGetThemeFilename = (PtrGetThemeFilename )themeLib.resolve("GetThemeFilename"); + pGetThemeFont = (PtrGetThemeFont )themeLib.resolve("GetThemeFont"); + pGetThemeInt = (PtrGetThemeInt )themeLib.resolve("GetThemeInt"); + pGetThemeIntList = (PtrGetThemeIntList )themeLib.resolve("GetThemeIntList"); + pGetThemeMargins = (PtrGetThemeMargins )themeLib.resolve("GetThemeMargins"); + pGetThemeMetric = (PtrGetThemeMetric )themeLib.resolve("GetThemeMetric"); + pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); + pGetThemePosition = (PtrGetThemePosition )themeLib.resolve("GetThemePosition"); + pGetThemePropertyOrigin = (PtrGetThemePropertyOrigin)themeLib.resolve("GetThemePropertyOrigin"); + pGetThemeRect = (PtrGetThemeRect )themeLib.resolve("GetThemeRect"); + pGetThemeString = (PtrGetThemeString )themeLib.resolve("GetThemeString"); + pGetThemeBackgroundRegion = (PtrGetThemeBackgroundRegion )themeLib.resolve("GetThemeBackgroundRegion"); + pGetThemeDocumentationProperty = (PtrGetThemeDocumentationProperty )themeLib.resolve("GetThemeDocumentationProperty"); + pIsThemeBackgroundPartiallyTransparent = (PtrIsThemeBackgroundPartiallyTransparent)themeLib.resolve("IsThemeBackgroundPartiallyTransparent"); + } + } + + return pIsAppThemed != 0; +} + +/*! \internal + Returns a native buffer (DIB section) of at least the size of + ( \a x , \a y ). The buffer has a 32 bit depth, to not lose + the alpha values on proper alpha-pixmaps. +*/ +HBITMAP QWindowsXPStylePrivate::buffer(int w, int h) +{ + // If we already have a HBITMAP which is of adequate size, just return that + if (bufferBitmap) { + if (bufferW >= w && bufferH >= h) + return bufferBitmap; + // Not big enough, discard the old one + if (bufferDC && nullBitmap) + SelectObject(bufferDC, nullBitmap); + DeleteObject(bufferBitmap); + bufferBitmap = 0; + } + + w = qMax(bufferW, w); + h = qMax(bufferH, h); + + if (!bufferDC) + bufferDC = CreateCompatibleDC(qt_win_display_dc()); + + // Define the header + BITMAPINFO bmi; + memset(&bmi, 0, sizeof(bmi)); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = w; + bmi.bmiHeader.biHeight = -h; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + + // Create the pixmap + bufferPixels = 0; + bufferBitmap = CreateDIBSection(bufferDC, &bmi, DIB_RGB_COLORS, (void **) &bufferPixels, 0, 0); + GdiFlush(); + nullBitmap = (HBITMAP)SelectObject(bufferDC, bufferBitmap); + + if (!bufferBitmap) { + qErrnoWarning("QWindowsXPStylePrivate::buffer(w,h), failed to create dibsection"); + bufferW = 0; + bufferH = 0; + return 0; + } + if (!bufferPixels) { + qErrnoWarning("QWindowsXPStylePrivate::buffer(w,h), did not allocate pixel data"); + bufferW = 0; + bufferH = 0; + return 0; + } + bufferW = w; + bufferH = h; +#ifdef DEBUG_XP_STYLE + qDebug("Creating new dib section (%d, %d)", w, h); +#endif + return bufferBitmap; +} + +/*! \internal + Returns true if the part contains any transparency at all. This does + not indicate what kind of transparency we're dealing with. It can be + - Alpha transparency + - Masked transparency +*/ +bool QWindowsXPStylePrivate::isTransparent(XPThemeData &themeData) +{ + return pIsThemeBackgroundPartiallyTransparent(themeData.handle(), themeData.partId, + themeData.stateId); +} + + +/*! \internal + Returns a QRegion of the region of the part +*/ +QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData) +{ + HRGN hRgn = 0; + RECT rect = themeData.toRECT(themeData.rect); + if (!SUCCEEDED(pGetThemeBackgroundRegion(themeData.handle(), bufferHDC(), themeData.partId, + themeData.stateId, &rect, &hRgn))) + return QRegion(); + + HRGN dest = CreateRectRgn(0, 0, 0, 0); + const bool success = CombineRgn(dest, hRgn, 0, RGN_COPY) != ERROR; + + QRegion region; + + if (success) + region = qt_region_from_HRGN(dest); + + DeleteObject(hRgn); + DeleteObject(dest); + + return region; +} + +/*! \internal + Sets the parts region on a window. +*/ +void QWindowsXPStylePrivate::setTransparency(QWidget *widget, XPThemeData &themeData) +{ + HRGN hrgn = themeData.mask(); + if (hrgn && widget) + SetWindowRgn(winId(widget), hrgn, true); +} + +/*! \internal + Returns true if the native doublebuffer contains a pixel which + has a non-0xFF alpha value. Should only be use when its + guaranteed that data painted into the buffer wasn't a proper + alpha pixmap. +*/ +bool QWindowsXPStylePrivate::hasAnyData(const QRect &rect) +{ + const int startX = rect.left(); + const int startY = rect.top(); + const int w = rect.width(); + const int h = rect.height(); + + for (int y = startY; y < h; ++y) { + register DWORD *buffer = (DWORD*)bufferPixels + (y * bufferW); + for (int x = startX; x < w; ++x, ++buffer) { + int alpha = (*buffer) >> 24; + if (alpha != 0xFF) // buffer has been touched + return true; + } + } + return false; +} + +/*! \internal + Returns true if the native doublebuffer contains pixels with + varying alpha value. +*/ +bool QWindowsXPStylePrivate::hasAlphaChannel(const QRect &rect) +{ + const int startX = rect.left(); + const int startY = rect.top(); + const int w = rect.width(); + const int h = rect.height(); + + int firstAlpha = -1; + for (int y = startY; y < h/2; ++y) { + register DWORD *buffer = (DWORD*)bufferPixels + (y * bufferW); + for (int x = startX; x < w; ++x, ++buffer) { + int alpha = (*buffer) >> 24; + if (firstAlpha == -1) + firstAlpha = alpha; + else if (alpha != firstAlpha) + return true; + } + } + return false; +} + +/*! \internal + When the theme engine paints both a true alpha pixmap and a glyph + into our buffer, the glyph might not contain a proper alpha value. + The rule of thumb for premultiplied pixmaps is that the color + values of a pixel can never be higher than the alpha values, so + we use this to our advantage here, and fix all instances where + this occures. +*/ +bool QWindowsXPStylePrivate::fixAlphaChannel(const QRect &rect) +{ + const int startX = rect.left(); + const int startY = rect.top(); + const int w = rect.width(); + const int h = rect.height(); + bool hasFixedAlphaValue = false; + + for (int y = startY; y < h; ++y) { + register DWORD *buffer = (DWORD*)bufferPixels + (y * bufferW); + for (register int x = startX; x < w; ++x, ++buffer) { + uint pixel = *buffer; + int alpha = qAlpha(pixel); + if (qRed(pixel) > alpha || qGreen(pixel) > alpha || qBlue(pixel) > alpha) { + *buffer |= 0xff000000; + hasFixedAlphaValue = true; + } + } + } + return hasFixedAlphaValue; +} + +/*! \internal + Swaps the alpha values on certain pixels: + 0xFF?????? -> 0x00?????? + 0x00?????? -> 0xFF?????? + Used to determin the mask of a non-alpha transparent pixmap in + the native doublebuffer, and swap the alphas so we may paint + the image as a Premultiplied QImage with drawImage(), and obtain + the mask transparency. +*/ +bool QWindowsXPStylePrivate::swapAlphaChannel(const QRect &rect, bool allPixels) +{ + const int startX = rect.left(); + const int startY = rect.top(); + const int w = rect.width(); + const int h = rect.height(); + bool valueChange = false; + + // Flip the alphas, so that 255-alpha pixels are 0, and 0-alpha are 255. + for (int y = startY; y < h; ++y) { + register DWORD *buffer = (DWORD*)bufferPixels + (y * bufferW); + for (register int x = startX; x < w; ++x, ++buffer) { + if (allPixels) { + *buffer |= 0xFF000000; + continue; + } + register unsigned int alphaValue = (*buffer) & 0xFF000000; + if (alphaValue == 0xFF000000) { + *buffer = 0; + valueChange = true; + } else if (alphaValue == 0) { + *buffer |= 0xFF000000; + valueChange = true; + } + } + } + return valueChange; +} + +/*! \internal + Main theme drawing function. + Determines the correct lowlevel drawing method depending on several + factors. + Use drawBackgroundThruNativeBuffer() if: + - Painter does not have an HDC + - Theme part is flipped (mirrored horizontally) + else use drawBackgroundDirectly(). +*/ +void QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) +{ + if (themeData.rect.isEmpty()) + return; + + QPainter *painter = themeData.painter; + Q_ASSERT_X(painter != 0, "QWindowsXPStylePrivate::drawBackground()", "Trying to draw a theme part without a painter"); + if (!painter || !painter->isActive()) + return; + + painter->save(); + + bool complexXForm = painter->deviceTransform().type() > QTransform::TxTranslate; + + bool translucentToplevel = false; + QPaintDevice *pdev = painter->device(); + if (pdev->devType() == QInternal::Widget) { + QWidget *win = ((QWidget *) pdev)->window(); + translucentToplevel = win->testAttribute(Qt::WA_TranslucentBackground); + } + + bool useFallback = painter->paintEngine()->getDC() == 0 + || painter->opacity() != 1.0 + || themeData.rotate + || complexXForm + || themeData.mirrorVertically + || (themeData.mirrorHorizontally && pDrawThemeBackgroundEx == 0) + || translucentToplevel; + + if (!useFallback) + drawBackgroundDirectly(themeData); + else + drawBackgroundThruNativeBuffer(themeData); + + painter->restore(); +} + +/*! \internal + This function draws the theme parts directly to the paintengines HDC. + Do not use this if you need to perform other transformations on the + resulting data. +*/ +void QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData) +{ + QPainter *painter = themeData.painter; + HDC dc = painter->paintEngine()->getDC(); + + QPoint redirectionDelta(int(painter->deviceMatrix().dx()), + int(painter->deviceMatrix().dy())); + QRect area = themeData.rect.translated(redirectionDelta); + + QRegion sysRgn = painter->paintEngine()->systemClip(); + if (sysRgn.isEmpty()) + sysRgn = area; + else + sysRgn &= area; + if (painter->hasClipping()) + sysRgn &= painter->clipRegion().translated(redirectionDelta); + SelectClipRgn(dc, sysRgn.handle()); + +#ifdef DEBUG_XP_STYLE + printf("---[ DIRECT PAINTING ]------------------> Name(%-10s) Part(%d) State(%d)\n", + qPrintable(themeData.name), themeData.partId, themeData.stateId); + showProperties(themeData); +#endif + + RECT drawRECT = themeData.toRECT(area); + DTBGOPTS drawOptions; + drawOptions.dwSize = sizeof(drawOptions); + drawOptions.rcClip = themeData.toRECT(sysRgn.boundingRect()); + drawOptions.dwFlags = DTBG_CLIPRECT + | (themeData.noBorder ? DTBG_OMITBORDER : 0) + | (themeData.noContent ? DTBG_OMITCONTENT : 0) + | (themeData.mirrorHorizontally ? DTBG_MIRRORDC : 0); + + if (pDrawThemeBackgroundEx != 0) { + pDrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawRECT), &drawOptions); + } else { + // We are running on a system where the uxtheme.dll does not have + // the DrawThemeBackgroundEx function, so we need to clip away + // borders or contents manually. All flips and mirrors uses the + // fallback implementation + + int borderSize = 0; + PROPERTYORIGIN origin = PO_NOTFOUND; + pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &origin); + pGetThemeInt(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &borderSize); + + // Clip away border region + QRegion extraClip = sysRgn; + if ((origin == PO_CLASS || origin == PO_PART || origin == PO_STATE) && borderSize > 0) { + if (themeData.noBorder) { + // extraClip &= area is already done + drawRECT = themeData.toRECT(area.adjusted(-borderSize, -borderSize, borderSize, borderSize)); + } + + // Clip away content region + if (themeData.noContent) { + QRegion content = area.adjusted(borderSize, borderSize, -borderSize, -borderSize); + extraClip ^= content; + } + + // Set the clip region, if used.. + if (themeData.noBorder || themeData.noContent) + SelectClipRgn(dc, extraClip.handle()); + } + + pDrawThemeBackground(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawRECT), &(drawOptions.rcClip)); + } + SelectClipRgn(dc, 0); +} + +/*! \internal + This function uses a secondary Native doublebuffer for painting parts. + It should only be used when the painteengine doesn't provide a proper + HDC for direct painting (e.g. when doing a grabWidget(), painting to + other pixmaps etc), or when special transformations are needed (e.g. + flips (horizonal mirroring only, vertical are handled by the theme + engine). +*/ +void QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeData) +{ + QPainter *painter = themeData.painter; + QRect rect = themeData.rect; + + if ((themeData.rotate + 90) % 180 == 0) { // Catch 90,270,etc.. degree flips. + rect = QRect(0, 0, rect.height(), rect.width()); + } + rect.moveTo(0,0); + int partId = themeData.partId; + int stateId = themeData.stateId; + int w = rect.width(); + int h = rect.height(); + + // Values initialized later, either from cached values, or from function calls + AlphaChannelType alphaType = UnknownAlpha; + bool stateHasData = true; // We assume so; + bool hasAlpha = false; + bool partIsTransparent; + bool inspectData; + bool potentialInvalidAlpha; + + QString pixmapCacheKey = QString::fromLatin1("$qt_xp_%1p%2s%3s%4b%5c%6w%7h").arg(themeData.name) + .arg(partId).arg(stateId).arg(!themeData.noBorder).arg(!themeData.noContent) + .arg(w).arg(h); + QPixmap cachedPixmap; + ThemeMapKey key(themeData); + ThemeMapData data = alphaCache.value(key); + + bool haveCachedPixmap = false; + bool isCached = data.dataValid; + if (isCached) { + if (!(stateHasData = data.hasAnyData)) + return; // Cached NOOP + inspectData = data.wasAlphaSwapped; + partIsTransparent = data.partIsTransparent; + hasAlpha = data.hasAlphaChannel; + alphaType = data.alphaType; + potentialInvalidAlpha = data.hadInvalidAlpha; + + haveCachedPixmap = QPixmapCache::find(pixmapCacheKey, cachedPixmap); + +#ifdef DEBUG_XP_STYLE + char buf[25]; + ::sprintf(buf, "+ Pixmap(%3d, %3d) ]", w, h); + printf("---[ CACHED %s--------> Name(%-10s) Part(%d) State(%d)\n", + haveCachedPixmap ? buf : "]-------------------", + qPrintable(themeData.name), themeData.partId, themeData.stateId); +#endif + } else { + // Not cached, so get values from Theme Engine + BOOL tmt_borderonly = false; + COLORREF tmt_transparentcolor = 0x0; + PROPERTYORIGIN proporigin = PO_NOTFOUND; + pGetThemeBool(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERONLY, &tmt_borderonly); + pGetThemeColor(themeData.handle(), themeData.partId, themeData.stateId, TMT_TRANSPARENTCOLOR, &tmt_transparentcolor); + pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_CAPTIONMARGINS, &proporigin); + inspectData = (tmt_transparentcolor != 0 || tmt_borderonly || proporigin == PO_PART || proporigin == PO_STATE); + + // ### This is a vista-specific workaround for broken alpha in titlebar pixmaps + if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) { + if (themeData.partId == WP_CAPTION || themeData.partId == WP_SMALLCAPTION) + inspectData = false; + } + + partIsTransparent = isTransparent(themeData); + + potentialInvalidAlpha = false; + pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_GLYPHTYPE, &proporigin); + if (proporigin == PO_PART || proporigin == PO_STATE) { + int tmt_glyphtype = GT_NONE; + pGetThemeEnumValue(themeData.handle(), themeData.partId, themeData.stateId, TMT_GLYPHTYPE, &tmt_glyphtype); + potentialInvalidAlpha = partIsTransparent && !inspectData && tmt_glyphtype == GT_IMAGEGLYPH; + } + +#ifdef DEBUG_XP_STYLE + printf("---[ NOT CACHED ]-----------------------> Name(%-10s) Part(%d) State(%d)\n", + qPrintable(themeData.name), themeData.partId, themeData.stateId); + printf("-->partIsTransparen = %d\n", partIsTransparent); + printf("-->inspectData = %d\n", inspectData); + printf("-->potentialInvalidAlpha = %d\n", potentialInvalidAlpha); + showProperties(themeData); +#endif + } + bool wasAlphaSwapped = false; + bool wasAlphaFixed = false; + + // OLD PSDK Workaround ------------------------------------------------------------------------ + // See if we need extra clipping for the older PSDK, which does + // not have a DrawThemeBackgroundEx function for DTGB_OMITBORDER + // and DTGB_OMITCONTENT + bool addBorderContentClipping = false; + QRegion extraClip; + QRect area = rect; + if (themeData.noBorder || themeData.noContent) { + extraClip = area; + // We are running on a system where the uxtheme.dll does not have + // the DrawThemeBackgroundEx function, so we need to clip away + // borders or contents manually. + + int borderSize = 0; + PROPERTYORIGIN origin = PO_NOTFOUND; + pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &origin); + pGetThemeInt(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &borderSize); + + // Clip away border region + if ((origin == PO_CLASS || origin == PO_PART || origin == PO_STATE) && borderSize > 0) { + if (themeData.noBorder) { + extraClip &= area; + area = area.adjusted(-borderSize, -borderSize, borderSize, borderSize); + } + + // Clip away content region + if (themeData.noContent) { + QRegion content = area.adjusted(borderSize, borderSize, -borderSize, -borderSize); + extraClip ^= content; + } + } + addBorderContentClipping = (themeData.noBorder | themeData.noContent); + } + + QImage img; + if (!haveCachedPixmap) { // If the pixmap is not cached, generate it! ------------------------- + buffer(w, h); // Ensure a buffer of at least (w, h) in size + HDC dc = bufferHDC(); + + // Clear the buffer + if (alphaType != NoAlpha) { + // Consider have separate "memset" function for small chunks for more speedup + memset(bufferPixels, inspectData ? 0xFF : 0x00, bufferW * h * 4); + } + + // Difference between area and rect + int dx = area.x() - rect.x(); + int dy = area.y() - rect.y(); + int dr = area.right() - rect.right(); + int db = area.bottom() - rect.bottom(); + + // Adjust so painting rect starts from Origo + rect.moveTo(0,0); + area.moveTo(dx,dy); + DTBGOPTS drawOptions; + drawOptions.dwSize = sizeof(drawOptions); + drawOptions.rcClip = themeData.toRECT(rect); + drawOptions.dwFlags = DTBG_CLIPRECT + | (themeData.noBorder ? DTBG_OMITBORDER : 0) + | (themeData.noContent ? DTBG_OMITCONTENT : 0); + + // Drawing the part into the backing store + if (pDrawThemeBackgroundEx != 0) { + RECT rect(themeData.toRECT(area)); + pDrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &rect, &drawOptions); + } else { + // Set the clip region, if used.. + if (addBorderContentClipping) { + SelectClipRgn(dc, extraClip.handle()); + // Compensate for the noBorder area difference (noContent has the same area) + drawOptions.rcClip = themeData.toRECT(rect.adjusted(dx, dy, dr, db)); + } + + pDrawThemeBackground(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawOptions.rcClip), 0); + + if (addBorderContentClipping) + SelectClipRgn(dc, 0); + } + + // If not cached, analyze the buffer data to figure + // out alpha type, and if it contains data + if (!isCached) { + if (inspectData) + stateHasData = hasAnyData(rect); + // SHORTCUT: If the part's state has no data, cache it for NOOP later + if (!stateHasData) { + memset(&data, 0, sizeof(data)); + data.dataValid = true; + alphaCache.insert(key, data); + return; + } + hasAlpha = hasAlphaChannel(rect); + if (!hasAlpha && partIsTransparent) + potentialInvalidAlpha = true; +#if defined(DEBUG_XP_STYLE) && 1 + dumpNativeDIB(w, h); +#endif + } + + // Swap alpha values, if needed + if (inspectData) + wasAlphaSwapped = swapAlphaChannel(rect); + + // Fix alpha values, if needed + if (potentialInvalidAlpha) + wasAlphaFixed = fixAlphaChannel(rect); + + QImage::Format format; + if ((partIsTransparent && !wasAlphaSwapped) || (!partIsTransparent && hasAlpha)) { + format = QImage::Format_ARGB32_Premultiplied; + alphaType = RealAlpha; + } else if (wasAlphaSwapped) { + format = QImage::Format_ARGB32_Premultiplied; + alphaType = MaskAlpha; + } else { + format = QImage::Format_RGB32; + // The image data we got from the theme engine does not have any transparency, + // thus the alpha channel is set to 0. + // However, Format_RGB32 requires the alpha part to be set to 0xff, thus + // we must flip it from 0x00 to 0xff + swapAlphaChannel(rect, true); + alphaType = NoAlpha; + } +#if defined(DEBUG_XP_STYLE) && 1 + printf("Image format is: %s\n", alphaType == RealAlpha ? "Real Alpha" : alphaType == MaskAlpha ? "Masked Alpha" : "No Alpha"); +#endif + img = QImage(bufferPixels, bufferW, bufferH, format); + } + + // Blitting backing store + bool useRegion = partIsTransparent && !hasAlpha && !wasAlphaSwapped; + + QRegion newRegion; + QRegion oldRegion; + if (useRegion) { + newRegion = region(themeData); + oldRegion = painter->clipRegion(); + painter->setClipRegion(newRegion); +#if defined(DEBUG_XP_STYLE) && 0 + printf("Using region:\n"); + QVector rects = newRegion.rects(); + for (int i = 0; i < rects.count(); ++i) { + const QRect &r = rects.at(i); + printf(" (%d, %d, %d, %d)\n", r.x(), r.y(), r.right(), r.bottom()); + } +#endif + } + + if (addBorderContentClipping) + painter->setClipRegion(extraClip, Qt::IntersectClip); + + if (!themeData.mirrorHorizontally && !themeData.mirrorVertically && !themeData.rotate) { + if (!haveCachedPixmap) + painter->drawImage(themeData.rect, img, rect); + else + painter->drawPixmap(themeData.rect, cachedPixmap); + } else { + // This is _slow_! + // Make a copy containing only the necessary data, and mirror + // on all wanted axes. Then draw the copy. + // If cached, the normal pixmap is cached, instead of caching + // all possible orientations for each part and state. + QImage imgCopy; + if (!haveCachedPixmap) + imgCopy = img.copy(rect); + else + imgCopy = cachedPixmap.toImage(); + + if (themeData.rotate) { + QMatrix rotMatrix; + rotMatrix.rotate(themeData.rotate); + imgCopy = imgCopy.transformed(rotMatrix); + } + if (themeData.mirrorHorizontally || themeData.mirrorVertically) { + imgCopy = imgCopy.mirrored(themeData.mirrorHorizontally, themeData.mirrorVertically); + } + painter->drawImage(themeData.rect, + imgCopy); + } + + if (useRegion || addBorderContentClipping) { + if (oldRegion.isEmpty()) + painter->setClipping(false); + else + painter->setClipRegion(oldRegion); + } + + // Cache the pixmap to avoid expensive swapAlphaChannel() calls + if (!haveCachedPixmap && w && h) { + QPixmap pix = QPixmap::fromImage(img).copy(rect); + QPixmapCache::insert(pixmapCacheKey, pix); +#ifdef DEBUG_XP_STYLE + printf("+++Adding pixmap to cache, size(%d, %d), wasAlphaSwapped(%d), wasAlphaFixed(%d), name(%s)\n", + w, h, wasAlphaSwapped, wasAlphaFixed, qPrintable(pixmapCacheKey)); +#endif + } + + // Add to theme part cache + if (!isCached) { + memset(&data, 0, sizeof(data)); + data.dataValid = true; + data.partIsTransparent = partIsTransparent; + data.alphaType = alphaType; + data.hasAlphaChannel = hasAlpha; + data.hasAnyData = stateHasData; + data.wasAlphaSwapped = wasAlphaSwapped; + data.hadInvalidAlpha = wasAlphaFixed; + alphaCache.insert(key, data); + } +} + + +// ------------------------------------------------------------------------------------------------ + +/*! + \class QWindowsXPStyle + \brief The QWindowsXPStyle class provides a Microsoft Windows XP-like look and feel. + + \ingroup appearance + + \warning This style is only available on the Windows XP platform + because it makes use of Windows XP's style engine. + + Most of the functions are documented in the base classes + QWindowsStyle, QCommonStyle, and QStyle, but the + QWindowsXPStyle overloads of drawComplexControl(), drawControl(), + drawControlMask(), drawPrimitive(), proxy()->subControlRect(), and + sizeFromContents(), are documented here. + + \img qwindowsxpstyle.png + \sa QMacStyle, QWindowsStyle, QPlastiqueStyle, QCDEStyle, QMotifStyle +*/ + +/*! + Constructs a QWindowsStyle +*/ +QWindowsXPStyle::QWindowsXPStyle() + : QWindowsStyle(*new QWindowsXPStylePrivate) +{ +} + +/*! + Destroys the style. +*/ +QWindowsXPStyle::~QWindowsXPStyle() +{ +} + +/*! \reimp */ +void QWindowsXPStyle::unpolish(QApplication *app) +{ + QWindowsStyle::unpolish(app); +} + +/*! \reimp */ +void QWindowsXPStyle::polish(QApplication *app) +{ + QWindowsStyle::polish(app); + if (!QWindowsXPStylePrivate::useXP()) + return; +} + +/*! \reimp */ +void QWindowsXPStyle::polish(QWidget *widget) +{ + QWindowsStyle::polish(widget); + if (!QWindowsXPStylePrivate::useXP()) + return; + + if (qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast(widget) +#endif // QT_NO_COMBOBOX + || qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget) +#ifndef QT_NO_SPINBOX + || qobject_cast(widget) + || qobject_cast(widget) +#endif // QT_NO_SPINBOX + || widget->inherits("QWorkspaceChild") + || widget->inherits("Q3TitleBar")) + widget->setAttribute(Qt::WA_Hover); + +#ifndef QT_NO_RUBBERBAND + if (qobject_cast(widget)) { + widget->setWindowOpacity(0.6); + } +#endif + if (qobject_cast(widget) && + qobject_cast(widget->parent())) + widget->parentWidget()->setAttribute(Qt::WA_ContentsPropagated); + + Q_D(QWindowsXPStyle); + if (!d->hasInitColors) { + // Get text color for group box labels + COLORREF cref; + XPThemeData theme(0, 0, QLatin1String("BUTTON"), 0, 0); + pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_NORMAL, TMT_TEXTCOLOR, &cref); + d->groupBoxTextColor = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref)); + pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_DISABLED, TMT_TEXTCOLOR, &cref); + d->groupBoxTextColorDisabled = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref)); + // Where does this color come from? + //pGetThemeColor(theme.handle(), TKP_TICS, TSS_NORMAL, TMT_COLOR, &cref); + d->sliderTickColor = qRgb(165, 162, 148); + d->hasInitColors = true; + } +} + +/*! \reimp */ +void QWindowsXPStyle::polish(QPalette &pal) +{ + QWindowsStyle::polish(pal); + pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110)); +} + +/*! \reimp */ +void QWindowsXPStyle::unpolish(QWidget *widget) +{ +#ifndef QT_NO_RUBBERBAND + if (qobject_cast(widget)) { + widget->setWindowOpacity(1.0); + } +#endif + Q_D(QWindowsXPStyle); + // Unpolish of widgets is the first thing that + // happens when a theme changes, or the theme + // engine is turned off. So we detect it here. + bool oldState = QWindowsXPStylePrivate::useXP(); + bool newState = QWindowsXPStylePrivate::useXP(true); + if ((oldState != newState) && newState) { + d->cleanup(true); + d->init(true); + } else { + // Cleanup handle map, if just changing style, + // or turning it on. In both cases the values + // already in the map might be old (other style). + d->cleanupHandleMap(); + } + if (qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast(widget) +#endif // QT_NO_COMBOBOX + || qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget) +#ifndef QT_NO_SPINBOX + || qobject_cast(widget) + || qobject_cast(widget) +#endif // QT_NO_SPINBOX + || widget->inherits("QWorkspaceChild") + || widget->inherits("Q3TitleBar")) + widget->setAttribute(Qt::WA_Hover, false); + QWindowsStyle::unpolish(widget); +} + +/*! \reimp */ +QRect QWindowsXPStyle::subElementRect(SubElement sr, const QStyleOption *option, const QWidget *widget) const +{ + if (!QWindowsXPStylePrivate::useXP()) { + return QWindowsStyle::subElementRect(sr, option, widget); + } + + QRect rect(option->rect); + switch(sr) { + case SE_DockWidgetCloseButton: + case SE_DockWidgetFloatButton: + rect = QWindowsStyle::subElementRect(sr, option, widget); + return rect.translated(0, 1); + break; + case SE_TabWidgetTabContents: + if (qstyleoption_cast(option)) + { + rect = QWindowsStyle::subElementRect(sr, option, widget); + if (sr == SE_TabWidgetTabContents) + rect.adjust(0, 0, -2, -2); + } + break; + case SE_TabWidgetTabBar: { + rect = QWindowsStyle::subElementRect(sr, option, widget); + const QStyleOptionTabWidgetFrame *twfOption = + qstyleoption_cast(option); + if (twfOption && twfOption->direction == Qt::RightToLeft + && (twfOption->shape == QTabBar::RoundedNorth + || twfOption->shape == QTabBar::RoundedSouth)) + { + QStyleOptionTab otherOption; + otherOption.shape = (twfOption->shape == QTabBar::RoundedNorth + ? QTabBar::RoundedEast : QTabBar::RoundedSouth); + int overlap = proxy()->pixelMetric(PM_TabBarBaseOverlap, &otherOption, widget); + int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget); + rect.adjust(-overlap + borderThickness, 0, -overlap + borderThickness, 0); + } + break;} + + case SE_PushButtonContents: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { + MARGINS borderSize; + if (widget) { + XPThemeData buttontheme(widget, 0, QLatin1String("Button")); + HTHEME theme = buttontheme.handle(); + if (theme) { + int stateId; + if (!(option->state & State_Enabled)) + stateId = PBS_DISABLED; + else if (option->state & State_Sunken) + stateId = PBS_PRESSED; + else if (option->state & State_MouseOver) + stateId = PBS_HOT; + else if (btn->features & QStyleOptionButton::DefaultButton) + stateId = PBS_DEFAULTED; + else + stateId = PBS_NORMAL; + + int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget); + rect = option->rect.adjusted(border, border, -border, -border); + + int result = pGetThemeMargins(theme, + NULL, + BP_PUSHBUTTON, + stateId, + TMT_CONTENTMARGINS, + NULL, + &borderSize); + + if (result == S_OK) { + rect.adjust(borderSize.cxLeftWidth, borderSize.cyTopHeight, + -borderSize.cxRightWidth, -borderSize.cyBottomHeight); + rect = visualRect(option->direction, option->rect, rect); + } + } + } + } + break; + case SE_ProgressBarContents: + rect = QCommonStyle::subElementRect(SE_ProgressBarGroove, option, widget); + if (option->state & QStyle::State_Horizontal) + rect.adjust(4, 3, -4, -3); + else + rect.adjust(3, 2, -3, -2); + break; + default: + rect = QWindowsStyle::subElementRect(sr, option, widget); + } + return rect; +} + +/*! + \reimp +*/ +void QWindowsXPStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *option, QPainter *p, + const QWidget *widget) const +{ + QWindowsXPStylePrivate *d = const_cast(d_func()); + + if (!QWindowsXPStylePrivate::useXP()) { + QWindowsStyle::drawPrimitive(pe, option, p, widget); + return; + } + + QString name; + int partId = 0; + int stateId = 0; + QRect rect = option->rect; + State flags = option->state; + bool hMirrored = false; + bool vMirrored = false; + bool noBorder = false; + bool noContent = false; + int rotate = 0; + + switch (pe) { + case PE_FrameTabBarBase: + if (const QStyleOptionTabBarBase *tbb + = qstyleoption_cast(option)) { + p->save(); + switch (tbb->shape) { + case QTabBar::RoundedNorth: + p->setPen(QPen(tbb->palette.dark(), 0)); + p->drawLine(tbb->rect.topLeft(), tbb->rect.topRight()); + break; + case QTabBar::RoundedWest: + p->setPen(QPen(tbb->palette.dark(), 0)); + p->drawLine(tbb->rect.left(), tbb->rect.top(), tbb->rect.left(), tbb->rect.bottom()); + break; + case QTabBar::RoundedSouth: + p->setPen(QPen(tbb->palette.dark(), 0)); + p->drawLine(tbb->rect.left(), tbb->rect.top(), + tbb->rect.right(), tbb->rect.top()); + break; + case QTabBar::RoundedEast: + p->setPen(QPen(tbb->palette.dark(), 0)); + p->drawLine(tbb->rect.topLeft(), tbb->rect.bottomLeft()); + break; + case QTabBar::TriangularNorth: + case QTabBar::TriangularEast: + case QTabBar::TriangularWest: + case QTabBar::TriangularSouth: + p->restore(); + QWindowsStyle::drawPrimitive(pe, option, p, widget); + return; + } + p->restore(); + } + return; + case PE_PanelButtonBevel: + name = QLatin1String("BUTTON"); + partId = BP_PUSHBUTTON; + if (!(flags & State_Enabled)) + stateId = PBS_DISABLED; + else if ((flags & State_Sunken) || (flags & State_On)) + stateId = PBS_PRESSED; + else if (flags & State_MouseOver) + stateId = PBS_HOT; + //else if (flags & State_ButtonDefault) + // stateId = PBS_DEFAULTED; + else + stateId = PBS_NORMAL; + break; + + case PE_PanelButtonTool: + if (widget && widget->inherits("QDockWidgetTitleButton")) { + if (const QWidget *dw = widget->parentWidget()) + if (dw->isWindow()) + return; + } + name = QLatin1String("TOOLBAR"); + partId = TP_BUTTON; + if (!(flags & State_Enabled)) + stateId = TS_DISABLED; + else if (flags & State_Sunken) + stateId = TS_PRESSED; + else if (flags & State_MouseOver) + stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT; + else if (flags & State_On) + stateId = TS_CHECKED; + else if (!(flags & State_AutoRaise)) + stateId = TS_HOT; + else + stateId = TS_NORMAL; + break; + + case PE_IndicatorButtonDropDown: + name = QLatin1String("TOOLBAR"); + partId = TP_SPLITBUTTONDROPDOWN; + if (!(flags & State_Enabled)) + stateId = TS_DISABLED; + else if (flags & State_Sunken) + stateId = TS_PRESSED; + else if (flags & State_MouseOver) + stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT; + else if (flags & State_On) + stateId = TS_CHECKED; + else if (!(flags & State_AutoRaise)) + stateId = TS_HOT; + else + stateId = TS_NORMAL; + if (option->direction == Qt::RightToLeft) + hMirrored = true; + break; + + case PE_IndicatorCheckBox: + name = QLatin1String("BUTTON"); + partId = BP_CHECKBOX; + if (!(flags & State_Enabled)) + stateId = CBS_UNCHECKEDDISABLED; + else if (flags & State_Sunken) + stateId = CBS_UNCHECKEDPRESSED; + else if (flags & State_MouseOver) + stateId = CBS_UNCHECKEDHOT; + else + stateId = CBS_UNCHECKEDNORMAL; + + if (flags & State_On) + stateId += CBS_CHECKEDNORMAL-1; + else if (flags & State_NoChange) + stateId += CBS_MIXEDNORMAL-1; + + break; + + case PE_IndicatorRadioButton: + name = QLatin1String("BUTTON"); + partId = BP_RADIOBUTTON; + if (!(flags & State_Enabled)) + stateId = RBS_UNCHECKEDDISABLED; + else if (flags & State_Sunken) + stateId = RBS_UNCHECKEDPRESSED; + else if (flags & State_MouseOver) + stateId = RBS_UNCHECKEDHOT; + else + stateId = RBS_UNCHECKEDNORMAL; + + if (flags & State_On) + stateId += RBS_CHECKEDNORMAL-1; + break; + + case PE_IndicatorDockWidgetResizeHandle: + return; + +case PE_Frame: + { + if (flags & State_Raised) + return; + name = QLatin1String("LISTVIEW"); + partId = LVP_LISTGROUP; + XPThemeData theme(0, 0, name, partId, 0); + + if (!(flags & State_Enabled)) + stateId = ETS_DISABLED; + else + stateId = ETS_NORMAL; + int fillType; + if (pGetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &fillType) == S_OK) { + if (fillType == BT_BORDERFILL) { + COLORREF bcRef; + pGetThemeColor(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &bcRef); + QColor bordercolor(qRgb(GetRValue(bcRef), GetGValue(bcRef), GetBValue(bcRef))); + QPen oldPen = p->pen(); + // int borderSize = 1; + // pGetThemeInt(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &borderSize); + + // Inner white border + p->setPen(QPen(option->palette.base().color(), 1)); + p->drawRect(option->rect.adjusted(1, 1, -2, -2)); + // Outer dark border + p->setPen(QPen(bordercolor, 1)); + p->drawRect(option->rect.adjusted(0, 0, -1, -1)); + p->setPen(oldPen); + return; + } else if (fillType == BT_NONE) { + return; + } else { + break; + } + } + } + case PE_FrameLineEdit: { + // we try to check if this lineedit is a delegate on a QAbstractItemView-derived class. + QWidget *parentWidget = 0; + if (widget) + parentWidget = widget->parentWidget(); + if (parentWidget) + parentWidget = parentWidget->parentWidget(); + if (widget && widget->inherits("QLineEdit") + && parentWidget && parentWidget->inherits("QAbstractItemView")) { + QPen oldPen = p->pen(); + // Inner white border + p->setPen(QPen(option->palette.base().color(), 1)); + p->drawRect(option->rect.adjusted(1, 1, -2, -2)); + // Outer dark border + p->setPen(QPen(option->palette.shadow().color(), 1)); + p->drawRect(option->rect.adjusted(0, 0, -1, -1)); + p->setPen(oldPen); + return; + } else if (qstyleoption_cast(option)) { + name = QLatin1String("EDIT"); + partId = EP_EDITTEXT; + noContent = true; + if (!(flags & State_Enabled)) + stateId = ETS_DISABLED; + else + stateId = ETS_NORMAL; + } + break; + } + + case PE_PanelLineEdit: + if (const QStyleOptionFrame *panel = qstyleoption_cast(option)) { + name = QLatin1String("EDIT"); + partId = EP_EDITTEXT; + noBorder = true; + QBrush bg; + bool usePalette = false; + bool isEnabled = flags & State_Enabled; + uint resolve_mask = panel->palette.resolve(); + +#ifndef QT_NO_SPINBOX + //Since spin box includes a line edit we need to resolve the palette on the spin box instead + if (widget) { + if (QAbstractSpinBox *spinbox = qobject_cast(widget->parentWidget())) + resolve_mask = spinbox->palette().resolve(); + } +#endif // QT_NO_SPINBOX + if (resolve_mask & (1 << QPalette::Base)) { + // Base color is set for this widget, so use it + bg = panel->palette.brush(QPalette::Base); + usePalette = true; + } + + stateId = isEnabled ? ETS_NORMAL : ETS_DISABLED; + + if (usePalette) { + p->fillRect(panel->rect, bg); + } else { + XPThemeData theme(0, p, name, partId, stateId, rect); + if (!theme.isValid()) { + QWindowsStyle::drawPrimitive(pe, option, p, widget); + return; + } + int bgType; + pGetThemeEnumValue( theme.handle(), + partId, + stateId, + TMT_BGTYPE, + &bgType); + if( bgType == BT_IMAGEFILE ) { + theme.mirrorHorizontally = hMirrored; + theme.mirrorVertically = vMirrored; + theme.noBorder = noBorder; + theme.noContent = noContent; + theme.rotate = rotate; + d->drawBackground(theme); + } else { + QBrush fillColor = option->palette.brush(QPalette::Base); + + if (!isEnabled) { + PROPERTYORIGIN origin = PO_NOTFOUND; + pGetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin); + // Use only if the fill property comes from our part + if ((origin == PO_PART || origin == PO_STATE)) { + COLORREF bgRef; + pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); + fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef))); + } + } + p->fillRect(option->rect, fillColor); + } + } + + if (panel->lineWidth > 0) + proxy()->drawPrimitive(PE_FrameLineEdit, panel, p, widget); + return; + } + break; + + case PE_FrameTabWidget: + if (const QStyleOptionTabWidgetFrame *tab = qstyleoption_cast(option)) + { + name = QLatin1String("TAB"); + partId = TABP_PANE; + + if (widget) { + bool useGradient = true; + const int maxlength = 256; + wchar_t themeFileName[maxlength]; + wchar_t themeColor[maxlength]; + // Due to a a scaling issue with the XP Silver theme, tab gradients are not used with it + if (pGetCurrentThemeName(themeFileName, maxlength, themeColor, maxlength, NULL, 0) == S_OK) { + wchar_t *offset = 0; + if ((offset = wcsrchr(themeFileName, QChar(QLatin1Char('\\')).unicode())) != NULL) { + offset++; + if (!lstrcmp(offset, L"Luna.msstyles") && !lstrcmp(offset, L"Metallic")) { + useGradient = false; + } + } + } + // This should work, but currently there's an error in the ::drawBackgroundDirectly() + // code, when using the HDC directly.. + if (useGradient) { + QStyleOptionTabWidgetFrameV2 frameOpt = *tab; + frameOpt.rect = widget->rect(); + QRect contentsRect = subElementRect(SE_TabWidgetTabContents, &frameOpt, widget); + QRegion reg = option->rect; + reg -= contentsRect; + p->setClipRegion(reg); + XPThemeData theme(widget, p, name, partId, stateId, rect); + theme.mirrorHorizontally = hMirrored; + theme.mirrorVertically = vMirrored; + d->drawBackground(theme); + p->setClipRect(contentsRect); + partId = TABP_BODY; + } + } + switch (tab->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + vMirrored = true; + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + rotate = 90; + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + rotate = 90; + hMirrored = true; + break; + default: + break; + } + } + break; + + case PE_FrameMenu: + p->save(); + p->setPen(option->palette.dark().color()); + p->drawRect(rect.adjusted(0, 0, -1, -1)); + p->restore(); + return; + + case PE_PanelMenuBar: + break; + + case PE_FrameDockWidget: + if (const QStyleOptionFrame *frm = qstyleoption_cast(option)) + { + name = QLatin1String("WINDOW"); + if (flags & State_Active) + stateId = FS_ACTIVE; + else + stateId = FS_INACTIVE; + + int fwidth = proxy()->pixelMetric(PM_DockWidgetFrameWidth, frm, widget); + + XPThemeData theme(widget, p, name, 0, stateId); + if (!theme.isValid()) + break; + theme.rect = QRect(frm->rect.x(), frm->rect.y(), frm->rect.x()+fwidth, frm->rect.height()-fwidth); theme.partId = WP_SMALLFRAMELEFT; + d->drawBackground(theme); + theme.rect = QRect(frm->rect.width()-fwidth, frm->rect.y(), fwidth, frm->rect.height()-fwidth); + theme.partId = WP_SMALLFRAMERIGHT; + d->drawBackground(theme); + theme.rect = QRect(frm->rect.x(), frm->rect.bottom()-fwidth+1, frm->rect.width(), fwidth); + theme.partId = WP_SMALLFRAMEBOTTOM; + d->drawBackground(theme); + return; + } + break; + + case PE_IndicatorHeaderArrow: + { +#if 0 // XP theme engine doesn't know about this :( + name = QLatin1String("HEADER"); + partId = HP_HEADERSORTARROW; + if (flags & State_Down) + stateId = HSAS_SORTEDDOWN; + else + stateId = HSAS_SORTEDUP; +#else + if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { + p->save(); + p->setPen(option->palette.dark().color()); + p->translate(0, option->rect.height()/2 - 4); + if (header->sortIndicator & QStyleOptionHeader::SortUp) { // invert logic to follow Windows style guide + p->drawLine(option->rect.x(), option->rect.y(), option->rect.x()+8, option->rect.y()); + p->drawLine(option->rect.x()+1, option->rect.y()+1, option->rect.x()+7, option->rect.y()+1); + p->drawLine(option->rect.x()+2, option->rect.y()+2, option->rect.x()+6, option->rect.y()+2); + p->drawLine(option->rect.x()+3, option->rect.y()+3, option->rect.x()+5, option->rect.y()+3); + p->drawPoint(option->rect.x()+4, option->rect.y()+4); + } else if(header->sortIndicator & QStyleOptionHeader::SortDown) { + p->drawLine(option->rect.x(), option->rect.y()+4, option->rect.x()+8, option->rect.y()+4); + p->drawLine(option->rect.x()+1, option->rect.y()+3, option->rect.x()+7, option->rect.y()+3); + p->drawLine(option->rect.x()+2, option->rect.y()+2, option->rect.x()+6, option->rect.y()+2); + p->drawLine(option->rect.x()+3, option->rect.y()+1, option->rect.x()+5, option->rect.y()+1); + p->drawPoint(option->rect.x()+4, option->rect.y()); + } + p->restore(); + return; + } +#endif + } + break; + + case PE_FrameStatusBarItem: + name = QLatin1String("STATUS"); + partId = SP_PANE; + break; + + case PE_FrameGroupBox: + name = QLatin1String("BUTTON"); + partId = BP_GROUPBOX; + if (!(flags & State_Enabled)) + stateId = GBS_DISABLED; + else + stateId = GBS_NORMAL; + if (const QStyleOptionFrame *frame = qstyleoption_cast(option)) { + const QStyleOptionFrameV2 *frame2 = qstyleoption_cast(option); + if (frame2->features & QStyleOptionFrameV2::Flat) { + // Windows XP does not have a theme part for a flat GroupBox, paint it with the windows style + QRect fr = frame->rect; + QPoint p1(fr.x(), fr.y() + 1); + QPoint p2(fr.x() + fr.width(), p1.y() + 1); + rect = QRect(p1, p2); + name = QLatin1String(""); + } + } + break; + + case PE_IndicatorProgressChunk: + { + Qt::Orientation orient = Qt::Horizontal; + bool inverted = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(option)) { + orient = pb2->orientation; + if (pb2->invertedAppearance) + inverted = true; + } + if (orient == Qt::Horizontal) { + partId = PP_CHUNK; + rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.height() ); + if (inverted && option->direction == Qt::LeftToRight) + hMirrored = true; + } else { + partId = PP_CHUNKVERT; + rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.height()); + } + name = QLatin1String("PROGRESS"); + stateId = 1; + } + break; + + case PE_Q3DockWindowSeparator: + name = QLatin1String("TOOLBAR"); + if (flags & State_Horizontal) + partId = TP_SEPARATOR; + else + partId = TP_SEPARATORVERT; + break; + + case PE_FrameWindow: + if (const QStyleOptionFrame *frm = qstyleoption_cast(option)) + { + name = QLatin1String("WINDOW"); + if (flags & State_Active) + stateId = FS_ACTIVE; + else + stateId = FS_INACTIVE; + + int fwidth = frm->lineWidth + frm->midLineWidth; + + XPThemeData theme(0, p, name, 0, stateId); + if (!theme.isValid()) + break; + + theme.rect = QRect(option->rect.x(), option->rect.y()+fwidth, option->rect.x()+fwidth, option->rect.height()-fwidth); + theme.partId = WP_FRAMELEFT; + d->drawBackground(theme); + theme.rect = QRect(option->rect.width()-fwidth, option->rect.y()+fwidth, fwidth, option->rect.height()-fwidth); + theme.partId = WP_FRAMERIGHT; + d->drawBackground(theme); + theme.rect = QRect(option->rect.x(), option->rect.height()-fwidth, option->rect.width(), fwidth); + theme.partId = WP_FRAMEBOTTOM; + d->drawBackground(theme); + theme.rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.y()+fwidth); + theme.partId = WP_CAPTION; + d->drawBackground(theme); + return; + } + break; + + case PE_IndicatorBranch: + { + static const int decoration_size = 9; + int mid_h = option->rect.x() + option->rect.width() / 2; + int mid_v = option->rect.y() + option->rect.height() / 2; + int bef_h = mid_h; + int bef_v = mid_v; + int aft_h = mid_h; + int aft_v = mid_v; + QBrush brush(option->palette.dark().color(), Qt::Dense4Pattern); + if (option->state & State_Item) { + if (option->direction == Qt::RightToLeft) + p->fillRect(option->rect.left(), mid_v, bef_h - option->rect.left(), 1, brush); + else + p->fillRect(aft_h, mid_v, option->rect.right() - aft_h + 1, 1, brush); + } + if (option->state & State_Sibling) + p->fillRect(mid_h, aft_v, 1, option->rect.bottom() - aft_v + 1, brush); + if (option->state & (State_Open | State_Children | State_Item | State_Sibling)) + p->fillRect(mid_h, option->rect.y(), 1, bef_v - option->rect.y(), brush); + if (option->state & State_Children) { + int delta = decoration_size / 2; + bef_h -= delta; + bef_v -= delta; + aft_h += delta; + aft_v += delta; + XPThemeData theme(0, p, QLatin1String("TREEVIEW")); + theme.rect = QRect(bef_h, bef_v, decoration_size, decoration_size); + theme.partId = TVP_GLYPH; + theme.stateId = flags & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED; + d->drawBackground(theme); + } + } + return; + + case PE_IndicatorToolBarSeparator: + if (option->rect.height() < 3) { + // XP style requires a few pixels for the separator + // to be visible. + QWindowsStyle::drawPrimitive(pe, option, p, widget); + return; + } + name = QLatin1String("TOOLBAR"); + partId = TP_SEPARATOR; + + if (option->state & State_Horizontal) + partId = TP_SEPARATOR; + else + partId = TP_SEPARATORVERT; + + break; + + case PE_IndicatorToolBarHandle: + + name = QLatin1String("REBAR"); + partId = RP_GRIPPER; + if (option->state & State_Horizontal) { + partId = RP_GRIPPER; + rect.adjust(0, 0, -2, 0); + } + else { + partId = RP_GRIPPERVERT; + rect.adjust(0, 0, 0, -2); + } + break; + + case PE_IndicatorItemViewItemCheck: { + QStyleOptionButton button; + button.QStyleOption::operator=(*option); + button.state &= ~State_MouseOver; + proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, p, widget); + return; + } + + default: + break; + } + + XPThemeData theme(0, p, name, partId, stateId, rect); + if (!theme.isValid()) { + QWindowsStyle::drawPrimitive(pe, option, p, widget); + return; + } + theme.mirrorHorizontally = hMirrored; + theme.mirrorVertically = vMirrored; + theme.noBorder = noBorder; + theme.noContent = noContent; + theme.rotate = rotate; + d->drawBackground(theme); +} + +/*! + \reimp +*/ +void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *p, + const QWidget *widget) const +{ + QWindowsXPStylePrivate *d = const_cast(d_func()); + if (!QWindowsXPStylePrivate::useXP()) { + QWindowsStyle::drawControl(element, option, p, widget); + return; + } + + QRect rect(option->rect); + State flags = option->state; + + int rotate = 0; + bool hMirrored = false; + bool vMirrored = false; + + QString name; + int partId = 0; + int stateId = 0; + switch (element) { + case CE_SizeGrip: + { + name = QLatin1String("STATUS"); + partId = SP_GRIPPER; + SIZE sz; + XPThemeData theme(0, p, name, partId, 0); + pGetThemePartSize(theme.handle(), 0, partId, 0, 0, TS_TRUE, &sz); + --sz.cy; + if (const QStyleOptionSizeGrip *sg = qstyleoption_cast(option)) { + switch (sg->corner) { + case Qt::BottomRightCorner: + rect = QRect(rect.right() - sz.cx, rect.bottom() - sz.cy, sz.cx, sz.cy); + break; + case Qt::BottomLeftCorner: + rect = QRect(rect.left() + 1, rect.bottom() - sz.cy, sz.cx, sz.cy); + hMirrored = true; + break; + case Qt::TopRightCorner: + rect = QRect(rect.right() - sz.cx, rect.top() + 1, sz.cx, sz.cy); + vMirrored = true; + break; + case Qt::TopLeftCorner: + rect = QRect(rect.left() + 1, rect.top() + 1, sz.cx, sz.cy); + hMirrored = vMirrored = true; + } + } + } + break; + + case CE_HeaderSection: + name = QLatin1String("HEADER"); + partId = HP_HEADERITEM; + if (flags & State_Sunken) + stateId = HIS_PRESSED; + else if (flags & State_MouseOver) + stateId = HIS_HOT; + else + stateId = HIS_NORMAL; + break; + + case CE_Splitter: + p->eraseRect(option->rect); + return; + + case CE_PushButtonBevel: + if (const QStyleOptionButton *btn = qstyleoption_cast(option)) + { + name = QLatin1String("BUTTON"); + partId = BP_PUSHBUTTON; + bool justFlat = ((btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken))) + || ((btn->features & QStyleOptionButton::CommandLinkButton) + && !(flags & State_MouseOver) + && !(btn->features & QStyleOptionButton::DefaultButton)); + if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat)) + stateId = PBS_DISABLED; + else if (justFlat) + ; + else if (flags & (State_Sunken | State_On)) + stateId = PBS_PRESSED; + else if (flags & State_MouseOver) + stateId = PBS_HOT; + else if (btn->features & QStyleOptionButton::DefaultButton) + stateId = PBS_DEFAULTED; + else + stateId = PBS_NORMAL; + + if (!justFlat) { + XPThemeData theme(widget, p, name, partId, stateId, rect); + d->drawBackground(theme); + } + + if (btn->features & QStyleOptionButton::HasMenu) { + int mbiw = 0, mbih = 0; + XPThemeData theme(widget, 0, QLatin1String("TOOLBAR"), TP_SPLITBUTTONDROPDOWN); + if (theme.isValid()) { + SIZE size; + pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + mbiw = size.cx; + mbih = size.cy; + } + + QRect ir = btn->rect; + QStyleOptionButton newBtn = *btn; + newBtn.rect = QRect(ir.right() - mbiw - 1, 1 + (ir.height()/2) - (mbih/2), mbiw, mbih); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); + } + return; + } + break; + case CE_TabBarTab: + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) + { + stateId = tab->state & State_Enabled ? TIS_NORMAL : TIS_DISABLED; + } + break; + + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) + { + name = QLatin1String("TAB"); + bool isDisabled = !(tab->state & State_Enabled); + bool hasFocus = tab->state & State_HasFocus; + bool isHot = tab->state & State_MouseOver; + bool selected = tab->state & State_Selected; + bool lastTab = tab->position == QStyleOptionTab::End; + bool firstTab = tab->position == QStyleOptionTab::Beginning; + bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab; + bool leftAligned = proxy()->styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignLeft; + bool centerAligned = proxy()->styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignCenter; + int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget); + int tabOverlap = proxy()->pixelMetric(PM_TabBarTabOverlap, option, widget); + + if (isDisabled) + stateId = TIS_DISABLED; + else if (selected) + stateId = TIS_SELECTED; + else if (hasFocus) + stateId = TIS_FOCUSED; + else if (isHot) + stateId = TIS_HOT; + else + stateId = TIS_NORMAL; + + // Selecting proper part depending on position + if (firstTab || onlyOne) { + if (leftAligned) { + partId = TABP_TABITEMLEFTEDGE; + } else if (centerAligned) { + partId = TABP_TABITEM; + } else { // rightAligned + partId = TABP_TABITEMRIGHTEDGE; + } + } else { + partId = TABP_TABITEM; + } + + if (tab->direction == Qt::RightToLeft + && (tab->shape == QTabBar::RoundedNorth + || tab->shape == QTabBar::RoundedSouth)) { + bool temp = firstTab; + firstTab = lastTab; + lastTab = temp; + } + bool begin = firstTab || onlyOne; + bool end = lastTab || onlyOne; + switch (tab->shape) { + case QTabBar::RoundedNorth: + if (selected) + rect.adjust(begin ? 0 : -tabOverlap, 0, end ? 0 : tabOverlap, borderThickness); + else + rect.adjust(begin? tabOverlap : 0, tabOverlap, end ? -tabOverlap : 0, 0); + break; + case QTabBar::RoundedSouth: + //vMirrored = true; + rotate = 180; // Not 100% correct, but works + if (selected) + rect.adjust(begin ? 0 : -tabOverlap , -borderThickness, end ? 0 : tabOverlap, 0); + else + rect.adjust(begin ? tabOverlap : 0, 0, end ? -tabOverlap : 0 , -tabOverlap); + break; + case QTabBar::RoundedEast: + rotate = 90; + if (selected) { + rect.adjust(-borderThickness, begin ? 0 : -tabOverlap, 0, end ? 0 : tabOverlap); + }else{ + rect.adjust(0, begin ? tabOverlap : 0, -tabOverlap, end ? -tabOverlap : 0); + } + break; + case QTabBar::RoundedWest: + hMirrored = true; + rotate = 90; + if (selected) { + rect.adjust(0, begin ? 0 : -tabOverlap, borderThickness, end ? 0 : tabOverlap); + }else{ + rect.adjust(tabOverlap, begin ? tabOverlap : 0, 0, end ? -tabOverlap : 0); + } + break; + default: + name = QLatin1String(""); // Do our own painting for triangular + break; + } + + if (!selected) { + switch (tab->shape) { + case QTabBar::RoundedNorth: + rect.adjust(0,0, 0,-1); + break; + case QTabBar::RoundedSouth: + rect.adjust(0,1, 0,0); + break; + case QTabBar::RoundedEast: + rect.adjust( 1,0, 0,0); + break; + case QTabBar::RoundedWest: + rect.adjust(0,0, -1,0); + break; + default: + break; + } + } + } + break; + + case CE_ProgressBarGroove: + { + Qt::Orientation orient = Qt::Horizontal; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(option)) + orient = pb2->orientation; + partId = (orient == Qt::Horizontal) ? PP_BAR : PP_BARVERT; + name = QLatin1String("PROGRESS"); + stateId = 1; + } + break; + + case CE_MenuEmptyArea: + case CE_MenuItem: + if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) + { + int tab = menuitem->tabWidth; + bool dis = !(menuitem->state & State_Enabled); + bool act = menuitem->state & State_Selected; + bool checkable = menuitem->menuHasCheckableItems; + bool checked = checkable ? menuitem->checked : false; + + // windows always has a check column, regardless whether we have an icon or not + int checkcol = qMax(menuitem->maxIconWidth, 12); + + int x, y, w, h; + rect.getRect(&x, &y, &w, &h); + + QBrush fill = menuitem->palette.brush(act ? QPalette::Highlight : QPalette::Button); + p->fillRect(rect, fill); + + if (element == CE_MenuEmptyArea) + break; + + // draw separator ------------------------------------------------- + if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) { + int yoff = y-1 + h / 2; + p->setPen(menuitem->palette.dark().color()); + p->drawLine(x, yoff, x+w, yoff); + ++yoff; + p->setPen(menuitem->palette.light().color()); + p->drawLine(x, yoff, x+w, yoff); + return; + } + + int xpos = x; + + // draw icon ------------------------------------------------------ + if (!menuitem->icon.isNull()) { + QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; + if (act && !dis) + mode = QIcon::Active; + QPixmap pixmap = checked ? + menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On) : + menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + QRect iconRect(0, 0, pixw, pixh); + iconRect.moveCenter(QRect(xpos, y, checkcol, h).center()); + QRect vIconRect = visualRect(option->direction, option->rect, iconRect); + p->setPen(menuitem->palette.text().color()); + p->setBrush(Qt::NoBrush); + if (checked) + p->drawRect(vIconRect.adjusted(-1, -1, 0, 0)); + p->drawPixmap(vIconRect.topLeft(), pixmap); + + // draw checkmark ------------------------------------------------- + } else if (checked) { + QStyleOptionMenuItem newMi = *menuitem; + newMi.state = State_None; + if (!dis) + newMi.state |= State_Enabled; + if (act) + newMi.state |= State_On; + + QRect checkMarkRect = QRect(menuitem->rect.x() + windowsItemFrame, + menuitem->rect.y() + windowsItemFrame, + checkcol - 2 * windowsItemFrame, + menuitem->rect.height() - 2*windowsItemFrame); + newMi.rect = visualRect(option->direction, option->rect, checkMarkRect); + proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget); + } + + QColor textColor = dis ? menuitem->palette.text().color() : + act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color(); + p->setPen(textColor); + + // draw text ------------------------------------------------------ + int xm = windowsItemFrame + checkcol + windowsItemHMargin; + xpos = menuitem->rect.x() + xm; + QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); + QRect vTextRect = visualRect(option->direction, option->rect, textRect); + QString s = menuitem->text; + if (!s.isEmpty()) { + p->save(); + int t = s.indexOf(QLatin1Char('\t')); + int text_flags = Qt::AlignVCenter|Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine | Qt::AlignLeft; + if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget)) + text_flags |= Qt::TextHideMnemonic; + // draw tab text ---------------- + if (t >= 0) { + QRect vShortcutRect = visualRect(option->direction, option->rect, QRect(textRect.topRight(), menuitem->rect.bottomRight())); + if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { + p->setPen(menuitem->palette.light().color()); + p->drawText(vShortcutRect.adjusted(1,1,1,1), text_flags, s.mid(t + 1)); + p->setPen(textColor); + } + p->drawText(vShortcutRect, text_flags, s.mid(t + 1)); + s = s.left(t); + } + QFont font = menuitem->font; + if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) + font.setBold(true); + p->setFont(font); + if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { + p->setPen(menuitem->palette.light().color()); + p->drawText(vTextRect.adjusted(1,1,1,1), text_flags, s.left(t)); + p->setPen(textColor); + } + p->drawText(vTextRect, text_flags, s); + p->restore(); + } + + // draw sub menu arrow -------------------------------------------- + if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) { + int dim = (h - 2) / 2; + PrimitiveElement arrow; + arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; + xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim; + QRect vSubMenuRect = visualRect(option->direction, option->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim)); + QStyleOptionMenuItem newMI = *menuitem; + newMI.rect = vSubMenuRect; + newMI.state = dis ? State_None : State_Enabled; + if (act) + newMI.palette.setColor(QPalette::ButtonText, newMI.palette.highlightedText().color()); + proxy()->drawPrimitive(arrow, &newMI, p, widget); + } + } + return; + + case CE_MenuBarItem: + if (const QStyleOptionMenuItem *mbi = qstyleoption_cast(option)) + { + if (mbi->menuItemType == QStyleOptionMenuItem::DefaultItem) + break; + + bool act = mbi->state & State_Selected; + bool dis = !(mbi->state & State_Enabled); + + QBrush fill = mbi->palette.brush(act ? QPalette::Highlight : QPalette::Button); + QPalette::ColorRole textRole = dis ? QPalette::Text: + act ? QPalette::HighlightedText : QPalette::ButtonText; + QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal); + + uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget)) + alignment |= Qt::TextHideMnemonic; + + p->fillRect(rect, fill); + if (!pix.isNull()) + drawItemPixmap(p, mbi->rect, alignment, pix); + else + drawItemText(p, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole); + } + return; +#ifndef QT_NO_DOCKWIDGET + case CE_DockWidgetTitle: + if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast(option)) + { + int buttonMargin = 4; + int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget); + int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget); + bool isFloating = widget && widget->isWindow(); + bool isActive = dwOpt->state & State_Active; + + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast(dwOpt); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + + if (verticalTitleBar) { + QSize s = rect.size(); + s.transpose(); + rect.setSize(s); + + p->translate(rect.left() - 1, rect.top() + rect.width()); + p->rotate(-90); + p->translate(-rect.left() + 1, -rect.top()); + } + QRect r = rect.adjusted(0, 2, -1, -3); + QRect titleRect = r; + + if (dwOpt->closable) { + QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10)); + titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0); + } + + if (dwOpt->floatable) { + QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10)); + titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0); + } + + if (isFloating) { + titleRect.adjust(0, -fw, 0, 0); + if (widget != 0 && widget->windowIcon().cacheKey() != QApplication::windowIcon().cacheKey()) + titleRect.adjust(titleRect.height() + mw, 0, 0, 0); + } else { + titleRect.adjust(mw, 0, 0, 0); + if (!dwOpt->floatable && !dwOpt->closable) + titleRect.adjust(0, 0, -mw, 0); + } + + if (!verticalTitleBar) + titleRect = visualRect(dwOpt->direction, r, titleRect); + + if (!isFloating) { + QPen oldPen = p->pen(); + QString titleText = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width()); + p->setPen(dwOpt->palette.color(QPalette::Dark)); + p->drawRect(r); + + if (!titleText.isEmpty()) { + drawItemText(p, titleRect, + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette, + dwOpt->state & State_Enabled, titleText, + QPalette::WindowText); + } + + p->setPen(oldPen); + } else { + name = QLatin1String("WINDOW"); + if (isActive) + stateId = CS_ACTIVE; + else + stateId = CS_INACTIVE; + + int titleHeight = rect.height() - 2; + rect = rect.adjusted(-fw, -fw, fw, 0); + + XPThemeData theme(widget, p, name, 0, stateId); + if (!theme.isValid()) + break; + + // Draw small type title bar + theme.rect = rect; + theme.partId = WP_SMALLCAPTION; + d->drawBackground(theme); + + // Figure out maximal button space on title bar + + QIcon ico = widget->windowIcon(); + bool hasIcon = (ico.cacheKey() != QApplication::windowIcon().cacheKey()); + if (hasIcon) { + QPixmap pxIco = ico.pixmap(titleHeight); + if (!verticalTitleBar && dwOpt->direction == Qt::RightToLeft) + p->drawPixmap(rect.width() - titleHeight - pxIco.width(), rect.bottom() - titleHeight - 2, pxIco); + else + p->drawPixmap(fw, rect.bottom() - titleHeight - 2, pxIco); + } + if (!dwOpt->title.isEmpty()) { + QPen oldPen = p->pen(); + QFont oldFont = p->font(); + QFont titleFont = oldFont; + titleFont.setBold(true); + p->setFont(titleFont); + QString titleText + = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width()); + + int result = TST_NONE; + pGetThemeEnumValue(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); + if (result != TST_NONE) { + COLORREF textShadowRef; + pGetThemeColor(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef); + QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef)); + p->setPen(textShadow); + drawItemText(p, titleRect.adjusted(1, 1, 1, 1), + Qt::AlignLeft | Qt::AlignBottom, dwOpt->palette, + dwOpt->state & State_Enabled, titleText); + } + + COLORREF captionText = GetSysColor(isActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT); + QColor textColor = qRgb(GetRValue(captionText), GetGValue(captionText), GetBValue(captionText)); + p->setPen(textColor); + drawItemText(p, titleRect, + Qt::AlignLeft | Qt::AlignBottom, dwOpt->palette, + dwOpt->state & State_Enabled, titleText); + p->setFont(oldFont); + p->setPen(oldPen); + } + + } + + return; + } + break; +#endif // QT_NO_DOCKWIDGET +#ifndef QT_NO_RUBBERBAND + case CE_RubberBand: + if (qstyleoption_cast(option)) { + QColor highlight = option->palette.color(QPalette::Active, QPalette::Highlight); + p->save(); + QRect r = option->rect; + p->setPen(highlight.darker(120)); + QColor dimHighlight(qMin(highlight.red()/2 + 110, 255), + qMin(highlight.green()/2 + 110, 255), + qMin(highlight.blue()/2 + 110, 255), + (widget && widget->isTopLevel())? 255 : 127); + p->setBrush(dimHighlight); + p->drawRect(option->rect.adjusted(0, 0, -1, -1)); + p->restore(); + return; + } +#endif // QT_NO_RUBBERBAND + case CE_HeaderEmptyArea: + if (option->state & State_Horizontal) + { + name = QLatin1String("HEADER"); + stateId = HIS_NORMAL; + } + else { + QWindowsStyle::drawControl(CE_HeaderEmptyArea, option, p, widget); + return; + } + break; + default: + break; + } + + XPThemeData theme(widget, p, name, partId, stateId, rect); + if (!theme.isValid()) { + QWindowsStyle::drawControl(element, option, p, widget); + return; + } + + theme.rotate = rotate; + theme.mirrorHorizontally = hMirrored; + theme.mirrorVertically = vMirrored; + d->drawBackground(theme); +} + + +/*! + \reimp +*/ +void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option, + QPainter *p, const QWidget *widget) const +{ + QWindowsXPStylePrivate *d = const_cast(d_func()); + + if (!QWindowsXPStylePrivate::useXP()) { + QWindowsStyle::drawComplexControl(cc, option, p, widget); + return; + } + + State flags = option->state; + SubControls sub = option->subControls; + QRect r = option->rect; + + int partId = 0; + int stateId = 0; + if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow()) + flags |= State_MouseOver; + + switch (cc) { +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *sb = qstyleoption_cast(option)) + { + XPThemeData theme(widget, p, QLatin1String("SPIN")); + + if (sb->frame && (sub & SC_SpinBoxFrame)) { + partId = EP_EDITTEXT; + if (!(flags & State_Enabled)) + stateId = ETS_DISABLED; + else if (flags & State_HasFocus) + stateId = ETS_FOCUSED; + else + stateId = ETS_NORMAL; + + XPThemeData ftheme(widget, p, QLatin1String("EDIT"), partId, stateId, r); + ftheme.noContent = true; + d->drawBackground(ftheme); + } + if (sub & SC_SpinBoxUp) { + theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget); + partId = SPNP_UP; + if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled)) + stateId = UPS_DISABLED; + else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken)) + stateId = UPS_PRESSED; + else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_MouseOver)) + stateId = UPS_HOT; + else + stateId = UPS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_SpinBoxDown) { + theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget); + partId = SPNP_DOWN; + if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled)) + stateId = DNS_DISABLED; + else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken)) + stateId = DNS_PRESSED; + else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_MouseOver)) + stateId = DNS_HOT; + else + stateId = DNS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + } + break; +#endif // QT_NO_SPINBOX +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) + { + if (sub & SC_ComboBoxEditField) { + if (cmb->frame) { + partId = EP_EDITTEXT; + if (!(flags & State_Enabled)) + stateId = ETS_DISABLED; + else if (flags & State_HasFocus) + stateId = ETS_FOCUSED; + else + stateId = ETS_NORMAL; + XPThemeData theme(widget, p, QLatin1String("EDIT"), partId, stateId, r); + d->drawBackground(theme); + } else { + QBrush editBrush = cmb->palette.brush(QPalette::Base); + p->fillRect(option->rect, editBrush); + } + if (!cmb->editable) { + QRect re = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget); + if (option->state & State_HasFocus) { + p->fillRect(re, option->palette.highlight()); + p->setPen(option->palette.highlightedText().color()); + p->setBackground(option->palette.highlight()); + } else { + p->fillRect(re, option->palette.base()); + p->setPen(option->palette.text().color()); + p->setBackground(option->palette.base()); + } + } + } + + if (sub & SC_ComboBoxArrow) { + XPThemeData theme(widget, p, QLatin1String("COMBOBOX")); + theme.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget); + partId = CP_DROPDOWNBUTTON; + if (!(flags & State_Enabled)) + stateId = CBXS_DISABLED; + else if (cmb->activeSubControls == SC_ComboBoxArrow && (cmb->state & State_Sunken)) + stateId = CBXS_PRESSED; + else if (cmb->activeSubControls == SC_ComboBoxArrow && (cmb->state & State_MouseOver)) + stateId = CBXS_HOT; + else + stateId = CBXS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + } + break; +#endif // QT_NO_COMBOBOX + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(option)) + { + XPThemeData theme(widget, p, QLatin1String("SCROLLBAR")); + bool maxedOut = (scrollbar->maximum == scrollbar->minimum); + if (maxedOut) + flags &= ~State_Enabled; + + bool isHorz = flags & State_Horizontal; + bool isRTL = option->direction == Qt::RightToLeft; + if (sub & SC_ScrollBarAddLine) { + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget); + partId = SBP_ARROWBTN; + if (!(flags & State_Enabled)) + stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED); + else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_Sunken)) + stateId = (isHorz ? (isRTL ? ABS_LEFTPRESSED : ABS_RIGHTPRESSED) : ABS_DOWNPRESSED); + else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_MouseOver)) + stateId = (isHorz ? (isRTL ? ABS_LEFTHOT : ABS_RIGHTHOT) : ABS_DOWNHOT); + else + stateId = (isHorz ? (isRTL ? ABS_LEFTNORMAL : ABS_RIGHTNORMAL) : ABS_DOWNNORMAL); + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_ScrollBarSubLine) { + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget); + partId = SBP_ARROWBTN; + if (!(flags & State_Enabled)) + stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED); + else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_Sunken)) + stateId = (isHorz ? (isRTL ? ABS_RIGHTPRESSED : ABS_LEFTPRESSED) : ABS_UPPRESSED); + else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_MouseOver)) + stateId = (isHorz ? (isRTL ? ABS_RIGHTHOT : ABS_LEFTHOT) : ABS_UPHOT); + else + stateId = (isHorz ? (isRTL ? ABS_RIGHTNORMAL : ABS_LEFTNORMAL) : ABS_UPNORMAL); + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (maxedOut) { + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); + theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget)); + theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget)); + partId = scrollbar->orientation == Qt::Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; + stateId = SCRBS_DISABLED; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } else { + if (sub & SC_ScrollBarSubPage) { + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget); + partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT; + if (!(flags & State_Enabled)) + stateId = SCRBS_DISABLED; + else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_Sunken)) + stateId = SCRBS_PRESSED; + else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_MouseOver)) + stateId = SCRBS_HOT; + else + stateId = SCRBS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_ScrollBarAddPage) { + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget); + partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; + if (!(flags & State_Enabled)) + stateId = SCRBS_DISABLED; + else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_Sunken)) + stateId = SCRBS_PRESSED; + else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_MouseOver)) + stateId = SCRBS_HOT; + else + stateId = SCRBS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_ScrollBarSlider) { + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); + if (!(flags & State_Enabled)) + stateId = SCRBS_DISABLED; + else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken)) + stateId = SCRBS_PRESSED; + else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_MouseOver)) + stateId = SCRBS_HOT; + else + stateId = SCRBS_NORMAL; + + // Draw handle + theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); + theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT; + theme.stateId = stateId; + d->drawBackground(theme); + + // Calculate rect of gripper + const int swidth = theme.rect.width(); + const int sheight = theme.rect.height(); + + MARGINS contentsMargin; + RECT rect = theme.toRECT(theme.rect); + pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); + + SIZE size; + theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; + pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + int gw = size.cx, gh = size.cy; + + + QRect gripperBounds; + if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) { + gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); + gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); + gripperBounds.setWidth(gw); + gripperBounds.setHeight(gh); + } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) { + gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); + gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); + gripperBounds.setWidth(gw); + gripperBounds.setHeight(gh); + } + + // Draw gripper if there is enough space + if (!gripperBounds.isEmpty()) { + p->save(); + theme.rect = gripperBounds; + p->setClipRegion(d->region(theme));// Only change inside the region of the gripper + d->drawBackground(theme); // Transparent gripper ontop of background + p->restore(); + } + } + } + } + break; + +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) + { + XPThemeData theme(widget, p, QLatin1String("TRACKBAR")); + QRect slrect = slider->rect; + QRegion tickreg = slrect; + if (sub & SC_SliderGroove) { + theme.rect = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget); + if (slider->orientation == Qt::Horizontal) { + partId = TKP_TRACK; + stateId = TRS_NORMAL; + theme.rect = QRect(slrect.left(), theme.rect.center().y() - 2, slrect.width(), 4); + } else { + partId = TKP_TRACKVERT; + stateId = TRVS_NORMAL; + theme.rect = QRect(theme.rect.center().x() - 2, slrect.top(), 4, slrect.height()); + } + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + tickreg -= theme.rect; + } + if (sub & SC_SliderTickmarks) { + int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget); + int ticks = slider->tickPosition; + int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget); + int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); + int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget); + int interval = slider->tickInterval; + if (interval <= 0) { + interval = slider->singleStep; + if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval, + available) + - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, + 0, available) < 3) + interval = slider->pageStep; + } + if (!interval) + interval = 1; + int fudge = len / 2; + int pos; + int bothOffset = (ticks & QSlider::TicksAbove && ticks & QSlider::TicksBelow) ? 1 : 0; + p->setPen(d->sliderTickColor); + QVarLengthArray lines; + int v = slider->minimum; + while (v <= slider->maximum + 1) { + if (v == slider->maximum + 1 && interval == 1) + break; + const int v_ = qMin(v, slider->maximum); + int tickLength = (v_ == slider->minimum || v_ >= slider->maximum) ? 4 : 3; + pos = QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, + v_, available) + fudge; + if (slider->orientation == Qt::Horizontal) { + if (ticks & QSlider::TicksAbove) + lines.append(QLine(pos, tickOffset - 1 - bothOffset, + pos, tickOffset - 1 - bothOffset - tickLength)); + + if (ticks & QSlider::TicksBelow) + lines.append(QLine(pos, tickOffset + thickness + bothOffset, + pos, tickOffset + thickness + bothOffset + tickLength)); + } else { + if (ticks & QSlider::TicksAbove) + lines.append(QLine(tickOffset - 1 - bothOffset, pos, + tickOffset - 1 - bothOffset - tickLength, pos)); + + if (ticks & QSlider::TicksBelow) + lines.append(QLine(tickOffset + thickness + bothOffset, pos, + tickOffset + thickness + bothOffset + tickLength, pos)); + } + // in the case where maximum is max int + int nextInterval = v + interval; + if (nextInterval < v) + break; + v = nextInterval; + } + if (lines.size() > 0) { + p->save(); + p->translate(slrect.topLeft()); + p->drawLines(lines.constData(), lines.size()); + p->restore(); + } + } + if (sub & SC_SliderHandle) { + theme.rect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget); + if (slider->orientation == Qt::Horizontal) { + if (slider->tickPosition == QSlider::TicksAbove) + partId = TKP_THUMBTOP; + else if (slider->tickPosition == QSlider::TicksBelow) + partId = TKP_THUMBBOTTOM; + else + partId = TKP_THUMB; + + if (!(slider->state & State_Enabled)) + stateId = TUS_DISABLED; + else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_Sunken)) + stateId = TUS_PRESSED; + else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_MouseOver)) + stateId = TUS_HOT; + else if (flags & State_HasFocus) + stateId = TUS_FOCUSED; + else + stateId = TUS_NORMAL; + } else { + if (slider->tickPosition == QSlider::TicksLeft) + partId = TKP_THUMBLEFT; + else if (slider->tickPosition == QSlider::TicksRight) + partId = TKP_THUMBRIGHT; + else + partId = TKP_THUMBVERT; + + if (!(slider->state & State_Enabled)) + stateId = TUVS_DISABLED; + else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_Sunken)) + stateId = TUVS_PRESSED; + else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_MouseOver)) + stateId = TUVS_HOT; + else if (flags & State_HasFocus) + stateId = TUVS_FOCUSED; + else + stateId = TUVS_NORMAL; + } + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (slider->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*slider); + fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + break; +#endif +#ifndef QT_NO_TOOLBUTTON + case CC_ToolButton: + if (const QStyleOptionToolButton *toolbutton + = qstyleoption_cast(option)) { + QRect button, menuarea; + button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget); + menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget); + + State bflags = toolbutton->state & ~State_Sunken; + State mflags = bflags; + bool autoRaise = flags & State_AutoRaise; + if (autoRaise) { + if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) { + bflags &= ~State_Raised; + } + } + + if (toolbutton->state & State_Sunken) { + if (toolbutton->activeSubControls & SC_ToolButton) { + bflags |= State_Sunken; + mflags |= State_MouseOver | State_Sunken; + } else if (toolbutton->activeSubControls & SC_ToolButtonMenu) { + mflags |= State_Sunken; + bflags |= State_MouseOver; + } + } + + QStyleOption tool(0); + tool.palette = toolbutton->palette; + if (toolbutton->subControls & SC_ToolButton) { + if (flags & (State_Sunken | State_On | State_Raised) || !autoRaise) { + if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup && autoRaise) { + XPThemeData theme(widget, p, QLatin1String("TOOLBAR")); + theme.partId = TP_SPLITBUTTON; + theme.rect = button; + if (!(bflags & State_Enabled)) + stateId = TS_DISABLED; + else if (bflags & State_Sunken) + stateId = TS_PRESSED; + else if (bflags & State_MouseOver || !(flags & State_AutoRaise)) + stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT; + else if (bflags & State_On) + stateId = TS_CHECKED; + else + stateId = TS_NORMAL; + if (option->direction == Qt::RightToLeft) + theme.mirrorHorizontally = true; + theme.stateId = stateId; + d->drawBackground(theme); + } else { + tool.rect = option->rect; + tool.state = bflags; + if (autoRaise) // for tool bars + proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + else + proxy()->drawPrimitive(PE_PanelButtonBevel, &tool, p, widget); + } + } + } + + if (toolbutton->state & State_HasFocus) { + QStyleOptionFocusRect fr; + fr.QStyleOption::operator=(*toolbutton); + fr.rect.adjust(3, 3, -3, -3); + if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup) + fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, + toolbutton, widget), 0); + proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget); + } + QStyleOptionToolButton label = *toolbutton; + label.state = bflags; + int fw = 2; + if (!autoRaise) + label.state &= ~State_Sunken; + label.rect = button.adjusted(fw, fw, -fw, -fw); + proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); + + if (toolbutton->subControls & SC_ToolButtonMenu) { + tool.rect = menuarea; + tool.state = mflags; + if (autoRaise) { + proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); + } else { + tool.state = mflags; + menuarea.adjust(-2, 0, 0, 0); + // Draw menu button + if ((bflags & State_Sunken) != (mflags & State_Sunken)){ + p->save(); + p->setClipRect(menuarea); + tool.rect = option->rect; + proxy()->drawPrimitive(PE_PanelButtonBevel, &tool, p, 0); + p->restore(); + } + // Draw arrow + p->save(); + p->setPen(option->palette.dark().color()); + p->drawLine(menuarea.left(), menuarea.top() + 3, + menuarea.left(), menuarea.bottom() - 3); + p->setPen(option->palette.light().color()); + p->drawLine(menuarea.left() - 1, menuarea.top() + 3, + menuarea.left() - 1, menuarea.bottom() - 3); + + tool.rect = menuarea.adjusted(2, 3, -2, -1); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget); + p->restore(); + } + } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { + int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget); + QRect ir = toolbutton->rect; + QStyleOptionToolButton newBtn = *toolbutton; + newBtn.rect = QRect(ir.right() + 4 - mbi, ir.height() - mbi + 4, mbi - 5, mbi - 5); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); + } + } + break; +#endif // QT_NO_TOOLBUTTON + + case CC_TitleBar: + { + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(option)) + { + bool isActive = tb->titleBarState & QStyle::State_Active; + XPThemeData theme(widget, p, QLatin1String("WINDOW")); + if (sub & SC_TitleBarLabel) { + +#ifdef QT3_SUPPORT + if (widget && widget->inherits("Q3DockWindowTitleBar")) { + partId = WP_SMALLCAPTION; + } else +#endif + partId = (tb->titleBarState & Qt::WindowMinimized) ? WP_MINCAPTION : WP_CAPTION; + theme.rect = option->rect; + if (widget && !widget->isEnabled()) + stateId = CS_DISABLED; + else if (isActive) + stateId = CS_ACTIVE; + else + stateId = CS_INACTIVE; + + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + + QRect ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget); + + int result = TST_NONE; + pGetThemeEnumValue(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); + if (result != TST_NONE) { + COLORREF textShadowRef; + pGetThemeColor(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef); + QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef)); + p->setPen(textShadow); + p->drawText(ir.x() + 3, ir.y() + 2, ir.width() - 1, ir.height(), + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text); + } + COLORREF captionText = GetSysColor(isActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT); + QColor textColor = qRgb(GetRValue(captionText), GetGValue(captionText), GetBValue(captionText)); + p->setPen(textColor); + p->drawText(ir.x() + 2, ir.y() + 1, ir.width() - 2, ir.height(), + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text); + } + if (sub & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) { + theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarSysMenu, widget); + partId = WP_SYSBUTTON; + if ((widget && !widget->isEnabled()) || !isActive) + stateId = SBS_DISABLED; + else if (option->activeSubControls == SC_TitleBarSysMenu && (option->state & State_Sunken)) + stateId = SBS_PUSHED; + else if (option->activeSubControls == SC_TitleBarSysMenu && (option->state & State_MouseOver)) + stateId = SBS_HOT; + else + stateId = SBS_NORMAL; + if (!tb->icon.isNull()) { + tb->icon.paint(p, theme.rect); + } else { + theme.partId = partId; + theme.stateId = stateId; + SIZE sz; + pGetThemePartSize(theme.handle(), qt_win_display_dc(), theme.partId, theme.stateId, 0, TS_TRUE, &sz); + if (sz.cx == 0 || sz.cy == 0) { + int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget); + QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, tb, widget).pixmap(iconSize, iconSize); + p->save(); + drawItemPixmap(p, theme.rect, Qt::AlignCenter, pm); + p->restore(); + } else { + d->drawBackground(theme); + } + } + } + + if (sub & SC_TitleBarMinButton && tb->titleBarFlags & Qt::WindowMinimizeButtonHint + && !(tb->titleBarState & Qt::WindowMinimized)) { + theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMinButton, widget); + partId = WP_MINBUTTON; + if (widget && !widget->isEnabled()) + stateId = MINBS_DISABLED; + else if (option->activeSubControls == SC_TitleBarMinButton && (option->state & State_Sunken)) + stateId = MINBS_PUSHED; + else if (option->activeSubControls == SC_TitleBarMinButton && (option->state & State_MouseOver)) + stateId = MINBS_HOT; + else if (!isActive) + stateId = MINBS_INACTIVE; + else + stateId = MINBS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_TitleBarMaxButton && tb->titleBarFlags & Qt::WindowMaximizeButtonHint + && !(tb->titleBarState & Qt::WindowMaximized)) { + theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMaxButton, widget); + partId = WP_MAXBUTTON; + if (widget && !widget->isEnabled()) + stateId = MAXBS_DISABLED; + else if (option->activeSubControls == SC_TitleBarMaxButton && (option->state & State_Sunken)) + stateId = MAXBS_PUSHED; + else if (option->activeSubControls == SC_TitleBarMaxButton && (option->state & State_MouseOver)) + stateId = MAXBS_HOT; + else if (!isActive) + stateId = MAXBS_INACTIVE; + else + stateId = MAXBS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_TitleBarContextHelpButton + && tb->titleBarFlags & Qt::WindowContextHelpButtonHint) { + theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarContextHelpButton, widget); + partId = WP_HELPBUTTON; + if (widget && !widget->isEnabled()) + stateId = MINBS_DISABLED; + else if (option->activeSubControls == SC_TitleBarContextHelpButton && (option->state & State_Sunken)) + stateId = MINBS_PUSHED; + else if (option->activeSubControls == SC_TitleBarContextHelpButton && (option->state & State_MouseOver)) + stateId = MINBS_HOT; + else if (!isActive) + stateId = MINBS_INACTIVE; + else + stateId = MINBS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + bool drawNormalButton = (sub & SC_TitleBarNormalButton) + && (((tb->titleBarFlags & Qt::WindowMinimizeButtonHint) + && (tb->titleBarState & Qt::WindowMinimized)) + || ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint) + && (tb->titleBarState & Qt::WindowMaximized))); + if (drawNormalButton) { + theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarNormalButton, widget); + partId = WP_RESTOREBUTTON; + if (widget && !widget->isEnabled()) + stateId = RBS_DISABLED; + else if (option->activeSubControls == SC_TitleBarNormalButton && (option->state & State_Sunken)) + stateId = RBS_PUSHED; + else if (option->activeSubControls == SC_TitleBarNormalButton && (option->state & State_MouseOver)) + stateId = RBS_HOT; + else if (!isActive) + stateId = RBS_INACTIVE; + else + stateId = RBS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_TitleBarShadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint + && !(tb->titleBarState & Qt::WindowMinimized)) { + theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarShadeButton, widget); + partId = WP_MINBUTTON; + if (widget && !widget->isEnabled()) + stateId = MINBS_DISABLED; + else if (option->activeSubControls == SC_TitleBarShadeButton && (option->state & State_Sunken)) + stateId = MINBS_PUSHED; + else if (option->activeSubControls == SC_TitleBarShadeButton && (option->state & State_MouseOver)) + stateId = MINBS_HOT; + else if (!isActive) + stateId = MINBS_INACTIVE; + else + stateId = MINBS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_TitleBarUnshadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint + && tb->titleBarState & Qt::WindowMinimized) { + theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarUnshadeButton, widget); + partId = WP_RESTOREBUTTON; + if (widget && !widget->isEnabled()) + stateId = RBS_DISABLED; + else if (option->activeSubControls == SC_TitleBarUnshadeButton && (option->state & State_Sunken)) + stateId = RBS_PUSHED; + else if (option->activeSubControls == SC_TitleBarUnshadeButton && (option->state & State_MouseOver)) + stateId = RBS_HOT; + else if (!isActive) + stateId = RBS_INACTIVE; + else + stateId = RBS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + if (sub & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) { + theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarCloseButton, widget); + //partId = titlebar->testWFlags(Qt::WA_WState_Tool) ? WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON; + partId = WP_CLOSEBUTTON; + if (widget && !widget->isEnabled()) + stateId = CBS_DISABLED; + else if (option->activeSubControls == SC_TitleBarCloseButton && (option->state & State_Sunken)) + stateId = CBS_PUSHED; + else if (option->activeSubControls == SC_TitleBarCloseButton && (option->state & State_MouseOver)) + stateId = CBS_HOT; + else if (!isActive) + stateId = CBS_INACTIVE; + else + stateId = CBS_NORMAL; + theme.partId = partId; + theme.stateId = stateId; + d->drawBackground(theme); + } + } + } + break; + +#ifndef QT_NO_WORKSPACE + case CC_MdiControls: + { + QRect buttonRect; + XPThemeData theme(widget, p, QLatin1String("WINDOW"), WP_MDICLOSEBUTTON, CBS_NORMAL); + + if (option->subControls & SC_MdiCloseButton) { + buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiCloseButton, widget); + if (theme.isValid()) { + theme.partId = WP_MDICLOSEBUTTON; + theme.rect = buttonRect; + if (!(flags & State_Enabled)) + theme.stateId = CBS_INACTIVE; + else if (flags & State_Sunken && (option->activeSubControls & SC_MdiCloseButton)) + theme.stateId = CBS_PUSHED; + else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiCloseButton)) + theme.stateId = CBS_HOT; + else + theme.stateId = CBS_NORMAL; + d->drawBackground(theme); + } + } + if (option->subControls & SC_MdiNormalButton) { + buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiNormalButton, widget); + if (theme.isValid()) { + theme.partId = WP_MDIRESTOREBUTTON; + theme.rect = buttonRect; + if (!(flags & State_Enabled)) + theme.stateId = CBS_INACTIVE; + else if (flags & State_Sunken && (option->activeSubControls & SC_MdiNormalButton)) + theme.stateId = CBS_PUSHED; + else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiNormalButton)) + theme.stateId = CBS_HOT; + else + theme.stateId = CBS_NORMAL; + d->drawBackground(theme); + } + } + if (option->subControls & QStyle::SC_MdiMinButton) { + buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiMinButton, widget); + if (theme.isValid()) { + theme.partId = WP_MDIMINBUTTON; + theme.rect = buttonRect; + if (!(flags & State_Enabled)) + theme.stateId = CBS_INACTIVE; + else if (flags & State_Sunken && (option->activeSubControls & SC_MdiMinButton)) + theme.stateId = CBS_PUSHED; + else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiMinButton)) + theme.stateId = CBS_HOT; + else + theme.stateId = CBS_NORMAL; + d->drawBackground(theme); + } + } + } + break; +#endif //QT_NO_WORKSPACE +#ifndef QT_NO_DIAL + case CC_Dial: + if (const QStyleOptionSlider *dial = qstyleoption_cast(option)) + QStyleHelper::drawDial(dial, p); + break; +#endif // QT_NO_DIAL + default: + QWindowsStyle::drawComplexControl(cc, option, p, widget); + break; + } +} + +/*! \reimp */ +int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, const QWidget *widget) const +{ + if (!QWindowsXPStylePrivate::useXP()) + return QWindowsStyle::pixelMetric(pm, option, widget); + + int res = 0; + switch (pm) { + case PM_MenuBarPanelWidth: + res = 0; + break; + + case PM_DefaultFrameWidth: + if (qobject_cast(widget)) + res = 2; + else + res = 1; + break; + case PM_MenuPanelWidth: + case PM_SpinBoxFrameWidth: + res = 1; + break; + + case PM_TabBarTabOverlap: + case PM_MenuHMargin: + case PM_MenuVMargin: + res = 2; + break; + + case PM_TabBarBaseOverlap: + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { + switch (tab->shape) { + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + res = 1; + break; + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + res = 2; + break; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + res = 3; + break; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + res = 1; + break; + } + } + break; + + case PM_SplitterWidth: + res = qMax(int(QStyleHelper::dpiScaled(5.)), QApplication::globalStrut().width()); + break; + + case PM_IndicatorWidth: + case PM_IndicatorHeight: + { + XPThemeData theme(widget, 0, QLatin1String("BUTTON"), BP_CHECKBOX, CBS_UNCHECKEDNORMAL); + if (theme.isValid()) { + SIZE size; + pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + res = (pm == PM_IndicatorWidth) ? size.cx : size.cy; + } + } + break; + + case PM_ExclusiveIndicatorWidth: + case PM_ExclusiveIndicatorHeight: + { + XPThemeData theme(widget, 0, QLatin1String("BUTTON"), BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL); + if (theme.isValid()) { + SIZE size; + pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + res = (pm == PM_ExclusiveIndicatorWidth) ? size.cx : size.cy; + } + } + break; + + case PM_ProgressBarChunkWidth: + { + Qt::Orientation orient = Qt::Horizontal; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(option)) + orient = pb2->orientation; + XPThemeData theme(widget, 0, QLatin1String("PROGRESS"), (orient == Qt::Horizontal) ? PP_CHUNK : PP_CHUNKVERT); + if (theme.isValid()) { + SIZE size; + pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + res = (orient == Qt::Horizontal) ? size.cx : size.cy; + } + } + break; + + case PM_SliderThickness: + { + XPThemeData theme(widget, 0, QLatin1String("TRACKBAR"), TKP_THUMB); + if (theme.isValid()) { + SIZE size; + pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + res = size.cy; + } + } + break; + + case PM_TitleBarHeight: + { +#ifdef QT3_SUPPORT + if (widget && widget->inherits("Q3DockWindowTitleBar")) { + res = GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); + } else +#endif + if (widget && (widget->windowType() == Qt::Tool)) + res = GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); + else + res = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); + } + break; + + case PM_MdiSubWindowFrameWidth: + { + XPThemeData theme(widget, 0, QLatin1String("WINDOW"), WP_FRAMELEFT, FS_ACTIVE); + if (theme.isValid()) { + SIZE size; + pGetThemePartSize(theme.handle(), 0, WP_FRAMELEFT, FS_ACTIVE, 0, TS_TRUE, &size); + res = size.cx-1; + } + } + break; + + case PM_MdiSubWindowMinimizedWidth: + res = 160; + break; + +#ifndef QT_NO_TOOLBAR + case PM_ToolBarHandleExtent: + res = int(QStyleHelper::dpiScaled(8.)); + break; + +#endif // QT_NO_TOOLBAR + case PM_DockWidgetFrameWidth: + { + XPThemeData theme(widget, 0, QLatin1String("WINDOW"), WP_SMALLFRAMERIGHT, FS_ACTIVE); + if (theme.isValid()) { + SIZE size; + pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + res = size.cx; + } + } + break; + case PM_DockWidgetSeparatorExtent: + res = int(QStyleHelper::dpiScaled(4.)); + break; + case PM_DockWidgetTitleMargin: + res = int(QStyleHelper::dpiScaled(4.)); + break; + + case PM_ButtonShiftHorizontal: + case PM_ButtonShiftVertical: + if (qstyleoption_cast(option)) + res = 1; + else + res = 0; + break; + + case PM_ButtonDefaultIndicator: + res = 0; + break; + + default: + res = QWindowsStyle::pixelMetric(pm, option, widget); + } + + return res; +} + +/* + This function is used by subControlRect to check if a button + should be drawn for the given subControl given a set of window flags. +*/ +static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBar *tb){ + + bool isMinimized = tb->titleBarState & Qt::WindowMinimized; + bool isMaximized = tb->titleBarState & Qt::WindowMaximized; + const uint flags = tb->titleBarFlags; + bool retVal = false; + switch (sc) { + case QStyle::SC_TitleBarContextHelpButton: + if (flags & Qt::WindowContextHelpButtonHint) + retVal = true; + break; + case QStyle::SC_TitleBarMinButton: + if (!isMinimized && (flags & Qt::WindowMinimizeButtonHint)) + retVal = true; + break; + case QStyle::SC_TitleBarNormalButton: + if (isMinimized && (flags & Qt::WindowMinimizeButtonHint)) + retVal = true; + else if (isMaximized && (flags & Qt::WindowMaximizeButtonHint)) + retVal = true; + break; + case QStyle::SC_TitleBarMaxButton: + if (!isMaximized && (flags & Qt::WindowMaximizeButtonHint)) + retVal = true; + break; + case QStyle::SC_TitleBarShadeButton: + if (!isMinimized && flags & Qt::WindowShadeButtonHint) + retVal = true; + break; + case QStyle::SC_TitleBarUnshadeButton: + if (isMinimized && flags & Qt::WindowShadeButtonHint) + retVal = true; + break; + case QStyle::SC_TitleBarCloseButton: + if (flags & Qt::WindowSystemMenuHint) + retVal = true; + break; + case QStyle::SC_TitleBarSysMenu: + if (flags & Qt::WindowSystemMenuHint) + retVal = true; + break; + default : + retVal = true; + } + return retVal; +} + +/*! + \reimp +*/ +QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option, + SubControl subControl, const QWidget *widget) const +{ + if (!QWindowsXPStylePrivate::useXP()) + return QWindowsStyle::subControlRect(cc, option, subControl, widget); + + QRect rect; + + switch (cc) { + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast(option)) { + if (!buttonVisible(subControl, tb)) + return rect; + const bool isToolTitle = false; + const int height = tb->rect.height(); + const int width = tb->rect.width(); + int buttonHeight = GetSystemMetrics(SM_CYSIZE) - 4; + int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4; + const int delta = buttonWidth + 2; + int controlTop = option->rect.bottom() - buttonHeight - 2; + const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); + const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0; + const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0; + const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0; + const bool contextHint = (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) != 0; + const bool shadeHint = (tb->titleBarFlags & Qt::WindowShadeButtonHint) != 0; + bool isMinimized = tb->titleBarState & Qt::WindowMinimized; + bool isMaximized = tb->titleBarState & Qt::WindowMaximized; + int offset = 0; + + switch (subControl) { + case SC_TitleBarLabel: + rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height); + if (isToolTitle) { + if (sysmenuHint) { + rect.adjust(0, 0, -buttonWidth - 3, 0); + } + if (minimizeHint || maximizeHint) + rect.adjust(0, 0, -buttonWidth - 2, 0); + } else { + if (sysmenuHint) { + const int leftOffset = height - 8; + rect.adjust(leftOffset, 0, 0, 0); + } + if (minimizeHint) + rect.adjust(0, 0, -buttonWidth - 2, 0); + if (maximizeHint) + rect.adjust(0, 0, -buttonWidth - 2, 0); + if (contextHint) + rect.adjust(0, 0, -buttonWidth - 2, 0); + if (shadeHint) + rect.adjust(0, 0, -buttonWidth - 2, 0); + } + break; + + case SC_TitleBarContextHelpButton: + if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) + offset += delta; + //fall through + case SC_TitleBarMinButton: + if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (subControl == SC_TitleBarMinButton) + break; + //fall through + case SC_TitleBarNormalButton: + if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + offset += delta; + else if (subControl == SC_TitleBarNormalButton) + break; + //fall through + case SC_TitleBarMaxButton: + if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + offset += delta; + else if (subControl == SC_TitleBarMaxButton) + break; + //fall through + case SC_TitleBarShadeButton: + if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) + offset += delta; + else if (subControl == SC_TitleBarShadeButton) + break; + //fall through + case SC_TitleBarUnshadeButton: + if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) + offset += delta; + else if (subControl == SC_TitleBarUnshadeButton) + break; + //fall through + case SC_TitleBarCloseButton: + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + offset += delta; + else if (subControl == SC_TitleBarCloseButton) + break; + + rect.setRect(width - offset - controlTop + 1, controlTop, + buttonWidth, buttonHeight); + break; + + case SC_TitleBarSysMenu: + { + const int controlTop = 6; + const int controlHeight = height - controlTop - 3; + const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); + QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent)); + if (tb->icon.isNull()) + iconSize = QSize(controlHeight, controlHeight); + int hPad = (controlHeight - iconSize.height())/2; + int vPad = (controlHeight - iconSize.width())/2; + rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height()); + } + break; + default: + break; + } + } + break; + + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) { + int x = cmb->rect.x(), y = cmb->rect.y(), wi = cmb->rect.width(), he = cmb->rect.height(); + int xpos = x; + xpos += wi - 1 - 16; + + switch (subControl) { + case SC_ComboBoxFrame: + rect = cmb->rect; + break; + + case SC_ComboBoxArrow: + rect = QRect(xpos, y+1, 16, he-2); + break; + + case SC_ComboBoxEditField: + rect = QRect(x+2, y+2, wi-3-16, he-4); + break; + + case SC_ComboBoxListBoxPopup: + rect = cmb->rect; + break; + + default: + break; + } + } + break; +#ifndef QT_NO_WORKSPACE + case CC_MdiControls: + { + int numSubControls = 0; + if (option->subControls & SC_MdiCloseButton) + ++numSubControls; + if (option->subControls & SC_MdiMinButton) + ++numSubControls; + if (option->subControls & SC_MdiNormalButton) + ++numSubControls; + if (numSubControls == 0) + break; + + int buttonWidth = option->rect.width()/ numSubControls; + int offset = 0; + switch (subControl) { + case SC_MdiCloseButton: + // Only one sub control, no offset needed. + if (numSubControls == 1) + break; + offset += buttonWidth; + //FALL THROUGH + case SC_MdiNormalButton: + // No offset needed if + // 1) There's only one sub control + // 2) We have a close button and a normal button (offset already added in SC_MdiClose) + if (numSubControls == 1 || (numSubControls == 2 && !(option->subControls & SC_MdiMinButton))) + break; + if (option->subControls & SC_MdiNormalButton) + offset += buttonWidth; + break; + default: + break; + } + rect = QRect(offset, 0, buttonWidth, option->rect.height()); + break; + } +#endif // QT_NO_WORKSPACE + + default: + rect = visualRect(option->direction, option->rect, + QWindowsStyle::subControlRect(cc, option, subControl, widget)); + break; + } + return visualRect(option->direction, option->rect, rect); +} + +/*! + \reimp +*/ +QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *option, + const QSize &contentsSize, const QWidget *widget) const +{ + if (!QWindowsXPStylePrivate::useXP()) + return QWindowsStyle::sizeFromContents(ct, option, contentsSize, widget); + + QSize sz(contentsSize); + switch (ct) { + case CT_LineEdit: + case CT_ComboBox: + { + XPThemeData buttontheme(widget, 0, QLatin1String("Button")); + HTHEME theme = buttontheme.handle(); + MARGINS borderSize; + if (theme) { + int result = pGetThemeMargins(theme, + NULL, + BP_PUSHBUTTON, + PBS_NORMAL, + TMT_CONTENTMARGINS, + NULL, + &borderSize); + if (result == S_OK) { + sz += QSize(borderSize.cxLeftWidth + borderSize.cxRightWidth - 2, + borderSize.cyBottomHeight + borderSize.cyTopHeight - 2); + } + const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1); + sz += QSize(qMax(pixelMetric(QStyle::PM_ScrollBarExtent, option, widget) + + textMargins, 23), 0); //arrow button + } + } + break; + case CT_SpinBox: + { + //Spinbox adds frame twice + sz = QWindowsStyle::sizeFromContents(ct, option, contentsSize, widget); + int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget); + sz -= QSize(2*border, 2*border); + } + break; + case CT_TabWidget: + sz += QSize(6, 6); + break; + case CT_Menu: + sz += QSize(1, 0); + break; +#ifndef QT_NO_MENUBAR + case CT_MenuBarItem: + if (!sz.isEmpty()) + sz += QSize(windowsItemHMargin * 5 + 1, 6); + break; +#endif + case CT_MenuItem: + if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) + { + if (menuitem->menuItemType != QStyleOptionMenuItem::Separator) { + sz = QWindowsStyle::sizeFromContents(ct, option, sz, widget); + sz.setHeight(sz.height() - 2); + return sz; + } + } + sz = QWindowsStyle::sizeFromContents(ct, option, sz, widget); + break; + + case CT_MdiControls: + if (const QStyleOptionComplex *styleOpt = qstyleoption_cast(option)) { + int width = 0; + if (styleOpt->subControls & SC_MdiMinButton) + width += 17 + 1; + if (styleOpt->subControls & SC_MdiNormalButton) + width += 17 + 1; + if (styleOpt->subControls & SC_MdiCloseButton) + width += 17 + 1; + sz = QSize(width, 19); + } else { + sz = QSize(54, 19); + } + break; + + default: + sz = QWindowsStyle::sizeFromContents(ct, option, sz, widget); + break; + } + + return sz; +} + + +/*! \reimp */ +int QWindowsXPStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, + QStyleHintReturn *returnData) const +{ + QWindowsXPStylePrivate *d = const_cast(d_func()); + if (!QWindowsXPStylePrivate::useXP()) + return QWindowsStyle::styleHint(hint, option, widget, returnData); + + int res = 0; + switch (hint) { + + case SH_EtchDisabledText: + res = (qobject_cast(widget) != 0); + break; + + case SH_SpinControls_DisableOnBounds: + res = 0; + break; + + case SH_TitleBar_AutoRaise: + case SH_TitleBar_NoBorder: + res = 1; + break; + + case SH_GroupBox_TextLabelColor: + if (!widget || (widget && widget->isEnabled())) + res = d->groupBoxTextColor; + else + res = d->groupBoxTextColorDisabled; + break; + + case SH_Table_GridLineColor: + res = 0xC0C0C0; + break; + + case SH_WindowFrame_Mask: + { + res = 1; + QStyleHintReturnMask *mask = qstyleoption_cast(returnData); + const QStyleOptionTitleBar *titlebar = qstyleoption_cast(option); + if (mask && titlebar) { + // Note certain themes will not return the whole window frame but only the titlebar part when + // queried This function needs to return the entire window mask, hence we will only fetch the mask for the + // titlebar itself and add the remaining part of the window rect at the bottom. + int tbHeight = proxy()->pixelMetric(PM_TitleBarHeight, option, widget); + QRect titleBarRect = option->rect; + titleBarRect.setHeight(tbHeight); + XPThemeData themeData; + if (titlebar->titleBarState & Qt::WindowMinimized) { + themeData = XPThemeData(widget, 0, QLatin1String("WINDOW"), WP_MINCAPTION, CS_ACTIVE, titleBarRect); + } else + themeData = XPThemeData(widget, 0, QLatin1String("WINDOW"), WP_CAPTION, CS_ACTIVE, titleBarRect); + mask->region = d->region(themeData) + + QRect(0, tbHeight, option->rect.width(), option->rect.height() - tbHeight); + } + } + break; +#ifndef QT_NO_RUBBERBAND + case SH_RubberBand_Mask: + if (qstyleoption_cast(option)) { + res = 0; + break; + } +#endif // QT_NO_RUBBERBAND + + case SH_ItemView_DrawDelegateFrame: + res = 1; + break; + + default: + res =QWindowsStyle::styleHint(hint, option, widget, returnData); + } + + return res; +} + +/*! \reimp */ +QPalette QWindowsXPStyle::standardPalette() const +{ + if (QWindowsXPStylePrivate::useXP() && QApplicationPrivate::sys_pal) + return *QApplicationPrivate::sys_pal; + else + return QWindowsStyle::standardPalette(); +} + +/*! + \reimp +*/ +QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option, + const QWidget *widget) const +{ + if (!QWindowsXPStylePrivate::useXP()) + return QWindowsStyle::standardPixmap(standardPixmap, option, widget); + + switch(standardPixmap) { + case SP_TitleBarMaxButton: + case SP_TitleBarCloseButton: + if (qstyleoption_cast(option)) + { + if (widget && widget->isWindow()) { + XPThemeData theme(widget, 0, QLatin1String("WINDOW"), WP_SMALLCLOSEBUTTON, CBS_NORMAL); + if (theme.isValid()) { + SIZE sz; + pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &sz); + return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(QSize(sz.cx, sz.cy)); + } + } + } + break; + default: + break; + } + return QWindowsStyle::standardPixmap(standardPixmap, option, widget); +} + +/*! + \internal +*/ +QIcon QWindowsXPStyle::standardIconImplementation(StandardPixmap standardIcon, + const QStyleOption *option, + const QWidget *widget) const +{ + if (!QWindowsXPStylePrivate::useXP()) { + return QWindowsStyle::standardIconImplementation(standardIcon, option, widget); + } + + QWindowsXPStylePrivate *d = const_cast(d_func()); + switch(standardIcon) { + case SP_TitleBarMaxButton: + if (qstyleoption_cast(option)) + { + if (d->dockFloat.isNull()) { + XPThemeData themeSize(0, 0, QLatin1String("WINDOW"), WP_SMALLCLOSEBUTTON, CBS_NORMAL); + XPThemeData theme(0, 0, QLatin1String("WINDOW"), WP_MAXBUTTON, MAXBS_NORMAL); + if (theme.isValid()) { + SIZE size; + pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); + QPixmap pm = QPixmap(size.cx, size.cy); + pm.fill(Qt::transparent); + QPainter p(&pm); + theme.painter = &p; + theme.rect = QRect(0, 0, size.cx, size.cy); + d->drawBackground(theme); + d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal + pm.fill(Qt::transparent); + theme.stateId = MAXBS_PUSHED; + d->drawBackground(theme); + d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed + pm.fill(Qt::transparent); + theme.stateId = MAXBS_HOT; + d->drawBackground(theme); + d->dockFloat.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover + pm.fill(Qt::transparent); + theme.stateId = MAXBS_INACTIVE; + d->drawBackground(theme); + d->dockFloat.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled + } + } + if (widget && widget->isWindow()) + return d->dockFloat; + + } + break; + case SP_TitleBarCloseButton: + if (qstyleoption_cast(option)) + { + if (d->dockClose.isNull()) { + XPThemeData theme(0, 0, QLatin1String("WINDOW"), WP_SMALLCLOSEBUTTON, CBS_NORMAL); + if (theme.isValid()) { + SIZE size; + pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + QPixmap pm = QPixmap(size.cx, size.cy); + pm.fill(Qt::transparent); + QPainter p(&pm); + theme.painter = &p; + theme.partId = WP_CLOSEBUTTON; // #### + theme.rect = QRect(0, 0, size.cx, size.cy); + d->drawBackground(theme); + d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal + pm.fill(Qt::transparent); + theme.stateId = CBS_PUSHED; + d->drawBackground(theme); + d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed + pm.fill(Qt::transparent); + theme.stateId = CBS_HOT; + d->drawBackground(theme); + d->dockClose.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover + pm.fill(Qt::transparent); + theme.stateId = CBS_INACTIVE; + d->drawBackground(theme); + d->dockClose.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled + } + } + if (widget && widget->isWindow()) + return d->dockClose; + } + break; + case SP_TitleBarNormalButton: + if (qstyleoption_cast(option)) + { + if (d->dockFloat.isNull()) { + XPThemeData themeSize(0, 0, QLatin1String("WINDOW"), WP_SMALLCLOSEBUTTON, CBS_NORMAL); + XPThemeData theme(0, 0, QLatin1String("WINDOW"), WP_RESTOREBUTTON, RBS_NORMAL); + if (theme.isValid()) { + SIZE size; + pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); + QPixmap pm = QPixmap(size.cx, size.cy); + pm.fill(Qt::transparent); + QPainter p(&pm); + theme.painter = &p; + theme.rect = QRect(0, 0, size.cx, size.cy); + d->drawBackground(theme); + d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal + pm.fill(Qt::transparent); + theme.stateId = RBS_PUSHED; + d->drawBackground(theme); + d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed + pm.fill(Qt::transparent); + theme.stateId = RBS_HOT; + d->drawBackground(theme); + d->dockFloat.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover + pm.fill(Qt::transparent); + theme.stateId = RBS_INACTIVE; + d->drawBackground(theme); + d->dockFloat.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled + } + } + if (widget && widget->isWindow()) + return d->dockFloat; + + } + break; + default: + break; + } + + return QWindowsStyle::standardIconImplementation(standardIcon, option, widget); +} + +/*! + \internal + + Constructs a QWindowsXPStyle object. +*/ +QWindowsXPStyle::QWindowsXPStyle(QWindowsXPStylePrivate &dd) : QWindowsStyle(dd) +{ +} + + +// Debugging code ---------------------------------------------------------------------[ START ]--- +// The code for this point on is not compiled by default, but only used as assisting +// debugging code when you uncomment the DEBUG_XP_STYLE define at the top of the file. + +#ifdef DEBUG_XP_STYLE +// The schema file expects these to be defined by the user. +#define TMT_ENUMDEF 8 +#define TMT_ENUMVAL TEXT('A') +#define TMT_ENUM TEXT('B') +#define SCHEMA_STRINGS // For 2nd pass on schema file +QT_BEGIN_INCLUDE_NAMESPACE +#include +QT_END_INCLUDE_NAMESPACE + +// A property's value, type and name combo +struct PropPair { + int propValue; + int propType; + LPCWSTR propName; +}; + +// Operator for sorting of PropPairs +bool operator<(PropPair a, PropPair b) { + return wcscmp(a.propName, b.propName) < 0; +} + +// Our list of all possible properties +static QList all_props; + + +/*! \internal + Dumps a portion of the full native DIB section double buffer. + The DIB section double buffer is only used when doing special + transformations to the theme part, or when the real double + buffer in the paintengine does not have an HDC we may use + directly. + Since we cannot rely on the pixel data we get from Microsoft + when drawing into the DIB section, we use this function to + see the actual data we got, and can determin the appropriate + action. +*/ +void QWindowsXPStylePrivate::dumpNativeDIB(int w, int h) +{ + if (w && h) { + static int pCount = 0; + DWORD *bufPix = (DWORD*)bufferPixels; + + char *bufferDump = new char[bufferH * bufferW * 16]; + char *bufferPos = bufferDump; + + memset(bufferDump, 0, sizeof(bufferDump)); + bufferPos += sprintf(bufferPos, "const int pixelBufferW%d = %d;\n", pCount, w); + bufferPos += sprintf(bufferPos, "const int pixelBufferH%d = %d;\n", pCount, h); + bufferPos += sprintf(bufferPos, "const unsigned DWORD pixelBuffer%d[] = {", pCount); + for (int iy = 0; iy < h; ++iy) { + bufferPos += sprintf(bufferPos, "\n "); + bufPix = (DWORD*)(bufferPixels + (iy * bufferW * 4)); + for (int ix = 0; ix < w; ++ix) { + bufferPos += sprintf(bufferPos, "0x%08x, ", *bufPix); + ++bufPix; + } + } + bufferPos += sprintf(bufferPos, "\n};\n\n"); + printf(bufferDump); + + delete[] bufferDump; + ++pCount; + } +} + +/*! \internal + Shows the value of a given property for a part. +*/ +static void showProperty(XPThemeData &themeData, const PropPair &prop) +{ + PROPERTYORIGIN origin = PO_NOTFOUND; + pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &origin); + const char *originStr; + switch(origin) { + case PO_STATE: + originStr = "State "; + break; + case PO_PART: + originStr = "Part "; + break; + case PO_CLASS: + originStr = "Class "; + break; + case PO_GLOBAL: + originStr = "Globl "; + break; + case PO_NOTFOUND: + default: + originStr = "Unkwn "; + break; + } + + switch(prop.propType) { + case TMT_STRING: + { + wchar_t buffer[512]; + pGetThemeString(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, buffer, 512); + printf(" (%sString) %-20S: %S\n", originStr, prop.propName, buffer); + } + break; + case TMT_ENUM: + { + int result = -1; + pGetThemeEnumValue(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); + printf(" (%sEnum) %-20S: %d\n", originStr, prop.propName, result); + } + break; + case TMT_INT: + { + int result = -1; + pGetThemeInt(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); + printf(" (%sint) %-20S: %d\n", originStr, prop.propName, result); + } + break; + case TMT_BOOL: + { + BOOL result = false; + pGetThemeBool(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); + printf(" (%sbool) %-20S: %d\n", originStr, prop.propName, result); + } + break; + case TMT_COLOR: + { + COLORREF result = 0; + pGetThemeColor(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); + printf(" (%scolor) %-20S: 0x%08X\n", originStr, prop.propName, result); + } + break; + case TMT_MARGINS: + { + MARGINS result; + memset(&result, 0, sizeof(result)); + pGetThemeMargins(themeData.handle(), 0, themeData.partId, themeData.stateId, prop.propValue, 0, &result); + printf(" (%smargins) %-20S: (%d, %d, %d, %d)\n", originStr, + prop.propName, result.cxLeftWidth, result.cyTopHeight, result.cxRightWidth, result.cyBottomHeight); + } + break; + case TMT_FILENAME: + { + wchar_t buffer[512]; + pGetThemeFilename(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, buffer, 512); + printf(" (%sfilename)%-20S: %S\n", originStr, prop.propName, buffer); + } + break; + case TMT_SIZE: + { + SIZE result1; + SIZE result2; + SIZE result3; + memset(&result1, 0, sizeof(result1)); + memset(&result2, 0, sizeof(result2)); + memset(&result3, 0, sizeof(result3)); + pGetThemePartSize(themeData.handle(), 0, themeData.partId, themeData.stateId, 0, TS_MIN, &result1); + pGetThemePartSize(themeData.handle(), 0, themeData.partId, themeData.stateId, 0, TS_TRUE, &result2); + pGetThemePartSize(themeData.handle(), 0, themeData.partId, themeData.stateId, 0, TS_DRAW, &result3); + printf(" (%ssize) %-20S: Min (%d, %d), True(%d, %d), Draw(%d, %d)\n", originStr, prop.propName, + result1.cx, result1.cy, result2.cx, result2.cy, result3.cx, result3.cy); + } + break; + case TMT_POSITION: + { + POINT result; + memset(&result, 0, sizeof(result)); + pGetThemePosition(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); + printf(" (%sPosition)%-20S: (%d, %d)\n", originStr, prop.propName, result.x, result.y); + } + break; + case TMT_RECT: + { + RECT result; + memset(&result, 0, sizeof(result)); + pGetThemeRect(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); + printf(" (%sRect) %-20S: (%d, %d, %d, %d)\n", originStr, prop.propName, result.left, result.top, result.right, result.bottom); + } + break; + case TMT_FONT: + { + LOGFONT result; + memset(&result, 0, sizeof(result)); + pGetThemeFont(themeData.handle(), 0, themeData.partId, themeData.stateId, prop.propValue, &result); + printf(" (%sFont) %-20S: %S height(%d) width(%d) weight(%d)\n", originStr, prop.propName, + result.lfFaceName, result.lfHeight, result.lfWidth, result.lfWeight); + } + break; + case TMT_INTLIST: + { + INTLIST result; + memset(&result, 0, sizeof(result)); + pGetThemeIntList(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); + printf(" (%sInt list)%-20S: { ", originStr, prop.propName); + for (int i = 0; i < result.iValueCount; ++i) + printf("%d ", result.iValues[i]); + printf("}\n"); + } + break; + default: + printf(" %s%S : Unknown property type (%d)!\n", originStr, prop.propName, prop.propType); + } +} + +/*! \internal + Dump all valid properties for a part. + If it's the first time this function is called, then the name, + enum value and documentation of all properties are shown, as + well as all global properties. +*/ +void QWindowsXPStylePrivate::showProperties(XPThemeData &themeData) +{ + if (!all_props.count()) { + const TMSCHEMAINFO *infoTable = GetSchemaInfo(); + for (int i = 0; i < infoTable->iPropCount; ++i) { + int propType = infoTable->pPropTable[i].bPrimVal; + int propValue = infoTable->pPropTable[i].sEnumVal; + LPCWSTR propName = infoTable->pPropTable[i].pszName; + + switch(propType) { + case TMT_ENUMDEF: + case TMT_ENUMVAL: + continue; + default: + if (propType != propValue) { + PropPair prop; + prop.propValue = propValue; + prop.propName = propName; + prop.propType = propType; + all_props.append(prop); + } + } + } + qSort(all_props); + + {// List all properties + printf("part properties count = %d:\n", all_props.count()); + printf(" Enum Property Name Description\n"); + printf("-----------------------------------------------------------\n"); + wchar_t themeName[256]; + pGetCurrentThemeName(themeName, 256, 0, 0, 0, 0); + for (int j = 0; j < all_props.count(); ++j) { + PropPair prop = all_props.at(j); + wchar_t buf[500]; + pGetThemeDocumentationProperty(themeName, prop.propName, buf, 500); + printf("%3d: (%4d) %-20S %S\n", j, prop.propValue, prop.propName, buf); + } + } + + {// Show Global values + printf("Global Properties:\n"); + for (int j = 0; j < all_props.count(); ++j) { + PropPair prop = all_props.at(j); + PROPERTYORIGIN origin = PO_NOTFOUND; + pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &origin); + if (origin == PO_GLOBAL) { + showProperty(themeData, prop); + } + } + } + } + + for (int j = 0; j < all_props.count(); ++j) { + PropPair prop = all_props.at(j); + PROPERTYORIGIN origin = PO_NOTFOUND; + pGetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &origin); + if (origin != PO_NOTFOUND) + { + showProperty(themeData, prop); + } + } +} +#endif +// Debugging code -----------------------------------------------------------------------[ END ]--- + + +QT_END_NAMESPACE + +#endif //QT_NO_WINDOWSXP diff --git a/src/widgets/styles/qwindowsxpstyle.h b/src/widgets/styles/qwindowsxpstyle.h new file mode 100644 index 0000000000..08582d13a1 --- /dev/null +++ b/src/widgets/styles/qwindowsxpstyle.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSXPSTYLE_H +#define QWINDOWSXPSTYLE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_STYLE_WINDOWSXP) + +class QWindowsXPStylePrivate; +class Q_GUI_EXPORT QWindowsXPStyle : public QWindowsStyle +{ + Q_OBJECT +public: + QWindowsXPStyle(); + QWindowsXPStyle(QWindowsXPStylePrivate &dd); + ~QWindowsXPStyle(); + + void unpolish(QApplication*); + void polish(QApplication*); + void polish(QWidget*); + void polish(QPalette&); + void unpolish(QWidget*); + + void drawPrimitive(PrimitiveElement pe, const QStyleOption *option, QPainter *p, + const QWidget *widget = 0) const; + void drawControl(ControlElement element, const QStyleOption *option, QPainter *p, + const QWidget *wwidget = 0) const; + QRect subElementRect(SubElement r, const QStyleOption *option, const QWidget *widget = 0) const; + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc, + const QWidget *widget = 0) const; + void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option, QPainter *p, + const QWidget *widget = 0) const; + QSize sizeFromContents(ContentsType ct, const QStyleOption *option, const QSize &contentsSize, + const QWidget *widget = 0) const; + int pixelMetric(PixelMetric pm, const QStyleOption *option = 0, + const QWidget *widget = 0) const; + int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, + QStyleHintReturn *returnData = 0) const; + + QPalette standardPalette() const; + QPixmap standardPixmap(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget = 0) const; + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget = 0) const; + +private: + Q_DISABLE_COPY(QWindowsXPStyle) + Q_DECLARE_PRIVATE(QWindowsXPStyle) + friend class QStyleFactory; + void *reserved; +}; + +#endif // QT_NO_STYLE_WINDOWSXP + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QWINDOWSXPSTYLE_H diff --git a/src/widgets/styles/qwindowsxpstyle_p.h b/src/widgets/styles/qwindowsxpstyle_p.h new file mode 100644 index 0000000000..5509cba512 --- /dev/null +++ b/src/widgets/styles/qwindowsxpstyle_p.h @@ -0,0 +1,356 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSXPSTYLE_P_H +#define QWINDOWSXPSTYLE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qwindowsxpstyle.h" +#include "qwindowsstyle_p.h" +#include +#include + +// Note, these tests are duplicated in qwizard_win.cpp. +#ifdef Q_CC_GNU +# include +# if (__W32API_MAJOR_VERSION >= 3 || (__W32API_MAJOR_VERSION == 2 && __W32API_MINOR_VERSION >= 5)) +# ifdef _WIN32_WINNT +# undef _WIN32_WINNT +# endif +# define _WIN32_WINNT 0x0501 +# include +# endif +#endif + +#include + +#if WINVER >= 0x0600 +#include +#else +#include +#endif + +#include + +QT_BEGIN_NAMESPACE + +// Older Platform SDKs do not have the extended DrawThemeBackgroundEx +// function. We add the needed parts here, and use the extended +// function dynamically, if available in uxtheme.dll. Else, we revert +// back to using the DrawThemeBackground function. +#ifndef DTBG_OMITBORDER +# ifndef DTBG_CLIPRECT +# define DTBG_CLIPRECT 0x00000001 +# endif +# ifndef DTBG_DRAWSOLID +# define DTBG_DRAWSOLID 0x00000002 +# endif +# ifndef DTBG_OMITBORDER +# define DTBG_OMITBORDER 0x00000004 +# endif +# ifndef DTBG_OMITCONTENT +# define DTBG_OMITCONTENT 0x00000008 +# endif +# ifndef DTBG_COMPUTINGREGION +# define DTBG_COMPUTINGREGION 0x00000010 +# endif +# ifndef DTBG_MIRRORDC +# define DTBG_MIRRORDC 0x00000020 +# endif + typedef struct _DTBGOPTS + { + DWORD dwSize; + DWORD dwFlags; + RECT rcClip; + } DTBGOPTS, *PDTBGOPTS; +#endif // _DTBGOPTS + +// Undefined for some compile environments +#ifndef TMT_TEXTCOLOR +# define TMT_TEXTCOLOR 3803 +#endif +#ifndef TMT_BORDERCOLORHINT +# define TMT_BORDERCOLORHINT 3822 +#endif +#ifndef TMT_BORDERSIZE +# define TMT_BORDERSIZE 2403 +#endif +#ifndef TMT_BORDERONLY +# define TMT_BORDERONLY 2203 +#endif +#ifndef TMT_TRANSPARENTCOLOR +# define TMT_TRANSPARENTCOLOR 3809 +#endif +#ifndef TMT_CAPTIONMARGINS +# define TMT_CAPTIONMARGINS 3603 +#endif +#ifndef TMT_CONTENTMARGINS +# define TMT_CONTENTMARGINS 3602 +#endif +#ifndef TMT_SIZINGMARGINS +# define TMT_SIZINGMARGINS 3601 +#endif +#ifndef TMT_GLYPHTYPE +# define TMT_GLYPHTYPE 4012 +#endif +#ifndef TMT_BGTYPE +# define TMT_BGTYPE 4001 +#endif +#ifndef TMT_TEXTSHADOWTYPE +# define TMT_TEXTSHADOWTYPE 4010 +#endif +#ifndef TMT_BORDERCOLOR +# define TMT_BORDERCOLOR 3801 +#endif +#ifndef BT_IMAGEFILE +# define BT_IMAGEFILE 0 +#endif +#ifndef BT_BORDERFILL +# define BT_BORDERFILL 1 +#endif +#ifndef BT_NONE +# define BT_NONE 2 +#endif +#ifndef TMT_FILLCOLOR +# define TMT_FILLCOLOR 3802 +#endif +#ifndef TMT_PROGRESSCHUNKSIZE +# define TMT_PROGRESSCHUNKSIZE 2411 +#endif + +// TMT_TEXTSHADOWCOLOR is wrongly defined in mingw +#if TMT_TEXTSHADOWCOLOR != 3818 +#undef TMT_TEXTSHADOWCOLOR +#define TMT_TEXTSHADOWCOLOR 3818 +#endif +#ifndef TST_NONE +# define TST_NONE 0 +#endif + +#ifndef GT_NONE +# define GT_NONE 0 +#endif +#ifndef GT_IMAGEGLYPH +# define GT_IMAGEGLYPH 1 +#endif + +// These defines are missing from the tmschema, but still exist as +// states for their parts +#ifndef MINBS_INACTIVE +#define MINBS_INACTIVE 5 +#endif +#ifndef MAXBS_INACTIVE +#define MAXBS_INACTIVE 5 +#endif +#ifndef RBS_INACTIVE +#define RBS_INACTIVE 5 +#endif +#ifndef HBS_INACTIVE +#define HBS_INACTIVE 5 +#endif +#ifndef CBS_INACTIVE +#define CBS_INACTIVE 5 +#endif + +// Uncomment define below to build debug assisting code, and output +// #define DEBUG_XP_STYLE + +#if !defined(QT_NO_STYLE_WINDOWSXP) + +// Declarations ----------------------------------------------------------------------------------- +class XPThemeData +{ +public: + XPThemeData(const QWidget *w = 0, QPainter *p = 0, const QString &theme = QString(), + int part = 0, int state = 0, const QRect &r = QRect()) + : widget(w), painter(p), name(theme), htheme(0), partId(part), stateId(state), + mirrorHorizontally(false), mirrorVertically(false), noBorder(false), + noContent(false), rotate(0), rect(r) + {} + + HRGN mask(); + HTHEME handle(); + + RECT toRECT(const QRect &qr); + bool isValid(); + + const QWidget *widget; + QPainter *painter; + QString name; + HTHEME htheme; + int partId; + int stateId; + + uint mirrorHorizontally : 1; + uint mirrorVertically : 1; + uint noBorder : 1; + uint noContent : 1; + uint rotate; + QRect rect; +}; + +struct ThemeMapKey { + QString name; + int partId; + int stateId; + bool noBorder; + bool noContent; + + ThemeMapKey() : partId(-1), stateId(-1) {} + ThemeMapKey(const XPThemeData &data) + : name(data.name), partId(data.partId), stateId(data.stateId), + noBorder(data.noBorder), noContent(data.noContent) {} + +}; + +inline uint qHash(const ThemeMapKey &key) +{ return qHash(key.name) ^ key.partId ^ key.stateId; } + +inline bool operator==(const ThemeMapKey &k1, const ThemeMapKey &k2) +{ + return k1.name == k2.name + && k1.partId == k2.partId + && k1.stateId == k2.stateId; +} + +enum AlphaChannelType { + UnknownAlpha = -1, // Alpha of part & state not yet known + NoAlpha, // Totally opaque, no need to touch alpha (RGB) + MaskAlpha, // Alpha channel must be fixed (ARGB) + RealAlpha // Proper alpha values from Windows (ARGB_Premultiplied) +}; + +struct ThemeMapData { + AlphaChannelType alphaType; // Which type of alpha on part & state + + bool dataValid : 1; // Only used to detect if hash value is ok + bool partIsTransparent : 1; + bool hasAnyData : 1; // False = part & state has not data, NOP + bool hasAlphaChannel : 1; // True = part & state has real Alpha + bool wasAlphaSwapped : 1; // True = alpha channel needs to be swapped + bool hadInvalidAlpha : 1; // True = alpha channel contained invalid alpha values + + ThemeMapData() : dataValid(false), partIsTransparent(false), hasAnyData(false), + hasAlphaChannel(false), wasAlphaSwapped(false), hadInvalidAlpha(false) {} +}; + +class QWindowsXPStylePrivate : public QWindowsStylePrivate +{ + Q_DECLARE_PUBLIC(QWindowsXPStyle) +public: + QWindowsXPStylePrivate() + : QWindowsStylePrivate(), hasInitColors(false), bufferDC(0), bufferBitmap(0), nullBitmap(0), + bufferPixels(0), bufferW(0), bufferH(0) + { init(); } + + ~QWindowsXPStylePrivate() + { cleanup(); } + + static HWND winId(const QWidget *widget); + + void init(bool force = false); + void cleanup(bool force = false); + void cleanupHandleMap(); + const QPixmap *tabBody(QWidget *widget); + + HBITMAP buffer(int w = 0, int h = 0); + HDC bufferHDC() + { return bufferDC;} + + static bool resolveSymbols(); + static bool useXP(bool update = false); + + bool isTransparent(XPThemeData &themeData); + QRegion region(XPThemeData &themeData); + + void setTransparency(QWidget *widget, XPThemeData &themeData); + void drawBackground(XPThemeData &themeData); + void drawBackgroundThruNativeBuffer(XPThemeData &themeData); + void drawBackgroundDirectly(XPThemeData &themeData); + + bool hasAnyData(const QRect &rect); + bool hasAlphaChannel(const QRect &rect); + bool fixAlphaChannel(const QRect &rect); + bool swapAlphaChannel(const QRect &rect, bool allPixels = false); + + QRgb groupBoxTextColor; + QRgb groupBoxTextColorDisabled; + QRgb sliderTickColor; + bool hasInitColors; + + static QMap *handleMap; + + QIcon dockFloat, dockClose; + +private: +#ifdef DEBUG_XP_STYLE + void dumpNativeDIB(int w, int h); + void showProperties(XPThemeData &themeData); +#endif + + static QBasicAtomicInt ref; + static bool use_xp; + static QWidget *limboWidget; + static QPixmap *tabbody; + + QHash alphaCache; + HDC bufferDC; + HBITMAP bufferBitmap; + HBITMAP nullBitmap; + uchar *bufferPixels; + int bufferW, bufferH; +}; + +#endif // QT_NO_STYLE_WINDOWS + +QT_END_NAMESPACE + +#endif //QWINDOWSXPSTYLE_P_H diff --git a/src/widgets/styles/styles.pri b/src/widgets/styles/styles.pri new file mode 100644 index 0000000000..b20caf726e --- /dev/null +++ b/src/widgets/styles/styles.pri @@ -0,0 +1,194 @@ +# Qt styles module + +HEADERS += \ + styles/qdrawutil.h \ + styles/qstyle.h \ + styles/qstylefactory.h \ + styles/qstyleoption.h \ + styles/qstyleplugin.h \ + styles/qcommonstylepixmaps_p.h \ + styles/qcommonstyle.h \ + styles/qstylehelper_p.h \ + styles/qproxystyle.h \ + styles/qproxystyle_p.h \ + styles/qstylepainter.h \ + styles/qstylesheetstyle_p.h + +SOURCES += \ + styles/qdrawutil.cpp \ + styles/qstyle.cpp \ + styles/qstylefactory.cpp \ + styles/qstyleoption.cpp \ + styles/qstyleplugin.cpp \ + styles/qstylehelper.cpp \ + styles/qcommonstyle.cpp \ + styles/qproxystyle.cpp \ + styles/qstylepainter.cpp \ + styles/qstylesheetstyle.cpp \ + styles/qstylesheetstyle_default.cpp + +wince* { + RESOURCES += styles/qstyle_wince.qrc +} else:symbian { + RESOURCES += styles/qstyle_s60.qrc +} else { + RESOURCES += styles/qstyle.qrc +} + +contains( styles, all ) { + styles = mac windows windowsxp windowsvista +} + +x11|qpa|!macx-*:styles -= mac + +x11{ + QMAKE_CXXFLAGS += $$QT_CFLAGS_QGTKSTYLE + LIBS_PRIVATE += $$QT_LIBS_QGTKSTYLE + styles += gtk +} + +contains( styles, mac ) { + HEADERS += \ + styles/qmacstyle_mac.h \ + styles/qmacstylepixmaps_mac_p.h \ + styles/qmacstyle_mac_p.h + OBJECTIVE_SOURCES += styles/qmacstyle_mac.mm + + !contains( styles, windows ) { + message( mac requires windows ) + styles += windows + DEFINES+= QT_STYLE_WINDOWS + } +} else { + DEFINES += QT_NO_STYLE_MAC +} + +contains( styles, cde ) { + HEADERS += styles/qcdestyle.h + SOURCES += styles/qcdestyle.cpp + + !contains( styles, motif ) { + message( cde requires motif ) + styles += motif + DEFINES+= QT_STYLE_MOTIF + } +} else { + DEFINES += QT_NO_STYLE_CDE +} + +contains( styles, windowsvista ) { + HEADERS += styles/qwindowsvistastyle.h + HEADERS += styles/qwindowsvistastyle_p.h + SOURCES += styles/qwindowsvistastyle.cpp + !contains( styles, windowsxp ) { + message( windowsvista requires windowsxp ) + styles += windowsxp + DEFINES+= QT_STYLE_WINDOWSXP + } +} else { + DEFINES += QT_NO_STYLE_WINDOWSVISTA +} + +contains( styles, windowsxp ) { + HEADERS += styles/qwindowsxpstyle.h + SOURCES += styles/qwindowsxpstyle.cpp + !contains( styles, windows ) { + message( windowsxp requires windows ) + styles += windows + DEFINES+= QT_STYLE_WINDOWS + } +} else { + DEFINES += QT_NO_STYLE_WINDOWSXP +} + +contains( styles, plastique ) { + HEADERS += styles/qplastiquestyle.h + SOURCES += styles/qplastiquestyle.cpp + !contains( styles, windows ) { + message( plastique requires windows ) + styles += windows + DEFINES+= QT_STYLE_WINDOWS + } +} else { + DEFINES += QT_NO_STYLE_PLASTIQUE +} + +contains( styles, gtk ) { + HEADERS += styles/qgtkstyle.h + HEADERS += styles/qgtkpainter_p.h + HEADERS += styles/qgtkstyle_p.h + SOURCES += styles/qgtkstyle.cpp + SOURCES += styles/qgtkpainter.cpp + SOURCES += styles/qgtkstyle_p.cpp + !contains( styles, cleanlooks ) { + styles += cleanlooks + DEFINES+= QT_STYLE_CLEANLOOKS + } +} else { + DEFINES += QT_NO_STYLE_GTK +} + +contains( styles, cleanlooks ) { + HEADERS += styles/qcleanlooksstyle.h + HEADERS += styles/qcleanlooksstyle_p.h + SOURCES += styles/qcleanlooksstyle.cpp + !contains( styles, windows ) { + styles += windows + DEFINES+= QT_STYLE_WINDOWS + } +} else { + DEFINES += QT_NO_STYLE_CLEANLOOKS +} + +contains( styles, windows ) { + HEADERS += styles/qwindowsstyle.h + SOURCES += styles/qwindowsstyle.cpp +} else { + DEFINES += QT_NO_STYLE_WINDOWS +} + +contains( styles, motif ) { + HEADERS += styles/qmotifstyle.h + SOURCES += styles/qmotifstyle.cpp +} else { + DEFINES += QT_NO_STYLE_MOTIF +} + +contains( styles, windowsce ) { + HEADERS += styles/qwindowscestyle.h + SOURCES += styles/qwindowscestyle.cpp +} else { + DEFINES += QT_NO_STYLE_WINDOWSCE +} + +contains( styles, windowsmobile ) { + HEADERS += styles/qwindowsmobilestyle.h + SOURCES += styles/qwindowsmobilestyle.cpp +} else { + DEFINES += QT_NO_STYLE_WINDOWSMOBILE +} + +contains( styles, s60 ):contains(QT_CONFIG, s60) { + HEADERS += \ + styles/qs60style.h \ + styles/qs60style_p.h + SOURCES += styles/qs60style.cpp + symbian { + SOURCES += styles/qs60style_s60.cpp + LIBS += -legul -lbmpanim + contains(CONFIG, is_using_gnupoc) { + LIBS += -laknicon -laknskins -laknskinsrv -lfontutils + } else { + LIBS += -lAknIcon -lAKNSKINS -lAKNSKINSRV -lFontUtils + } + } else { + SOURCES += styles/qs60style_simulated.cpp + RESOURCES += styles/qstyle_s60_simulated.qrc + } +} else { + symbian { + HEADERS += styles/qs60style.h + SOURCES += styles/qs60style_stub.cpp + } + DEFINES += QT_NO_STYLE_S60 +} -- cgit v1.2.3 From 94c0628d22e844a23e1ee27cd3df03cc9e0e2c25 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 7 May 2011 15:05:43 +0200 Subject: fix includes --- src/widgets/styles/qcdestyle.h | 2 +- src/widgets/styles/qcleanlooksstyle.h | 2 +- src/widgets/styles/qcommonstyle.h | 2 +- src/widgets/styles/qmacstyle_mac.h | 2 +- src/widgets/styles/qmacstyle_mac_p.h | 4 ++-- src/widgets/styles/qmotifstyle.cpp | 4 ++-- src/widgets/styles/qmotifstyle.h | 2 +- src/widgets/styles/qplastiquestyle.h | 2 +- src/widgets/styles/qproxystyle.h | 2 +- src/widgets/styles/qs60style.h | 2 +- src/widgets/styles/qstyle.h | 4 ++-- src/widgets/styles/qstyle_p.h | 2 +- src/widgets/styles/qstyleoption.h | 16 ++++++++-------- src/widgets/styles/qstylepainter.h | 4 ++-- src/widgets/styles/qstylesheetstyle.cpp | 2 +- src/widgets/styles/qstylesheetstyle_p.h | 6 +++--- src/widgets/styles/qwindowscestyle.h | 2 +- src/widgets/styles/qwindowsmobilestyle.h | 2 +- src/widgets/styles/qwindowsstyle.h | 2 +- src/widgets/styles/qwindowsvistastyle.h | 2 +- src/widgets/styles/qwindowsxpstyle.h | 2 +- 21 files changed, 34 insertions(+), 34 deletions(-) (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/qcdestyle.h b/src/widgets/styles/qcdestyle.h index ca43b6a530..b0f010fbc5 100644 --- a/src/widgets/styles/qcdestyle.h +++ b/src/widgets/styles/qcdestyle.h @@ -43,7 +43,7 @@ #ifndef QCDESTYLE_H #define QCDESTYLE_H -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qcleanlooksstyle.h b/src/widgets/styles/qcleanlooksstyle.h index 9ffa5789c0..de13b0947d 100644 --- a/src/widgets/styles/qcleanlooksstyle.h +++ b/src/widgets/styles/qcleanlooksstyle.h @@ -42,7 +42,7 @@ #ifndef QCLEANLOOKSSTYLE_H #define QCLEANLOOKSSTYLE_H -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qcommonstyle.h b/src/widgets/styles/qcommonstyle.h index 2b42367aac..b420dd9b04 100644 --- a/src/widgets/styles/qcommonstyle.h +++ b/src/widgets/styles/qcommonstyle.h @@ -42,7 +42,7 @@ #ifndef QCOMMONSTYLE_H #define QCOMMONSTYLE_H -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qmacstyle_mac.h b/src/widgets/styles/qmacstyle_mac.h index 78a25ce9b2..099c552929 100644 --- a/src/widgets/styles/qmacstyle_mac.h +++ b/src/widgets/styles/qmacstyle_mac.h @@ -42,7 +42,7 @@ #ifndef QMACSTYLE_MAC_H #define QMACSTYLE_MAC_H -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qmacstyle_mac_p.h b/src/widgets/styles/qmacstyle_mac_p.h index fbd6d57e09..d5d3ed0d0d 100644 --- a/src/widgets/styles/qmacstyle_mac_p.h +++ b/src/widgets/styles/qmacstyle_mac_p.h @@ -92,8 +92,8 @@ #include #include #include -#include -#include +#include +#include #include // diff --git a/src/widgets/styles/qmotifstyle.cpp b/src/widgets/styles/qmotifstyle.cpp index 3bf8996650..876db114c6 100644 --- a/src/widgets/styles/qmotifstyle.cpp +++ b/src/widgets/styles/qmotifstyle.cpp @@ -69,8 +69,8 @@ #include "qdialogbuttonbox.h" #include "qformlayout.h" #include -#include -#include +#include +#include #ifdef Q_WS_X11 #include "qx11info_x11.h" diff --git a/src/widgets/styles/qmotifstyle.h b/src/widgets/styles/qmotifstyle.h index 5ca0795216..809443d0fe 100644 --- a/src/widgets/styles/qmotifstyle.h +++ b/src/widgets/styles/qmotifstyle.h @@ -42,7 +42,7 @@ #ifndef QMOTIFSTYLE_H #define QMOTIFSTYLE_H -#include +#include #include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qplastiquestyle.h b/src/widgets/styles/qplastiquestyle.h index 20d2f490a6..1f9a0524ec 100644 --- a/src/widgets/styles/qplastiquestyle.h +++ b/src/widgets/styles/qplastiquestyle.h @@ -42,7 +42,7 @@ #ifndef QPLASTIQUESTYLE_H #define QPLASTIQUESTYLE_H -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qproxystyle.h b/src/widgets/styles/qproxystyle.h index 9d4a5cc56c..5c87c95ae8 100644 --- a/src/widgets/styles/qproxystyle.h +++ b/src/widgets/styles/qproxystyle.h @@ -42,7 +42,7 @@ #ifndef QPROXYSTYLE_H #define QPROXYSTYLE_H -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qs60style.h b/src/widgets/styles/qs60style.h index 5f44ca7b9b..61cf472b57 100644 --- a/src/widgets/styles/qs60style.h +++ b/src/widgets/styles/qs60style.h @@ -42,7 +42,7 @@ #ifndef QS60STYLE_H #define QS60STYLE_H -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h index 94f2ce102f..26a1e0fa20 100644 --- a/src/widgets/styles/qstyle.h +++ b/src/widgets/styles/qstyle.h @@ -45,10 +45,10 @@ #include #include #include -#include +#include #include #include -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qstyle_p.h b/src/widgets/styles/qstyle_p.h index 1fcd2eaf2a..0f3513d640 100644 --- a/src/widgets/styles/qstyle_p.h +++ b/src/widgets/styles/qstyle_p.h @@ -43,7 +43,7 @@ #define QSTYLE_P_H #include "private/qobject_p.h" -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/widgets/styles/qstyleoption.h b/src/widgets/styles/qstyleoption.h index 1b1de9cdf2..8611e952c2 100644 --- a/src/widgets/styles/qstyleoption.h +++ b/src/widgets/styles/qstyleoption.h @@ -43,15 +43,15 @@ #define QSTYLEOPTION_H #include -#include -#include +#include +#include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #ifndef QT_NO_ITEMVIEWS # include #endif diff --git a/src/widgets/styles/qstylepainter.h b/src/widgets/styles/qstylepainter.h index 0fc3f2b4b9..1a65ef0616 100644 --- a/src/widgets/styles/qstylepainter.h +++ b/src/widgets/styles/qstylepainter.h @@ -43,8 +43,8 @@ #define QSTYLEPAINTER_H #include -#include -#include +#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index faa929ebea..84272e23fb 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -84,7 +84,7 @@ #include "qdrawutil.h" #include -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/widgets/styles/qstylesheetstyle_p.h b/src/widgets/styles/qstylesheetstyle_p.h index 1f331b2642..1e885e0e52 100644 --- a/src/widgets/styles/qstylesheetstyle_p.h +++ b/src/widgets/styles/qstylesheetstyle_p.h @@ -42,15 +42,15 @@ #ifndef QSTYLESHEETSTYLE_P_H #define QSTYLESHEETSTYLE_P_H -#include "QtGui/qwindowsstyle.h" +#include "QtWidgets/qwindowsstyle.h" #ifndef QT_NO_STYLE_STYLESHEET -#include "QtGui/qstyleoption.h" +#include "QtWidgets/qstyleoption.h" #include "QtCore/qhash.h" #include "QtGui/qevent.h" #include "QtCore/qvector.h" -#include "QtGui/qapplication.h" +#include "QtWidgets/qapplication.h" #include "private/qcssparser_p.h" #include "QtGui/qbrush.h" diff --git a/src/widgets/styles/qwindowscestyle.h b/src/widgets/styles/qwindowscestyle.h index 3fd83bc764..15a8f2c66a 100644 --- a/src/widgets/styles/qwindowscestyle.h +++ b/src/widgets/styles/qwindowscestyle.h @@ -42,7 +42,7 @@ #ifndef QWINDOWSCESTYLE_H #define QWINDOWSCESTYLE_H -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qwindowsmobilestyle.h b/src/widgets/styles/qwindowsmobilestyle.h index 6ac1af1c35..2a396b5dbb 100644 --- a/src/widgets/styles/qwindowsmobilestyle.h +++ b/src/widgets/styles/qwindowsmobilestyle.h @@ -42,7 +42,7 @@ #ifndef QWINDOWSMOBILESTYLE_H #define QWINDOWSMOBILESTYLE_H -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qwindowsstyle.h b/src/widgets/styles/qwindowsstyle.h index 99f64fcb05..644da5e6fa 100644 --- a/src/widgets/styles/qwindowsstyle.h +++ b/src/widgets/styles/qwindowsstyle.h @@ -42,7 +42,7 @@ #ifndef QWINDOWSSTYLE_H #define QWINDOWSSTYLE_H -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qwindowsvistastyle.h b/src/widgets/styles/qwindowsvistastyle.h index c13dccf28b..83e336c4e4 100644 --- a/src/widgets/styles/qwindowsvistastyle.h +++ b/src/widgets/styles/qwindowsvistastyle.h @@ -42,7 +42,7 @@ #ifndef QWINDOWSVISTASTYLE_H #define QWINDOWSVISTASTYLE_H -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qwindowsxpstyle.h b/src/widgets/styles/qwindowsxpstyle.h index 08582d13a1..9895cc5f11 100644 --- a/src/widgets/styles/qwindowsxpstyle.h +++ b/src/widgets/styles/qwindowsxpstyle.h @@ -42,7 +42,7 @@ #ifndef QWINDOWSXPSTYLE_H #define QWINDOWSXPSTYLE_H -#include +#include QT_BEGIN_HEADER -- cgit v1.2.3 From 7ff96330ed28b957a80d294a43748c8051c0e483 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 7 May 2011 20:56:32 +0200 Subject: get QtWidgets to link some more changes, mainly exporting methods from QtGui to get QtWidgets to link. --- src/widgets/styles/qstylesheetstyle.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 84272e23fb..750b408bd9 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -978,8 +978,9 @@ QRenderRule::QRenderRule(const QVector &declarations, const QWidget hintValue = (int) decl.colorValue().rgba(); } else if (hintName.endsWith(QLatin1String("size"))) { hintValue = decl.sizeValue(); - } else if (hintName.endsWith(QLatin1String("icon"))) { - hintValue = decl.iconValue(); + // ### Qt5 +// } else if (hintName.endsWith(QLatin1String("icon"))) { +// hintValue = decl.iconValue(); } else if (hintName == QLatin1String("button-layout") && decl.d->values.count() != 0 && decl.d->values.at(0).type == Value::String) { hintValue = subControlLayout(decl.d->values.at(0).variant.toString()); @@ -2508,7 +2509,8 @@ void QStyleSheetStyle::setProperties(QWidget *w) } QVariant v; switch (value.type()) { - case QVariant::Icon: v = decl.iconValue(); break; + // ### Qt 5 +// case QVariant::Icon: v = decl.iconValue(); break; case QVariant::Image: v = QImage(decl.uriValue()); break; case QVariant::Pixmap: v = QPixmap(decl.uriValue()); break; case QVariant::Rect: v = decl.rectValue(); break; -- cgit v1.2.3 From 3d30c0fb60fd43cfdc3fdd4ffb839f1e863ccef6 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 7 May 2011 22:20:17 +0200 Subject: fix remaining includes Made easy thanks to the fixqt4includes script --- src/widgets/styles/qgtkpainter.cpp | 4 ++-- src/widgets/styles/qgtkpainter_p.h | 2 +- src/widgets/styles/qgtkstyle.cpp | 44 +++++++++++++++++++------------------- src/widgets/styles/qgtkstyle.h | 4 ++-- src/widgets/styles/qgtkstyle_p.cpp | 16 +++++++------- src/widgets/styles/qgtkstyle_p.h | 4 ++-- 6 files changed, 37 insertions(+), 37 deletions(-) (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/qgtkpainter.cpp b/src/widgets/styles/qgtkpainter.cpp index 68ade04984..0d86540974 100644 --- a/src/widgets/styles/qgtkpainter.cpp +++ b/src/widgets/styles/qgtkpainter.cpp @@ -48,8 +48,8 @@ // and takes care of converting all such calls into cached Qt pixmaps. #include -#include -#include +#include +#include #include QT_BEGIN_NAMESPACE diff --git a/src/widgets/styles/qgtkpainter_p.h b/src/widgets/styles/qgtkpainter_p.h index 1c253798a8..121466622b 100644 --- a/src/widgets/styles/qgtkpainter_p.h +++ b/src/widgets/styles/qgtkpainter_p.h @@ -56,7 +56,7 @@ #include #if !defined(QT_NO_STYLE_GTK) -#include +#include #include #include #include diff --git a/src/widgets/styles/qgtkstyle.cpp b/src/widgets/styles/qgtkstyle.cpp index 277e3025b5..047eb97195 100644 --- a/src/widgets/styles/qgtkstyle.cpp +++ b/src/widgets/styles/qgtkstyle.cpp @@ -45,29 +45,29 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #undef signals // Collides with GTK stymbols #include diff --git a/src/widgets/styles/qgtkstyle.h b/src/widgets/styles/qgtkstyle.h index 616ce24509..abf8ed4fbd 100644 --- a/src/widgets/styles/qgtkstyle.h +++ b/src/widgets/styles/qgtkstyle.h @@ -42,10 +42,10 @@ #ifndef QGTKSTYLE_H #define QGTKSTYLE_H -#include +#include #include #include -#include +#include QT_BEGIN_HEADER diff --git a/src/widgets/styles/qgtkstyle_p.cpp b/src/widgets/styles/qgtkstyle_p.cpp index d7c53c9a91..e0ebf51c5b 100644 --- a/src/widgets/styles/qgtkstyle_p.cpp +++ b/src/widgets/styles/qgtkstyle_p.cpp @@ -65,15 +65,15 @@ #include #include -#include -#include -#include +#include +#include +#include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include diff --git a/src/widgets/styles/qgtkstyle_p.h b/src/widgets/styles/qgtkstyle_p.h index 15a98c8257..8c84eb3b9d 100644 --- a/src/widgets/styles/qgtkstyle_p.h +++ b/src/widgets/styles/qgtkstyle_p.h @@ -60,9 +60,9 @@ #include #include -#include +#include -#include +#include #include #undef signals // Collides with GTK stymbols -- cgit v1.2.3 From 819f9ca965279562f34895dab405f28162c0b8ab Mon Sep 17 00:00:00 2001 From: Olli Werwolff Date: Wed, 8 Jun 2011 09:51:07 +0200 Subject: Use Q_WIDGETS_EXPORT for widgets library Reviewed-by: Lars Knoll --- src/widgets/styles/qcdestyle.h | 2 +- src/widgets/styles/qcleanlooksstyle.h | 2 +- src/widgets/styles/qcommonstyle.h | 2 +- src/widgets/styles/qdrawutil.h | 26 +++++----- src/widgets/styles/qgtkstyle.h | 2 +- src/widgets/styles/qgtkstyle_p.h | 8 +-- src/widgets/styles/qmacstyle_mac.h | 6 +-- src/widgets/styles/qmotifstyle.h | 2 +- src/widgets/styles/qplastiquestyle.h | 2 +- src/widgets/styles/qproxystyle.h | 2 +- src/widgets/styles/qs60style.h | 2 +- src/widgets/styles/qstyle.h | 4 +- src/widgets/styles/qstylefactory.h | 2 +- src/widgets/styles/qstyleoption.h | 88 ++++++++++++++++---------------- src/widgets/styles/qstyleplugin.h | 4 +- src/widgets/styles/qwindowscestyle.h | 2 +- src/widgets/styles/qwindowsmobilestyle.h | 2 +- src/widgets/styles/qwindowsstyle.h | 2 +- src/widgets/styles/qwindowsvistastyle.h | 2 +- src/widgets/styles/qwindowsxpstyle.cpp | 2 +- src/widgets/styles/qwindowsxpstyle.h | 2 +- 21 files changed, 83 insertions(+), 83 deletions(-) (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/qcdestyle.h b/src/widgets/styles/qcdestyle.h index 17ec47f938..854bfc6c69 100644 --- a/src/widgets/styles/qcdestyle.h +++ b/src/widgets/styles/qcdestyle.h @@ -53,7 +53,7 @@ QT_MODULE(Gui) #if !defined(QT_NO_STYLE_CDE) -class Q_GUI_EXPORT QCDEStyle : public QMotifStyle +class Q_WIDGETS_EXPORT QCDEStyle : public QMotifStyle { Q_OBJECT public: diff --git a/src/widgets/styles/qcleanlooksstyle.h b/src/widgets/styles/qcleanlooksstyle.h index 0c82497742..1b35aa7969 100644 --- a/src/widgets/styles/qcleanlooksstyle.h +++ b/src/widgets/styles/qcleanlooksstyle.h @@ -53,7 +53,7 @@ QT_MODULE(Gui) #if !defined(QT_NO_STYLE_CLEANLOOKS) class QCleanlooksStylePrivate; -class Q_GUI_EXPORT QCleanlooksStyle : public QWindowsStyle +class Q_WIDGETS_EXPORT QCleanlooksStyle : public QWindowsStyle { Q_OBJECT Q_DECLARE_PRIVATE(QCleanlooksStyle) diff --git a/src/widgets/styles/qcommonstyle.h b/src/widgets/styles/qcommonstyle.h index d7afea9333..a4a7ac11c5 100644 --- a/src/widgets/styles/qcommonstyle.h +++ b/src/widgets/styles/qcommonstyle.h @@ -51,7 +51,7 @@ QT_MODULE(Gui) class QCommonStylePrivate; -class Q_GUI_EXPORT QCommonStyle: public QStyle +class Q_WIDGETS_EXPORT QCommonStyle: public QStyle { Q_OBJECT diff --git a/src/widgets/styles/qdrawutil.h b/src/widgets/styles/qdrawutil.h index 01319c9427..2f35d236b7 100644 --- a/src/widgets/styles/qdrawutil.h +++ b/src/widgets/styles/qdrawutil.h @@ -63,52 +63,52 @@ class QRect; // Standard shade drawing // -Q_GUI_EXPORT void qDrawShadeLine(QPainter *p, int x1, int y1, int x2, int y2, +Q_WIDGETS_EXPORT void qDrawShadeLine(QPainter *p, int x1, int y1, int x2, int y2, const QPalette &pal, bool sunken = true, int lineWidth = 1, int midLineWidth = 0); -Q_GUI_EXPORT void qDrawShadeLine(QPainter *p, const QPoint &p1, const QPoint &p2, +Q_WIDGETS_EXPORT void qDrawShadeLine(QPainter *p, const QPoint &p1, const QPoint &p2, const QPalette &pal, bool sunken = true, int lineWidth = 1, int midLineWidth = 0); -Q_GUI_EXPORT void qDrawShadeRect(QPainter *p, int x, int y, int w, int h, +Q_WIDGETS_EXPORT void qDrawShadeRect(QPainter *p, int x, int y, int w, int h, const QPalette &pal, bool sunken = false, int lineWidth = 1, int midLineWidth = 0, const QBrush *fill = 0); -Q_GUI_EXPORT void qDrawShadeRect(QPainter *p, const QRect &r, +Q_WIDGETS_EXPORT void qDrawShadeRect(QPainter *p, const QRect &r, const QPalette &pal, bool sunken = false, int lineWidth = 1, int midLineWidth = 0, const QBrush *fill = 0); -Q_GUI_EXPORT void qDrawShadePanel(QPainter *p, int x, int y, int w, int h, +Q_WIDGETS_EXPORT void qDrawShadePanel(QPainter *p, int x, int y, int w, int h, const QPalette &pal, bool sunken = false, int lineWidth = 1, const QBrush *fill = 0); -Q_GUI_EXPORT void qDrawShadePanel(QPainter *p, const QRect &r, +Q_WIDGETS_EXPORT void qDrawShadePanel(QPainter *p, const QRect &r, const QPalette &pal, bool sunken = false, int lineWidth = 1, const QBrush *fill = 0); -Q_GUI_EXPORT void qDrawWinButton(QPainter *p, int x, int y, int w, int h, +Q_WIDGETS_EXPORT void qDrawWinButton(QPainter *p, int x, int y, int w, int h, const QPalette &pal, bool sunken = false, const QBrush *fill = 0); -Q_GUI_EXPORT void qDrawWinButton(QPainter *p, const QRect &r, +Q_WIDGETS_EXPORT void qDrawWinButton(QPainter *p, const QRect &r, const QPalette &pal, bool sunken = false, const QBrush *fill = 0); -Q_GUI_EXPORT void qDrawWinPanel(QPainter *p, int x, int y, int w, int h, +Q_WIDGETS_EXPORT void qDrawWinPanel(QPainter *p, int x, int y, int w, int h, const QPalette &pal, bool sunken = false, const QBrush *fill = 0); -Q_GUI_EXPORT void qDrawWinPanel(QPainter *p, const QRect &r, +Q_WIDGETS_EXPORT void qDrawWinPanel(QPainter *p, const QRect &r, const QPalette &pal, bool sunken = false, const QBrush *fill = 0); -Q_GUI_EXPORT void qDrawPlainRect(QPainter *p, int x, int y, int w, int h, const QColor &, +Q_WIDGETS_EXPORT void qDrawPlainRect(QPainter *p, int x, int y, int w, int h, const QColor &, int lineWidth = 1, const QBrush *fill = 0); -Q_GUI_EXPORT void qDrawPlainRect(QPainter *p, const QRect &r, const QColor &, +Q_WIDGETS_EXPORT void qDrawPlainRect(QPainter *p, const QRect &r, const QColor &, int lineWidth = 1, const QBrush *fill = 0); @@ -148,7 +148,7 @@ namespace QDrawBorderPixmap } #endif -Q_GUI_EXPORT void qDrawBorderPixmap(QPainter *painter, +Q_WIDGETS_EXPORT void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, const QPixmap &pixmap, diff --git a/src/widgets/styles/qgtkstyle.h b/src/widgets/styles/qgtkstyle.h index 56df2778e7..1ca6e3cc85 100644 --- a/src/widgets/styles/qgtkstyle.h +++ b/src/widgets/styles/qgtkstyle.h @@ -58,7 +58,7 @@ QT_MODULE(Gui) class QPainterPath; class QGtkStylePrivate; -class Q_GUI_EXPORT QGtkStyle : public QCleanlooksStyle +class Q_WIDGETS_EXPORT QGtkStyle : public QCleanlooksStyle { Q_OBJECT Q_DECLARE_PRIVATE(QGtkStyle) diff --git a/src/widgets/styles/qgtkstyle_p.h b/src/widgets/styles/qgtkstyle_p.h index 07d2a503de..55089268b3 100644 --- a/src/widgets/styles/qgtkstyle_p.h +++ b/src/widgets/styles/qgtkstyle_p.h @@ -271,10 +271,10 @@ typedef QString (*_qt_filedialog_save_filename_hook) (QWidget * parent, cons typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options); -extern Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook; -extern Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook; -extern Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook; -extern Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook; +extern Q_WIDGETS_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook; +extern Q_WIDGETS_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook; +extern Q_WIDGETS_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook; +extern Q_WIDGETS_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook; class QGtkStylePrivate; diff --git a/src/widgets/styles/qmacstyle_mac.h b/src/widgets/styles/qmacstyle_mac.h index ec4fed76eb..44940bd2b7 100644 --- a/src/widgets/styles/qmacstyle_mac.h +++ b/src/widgets/styles/qmacstyle_mac.h @@ -55,15 +55,15 @@ QT_MODULE(Gui) class QPalette; #if defined(QT_PLUGIN) -#define Q_GUI_EXPORT_STYLE_MAC +#define Q_WIDGETS_EXPORT_STYLE_MAC #else -#define Q_GUI_EXPORT_STYLE_MAC Q_GUI_EXPORT +#define Q_WIDGETS_EXPORT_STYLE_MAC Q_WIDGETS_EXPORT #endif class QPushButton; class QStyleOptionButton; class QMacStylePrivate; -class Q_GUI_EXPORT_STYLE_MAC QMacStyle : public QWindowsStyle +class Q_WIDGETS_EXPORT_STYLE_MAC QMacStyle : public QWindowsStyle { Q_OBJECT public: diff --git a/src/widgets/styles/qmotifstyle.h b/src/widgets/styles/qmotifstyle.h index 3fe470d1f1..35b3448289 100644 --- a/src/widgets/styles/qmotifstyle.h +++ b/src/widgets/styles/qmotifstyle.h @@ -57,7 +57,7 @@ class QPalette; class QFocusFrame; class QMotifStylePrivate; -class Q_GUI_EXPORT QMotifStyle : public QCommonStyle +class Q_WIDGETS_EXPORT QMotifStyle : public QCommonStyle { Q_OBJECT public: diff --git a/src/widgets/styles/qplastiquestyle.h b/src/widgets/styles/qplastiquestyle.h index 51a0139b21..d0afce6cf0 100644 --- a/src/widgets/styles/qplastiquestyle.h +++ b/src/widgets/styles/qplastiquestyle.h @@ -53,7 +53,7 @@ QT_MODULE(Gui) #if !defined(QT_NO_STYLE_PLASTIQUE) class QPlastiqueStylePrivate; -class Q_GUI_EXPORT QPlastiqueStyle : public QWindowsStyle +class Q_WIDGETS_EXPORT QPlastiqueStyle : public QWindowsStyle { Q_OBJECT Q_DECLARE_PRIVATE(QPlastiqueStyle) diff --git a/src/widgets/styles/qproxystyle.h b/src/widgets/styles/qproxystyle.h index 14b96ba0e4..96c5c34f18 100644 --- a/src/widgets/styles/qproxystyle.h +++ b/src/widgets/styles/qproxystyle.h @@ -53,7 +53,7 @@ QT_MODULE(Gui) #if !defined(QT_NO_STYLE_PROXY) class QProxyStylePrivate; -class Q_GUI_EXPORT QProxyStyle : public QCommonStyle +class Q_WIDGETS_EXPORT QProxyStyle : public QCommonStyle { Q_OBJECT diff --git a/src/widgets/styles/qs60style.h b/src/widgets/styles/qs60style.h index 0bd22bdb36..4520d19fd3 100644 --- a/src/widgets/styles/qs60style.h +++ b/src/widgets/styles/qs60style.h @@ -62,7 +62,7 @@ enum { class QS60StylePrivate; -class Q_GUI_EXPORT QS60Style : public QCommonStyle +class Q_WIDGETS_EXPORT QS60Style : public QCommonStyle { Q_OBJECT Q_DECLARE_PRIVATE(QS60Style) diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h index e87556d932..1896f129e1 100644 --- a/src/widgets/styles/qstyle.h +++ b/src/widgets/styles/qstyle.h @@ -65,7 +65,7 @@ class QStyleOption; class QStyleOptionComplex; class QStylePrivate; -class Q_GUI_EXPORT QStyle : public QObject +class Q_WIDGETS_EXPORT QStyle : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QStyle) @@ -879,7 +879,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QStyle::State) Q_DECLARE_OPERATORS_FOR_FLAGS(QStyle::SubControls) #if !defined(QT_NO_DEBUG_STREAM) -Q_GUI_EXPORT QDebug operator<<(QDebug debug, QStyle::State state); +Q_WIDGETS_EXPORT QDebug operator<<(QDebug debug, QStyle::State state); #endif QT_END_NAMESPACE diff --git a/src/widgets/styles/qstylefactory.h b/src/widgets/styles/qstylefactory.h index 92bd24fddb..b972c8e0e6 100644 --- a/src/widgets/styles/qstylefactory.h +++ b/src/widgets/styles/qstylefactory.h @@ -52,7 +52,7 @@ QT_MODULE(Gui) class QStyle; -class Q_GUI_EXPORT QStyleFactory +class Q_WIDGETS_EXPORT QStyleFactory { public: static QStringList keys(); diff --git a/src/widgets/styles/qstyleoption.h b/src/widgets/styles/qstyleoption.h index 557a297f7a..0640eef606 100644 --- a/src/widgets/styles/qstyleoption.h +++ b/src/widgets/styles/qstyleoption.h @@ -64,7 +64,7 @@ QT_MODULE(Gui) class QDebug; -class Q_GUI_EXPORT QStyleOption +class Q_WIDGETS_EXPORT QStyleOption { public: enum OptionType { @@ -100,7 +100,7 @@ public: QStyleOption &operator=(const QStyleOption &other); }; -class Q_GUI_EXPORT QStyleOptionFocusRect : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionFocusRect : public QStyleOption { public: enum StyleOptionType { Type = SO_FocusRect }; @@ -115,7 +115,7 @@ protected: QStyleOptionFocusRect(int version); }; -class Q_GUI_EXPORT QStyleOptionFrame : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionFrame : public QStyleOption { public: enum StyleOptionType { Type = SO_Frame }; @@ -131,7 +131,7 @@ protected: QStyleOptionFrame(int version); }; -class Q_GUI_EXPORT QStyleOptionFrameV2 : public QStyleOptionFrame +class Q_WIDGETS_EXPORT QStyleOptionFrameV2 : public QStyleOptionFrame { public: enum StyleOptionVersion { Version = 2 }; @@ -154,7 +154,7 @@ protected: Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionFrameV2::FrameFeatures) -class Q_GUI_EXPORT QStyleOptionFrameV3 : public QStyleOptionFrameV2 +class Q_WIDGETS_EXPORT QStyleOptionFrameV3 : public QStyleOptionFrameV2 { public: enum StyleOptionVersion { Version = 3 }; @@ -172,7 +172,7 @@ protected: #ifndef QT_NO_TABWIDGET -class Q_GUI_EXPORT QStyleOptionTabWidgetFrame : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionTabWidgetFrame : public QStyleOption { public: enum StyleOptionType { Type = SO_TabWidgetFrame }; @@ -193,7 +193,7 @@ protected: QStyleOptionTabWidgetFrame(int version); }; -class Q_GUI_EXPORT QStyleOptionTabWidgetFrameV2 : public QStyleOptionTabWidgetFrame +class Q_WIDGETS_EXPORT QStyleOptionTabWidgetFrameV2 : public QStyleOptionTabWidgetFrame { public: enum StyleOptionVersion { Version = 2 }; @@ -215,7 +215,7 @@ protected: #ifndef QT_NO_TABBAR -class Q_GUI_EXPORT QStyleOptionTabBarBase : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionTabBarBase : public QStyleOption { public: enum StyleOptionType { Type = SO_TabBarBase }; @@ -232,7 +232,7 @@ protected: QStyleOptionTabBarBase(int version); }; -class Q_GUI_EXPORT QStyleOptionTabBarBaseV2 : public QStyleOptionTabBarBase +class Q_WIDGETS_EXPORT QStyleOptionTabBarBaseV2 : public QStyleOptionTabBarBase { public: enum StyleOptionVersion { Version = 2 }; @@ -248,7 +248,7 @@ protected: #endif -class Q_GUI_EXPORT QStyleOptionHeader : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionHeader : public QStyleOption { public: enum StyleOptionType { Type = SO_Header }; @@ -276,7 +276,7 @@ protected: QStyleOptionHeader(int version); }; -class Q_GUI_EXPORT QStyleOptionButton : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionButton : public QStyleOption { public: enum StyleOptionType { Type = SO_Button }; @@ -301,7 +301,7 @@ protected: Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionButton::ButtonFeatures) #ifndef QT_NO_TABBAR -class Q_GUI_EXPORT QStyleOptionTab : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionTab : public QStyleOption { public: enum StyleOptionType { Type = SO_Tab }; @@ -330,7 +330,7 @@ protected: Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionTab::CornerWidgets) -class Q_GUI_EXPORT QStyleOptionTabV2 : public QStyleOptionTab +class Q_WIDGETS_EXPORT QStyleOptionTabV2 : public QStyleOptionTab { public: enum StyleOptionVersion { Version = 2 }; @@ -344,7 +344,7 @@ protected: QStyleOptionTabV2(int version); }; -class Q_GUI_EXPORT QStyleOptionTabV3 : public QStyleOptionTabV2 +class Q_WIDGETS_EXPORT QStyleOptionTabV3 : public QStyleOptionTabV2 { public: enum StyleOptionVersion { Version = 3 }; @@ -366,7 +366,7 @@ protected: #ifndef QT_NO_TOOLBAR -class Q_GUI_EXPORT QStyleOptionToolBar : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionToolBar : public QStyleOption { public: enum StyleOptionType { Type = SO_ToolBar }; @@ -393,7 +393,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionToolBar::ToolBarFeatures) -class Q_GUI_EXPORT QStyleOptionProgressBar : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionProgressBar : public QStyleOption { public: enum StyleOptionType { Type = SO_ProgressBar }; @@ -414,7 +414,7 @@ protected: }; // Adds style info for vertical progress bars -class Q_GUI_EXPORT QStyleOptionProgressBarV2 : public QStyleOptionProgressBar +class Q_WIDGETS_EXPORT QStyleOptionProgressBarV2 : public QStyleOptionProgressBar { public: enum StyleOptionType { Type = SO_ProgressBar }; @@ -432,7 +432,7 @@ protected: QStyleOptionProgressBarV2(int version); }; -class Q_GUI_EXPORT QStyleOptionMenuItem : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionMenuItem : public QStyleOption { public: enum StyleOptionType { Type = SO_MenuItem }; @@ -460,7 +460,7 @@ protected: QStyleOptionMenuItem(int version); }; -class Q_GUI_EXPORT QStyleOptionQ3ListViewItem : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionQ3ListViewItem : public QStyleOption { public: enum StyleOptionType { Type = SO_Q3ListViewItem }; @@ -485,7 +485,7 @@ protected: Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionQ3ListViewItem::Q3ListViewItemFeatures) -class Q_GUI_EXPORT QStyleOptionQ3DockWindow : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionQ3DockWindow : public QStyleOption { public: enum StyleOptionType { Type = SO_Q3DockWindow }; @@ -501,7 +501,7 @@ protected: QStyleOptionQ3DockWindow(int version); }; -class Q_GUI_EXPORT QStyleOptionDockWidget : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionDockWidget : public QStyleOption { public: enum StyleOptionType { Type = SO_DockWidget }; @@ -519,7 +519,7 @@ protected: QStyleOptionDockWidget(int version); }; -class Q_GUI_EXPORT QStyleOptionDockWidgetV2 : public QStyleOptionDockWidget +class Q_WIDGETS_EXPORT QStyleOptionDockWidgetV2 : public QStyleOptionDockWidget { public: enum StyleOptionVersion { Version = 2 }; @@ -536,7 +536,7 @@ protected: QStyleOptionDockWidgetV2(int version); }; -class Q_GUI_EXPORT QStyleOptionViewItem : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionViewItem : public QStyleOption { public: enum StyleOptionType { Type = SO_ViewItem }; @@ -559,7 +559,7 @@ protected: QStyleOptionViewItem(int version); }; -class Q_GUI_EXPORT QStyleOptionViewItemV2 : public QStyleOptionViewItem +class Q_WIDGETS_EXPORT QStyleOptionViewItemV2 : public QStyleOptionViewItem { public: enum StyleOptionVersion { Version = 2 }; @@ -587,7 +587,7 @@ protected: Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionViewItemV2::ViewItemFeatures) -class Q_GUI_EXPORT QStyleOptionViewItemV3 : public QStyleOptionViewItemV2 +class Q_WIDGETS_EXPORT QStyleOptionViewItemV3 : public QStyleOptionViewItemV2 { public: enum StyleOptionVersion { Version = 3 }; @@ -606,7 +606,7 @@ protected: }; #ifndef QT_NO_ITEMVIEWS -class Q_GUI_EXPORT QStyleOptionViewItemV4 : public QStyleOptionViewItemV3 +class Q_WIDGETS_EXPORT QStyleOptionViewItemV4 : public QStyleOptionViewItemV3 { public: enum StyleOptionVersion { Version = 4 }; @@ -630,7 +630,7 @@ protected: }; #endif -class Q_GUI_EXPORT QStyleOptionToolBox : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionToolBox : public QStyleOption { public: enum StyleOptionType { Type = SO_ToolBox }; @@ -646,7 +646,7 @@ protected: QStyleOptionToolBox(int version); }; -class Q_GUI_EXPORT QStyleOptionToolBoxV2 : public QStyleOptionToolBox +class Q_WIDGETS_EXPORT QStyleOptionToolBoxV2 : public QStyleOptionToolBox { public: enum StyleOptionVersion { Version = 2 }; @@ -666,7 +666,7 @@ protected: }; #ifndef QT_NO_RUBBERBAND -class Q_GUI_EXPORT QStyleOptionRubberBand : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionRubberBand : public QStyleOption { public: enum StyleOptionType { Type = SO_RubberBand }; @@ -684,7 +684,7 @@ protected: #endif // QT_NO_RUBBERBAND // -------------------------- Complex style options ------------------------------- -class Q_GUI_EXPORT QStyleOptionComplex : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionComplex : public QStyleOption { public: enum StyleOptionType { Type = SO_Complex }; @@ -698,7 +698,7 @@ public: }; #ifndef QT_NO_SLIDER -class Q_GUI_EXPORT QStyleOptionSlider : public QStyleOptionComplex +class Q_WIDGETS_EXPORT QStyleOptionSlider : public QStyleOptionComplex { public: enum StyleOptionType { Type = SO_Slider }; @@ -726,7 +726,7 @@ protected: #endif // QT_NO_SLIDER #ifndef QT_NO_SPINBOX -class Q_GUI_EXPORT QStyleOptionSpinBox : public QStyleOptionComplex +class Q_WIDGETS_EXPORT QStyleOptionSpinBox : public QStyleOptionComplex { public: enum StyleOptionType { Type = SO_SpinBox }; @@ -744,7 +744,7 @@ protected: }; #endif // QT_NO_SPINBOX -class Q_GUI_EXPORT QStyleOptionQ3ListView : public QStyleOptionComplex +class Q_WIDGETS_EXPORT QStyleOptionQ3ListView : public QStyleOptionComplex { public: enum StyleOptionType { Type = SO_Q3ListView }; @@ -765,7 +765,7 @@ protected: QStyleOptionQ3ListView(int version); }; -class Q_GUI_EXPORT QStyleOptionToolButton : public QStyleOptionComplex +class Q_WIDGETS_EXPORT QStyleOptionToolButton : public QStyleOptionComplex { public: enum StyleOptionType { Type = SO_ToolButton }; @@ -793,7 +793,7 @@ protected: Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleOptionToolButton::ToolButtonFeatures) -class Q_GUI_EXPORT QStyleOptionComboBox : public QStyleOptionComplex +class Q_WIDGETS_EXPORT QStyleOptionComboBox : public QStyleOptionComplex { public: enum StyleOptionType { Type = SO_ComboBox }; @@ -813,7 +813,7 @@ protected: QStyleOptionComboBox(int version); }; -class Q_GUI_EXPORT QStyleOptionTitleBar : public QStyleOptionComplex +class Q_WIDGETS_EXPORT QStyleOptionTitleBar : public QStyleOptionComplex { public: enum StyleOptionType { Type = SO_TitleBar }; @@ -831,7 +831,7 @@ protected: QStyleOptionTitleBar(int version); }; -class Q_GUI_EXPORT QStyleOptionGroupBox : public QStyleOptionComplex +class Q_WIDGETS_EXPORT QStyleOptionGroupBox : public QStyleOptionComplex { public: enum StyleOptionType { Type = SO_GroupBox }; @@ -850,7 +850,7 @@ protected: QStyleOptionGroupBox(int version); }; -class Q_GUI_EXPORT QStyleOptionSizeGrip : public QStyleOptionComplex +class Q_WIDGETS_EXPORT QStyleOptionSizeGrip : public QStyleOptionComplex { public: enum StyleOptionType { Type = SO_SizeGrip }; @@ -864,7 +864,7 @@ protected: QStyleOptionSizeGrip(int version); }; -class Q_GUI_EXPORT QStyleOptionGraphicsItem : public QStyleOption +class Q_WIDGETS_EXPORT QStyleOptionGraphicsItem : public QStyleOption { public: enum StyleOptionType { Type = SO_GraphicsItem }; @@ -904,7 +904,7 @@ T qstyleoption_cast(QStyleOption *opt) } // -------------------------- QStyleHintReturn ------------------------------- -class Q_GUI_EXPORT QStyleHintReturn { +class Q_WIDGETS_EXPORT QStyleHintReturn { public: enum HintReturnType { SH_Default=0xf000, SH_Mask, SH_Variant @@ -920,7 +920,7 @@ public: int type; }; -class Q_GUI_EXPORT QStyleHintReturnMask : public QStyleHintReturn { +class Q_WIDGETS_EXPORT QStyleHintReturnMask : public QStyleHintReturn { public: enum StyleOptionType { Type = SH_Mask }; enum StyleOptionVersion { Version = 1 }; @@ -930,7 +930,7 @@ public: QRegion region; }; -class Q_GUI_EXPORT QStyleHintReturnVariant : public QStyleHintReturn { +class Q_WIDGETS_EXPORT QStyleHintReturnVariant : public QStyleHintReturn { public: enum StyleOptionType { Type = SH_Variant }; enum StyleOptionVersion { Version = 1 }; @@ -959,8 +959,8 @@ T qstyleoption_cast(QStyleHintReturn *hint) } #if !defined(QT_NO_DEBUG_STREAM) -Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QStyleOption::OptionType &optionType); -Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QStyleOption &option); +Q_WIDGETS_EXPORT QDebug operator<<(QDebug debug, const QStyleOption::OptionType &optionType); +Q_WIDGETS_EXPORT QDebug operator<<(QDebug debug, const QStyleOption &option); #endif QT_END_NAMESPACE diff --git a/src/widgets/styles/qstyleplugin.h b/src/widgets/styles/qstyleplugin.h index 2dd8ccfcfd..ab55cdf54c 100644 --- a/src/widgets/styles/qstyleplugin.h +++ b/src/widgets/styles/qstyleplugin.h @@ -53,7 +53,7 @@ QT_MODULE(Gui) class QStyle; -struct Q_GUI_EXPORT QStyleFactoryInterface : public QFactoryInterface +struct Q_WIDGETS_EXPORT QStyleFactoryInterface : public QFactoryInterface { virtual QStyle *create(const QString &key) = 0; }; @@ -62,7 +62,7 @@ struct Q_GUI_EXPORT QStyleFactoryInterface : public QFactoryInterface Q_DECLARE_INTERFACE(QStyleFactoryInterface, QStyleFactoryInterface_iid) -class Q_GUI_EXPORT QStylePlugin : public QObject, public QStyleFactoryInterface +class Q_WIDGETS_EXPORT QStylePlugin : public QObject, public QStyleFactoryInterface { Q_OBJECT Q_INTERFACES(QStyleFactoryInterface:QFactoryInterface) diff --git a/src/widgets/styles/qwindowscestyle.h b/src/widgets/styles/qwindowscestyle.h index c9e7ecadfb..3db9be58e2 100644 --- a/src/widgets/styles/qwindowscestyle.h +++ b/src/widgets/styles/qwindowscestyle.h @@ -52,7 +52,7 @@ QT_MODULE(Gui) #if !defined(QT_NO_STYLE_WINDOWSCE) -class Q_GUI_EXPORT QWindowsCEStyle : public QWindowsStyle +class Q_WIDGETS_EXPORT QWindowsCEStyle : public QWindowsStyle { Q_OBJECT public: diff --git a/src/widgets/styles/qwindowsmobilestyle.h b/src/widgets/styles/qwindowsmobilestyle.h index 2a2a697ca9..050f641888 100644 --- a/src/widgets/styles/qwindowsmobilestyle.h +++ b/src/widgets/styles/qwindowsmobilestyle.h @@ -54,7 +54,7 @@ QT_MODULE(Gui) class QWindowsMobileStylePrivate; -class Q_GUI_EXPORT QWindowsMobileStyle : public QWindowsStyle +class Q_WIDGETS_EXPORT QWindowsMobileStyle : public QWindowsStyle { Q_OBJECT public: diff --git a/src/widgets/styles/qwindowsstyle.h b/src/widgets/styles/qwindowsstyle.h index 9c732132d4..acecfa9140 100644 --- a/src/widgets/styles/qwindowsstyle.h +++ b/src/widgets/styles/qwindowsstyle.h @@ -54,7 +54,7 @@ QT_MODULE(Gui) class QWindowsStylePrivate; -class Q_GUI_EXPORT QWindowsStyle : public QCommonStyle +class Q_WIDGETS_EXPORT QWindowsStyle : public QCommonStyle { Q_OBJECT public: diff --git a/src/widgets/styles/qwindowsvistastyle.h b/src/widgets/styles/qwindowsvistastyle.h index 24d673091a..68b489107e 100644 --- a/src/widgets/styles/qwindowsvistastyle.h +++ b/src/widgets/styles/qwindowsvistastyle.h @@ -53,7 +53,7 @@ QT_MODULE(Gui) #if !defined(QT_NO_STYLE_WINDOWSVISTA) class QWindowsVistaStylePrivate; -class Q_GUI_EXPORT QWindowsVistaStyle : public QWindowsXPStyle +class Q_WIDGETS_EXPORT QWindowsVistaStyle : public QWindowsXPStyle { Q_OBJECT public: diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index 3c33df3d11..83d47db20f 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -132,7 +132,7 @@ static const int windowsArrowHMargin = 6; // arrow horizontal margin static const int windowsRightBorder = 12; // right border on windows // External function calls -extern Q_GUI_EXPORT HDC qt_win_display_dc(); +extern Q_WIDGETS_EXPORT HDC qt_win_display_dc(); extern QRegion qt_region_from_HRGN(HRGN rgn); diff --git a/src/widgets/styles/qwindowsxpstyle.h b/src/widgets/styles/qwindowsxpstyle.h index d0f1329c30..1cfd16479b 100644 --- a/src/widgets/styles/qwindowsxpstyle.h +++ b/src/widgets/styles/qwindowsxpstyle.h @@ -53,7 +53,7 @@ QT_MODULE(Gui) #if !defined(QT_NO_STYLE_WINDOWSXP) class QWindowsXPStylePrivate; -class Q_GUI_EXPORT QWindowsXPStyle : public QWindowsStyle +class Q_WIDGETS_EXPORT QWindowsXPStyle : public QWindowsStyle { Q_OBJECT public: -- cgit v1.2.3 From 4b566e5db926470499bb9171b336f5e526e40bba Mon Sep 17 00:00:00 2001 From: Olli Werwolff Date: Wed, 8 Jun 2011 11:48:38 +0200 Subject: Most checks for windows in widgets have to be ws specific Reviewed-by: Samuel Reviewed-by: Lars Knoll --- src/widgets/styles/qwindowsstyle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index c0992733f8..d1d3865868 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -918,7 +918,7 @@ static const char *const question_xpm[] = { #endif //QT_NO_IMAGEFORMAT_XPM -#ifdef Q_OS_WIN +#ifdef Q_WS_WIN static QPixmap loadIconFromShell32( int resourceId, int size ) { #ifdef Q_OS_WINCE @@ -3256,7 +3256,7 @@ QIcon QWindowsStyle::standardIconImplementation(StandardPixmap standardIcon, con { QIcon icon; QPixmap pixmap; -#ifdef Q_OS_WIN +#ifdef Q_WS_WIN switch (standardIcon) { case SP_FileDialogNewFolder: { -- cgit v1.2.3 From 4ed17a650847d4ad129478608e9697c909126263 Mon Sep 17 00:00:00 2001 From: Morten Sorvig Date: Tue, 5 Jul 2011 15:02:39 +0200 Subject: Start porting the Mac menu system to QPA. Global changes: qglobal.h: remove code that sets Q_WS_MAC and Q_MAC_USE_COCOA - this is dead code now. Add qt_widget_helpers_mac_p.h/mm which will contain helper functions needed for widgets on Qt 5. Menu-related changes: Set AA_DontUseNativeMenuBar before creating the platform plugin. Change Q_WS_MAC to Q_OS_MAC in the menu code. Remove Q_MAC_USE_COCOA defines and Carbon code paths. Move some qt_mac helper functions only used by the menu system to qmenu_mac.mm. #ifdef out some code paths that require further porting. Native menus are now disabled by default but can be enabled by the QPA plugins that want them by clearing AA_DontUseNativeMenuBar. Since we at compile time don't know which plugin will be loaded the Mac menu code is always included when building on OS X. (The above is currently only relevant for the Cocoa plugin.) --- src/widgets/styles/qmacstyle_mac.mm | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index 40c28f6674..86b30cf7e0 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -395,29 +395,6 @@ static inline bool isTreeView(const QWidget *widget) )); } -QString qt_mac_removeMnemonics(const QString &original) -{ - QString returnText(original.size(), 0); - int finalDest = 0; - int currPos = 0; - int l = original.length(); - while (l) { - if (original.at(currPos) == QLatin1Char('&') - && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) { - ++currPos; - --l; - if (l == 0) - break; - } - returnText[finalDest] = original.at(currPos); - ++currPos; - ++finalDest; - --l; - } - returnText.truncate(finalDest); - return returnText; -} - static inline ThemeTabDirection getTabDirection(QTabBar::Shape shape) { ThemeTabDirection ttd; -- cgit v1.2.3 From f9f04ea63d2489bd2ecb91c5a6bee4c4a869ac20 Mon Sep 17 00:00:00 2001 From: Olli Werwolff Date: Thu, 7 Jul 2011 09:07:19 +0200 Subject: Use PlatformNativeInterface to obtain handles Change-Id: I8cdf3d5477e72e89bcde46ccb6670320bf4dd797 Reviewed-on: http://codereview.qt.nokia.com/1270 Reviewed-by: Qt Sanity Bot Reviewed-by: Friedemann Kleint --- src/widgets/styles/qwindowsvistastyle.cpp | 5 ++++- src/widgets/styles/qwindowsxpstyle.cpp | 37 ++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 7 deletions(-) (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index da484bafe1..55e83f79fa 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -43,6 +43,8 @@ #include "qwindowsvistastyle_p.h" #include #include +#include +#include #if !defined(QT_NO_STYLE_WINDOWSVISTA) || defined(QT_PLUGIN) @@ -2606,7 +2608,8 @@ QWidget *QWindowsVistaStylePrivate::treeViewHelper() { if (!m_treeViewHelper) { m_treeViewHelper = new QWidget(0); - pSetWindowTheme(m_treeViewHelper->winId(), L"explorer", NULL); + HWND handle = QApplicationPrivate::getHWNDForWidget(m_treeViewHelper); + pSetWindowTheme(handle, L"explorer", NULL); } return m_treeViewHelper; } diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index 83d47db20f..36e0852462 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -295,9 +296,10 @@ void QWindowsXPStylePrivate::cleanupHandleMap() */ HWND QWindowsXPStylePrivate::winId(const QWidget *widget) { - if (widget && widget->internalWinId()) - return widget->internalWinId(); - + if (widget && widget->internalWinId()) { + QWidget *w = const_cast(widget); + return QApplicationPrivate::getHWNDForWidget(w); + } if (!limboWidget) { limboWidget = new QWidget(0); limboWidget->createWinId(); @@ -307,7 +309,7 @@ HWND QWindowsXPStylePrivate::winId(const QWidget *widget) QWidgetPrivate::allWidgets->remove(limboWidget); } - return limboWidget->winId(); + return QApplicationPrivate::getHWNDForWidget(limboWidget); } /*! \internal @@ -466,8 +468,31 @@ QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData) QRegion region; - if (success) - region = qt_region_from_HRGN(dest); + if (success) { + int numBytes = GetRegionData(dest, 0, 0); + if (numBytes == 0) + return QRegion(); + + char *buf = new char[numBytes]; + if (buf == 0) + return QRegion(); + + RGNDATA *rd = reinterpret_cast(buf); + if (GetRegionData(dest, numBytes, rd) == 0) { + delete [] buf; + return QRegion(); + } + + RECT *r = reinterpret_cast(rd->Buffer); + for (uint i = 0; i < rd->rdh.nCount; ++i) { + QRect rect; + rect.setCoords(r->left, r->top, r->right - 1, r->bottom - 1); + ++r; + region |= rect; + } + + delete [] buf; + } DeleteObject(hRgn); DeleteObject(dest); -- cgit v1.2.3 From 992ef929dff21e079f7d8a207c07dbfd0c3c8f78 Mon Sep 17 00:00:00 2001 From: Olli Werwolff Date: Tue, 12 Jul 2011 13:02:54 +0200 Subject: Use PlatformNativeInterface to obtain backingStore's dc Change-Id: I6ec2fc0b8e7696fdfe4468920228df2d21c933fd Reviewed-on: http://codereview.qt.nokia.com/1501 Reviewed-by: Friedemann Kleint --- src/widgets/styles/qwindowsxpstyle.cpp | 19 ++++++++++++------- src/widgets/styles/qwindowsxpstyle_p.h | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index 36e0852462..ce5694c181 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -190,17 +190,17 @@ RECT XPThemeData::toRECT(const QRect &qr) Returns the native region of a part, if the part is considered transparent. The region is scaled to the parts size (rect). */ -HRGN XPThemeData::mask() +HRGN XPThemeData::mask(QWidget *widget) { if (!pIsThemeBackgroundPartiallyTransparent(handle(), partId, stateId)) return 0; HRGN hrgn; - HDC dc = painter == 0 ? 0 : painter->paintEngine()->getDC(); + QBackingStore *backingStore = widget->backingStore(); + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + HDC dc = static_cast(nativeInterface->nativeResourceForBackingStore("getDC", backingStore)); RECT nativeRect = toRECT(rect); pGetThemeBackgroundRegion(handle(), dc, partId, stateId, &nativeRect, &hrgn); - if (dc) - painter->paintEngine()->releaseDC(dc); return hrgn; } @@ -505,7 +505,7 @@ QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData) */ void QWindowsXPStylePrivate::setTransparency(QWidget *widget, XPThemeData &themeData) { - HRGN hrgn = themeData.mask(); + HRGN hrgn = themeData.mask(widget); if (hrgn && widget) SetWindowRgn(winId(widget), hrgn, true); } @@ -657,7 +657,10 @@ void QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) translucentToplevel = win->testAttribute(Qt::WA_TranslucentBackground); } - bool useFallback = painter->paintEngine()->getDC() == 0 + QBackingStore *backingStore = themeData.widget->backingStore(); + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + HDC dc = static_cast(nativeInterface->nativeResourceForBackingStore("getDC", backingStore )); + bool useFallback = dc == 0 || painter->opacity() != 1.0 || themeData.rotate || complexXForm @@ -681,7 +684,9 @@ void QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) void QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData) { QPainter *painter = themeData.painter; - HDC dc = painter->paintEngine()->getDC(); + QBackingStore *backingStore= themeData.widget->backingStore(); + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + HDC dc = static_cast(nativeInterface->nativeResourceForBackingStore("getDC", backingStore)); QPoint redirectionDelta(int(painter->deviceMatrix().dx()), int(painter->deviceMatrix().dy())); diff --git a/src/widgets/styles/qwindowsxpstyle_p.h b/src/widgets/styles/qwindowsxpstyle_p.h index 73803607a1..05ab2ec2e4 100644 --- a/src/widgets/styles/qwindowsxpstyle_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p.h @@ -216,7 +216,7 @@ public: noContent(false), rotate(0), rect(r) {} - HRGN mask(); + HRGN mask(QWidget *widget); HTHEME handle(); RECT toRECT(const QRect &qr); -- cgit v1.2.3 From 310519d6d11da546b23c1cba307f37c24e0a5c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 15 Jul 2011 14:07:12 +0200 Subject: Rename QPixmapData to QPlatformPixmap. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makes the API symmetric with the other Lighthouse APIs. Change-Id: I8a399f3c968ea35d4624711b31f2ac5bb94b7893 Reviewed-on: http://codereview.qt.nokia.com/1735 Reviewed-by: Qt Sanity Bot Reviewed-by: Jørgen Lind --- src/widgets/styles/qs60style_s60.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/qs60style_s60.cpp b/src/widgets/styles/qs60style_s60.cpp index f272ff4a90..f7ced9e8f8 100644 --- a/src/widgets/styles/qs60style_s60.cpp +++ b/src/widgets/styles/qs60style_s60.cpp @@ -647,17 +647,17 @@ QPixmap QS60StyleModeSpecifics::fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask return QPixmap(); QPixmap pixmap; - QScopedPointer pd(QPixmapData::create(0, 0, QPixmapData::PixmapType)); + QScopedPointer pd(QPlatformPixmap::create(0, 0, QPlatformPixmap::PixmapType)); if (mask) { // Try the efficient path with less copying and conversion. QVolatileImage img(icon, mask); - pd->fromNativeType(&img, QPixmapData::VolatileImage); + pd->fromNativeType(&img, QPlatformPixmap::VolatileImage); if (!pd->isNull()) pixmap = QPixmap(pd.take()); } if (pixmap.isNull()) { // Potentially more expensive path. - pd->fromNativeType(icon, QPixmapData::FbsBitmap); + pd->fromNativeType(icon, QPlatformPixmap::FbsBitmap); pixmap = QPixmap(pd.take()); if (mask) { pixmap.setAlphaChannel(QPixmap::fromSymbianCFbsBitmap(mask)); -- cgit v1.2.3 From 7589bdc7202b11f40c2fe5820aa0afaca3cf2670 Mon Sep 17 00:00:00 2001 From: Olli Werwolff Date: Mon, 15 Aug 2011 14:07:56 +0200 Subject: Disable WindowsXP/-Vista styles for now As these styles need functionality from qregion_win we disable them for now. Change-Id: I0d5d38f2f684d1ee619967341849d891d17c75e6 Reviewed-on: http://codereview.qt.nokia.com/2964 Reviewed-by: Qt Sanity Bot Reviewed-by: Friedemann Kleint --- src/widgets/styles/styles.pri | 1 + 1 file changed, 1 insertion(+) (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/styles.pri b/src/widgets/styles/styles.pri index b20caf726e..e6ebf6e7e3 100644 --- a/src/widgets/styles/styles.pri +++ b/src/widgets/styles/styles.pri @@ -40,6 +40,7 @@ contains( styles, all ) { } x11|qpa|!macx-*:styles -= mac +win32:qpa:styles -= windowsxp windowsvista x11{ QMAKE_CXXFLAGS += $$QT_CFLAGS_QGTKSTYLE -- cgit v1.2.3 From c402d35df807096b199c9f1adfcad4dfabb70697 Mon Sep 17 00:00:00 2001 From: Olli Werwolff Date: Wed, 17 Aug 2011 09:59:08 +0200 Subject: Readded (and fixed) WindowsXP and -Vista styles There are still issues in WindowsVista style and qwizard_win's icon will not be shown but these will be fixed in upcoming commits. Change-Id: I22705694f07bea7461333b053804a09bab661706 Reviewed-on: http://codereview.qt.nokia.com/3073 Reviewed-by: Qt Sanity Bot Reviewed-by: Friedemann Kleint --- src/widgets/styles/qwindowsxpstyle.cpp | 69 +++++++++++++++++++++++++++------- src/widgets/styles/styles.pri | 1 - 2 files changed, 56 insertions(+), 14 deletions(-) (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index ce5694c181..cbaf16989a 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -196,9 +196,12 @@ HRGN XPThemeData::mask(QWidget *widget) return 0; HRGN hrgn; - QBackingStore *backingStore = widget->backingStore(); - QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - HDC dc = static_cast(nativeInterface->nativeResourceForBackingStore("getDC", backingStore)); + HDC dc = 0; + if (widget) { + QBackingStore *backingStore = widget->backingStore(); + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + dc = static_cast(nativeInterface->nativeResourceForBackingStore("getDC", backingStore)); + } RECT nativeRect = toRECT(rect); pGetThemeBackgroundRegion(handle(), dc, partId, stateId, &nativeRect, &hrgn); return hrgn; @@ -212,6 +215,32 @@ QMap *QWindowsXPStylePrivate::handleMap = 0; bool QWindowsXPStylePrivate::use_xp = false; QBasicAtomicInt QWindowsXPStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting +static void qt_add_rect(HRGN &winRegion, QRect r) +{ + HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); + if (rgn) { + HRGN dest = CreateRectRgn(0,0,0,0); + int result = CombineRgn(dest, winRegion, rgn, RGN_OR); + if (result) { + DeleteObject(winRegion); + winRegion = dest; + } + DeleteObject(rgn); + } +} + +static HRGN qt_hrgn_from_qregion(const QRegion ®ion) +{ + HRGN hRegion = CreateRectRgn(0,0,0,0); + if (region.rectCount() == 1) { + qt_add_rect(hRegion, region.boundingRect()); + return hRegion; + } + foreach (const QRect &rect, region.rects()) + qt_add_rect(hRegion, rect); + return hRegion; +} + /* \internal Checks if the theme engine can/should be used, or if we should fall back to Windows style. @@ -657,9 +686,13 @@ void QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) translucentToplevel = win->testAttribute(Qt::WA_TranslucentBackground); } - QBackingStore *backingStore = themeData.widget->backingStore(); - QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - HDC dc = static_cast(nativeInterface->nativeResourceForBackingStore("getDC", backingStore )); + HDC dc = 0; + if (themeData.widget) { + QBackingStore *backingStore = themeData.widget->backingStore(); + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + dc = static_cast(nativeInterface->nativeResourceForBackingStore("getDC", backingStore )); + } + bool useFallback = dc == 0 || painter->opacity() != 1.0 || themeData.rotate @@ -684,9 +717,12 @@ void QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) void QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData) { QPainter *painter = themeData.painter; - QBackingStore *backingStore= themeData.widget->backingStore(); - QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - HDC dc = static_cast(nativeInterface->nativeResourceForBackingStore("getDC", backingStore)); + HDC dc = 0; + if (themeData.widget) { + QBackingStore *backingStore = themeData.widget->backingStore(); + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + dc = static_cast(nativeInterface->nativeResourceForBackingStore("getDC", backingStore)); + } QPoint redirectionDelta(int(painter->deviceMatrix().dx()), int(painter->deviceMatrix().dy())); @@ -699,7 +735,8 @@ void QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData) sysRgn &= area; if (painter->hasClipping()) sysRgn &= painter->clipRegion().translated(redirectionDelta); - SelectClipRgn(dc, sysRgn.handle()); + HRGN hrgn = qt_hrgn_from_qregion(sysRgn); + SelectClipRgn(dc, hrgn); #ifdef DEBUG_XP_STYLE printf("---[ DIRECT PAINTING ]------------------> Name(%-10s) Part(%d) State(%d)\n", @@ -744,13 +781,17 @@ void QWindowsXPStylePrivate::drawBackgroundDirectly(XPThemeData &themeData) } // Set the clip region, if used.. - if (themeData.noBorder || themeData.noContent) - SelectClipRgn(dc, extraClip.handle()); + if (themeData.noBorder || themeData.noContent) { + DeleteObject(hrgn); + hrgn = qt_hrgn_from_qregion(extraClip); + SelectClipRgn(dc, hrgn); + } } pDrawThemeBackground(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawRECT), &(drawOptions.rcClip)); } SelectClipRgn(dc, 0); + DeleteObject(hrgn); } /*! \internal @@ -916,9 +957,11 @@ void QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa } else { // Set the clip region, if used.. if (addBorderContentClipping) { - SelectClipRgn(dc, extraClip.handle()); + HRGN hrgn = qt_hrgn_from_qregion(extraClip); + SelectClipRgn(dc, hrgn); // Compensate for the noBorder area difference (noContent has the same area) drawOptions.rcClip = themeData.toRECT(rect.adjusted(dx, dy, dr, db)); + DeleteObject(hrgn); } pDrawThemeBackground(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawOptions.rcClip), 0); diff --git a/src/widgets/styles/styles.pri b/src/widgets/styles/styles.pri index e6ebf6e7e3..b20caf726e 100644 --- a/src/widgets/styles/styles.pri +++ b/src/widgets/styles/styles.pri @@ -40,7 +40,6 @@ contains( styles, all ) { } x11|qpa|!macx-*:styles -= mac -win32:qpa:styles -= windowsxp windowsvista x11{ QMAKE_CXXFLAGS += $$QT_CFLAGS_QGTKSTYLE -- cgit v1.2.3