diff options
author | axis <qt-info@nokia.com> | 2009-04-24 13:34:15 +0200 |
---|---|---|
committer | axis <qt-info@nokia.com> | 2009-04-24 13:34:15 +0200 |
commit | 8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76 (patch) | |
tree | a17e1a767a89542ab59907462206d7dcf2e504b2 /src/gui/styles | |
download | qt4-tools-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.gz |
Long live Qt for S60!
Diffstat (limited to 'src/gui/styles')
188 files changed, 73994 insertions, 0 deletions
diff --git a/src/gui/styles/gtksymbols.cpp b/src/gui/styles/gtksymbols.cpp new file mode 100644 index 0000000000..3fbf233384 --- /dev/null +++ b/src/gui/styles/gtksymbols.cpp @@ -0,0 +1,904 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "gtksymbols_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 <QtCore/qglobal.h> +#if !defined(QT_NO_STYLE_GTK) + +#include <QtCore/QEvent> +#include <QtCore/QFile> +#include <QtCore/QStringList> +#include <QtCore/QTextStream> +#include <QtCore/QHash> + +#include <private/qapplication_p.h> + +#include <QtGui/QMenu> +#include <QtGui/QStyle> +#include <QtGui/QApplication> +#include <QtGui/QPixmapCache> +#include <QtGui/QStatusBar> +#include <QtGui/QMenuBar> +#include <QtGui/QToolBar> +#include <QtGui/QX11Info> + +#include <X11/Xlib.h> + +QT_BEGIN_NAMESPACE + +static bool displayDepth = -1; + +typedef QHash<QString, GtkWidget*> WidgetMap; +Q_GLOBAL_STATIC(WidgetMap, gtkWidgetMap) + +Ptr_gtk_container_forall QGtk::gtk_container_forall = 0; +Ptr_gtk_init QGtk::gtk_init = 0; +Ptr_gtk_style_attach QGtk::gtk_style_attach = 0; +Ptr_gtk_window_new QGtk::gtk_window_new = 0; +Ptr_gtk_widget_destroy QGtk::gtk_widget_destroy = 0; +Ptr_gtk_widget_realize QGtk::gtk_widget_realize = 0; +Ptr_gtk_widget_set_default_direction QGtk::gtk_widget_set_default_direction = 0; +Ptr_gtk_widget_modify_color QGtk::gtk_widget_modify_fg = 0; +Ptr_gtk_widget_modify_color QGtk::gtk_widget_modify_bg = 0; +Ptr_gtk_arrow_new QGtk::gtk_arrow_new = 0; +Ptr_gtk_menu_item_new QGtk::gtk_menu_item_new = 0; +Ptr_gtk_check_menu_item_new QGtk::gtk_check_menu_item_new = 0; +Ptr_gtk_menu_bar_new QGtk::gtk_menu_bar_new = 0; +Ptr_gtk_menu_new QGtk::gtk_menu_new = 0; +Ptr_gtk_button_new QGtk::gtk_button_new = 0; +Ptr_gtk_hbutton_box_new QGtk::gtk_hbutton_box_new = 0; +Ptr_gtk_check_button_new QGtk::gtk_check_button_new = 0; +Ptr_gtk_radio_button_new QGtk::gtk_radio_button_new = 0; +Ptr_gtk_spin_button_new QGtk::gtk_spin_button_new = 0; +Ptr_gtk_frame_new QGtk::gtk_frame_new = 0; +Ptr_gtk_expander_new QGtk::gtk_expander_new = 0; +Ptr_gtk_statusbar_new QGtk::gtk_statusbar_new = 0; +Ptr_gtk_entry_new QGtk::gtk_entry_new = 0; +Ptr_gtk_hscale_new QGtk::gtk_hscale_new = 0; +Ptr_gtk_vscale_new QGtk::gtk_vscale_new = 0; +Ptr_gtk_hscrollbar_new QGtk::gtk_hscrollbar_new = 0; +Ptr_gtk_vscrollbar_new QGtk::gtk_vscrollbar_new = 0; +Ptr_gtk_scrolled_window_new QGtk::gtk_scrolled_window_new = 0; +Ptr_gtk_notebook_new QGtk::gtk_notebook_new = 0; +Ptr_gtk_toolbar_new QGtk::gtk_toolbar_new = 0; +Ptr_gtk_toolbar_insert QGtk::gtk_toolbar_insert = 0; +Ptr_gtk_separator_tool_item_new QGtk::gtk_separator_tool_item_new = 0; +Ptr_gtk_tree_view_new QGtk::gtk_tree_view_new = 0; +Ptr_gtk_combo_box_new QGtk::gtk_combo_box_new = 0; +Ptr_gtk_combo_box_entry_new QGtk::gtk_combo_box_entry_new = 0; +Ptr_gtk_progress_bar_new QGtk::gtk_progress_bar_new = 0; +Ptr_gtk_container_add QGtk::gtk_container_add = 0; +Ptr_gtk_menu_shell_append QGtk::gtk_menu_shell_append = 0; +Ptr_gtk_progress_set_adjustment QGtk::gtk_progress_set_adjustment = 0; +Ptr_gtk_range_set_adjustment QGtk::gtk_range_set_adjustment = 0; +Ptr_gtk_range_set_inverted QGtk::gtk_range_set_inverted = 0; +Ptr_gtk_icon_factory_lookup_default QGtk::gtk_icon_factory_lookup_default = 0; +Ptr_gtk_widget_style_get QGtk::gtk_widget_style_get = 0; +Ptr_gtk_icon_set_render_icon QGtk::gtk_icon_set_render_icon = 0; +Ptr_gtk_fixed_new QGtk::gtk_fixed_new = 0; +Ptr_gtk_tree_view_column_new QGtk::gtk_tree_view_column_new = 0; +Ptr_gtk_tree_view_get_column QGtk::gtk_tree_view_get_column = 0; +Ptr_gtk_tree_view_append_column QGtk::gtk_tree_view_append_column = 0; +Ptr_gtk_paint_check QGtk::gtk_paint_check = 0; +Ptr_gtk_paint_box QGtk::gtk_paint_box = 0; +Ptr_gtk_paint_box_gap QGtk::gtk_paint_box_gap = 0; +Ptr_gtk_paint_flat_box QGtk::gtk_paint_flat_box = 0; +Ptr_gtk_paint_option QGtk::gtk_paint_option = 0; +Ptr_gtk_paint_extension QGtk::gtk_paint_extension = 0; +Ptr_gtk_paint_slider QGtk::gtk_paint_slider = 0; +Ptr_gtk_paint_shadow QGtk::gtk_paint_shadow = 0; +Ptr_gtk_paint_resize_grip QGtk::gtk_paint_resize_grip = 0; +Ptr_gtk_paint_focus QGtk::gtk_paint_focus = 0; +Ptr_gtk_paint_arrow QGtk::gtk_paint_arrow = 0; +Ptr_gtk_paint_handle QGtk::gtk_paint_handle = 0; +Ptr_gtk_paint_expander QGtk::gtk_paint_expander = 0; +Ptr_gtk_adjustment_new QGtk::gtk_adjustment_new = 0; +Ptr_gtk_paint_hline QGtk::gtk_paint_hline = 0; +Ptr_gtk_paint_vline QGtk::gtk_paint_vline = 0; +Ptr_gtk_menu_item_set_submenu QGtk::gtk_menu_item_set_submenu = 0; +Ptr_gtk_settings_get_default QGtk::gtk_settings_get_default = 0; +Ptr_gtk_separator_menu_item_new QGtk::gtk_separator_menu_item_new = 0; +Ptr_gtk_widget_size_allocate QGtk::gtk_widget_size_allocate = 0; +Ptr_gtk_widget_set_direction QGtk::gtk_widget_set_direction = 0; +Ptr_gtk_widget_path QGtk::gtk_widget_path = 0; +Ptr_gtk_container_get_type QGtk::gtk_container_get_type = 0; +Ptr_gtk_window_get_type QGtk::gtk_window_get_type = 0; +Ptr_gtk_widget_get_type QGtk::gtk_widget_get_type = 0; +Ptr_gtk_rc_get_style_by_paths QGtk::gtk_rc_get_style_by_paths = 0; +Ptr_gtk_check_version QGtk::gtk_check_version = 0; + +Ptr_pango_font_description_get_size QGtk::pango_font_description_get_size = 0; +Ptr_pango_font_description_get_weight QGtk::pango_font_description_get_weight = 0; +Ptr_pango_font_description_get_family QGtk::pango_font_description_get_family = 0; +Ptr_pango_font_description_get_style QGtk::pango_font_description_get_style = 0; + +Ptr_gtk_file_filter_new QGtk::gtk_file_filter_new = 0; +Ptr_gtk_file_filter_set_name QGtk::gtk_file_filter_set_name = 0; +Ptr_gtk_file_filter_add_pattern QGtk::gtk_file_filter_add_pattern = 0; +Ptr_gtk_file_chooser_add_filter QGtk::gtk_file_chooser_add_filter = 0; +Ptr_gtk_file_chooser_set_filter QGtk::gtk_file_chooser_set_filter = 0; +Ptr_gtk_file_chooser_dialog_new QGtk::gtk_file_chooser_dialog_new = 0; +Ptr_gtk_file_chooser_set_current_folder QGtk::gtk_file_chooser_set_current_folder = 0; +Ptr_gtk_file_chooser_get_filename QGtk::gtk_file_chooser_get_filename = 0; +Ptr_gtk_file_chooser_get_filenames QGtk::gtk_file_chooser_get_filenames = 0; +Ptr_gtk_file_chooser_set_current_name QGtk::gtk_file_chooser_set_current_name = 0; +Ptr_gtk_dialog_run QGtk::gtk_dialog_run = 0; +Ptr_gtk_file_chooser_set_filename QGtk::gtk_file_chooser_set_filename = 0; + +Ptr_gdk_pixbuf_get_pixels QGtk::gdk_pixbuf_get_pixels = 0; +Ptr_gdk_pixbuf_get_width QGtk::gdk_pixbuf_get_width = 0; +Ptr_gdk_pixbuf_get_height QGtk::gdk_pixbuf_get_height = 0; +Ptr_gdk_pixmap_new QGtk::gdk_pixmap_new = 0; +Ptr_gdk_pixbuf_new QGtk::gdk_pixbuf_new = 0; +Ptr_gdk_pixbuf_get_from_drawable QGtk::gdk_pixbuf_get_from_drawable = 0; +Ptr_gdk_draw_rectangle QGtk::gdk_draw_rectangle = 0; +Ptr_gdk_pixbuf_unref QGtk::gdk_pixbuf_unref = 0; +Ptr_gdk_drawable_unref QGtk::gdk_drawable_unref = 0; +Ptr_gdk_drawable_get_depth QGtk::gdk_drawable_get_depth = 0; +Ptr_gdk_color_free QGtk::gdk_color_free = 0; +Ptr_gdk_x11_window_set_user_time QGtk::gdk_x11_window_set_user_time = 0; +Ptr_gdk_x11_drawable_get_xid QGtk::gdk_x11_drawable_get_xid = 0; +Ptr_gdk_x11_drawable_get_xdisplay QGtk::gdk_x11_drawable_get_xdisplay = 0; + +Ptr_gconf_client_get_default QGtk::gconf_client_get_default = 0; +Ptr_gconf_client_get_string QGtk::gconf_client_get_string = 0; + +static QString classPath(GtkWidget *widget) +{ + char* class_path; + QGtk::gtk_widget_path (widget, NULL, &class_path, NULL); + QString path = QLS(class_path); + g_free(class_path); + + // Remove the prefixes + path.remove(QLS("GtkWindow.")); + path.remove(QLS("GtkFixed.")); + return path; +} + +static void resolveGtk() +{ + const QString GTK_PATH(QLS("gtk-x11-2.0")); + QGtk::gtk_init = (Ptr_gtk_init)QLibrary::resolve(GTK_PATH, 0, "gtk_init"); + QGtk::gtk_window_new = (Ptr_gtk_window_new)QLibrary::resolve(GTK_PATH, 0, "gtk_window_new"); + QGtk::gtk_style_attach = (Ptr_gtk_style_attach)QLibrary::resolve(GTK_PATH, 0, "gtk_style_attach"); + QGtk::gtk_widget_destroy = (Ptr_gtk_widget_destroy)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_destroy"); + QGtk::gtk_widget_realize = (Ptr_gtk_widget_realize)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_realize"); + + QGtk::gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_current_folder"); + QGtk::gtk_file_filter_new = (Ptr_gtk_file_filter_new)QLibrary::resolve(GTK_PATH, 0, "gtk_file_filter_new"); + QGtk::gtk_file_filter_set_name = (Ptr_gtk_file_filter_set_name)QLibrary::resolve(GTK_PATH, 0, "gtk_file_filter_set_name"); + QGtk::gtk_file_filter_add_pattern = (Ptr_gtk_file_filter_add_pattern)QLibrary::resolve(GTK_PATH, 0, "gtk_file_filter_add_pattern"); + QGtk::gtk_file_chooser_add_filter = (Ptr_gtk_file_chooser_add_filter)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_add_filter"); + QGtk::gtk_file_chooser_set_filter = (Ptr_gtk_file_chooser_set_filter)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_filter"); + QGtk::gtk_file_chooser_dialog_new = (Ptr_gtk_file_chooser_dialog_new)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_dialog_new"); + QGtk::gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_current_folder"); + QGtk::gtk_file_chooser_get_filename = (Ptr_gtk_file_chooser_get_filename)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_get_filename"); + QGtk::gtk_file_chooser_get_filenames = (Ptr_gtk_file_chooser_get_filenames)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_get_filenames"); + QGtk::gtk_file_chooser_set_current_name = (Ptr_gtk_file_chooser_set_current_name)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_current_name"); + QGtk::gtk_dialog_run = (Ptr_gtk_dialog_run)QLibrary::resolve(GTK_PATH, 0, "gtk_dialog_run"); + QGtk::gtk_file_chooser_set_filename = (Ptr_gtk_file_chooser_set_filename)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_filename"); + + QGtk::gdk_pixbuf_get_pixels = (Ptr_gdk_pixbuf_get_pixels)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_get_pixels"); + QGtk::gdk_pixbuf_get_width = (Ptr_gdk_pixbuf_get_width)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_get_width"); + QGtk::gdk_pixbuf_get_height = (Ptr_gdk_pixbuf_get_height)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_get_height"); + QGtk::gdk_pixmap_new = (Ptr_gdk_pixmap_new)QLibrary::resolve(GTK_PATH, 0, "gdk_pixmap_new"); + QGtk::gdk_pixbuf_new = (Ptr_gdk_pixbuf_new)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_new"); + QGtk::gdk_pixbuf_get_from_drawable = (Ptr_gdk_pixbuf_get_from_drawable)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_get_from_drawable"); + QGtk::gdk_draw_rectangle = (Ptr_gdk_draw_rectangle)QLibrary::resolve(GTK_PATH, 0, "gdk_draw_rectangle"); + QGtk::gdk_pixbuf_unref = (Ptr_gdk_pixbuf_unref)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_unref"); + QGtk::gdk_drawable_unref = (Ptr_gdk_drawable_unref)QLibrary::resolve(GTK_PATH, 0, "gdk_drawable_unref"); + QGtk::gdk_drawable_get_depth = (Ptr_gdk_drawable_get_depth)QLibrary::resolve(GTK_PATH, 0, "gdk_drawable_get_depth"); + QGtk::gdk_color_free = (Ptr_gdk_color_free)QLibrary::resolve(GTK_PATH, 0, "gdk_color_free"); + QGtk::gdk_x11_window_set_user_time = (Ptr_gdk_x11_window_set_user_time)QLibrary::resolve(GTK_PATH, 0, "gdk_x11_window_set_user_time"); + QGtk::gdk_x11_drawable_get_xid = (Ptr_gdk_x11_drawable_get_xid)QLibrary::resolve(GTK_PATH, 0, "gdk_x11_drawable_get_xid"); + QGtk::gdk_x11_drawable_get_xdisplay = (Ptr_gdk_x11_drawable_get_xdisplay)QLibrary::resolve(GTK_PATH, 0, "gdk_x11_drawable_get_xdisplay"); + + QGtk::gtk_widget_set_default_direction = (Ptr_gtk_widget_set_default_direction)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_set_default_direction"); + QGtk::gtk_widget_modify_fg = (Ptr_gtk_widget_modify_color)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_modify_fg"); + QGtk::gtk_widget_modify_bg = (Ptr_gtk_widget_modify_color)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_modify_bg"); + QGtk::gtk_arrow_new = (Ptr_gtk_arrow_new)QLibrary::resolve(GTK_PATH, 0, "gtk_arrow_new"); + QGtk::gtk_menu_item_new = (Ptr_gtk_menu_item_new)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_item_new"); + QGtk::gtk_check_menu_item_new = (Ptr_gtk_check_menu_item_new)QLibrary::resolve(GTK_PATH, 0, "gtk_check_menu_item_new"); + QGtk::gtk_menu_bar_new = (Ptr_gtk_menu_bar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_bar_new"); + QGtk::gtk_menu_new = (Ptr_gtk_menu_new)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_new"); + QGtk::gtk_toolbar_new = (Ptr_gtk_toolbar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_toolbar_new"); + QGtk::gtk_separator_tool_item_new = (Ptr_gtk_separator_tool_item_new)QLibrary::resolve(GTK_PATH, 0, "gtk_separator_tool_item_new"); + QGtk::gtk_toolbar_insert = (Ptr_gtk_toolbar_insert)QLibrary::resolve(GTK_PATH, 0, "gtk_toolbar_insert"); + QGtk::gtk_button_new = (Ptr_gtk_button_new)QLibrary::resolve(GTK_PATH, 0, "gtk_button_new"); + QGtk::gtk_hbutton_box_new = (Ptr_gtk_hbutton_box_new)QLibrary::resolve(GTK_PATH, 0, "gtk_hbutton_box_new"); + QGtk::gtk_check_button_new = (Ptr_gtk_check_button_new)QLibrary::resolve(GTK_PATH, 0, "gtk_check_button_new"); + QGtk::gtk_radio_button_new = (Ptr_gtk_radio_button_new)QLibrary::resolve(GTK_PATH, 0, "gtk_radio_button_new"); + QGtk::gtk_notebook_new = (Ptr_gtk_notebook_new)QLibrary::resolve(GTK_PATH, 0, "gtk_notebook_new"); + QGtk::gtk_progress_bar_new = (Ptr_gtk_progress_bar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_progress_bar_new"); + QGtk::gtk_spin_button_new = (Ptr_gtk_spin_button_new)QLibrary::resolve(GTK_PATH, 0, "gtk_spin_button_new"); + QGtk::gtk_hscale_new = (Ptr_gtk_hscale_new)QLibrary::resolve(GTK_PATH, 0, "gtk_hscale_new"); + QGtk::gtk_vscale_new = (Ptr_gtk_vscale_new)QLibrary::resolve(GTK_PATH, 0, "gtk_vscale_new"); + QGtk::gtk_hscrollbar_new = (Ptr_gtk_hscrollbar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_hscrollbar_new"); + QGtk::gtk_vscrollbar_new = (Ptr_gtk_vscrollbar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_vscrollbar_new"); + QGtk::gtk_scrolled_window_new = (Ptr_gtk_scrolled_window_new)QLibrary::resolve(GTK_PATH, 0, "gtk_scrolled_window_new"); + QGtk::gtk_menu_shell_append = (Ptr_gtk_menu_shell_append)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_shell_append"); + QGtk::gtk_entry_new = (Ptr_gtk_entry_new)QLibrary::resolve(GTK_PATH, 0, "gtk_entry_new"); + QGtk::gtk_tree_view_new = (Ptr_gtk_tree_view_new)QLibrary::resolve(GTK_PATH, 0, "gtk_tree_view_new"); + QGtk::gtk_combo_box_new = (Ptr_gtk_combo_box_new)QLibrary::resolve(GTK_PATH, 0, "gtk_combo_box_new"); + QGtk::gtk_progress_set_adjustment = (Ptr_gtk_progress_set_adjustment)QLibrary::resolve(GTK_PATH, 0, "gtk_progress_set_adjustment"); + QGtk::gtk_range_set_adjustment = (Ptr_gtk_range_set_adjustment)QLibrary::resolve(GTK_PATH, 0, "gtk_range_set_adjustment"); + QGtk::gtk_range_set_inverted = (Ptr_gtk_range_set_inverted)QLibrary::resolve(GTK_PATH, 0, "gtk_range_set_inverted"); + QGtk::gtk_container_add = (Ptr_gtk_container_add)QLibrary::resolve(GTK_PATH, 0, "gtk_container_add"); + QGtk::gtk_icon_factory_lookup_default = (Ptr_gtk_icon_factory_lookup_default)QLibrary::resolve(GTK_PATH, 0, "gtk_icon_factory_lookup_default"); + QGtk::gtk_widget_style_get = (Ptr_gtk_widget_style_get)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_style_get"); + QGtk::gtk_icon_set_render_icon = (Ptr_gtk_icon_set_render_icon)QLibrary::resolve(GTK_PATH, 0, "gtk_icon_set_render_icon"); + QGtk::gtk_fixed_new = (Ptr_gtk_fixed_new)QLibrary::resolve(GTK_PATH, 0, "gtk_fixed_new"); + QGtk::gtk_tree_view_column_new = (Ptr_gtk_tree_view_column_new)QLibrary::resolve(GTK_PATH, 0, "gtk_tree_view_column_new"); + QGtk::gtk_tree_view_append_column= (Ptr_gtk_tree_view_append_column )QLibrary::resolve(GTK_PATH, 0, "gtk_tree_view_append_column"); + QGtk::gtk_tree_view_get_column = (Ptr_gtk_tree_view_get_column )QLibrary::resolve(GTK_PATH, 0, "gtk_tree_view_get_column"); + QGtk::gtk_paint_check = (Ptr_gtk_paint_check)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_check"); + QGtk::gtk_paint_box = (Ptr_gtk_paint_box)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_box"); + QGtk::gtk_paint_flat_box = (Ptr_gtk_paint_flat_box)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_flat_box"); + QGtk::gtk_paint_check = (Ptr_gtk_paint_check)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_check"); + QGtk::gtk_paint_box = (Ptr_gtk_paint_box)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_box"); + QGtk::gtk_paint_resize_grip = (Ptr_gtk_paint_resize_grip)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_resize_grip"); + QGtk::gtk_paint_focus = (Ptr_gtk_paint_focus)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_focus"); + QGtk::gtk_paint_shadow = (Ptr_gtk_paint_shadow)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_shadow"); + QGtk::gtk_paint_slider = (Ptr_gtk_paint_slider)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_slider"); + QGtk::gtk_paint_expander = (Ptr_gtk_paint_expander)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_expander"); + QGtk::gtk_paint_handle = (Ptr_gtk_paint_handle)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_handle"); + QGtk::gtk_paint_option = (Ptr_gtk_paint_option)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_option"); + QGtk::gtk_paint_arrow = (Ptr_gtk_paint_arrow)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_arrow"); + QGtk::gtk_paint_box_gap = (Ptr_gtk_paint_box_gap)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_box_gap"); + QGtk::gtk_paint_extension = (Ptr_gtk_paint_extension)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_extension"); + QGtk::gtk_paint_hline = (Ptr_gtk_paint_hline)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_hline"); + QGtk::gtk_paint_vline = (Ptr_gtk_paint_vline)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_vline"); + QGtk::gtk_adjustment_new = (Ptr_gtk_adjustment_new)QLibrary::resolve(GTK_PATH, 0, "gtk_adjustment_new"); + QGtk::gtk_menu_item_set_submenu = (Ptr_gtk_menu_item_set_submenu)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_item_set_submenu"); + QGtk::gtk_settings_get_default = (Ptr_gtk_settings_get_default)QLibrary::resolve(GTK_PATH, 0, "gtk_settings_get_default"); + QGtk::gtk_separator_menu_item_new = (Ptr_gtk_separator_menu_item_new)QLibrary::resolve(GTK_PATH, 0, "gtk_separator_menu_item_new"); + QGtk::gtk_frame_new = (Ptr_gtk_frame_new)QLibrary::resolve(GTK_PATH, 0, "gtk_frame_new"); + QGtk::gtk_expander_new = (Ptr_gtk_expander_new)QLibrary::resolve(GTK_PATH, 0, "gtk_expander_new"); + QGtk::gtk_statusbar_new = (Ptr_gtk_statusbar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_statusbar_new"); + QGtk::gtk_combo_box_entry_new = (Ptr_gtk_combo_box_entry_new)QLibrary::resolve(GTK_PATH, 0, "gtk_combo_box_entry_new"); + QGtk::gtk_container_forall = (Ptr_gtk_container_forall)QLibrary::resolve(GTK_PATH, 0, "gtk_container_forall"); + QGtk::gtk_widget_size_allocate =(Ptr_gtk_widget_size_allocate)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_size_allocate"); + QGtk::gtk_widget_set_direction =(Ptr_gtk_widget_set_direction)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_set_direction"); + QGtk::gtk_widget_path =(Ptr_gtk_widget_path)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_path"); + QGtk::gtk_container_get_type =(Ptr_gtk_container_get_type)QLibrary::resolve(GTK_PATH, 0, "gtk_container_get_type"); + QGtk::gtk_window_get_type =(Ptr_gtk_window_get_type)QLibrary::resolve(GTK_PATH, 0, "gtk_window_get_type"); + QGtk::gtk_widget_get_type =(Ptr_gtk_widget_get_type)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_get_type"); + QGtk::gtk_rc_get_style_by_paths =(Ptr_gtk_rc_get_style_by_paths)QLibrary::resolve(GTK_PATH, 0, "gtk_rc_get_style_by_paths"); + QGtk::gtk_check_version =(Ptr_gtk_check_version)QLibrary::resolve(GTK_PATH, 0, "gtk_check_version"); + QGtk::pango_font_description_get_size = (Ptr_pango_font_description_get_size)QLibrary::resolve(GTK_PATH, 0, "pango_font_description_get_size"); + QGtk::pango_font_description_get_weight = (Ptr_pango_font_description_get_weight)QLibrary::resolve(GTK_PATH, 0, "pango_font_description_get_weight"); + QGtk::pango_font_description_get_family = (Ptr_pango_font_description_get_family)QLibrary::resolve(GTK_PATH, 0, "pango_font_description_get_family"); + QGtk::pango_font_description_get_style = (Ptr_pango_font_description_get_style)QLibrary::resolve(GTK_PATH, 0, "pango_font_description_get_style"); +} + +void QGtk::cleanup_gtk_widgets() +{ + if (gtkWidgetMap()->contains(QLS("GtkWindow"))) // Gtk will destroy all children + QGtk::gtk_widget_destroy(gtkWidgetMap()->value(QLS("GtkWindow"))); +} + +static bool resolveGConf() +{ + if (!QGtk::gconf_client_get_default) { + QGtk::gconf_client_get_default = (Ptr_gconf_client_get_default)QLibrary::resolve(QLS("gconf-2"), 4, "gconf_client_get_default"); + QGtk::gconf_client_get_string = (Ptr_gconf_client_get_string)QLibrary::resolve(QLS("gconf-2"), 4, "gconf_client_get_string"); + } + return (QGtk::gconf_client_get_default !=0); +} + +typedef int (*x11ErrorHandler)(Display*, XErrorEvent*); + +static QString getGConfString(const QString &value) +{ + QString retVal; + if (resolveGConf()) { + g_type_init(); + GConfClient* client = QGtk::gconf_client_get_default(); + GError *err = 0; + char *str = QGtk::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; +} + +static QString 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(QLS("=")) - 1); + line.remove(QLS("\"")); + 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; +} + +static void init_gtk_window() +{ + static QString themeName; + if (!gtkWidgetMap()->contains(QLS("GtkWindow")) && themeName.isEmpty()) { + themeName = getThemeName(); + // Due to namespace conflicts with Qt3 and obvious recursion with Qt4, + // we cannot support the GTK_Qt Gtk engine + if (!(themeName.isEmpty() || themeName == QLS("Qt") || themeName == QLS("Qt4"))) { + resolveGtk(); + if (QGtk::gtk_init) { + // Gtk will set the Qt error handler so we have to reset it afterwards + x11ErrorHandler qt_x_errhandler = XSetErrorHandler(0); + QGtk::gtk_init (NULL, NULL); + XSetErrorHandler(qt_x_errhandler); + + GtkWidget* gtkWindow = QGtk::gtk_window_new(GTK_WINDOW_POPUP); + QGtk::gtk_widget_realize(gtkWindow); + if (displayDepth == -1) + displayDepth = QGtk::gdk_drawable_get_depth(gtkWindow->window); + gtkWidgetMap()->insert(QLS("GtkWindow"), gtkWindow); + } + else { + qWarning("QGtkStyle could not resolve GTK. Make sure you have installed the proper libraries."); + } + } else { + qWarning("QGtkStyle cannot be used together with the GTK_Qt engine."); + } + } +} + +static void setup_gtk_widget(GtkWidget* widget) +{ + if (Q_GTK_IS_WIDGET(widget)) { + static GtkWidget* protoLayout = 0; + if (!protoLayout) { + protoLayout = QGtk::gtk_fixed_new(); + QGtk::gtk_container_add((GtkContainer*)(gtkWidgetMap()->value(QLS("GtkWindow"))), protoLayout); + } + Q_ASSERT(protoLayout); + + QGtk::gtk_container_add((GtkContainer*)(protoLayout), widget); + QGtk::gtk_widget_realize(widget); + } +} + +static void add_widget_to_map(GtkWidget *widget) +{ + if (Q_GTK_IS_WIDGET(widget)) { + QGtk::gtk_widget_realize(widget); + gtkWidgetMap()->insert(classPath(widget), widget); + } + } + +static void add_all_sub_widgets(GtkWidget *widget, gpointer v = 0) +{ + Q_UNUSED(v); + add_widget_to_map(widget); + if (GTK_CHECK_TYPE ((widget), Q_GTK_TYPE_CONTAINER)) + QGtk::gtk_container_forall((GtkContainer*)widget, add_all_sub_widgets, NULL); +} + +static void init_gtk_menu() +{ + // Create menubar + GtkWidget *gtkMenuBar = QGtk::gtk_menu_bar_new(); + setup_gtk_widget(gtkMenuBar); + + GtkWidget *gtkMenuBarItem = QGtk::gtk_menu_item_new(); + QGtk::gtk_menu_shell_append((GtkMenuShell*)(gtkMenuBar), gtkMenuBarItem); + QGtk::gtk_widget_realize(gtkMenuBarItem); + + // Create menu + GtkWidget *gtkMenu = QGtk::gtk_menu_new(); + QGtk::gtk_menu_item_set_submenu((GtkMenuItem*)(gtkMenuBarItem), gtkMenu); + QGtk::gtk_widget_realize(gtkMenu); + + GtkWidget *gtkMenuItem = QGtk::gtk_menu_item_new(); + QGtk::gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkMenuItem); + QGtk::gtk_widget_realize(gtkMenuItem); + + GtkWidget *gtkCheckMenuItem = QGtk::gtk_check_menu_item_new(); + QGtk::gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkCheckMenuItem); + QGtk::gtk_widget_realize(gtkCheckMenuItem); + + GtkWidget *gtkMenuSeparator = QGtk::gtk_separator_menu_item_new(); + QGtk::gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkMenuSeparator); + + add_all_sub_widgets(gtkMenuBar); + add_all_sub_widgets(gtkMenu); +} + +// Updates window/windowtext palette based on the indicated gtk widget +static void ensureWidgetPalette(QWidget* widget, const QString >kWidgetName) +{ + GtkWidget *gtkWidget = QGtk::gtkWidget(gtkWidgetName); + Q_ASSERT(gtkWidget); + QPalette pal = widget->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); + widget->setPalette(pal); + widget->setAttribute(Qt::WA_SetPalette, false); +} + +bool QGtk::isKDE4Session() +{ + static int version = -1; + if (version == -1) + version = qgetenv("KDE_SESSION_VERSION").toInt(); + return (version == 4); +} + +// Maps a Gtk widget palettes to a Qt widget +void QGtk::applyGtkSystemPalette(QWidget *widget) +{ + // Do not apply if the widget has a custom palette; + if (widget->testAttribute(Qt::WA_SetPalette)) + return; + + QPalette pal; + if (QStatusBar *statusbar = qobject_cast<QStatusBar*> (widget)) + ensureWidgetPalette(statusbar, QLS("GtkStatusbar")); + else if (QMenuBar *menubar = qobject_cast<QMenuBar*> (widget)) + ensureWidgetPalette(menubar, QLS("GtkMenuBar")); + else if (QToolBar *toolbar = qobject_cast<QToolBar*> (widget)) + ensureWidgetPalette(toolbar, QLS("GtkToolbar")); + else if (QMenu *menubar = qobject_cast<QMenu*> (widget)) { + // This really applies to the combo box rendering since + // QComboBox copies the palette from a QMenu + QPalette pal = widget->palette(); + GdkColor gdkBg = QGtk::gtkWidget(QLS("GtkMenu"))->style->bg[GTK_STATE_NORMAL]; + QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); + pal.setBrush(QPalette::Base, bgColor); + menubar->setPalette(pal); + } + widget->setAttribute(Qt::WA_SetPalette, false); +} + +static void gtkStyleSetCallback(GtkWidget*, GtkStyle*, void*) +{ + static QString oldTheme(QLS("qt_not_set")); + QPixmapCache::clear(); + qApp->setFont(QGtk::getThemeFont()); + QGtk::initGtkWidgets(); + if (oldTheme != getThemeName()) { + oldTheme = getThemeName(); + QApplicationPrivate::setSystemPalette(qApp->style()->standardPalette()); + QList<QWidget*> widgets = QApplication::allWidgets(); + foreach (QWidget *widget, widgets) { + QGtk::applyGtkSystemPalette(widget); + } + } +} + +static void add_widget(GtkWidget *widget) +{ + if (widget) { + setup_gtk_widget(widget); + add_all_sub_widgets(widget); + } +} + +static void init_gtk_treeview() +{ + GtkWidget *gtkTreeView = QGtk::gtk_tree_view_new(); + QGtk::gtk_tree_view_append_column((GtkTreeView*)gtkTreeView, QGtk::gtk_tree_view_column_new()); + QGtk::gtk_tree_view_append_column((GtkTreeView*)gtkTreeView, QGtk::gtk_tree_view_column_new()); + QGtk::gtk_tree_view_append_column((GtkTreeView*)gtkTreeView, QGtk::gtk_tree_view_column_new()); + add_widget(gtkTreeView); +} + + +// Fetch the application font from the pango font description +// contained in the theme. +QFont QGtk::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; +} + +GtkWidget* QGtk::gtkWidget(const QString &path) +{ + GtkWidget *widget = gtkWidgetMap()->value(path); + if (!widget) { + // Theme might have rearranged widget internals + widget = gtkWidgetMap()->value(path); + } + return widget; +} + +GtkStyle* QGtk::gtkStyle(const QString &path) +{ + if (gtkWidgetMap()->contains(path)) + return gtkWidgetMap()->value(path)->style; + return 0; +} + +#ifdef Q_OS_LINUX +QT_END_NAMESPACE + +int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); +int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); + +QT_BEGIN_NAMESPACE +#endif + +void QGtk::initGtkWidgets() +{ + // From gtkmain.c + + uid_t ruid, rgid, euid, egid, suid, sgid; + +#ifdef Q_OS_LINUX + if (getresuid (&ruid, &euid, &suid) != 0 || getresgid (&rgid, &egid, &sgid) != 0) +#endif + { + suid = ruid = getuid (); + sgid = rgid = getgid (); + euid = geteuid (); + egid = getegid (); + } + if (ruid != euid || ruid != suid || rgid != egid || rgid != sgid) { + 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; + } + + init_gtk_window(); + + if (QGtk::gtk_init) { + + // Make all widgets respect the text direction + if (qApp->layoutDirection() == Qt::RightToLeft) + QGtk::gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL); + + if (!gtkWidgetMap()->contains(QLS("GtkButton"))) { + GtkWidget *gtkButton = QGtk::gtk_button_new(); + add_widget(gtkButton); + g_signal_connect(gtkButton, "style-set", G_CALLBACK(gtkStyleSetCallback), NULL); + add_widget(QGtk::gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE)); + add_widget(QGtk::gtk_hbutton_box_new()); + add_widget(QGtk::gtk_check_button_new()); + add_widget(QGtk::gtk_radio_button_new(NULL)); + add_widget(QGtk::gtk_combo_box_new()); + add_widget(QGtk::gtk_combo_box_entry_new()); + add_widget(QGtk::gtk_entry_new()); + add_widget(QGtk::gtk_frame_new(NULL)); + add_widget(QGtk::gtk_expander_new("")); + add_widget(QGtk::gtk_statusbar_new()); + add_widget(QGtk::gtk_hscale_new((GtkAdjustment*)(QGtk::gtk_adjustment_new(1, 0, 1, 0, 0, 0)))); + add_widget(QGtk::gtk_hscrollbar_new(NULL)); + add_widget(QGtk::gtk_scrolled_window_new(NULL, NULL)); + init_gtk_menu(); + add_widget(QGtk::gtk_notebook_new()); + add_widget(QGtk::gtk_progress_bar_new()); + add_widget(QGtk::gtk_spin_button_new((GtkAdjustment*) + (QGtk::gtk_adjustment_new(1, 0, 1, 0, 0, 0)), 0.1, 3)); + GtkWidget *toolbar = QGtk::gtk_toolbar_new(); + QGtk::gtk_toolbar_insert((GtkToolbar*)toolbar, QGtk::gtk_separator_tool_item_new(), -1); + add_widget(toolbar); + init_gtk_treeview(); + add_widget(QGtk::gtk_vscale_new((GtkAdjustment*)(QGtk::gtk_adjustment_new(1, 0, 1, 0, 0, 0)))); + add_widget(QGtk::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<QString, GtkWidget*> oldMap = *gtkWidgetMap(); + gtkWidgetMap()->clear(); + QHashIterator<QString, GtkWidget*> it(oldMap); + while (it.hasNext()) { + it.next(); + if (!it.key().contains(QLS("."))) { + add_all_sub_widgets(it.value()); + } + } + } + } +} + +// ----------- Native file dialogs ----------- + +// Extract filter list from expressions of type: foo (*.a *.b *.c)" +static QStringList 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); + +static void setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, + const QString &dir, const QString &filter, QString *selectedFilter, + QFileDialog::Options options, bool isSaveDialog = false) +{ + 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 = QGtk::gtk_file_filter_new (); + QString name = rawfilter.left(rawfilter.indexOf(QLatin1Char('('))); + QGtk::gtk_file_filter_set_name(gtkFilter, qPrintable(name)); + + QStringList extensions = extract_filter(rawfilter); + foreach (const QString &fileExtension, extensions) { + QGtk::gtk_file_filter_add_pattern (gtkFilter, qPrintable(fileExtension)); + } + QGtk::gtk_file_chooser_add_filter((GtkFileChooser*)gtkFileChooser, gtkFilter); + if (selectedFilter && (rawfilter == *selectedFilter)) + QGtk::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) { + QGtk::gtk_widget_realize(gtkFileChooser); // Creates X window + XSetTransientForHint(QGtk::gdk_x11_drawable_get_xdisplay(gtkFileChooser->window), + QGtk::gdk_x11_drawable_get_xid(gtkFileChooser->window), + modalFor->winId()); + QGtk::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()) { + QGtk::gtk_file_chooser_set_current_folder((GtkFileChooser*)gtkFileChooser, qPrintable(dir)); + } else if (isSaveDialog) { + QGtk::gtk_file_chooser_set_current_folder((GtkFileChooser*)gtkFileChooser, qPrintable(fileinfo.absolutePath())); + QGtk::gtk_file_chooser_set_current_name((GtkFileChooser*)gtkFileChooser, qPrintable(fileinfo.fileName())); + } else { + QGtk::gtk_file_chooser_set_filename((GtkFileChooser*)gtkFileChooser, qPrintable(dir)); + } +} + +QString QGtk::openFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options) +{ + + GtkWidget *gtkFileChooser = QGtk::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); + + QWidget modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + QString filename; + if (QGtk::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { + char *gtk_filename = QGtk::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; +} + + +QString QGtk::openDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options) +{ + GtkWidget *gtkFileChooser = QGtk::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 (QGtk::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { + char *gtk_filename = QGtk::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 QGtk::openFilenames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options) +{ + QStringList filenames; + GtkWidget *gtkFileChooser = QGtk::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); + 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 = QGtk::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); + } + + QApplicationPrivate::leaveModal(&modal_widget); + gtk_widget_destroy (gtkFileChooser); + return filenames; +} + +QString QGtk::saveFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options) +{ + GtkWidget *gtkFileChooser = QGtk::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); + + QWidget modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + QString filename; + if (QGtk::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { + char *gtk_filename = QGtk::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; +} + +QT_END_NAMESPACE + +#endif // !defined(QT_NO_STYLE_GTK) diff --git a/src/gui/styles/gtksymbols_p.h b/src/gui/styles/gtksymbols_p.h new file mode 100644 index 0000000000..0cea5428dd --- /dev/null +++ b/src/gui/styles/gtksymbols_p.h @@ -0,0 +1,335 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GTKSYMBOLS_H +#define GTKSYMBOLS_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 <QtCore/qglobal.h> +#if !defined(QT_NO_STYLE_GTK) + +#undef signals // Collides with GTK stymbols +#include <gtk/gtk.h> +#include <QtCore/QLibrary> +#include <QtGui/QFont> +#include <QtGui/QFileDialog> +typedef unsigned long XID; + +#undef GTK_OBJECT_FLAGS +#define GTK_OBJECT_FLAGS(obj)(((GtkObject*)(obj))->flags) +#define Q_GTK_TYPE_WIDGET QGtk::gtk_widget_get_type() +#define Q_GTK_IS_WIDGET(widget) widget && GTK_CHECK_TYPE ((widget), Q_GTK_TYPE_WIDGET) +#define Q_GTK_TYPE_WINDOW QGtk::gtk_window_get_type() +#define Q_GTK_TYPE_CONTAINER QGtk::gtk_container_get_type() + +#define QLS(x) QLatin1String(x) + +class GConf; +class GConfClient; + +typedef GConfClient* (*Ptr_gconf_client_get_default)(); +typedef char* (*Ptr_gconf_client_get_string)(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)(void); +typedef GtkWidget* (*Ptr_gtk_separator_menu_item_new)(void); +typedef GtkWidget* (*Ptr_gtk_check_menu_item_new)(void); +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_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 void (*Ptr_gtk_range_set_adjustment)(GtkRange *, GtkAdjustment *); +typedef void (*Ptr_gtk_progress_set_adjustment)(GtkProgress *, GtkAdjustment *); +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 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 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_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 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 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 + +class QGtk +{ +public: + static GtkWidget* gtkWidget(const QString &path); + static GtkStyle* gtkStyle(const QString &path = QLatin1String("GtkWindow")); + + static void cleanup_gtk_widgets(); + static void initGtkWidgets(); + static bool isKDE4Session(); + static void applyGtkSystemPalette(QWidget* widget); + static QFont getThemeFont(); + static bool isThemeAvailable() { return gtkStyle() != 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 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 gtk_menu_item_new; + static Ptr_gtk_arrow_new gtk_arrow_new; + static Ptr_gtk_check_menu_item_new gtk_check_menu_item_new; + 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_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_set_adjustment gtk_progress_set_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_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_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_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_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_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; +}; + +QT_END_NAMESPACE + +#endif // !QT_NO_STYLE_GTK +#endif // GTKSYMBOLS_H diff --git a/src/gui/styles/images/cdr-128.png b/src/gui/styles/images/cdr-128.png Binary files differnew file mode 100644 index 0000000000..c5daa15fc8 --- /dev/null +++ b/src/gui/styles/images/cdr-128.png diff --git a/src/gui/styles/images/cdr-16.png b/src/gui/styles/images/cdr-16.png Binary files differnew file mode 100644 index 0000000000..82d7533bd1 --- /dev/null +++ b/src/gui/styles/images/cdr-16.png diff --git a/src/gui/styles/images/cdr-32.png b/src/gui/styles/images/cdr-32.png Binary files differnew file mode 100644 index 0000000000..dcfb085da5 --- /dev/null +++ b/src/gui/styles/images/cdr-32.png diff --git a/src/gui/styles/images/closedock-16.png b/src/gui/styles/images/closedock-16.png Binary files differnew file mode 100644 index 0000000000..ab9d669eee --- /dev/null +++ b/src/gui/styles/images/closedock-16.png diff --git a/src/gui/styles/images/closedock-down-16.png b/src/gui/styles/images/closedock-down-16.png Binary files differnew file mode 100644 index 0000000000..c1791dd2cc --- /dev/null +++ b/src/gui/styles/images/closedock-down-16.png diff --git a/src/gui/styles/images/computer-16.png b/src/gui/styles/images/computer-16.png Binary files differnew file mode 100644 index 0000000000..43fb0bb581 --- /dev/null +++ b/src/gui/styles/images/computer-16.png diff --git a/src/gui/styles/images/computer-32.png b/src/gui/styles/images/computer-32.png Binary files differnew file mode 100644 index 0000000000..6d750ce89b --- /dev/null +++ b/src/gui/styles/images/computer-32.png diff --git a/src/gui/styles/images/desktop-16.png b/src/gui/styles/images/desktop-16.png Binary files differnew file mode 100644 index 0000000000..d612dfb0fc --- /dev/null +++ b/src/gui/styles/images/desktop-16.png diff --git a/src/gui/styles/images/desktop-32.png b/src/gui/styles/images/desktop-32.png Binary files differnew file mode 100644 index 0000000000..ad85b48d3a --- /dev/null +++ b/src/gui/styles/images/desktop-32.png diff --git a/src/gui/styles/images/dirclosed-128.png b/src/gui/styles/images/dirclosed-128.png Binary files differnew file mode 100644 index 0000000000..e4fa843162 --- /dev/null +++ b/src/gui/styles/images/dirclosed-128.png diff --git a/src/gui/styles/images/dirclosed-16.png b/src/gui/styles/images/dirclosed-16.png Binary files differnew file mode 100644 index 0000000000..333fe8eaac --- /dev/null +++ b/src/gui/styles/images/dirclosed-16.png diff --git a/src/gui/styles/images/dirclosed-32.png b/src/gui/styles/images/dirclosed-32.png Binary files differnew file mode 100644 index 0000000000..3add907ed5 --- /dev/null +++ b/src/gui/styles/images/dirclosed-32.png diff --git a/src/gui/styles/images/dirlink-128.png b/src/gui/styles/images/dirlink-128.png Binary files differnew file mode 100644 index 0000000000..ec299f8e52 --- /dev/null +++ b/src/gui/styles/images/dirlink-128.png diff --git a/src/gui/styles/images/dirlink-16.png b/src/gui/styles/images/dirlink-16.png Binary files differnew file mode 100644 index 0000000000..9f16cd3520 --- /dev/null +++ b/src/gui/styles/images/dirlink-16.png diff --git a/src/gui/styles/images/dirlink-32.png b/src/gui/styles/images/dirlink-32.png Binary files differnew file mode 100644 index 0000000000..776536d131 --- /dev/null +++ b/src/gui/styles/images/dirlink-32.png diff --git a/src/gui/styles/images/diropen-128.png b/src/gui/styles/images/diropen-128.png Binary files differnew file mode 100644 index 0000000000..b91c4af72a --- /dev/null +++ b/src/gui/styles/images/diropen-128.png diff --git a/src/gui/styles/images/diropen-16.png b/src/gui/styles/images/diropen-16.png Binary files differnew file mode 100644 index 0000000000..95f0771d06 --- /dev/null +++ b/src/gui/styles/images/diropen-16.png diff --git a/src/gui/styles/images/diropen-32.png b/src/gui/styles/images/diropen-32.png Binary files differnew file mode 100644 index 0000000000..af5f7e7e81 --- /dev/null +++ b/src/gui/styles/images/diropen-32.png diff --git a/src/gui/styles/images/dockdock-16.png b/src/gui/styles/images/dockdock-16.png Binary files differnew file mode 100644 index 0000000000..4ac9483176 --- /dev/null +++ b/src/gui/styles/images/dockdock-16.png diff --git a/src/gui/styles/images/dockdock-down-16.png b/src/gui/styles/images/dockdock-down-16.png Binary files differnew file mode 100644 index 0000000000..2e85a679be --- /dev/null +++ b/src/gui/styles/images/dockdock-down-16.png diff --git a/src/gui/styles/images/down-128.png b/src/gui/styles/images/down-128.png Binary files differnew file mode 100644 index 0000000000..09dfe43a93 --- /dev/null +++ b/src/gui/styles/images/down-128.png diff --git a/src/gui/styles/images/down-16.png b/src/gui/styles/images/down-16.png Binary files differnew file mode 100644 index 0000000000..c60a174e25 --- /dev/null +++ b/src/gui/styles/images/down-16.png diff --git a/src/gui/styles/images/down-32.png b/src/gui/styles/images/down-32.png Binary files differnew file mode 100644 index 0000000000..46eadb8e12 --- /dev/null +++ b/src/gui/styles/images/down-32.png diff --git a/src/gui/styles/images/dvd-128.png b/src/gui/styles/images/dvd-128.png Binary files differnew file mode 100644 index 0000000000..9ed9dc1e55 --- /dev/null +++ b/src/gui/styles/images/dvd-128.png diff --git a/src/gui/styles/images/dvd-16.png b/src/gui/styles/images/dvd-16.png Binary files differnew file mode 100644 index 0000000000..623386d4ca --- /dev/null +++ b/src/gui/styles/images/dvd-16.png diff --git a/src/gui/styles/images/dvd-32.png b/src/gui/styles/images/dvd-32.png Binary files differnew file mode 100644 index 0000000000..089b72accb --- /dev/null +++ b/src/gui/styles/images/dvd-32.png diff --git a/src/gui/styles/images/file-128.png b/src/gui/styles/images/file-128.png Binary files differnew file mode 100644 index 0000000000..46e6ceb49a --- /dev/null +++ b/src/gui/styles/images/file-128.png diff --git a/src/gui/styles/images/file-16.png b/src/gui/styles/images/file-16.png Binary files differnew file mode 100644 index 0000000000..664b56356b --- /dev/null +++ b/src/gui/styles/images/file-16.png diff --git a/src/gui/styles/images/file-32.png b/src/gui/styles/images/file-32.png Binary files differnew file mode 100644 index 0000000000..83e5c3d311 --- /dev/null +++ b/src/gui/styles/images/file-32.png diff --git a/src/gui/styles/images/filecontents-128.png b/src/gui/styles/images/filecontents-128.png Binary files differnew file mode 100644 index 0000000000..50e0a838e2 --- /dev/null +++ b/src/gui/styles/images/filecontents-128.png diff --git a/src/gui/styles/images/filecontents-16.png b/src/gui/styles/images/filecontents-16.png Binary files differnew file mode 100644 index 0000000000..b9399ccf2e --- /dev/null +++ b/src/gui/styles/images/filecontents-16.png diff --git a/src/gui/styles/images/filecontents-32.png b/src/gui/styles/images/filecontents-32.png Binary files differnew file mode 100644 index 0000000000..3761f70690 --- /dev/null +++ b/src/gui/styles/images/filecontents-32.png diff --git a/src/gui/styles/images/fileinfo-128.png b/src/gui/styles/images/fileinfo-128.png Binary files differnew file mode 100644 index 0000000000..8c5b331876 --- /dev/null +++ b/src/gui/styles/images/fileinfo-128.png diff --git a/src/gui/styles/images/fileinfo-16.png b/src/gui/styles/images/fileinfo-16.png Binary files differnew file mode 100644 index 0000000000..729be4d5f2 --- /dev/null +++ b/src/gui/styles/images/fileinfo-16.png diff --git a/src/gui/styles/images/fileinfo-32.png b/src/gui/styles/images/fileinfo-32.png Binary files differnew file mode 100644 index 0000000000..ca795aa49b --- /dev/null +++ b/src/gui/styles/images/fileinfo-32.png diff --git a/src/gui/styles/images/filelink-128.png b/src/gui/styles/images/filelink-128.png Binary files differnew file mode 100644 index 0000000000..be86a82901 --- /dev/null +++ b/src/gui/styles/images/filelink-128.png diff --git a/src/gui/styles/images/filelink-16.png b/src/gui/styles/images/filelink-16.png Binary files differnew file mode 100644 index 0000000000..6643f2c428 --- /dev/null +++ b/src/gui/styles/images/filelink-16.png diff --git a/src/gui/styles/images/filelink-32.png b/src/gui/styles/images/filelink-32.png Binary files differnew file mode 100644 index 0000000000..1e46fdc13c --- /dev/null +++ b/src/gui/styles/images/filelink-32.png diff --git a/src/gui/styles/images/floppy-128.png b/src/gui/styles/images/floppy-128.png Binary files differnew file mode 100644 index 0000000000..fa7a3e1334 --- /dev/null +++ b/src/gui/styles/images/floppy-128.png diff --git a/src/gui/styles/images/floppy-16.png b/src/gui/styles/images/floppy-16.png Binary files differnew file mode 100644 index 0000000000..91c59c567d --- /dev/null +++ b/src/gui/styles/images/floppy-16.png diff --git a/src/gui/styles/images/floppy-32.png b/src/gui/styles/images/floppy-32.png Binary files differnew file mode 100644 index 0000000000..e63b3213bf --- /dev/null +++ b/src/gui/styles/images/floppy-32.png diff --git a/src/gui/styles/images/fontbitmap-16.png b/src/gui/styles/images/fontbitmap-16.png Binary files differnew file mode 100644 index 0000000000..03efc9cbab --- /dev/null +++ b/src/gui/styles/images/fontbitmap-16.png diff --git a/src/gui/styles/images/fonttruetype-16.png b/src/gui/styles/images/fonttruetype-16.png Binary files differnew file mode 100644 index 0000000000..25205021e9 --- /dev/null +++ b/src/gui/styles/images/fonttruetype-16.png diff --git a/src/gui/styles/images/harddrive-128.png b/src/gui/styles/images/harddrive-128.png Binary files differnew file mode 100644 index 0000000000..0b73d9de1e --- /dev/null +++ b/src/gui/styles/images/harddrive-128.png diff --git a/src/gui/styles/images/harddrive-16.png b/src/gui/styles/images/harddrive-16.png Binary files differnew file mode 100644 index 0000000000..45d592baa3 --- /dev/null +++ b/src/gui/styles/images/harddrive-16.png diff --git a/src/gui/styles/images/harddrive-32.png b/src/gui/styles/images/harddrive-32.png Binary files differnew file mode 100644 index 0000000000..7041452b68 --- /dev/null +++ b/src/gui/styles/images/harddrive-32.png diff --git a/src/gui/styles/images/left-128.png b/src/gui/styles/images/left-128.png Binary files differnew file mode 100644 index 0000000000..a26a5195f8 --- /dev/null +++ b/src/gui/styles/images/left-128.png diff --git a/src/gui/styles/images/left-16.png b/src/gui/styles/images/left-16.png Binary files differnew file mode 100644 index 0000000000..110dd90f2d --- /dev/null +++ b/src/gui/styles/images/left-16.png diff --git a/src/gui/styles/images/left-32.png b/src/gui/styles/images/left-32.png Binary files differnew file mode 100644 index 0000000000..ec4107b372 --- /dev/null +++ b/src/gui/styles/images/left-32.png diff --git a/src/gui/styles/images/media-pause-16.png b/src/gui/styles/images/media-pause-16.png Binary files differnew file mode 100644 index 0000000000..6cb1fd7f63 --- /dev/null +++ b/src/gui/styles/images/media-pause-16.png diff --git a/src/gui/styles/images/media-pause-32.png b/src/gui/styles/images/media-pause-32.png Binary files differnew file mode 100644 index 0000000000..3f172a04d6 --- /dev/null +++ b/src/gui/styles/images/media-pause-32.png diff --git a/src/gui/styles/images/media-play-16.png b/src/gui/styles/images/media-play-16.png Binary files differnew file mode 100644 index 0000000000..d7ee3ccbe3 --- /dev/null +++ b/src/gui/styles/images/media-play-16.png diff --git a/src/gui/styles/images/media-play-32.png b/src/gui/styles/images/media-play-32.png Binary files differnew file mode 100644 index 0000000000..af8d2f7ba5 --- /dev/null +++ b/src/gui/styles/images/media-play-32.png diff --git a/src/gui/styles/images/media-seek-backward-16.png b/src/gui/styles/images/media-seek-backward-16.png Binary files differnew file mode 100644 index 0000000000..b8a8ea42d1 --- /dev/null +++ b/src/gui/styles/images/media-seek-backward-16.png diff --git a/src/gui/styles/images/media-seek-backward-32.png b/src/gui/styles/images/media-seek-backward-32.png Binary files differnew file mode 100644 index 0000000000..a21d1372fe --- /dev/null +++ b/src/gui/styles/images/media-seek-backward-32.png diff --git a/src/gui/styles/images/media-seek-forward-16.png b/src/gui/styles/images/media-seek-forward-16.png Binary files differnew file mode 100644 index 0000000000..3c900dcb62 --- /dev/null +++ b/src/gui/styles/images/media-seek-forward-16.png diff --git a/src/gui/styles/images/media-seek-forward-32.png b/src/gui/styles/images/media-seek-forward-32.png Binary files differnew file mode 100644 index 0000000000..4f8d370fa1 --- /dev/null +++ b/src/gui/styles/images/media-seek-forward-32.png diff --git a/src/gui/styles/images/media-skip-backward-16.png b/src/gui/styles/images/media-skip-backward-16.png Binary files differnew file mode 100644 index 0000000000..f5b3f4f56d --- /dev/null +++ b/src/gui/styles/images/media-skip-backward-16.png diff --git a/src/gui/styles/images/media-skip-backward-32.png b/src/gui/styles/images/media-skip-backward-32.png Binary files differnew file mode 100644 index 0000000000..1d338035ef --- /dev/null +++ b/src/gui/styles/images/media-skip-backward-32.png diff --git a/src/gui/styles/images/media-skip-forward-16.png b/src/gui/styles/images/media-skip-forward-16.png Binary files differnew file mode 100644 index 0000000000..27e205b02f --- /dev/null +++ b/src/gui/styles/images/media-skip-forward-16.png diff --git a/src/gui/styles/images/media-skip-forward-32.png b/src/gui/styles/images/media-skip-forward-32.png Binary files differnew file mode 100644 index 0000000000..a583fa1b11 --- /dev/null +++ b/src/gui/styles/images/media-skip-forward-32.png diff --git a/src/gui/styles/images/media-stop-16.png b/src/gui/styles/images/media-stop-16.png Binary files differnew file mode 100644 index 0000000000..9ce035d696 --- /dev/null +++ b/src/gui/styles/images/media-stop-16.png diff --git a/src/gui/styles/images/media-stop-32.png b/src/gui/styles/images/media-stop-32.png Binary files differnew file mode 100644 index 0000000000..aae24ba925 --- /dev/null +++ b/src/gui/styles/images/media-stop-32.png diff --git a/src/gui/styles/images/media-volume-16.png b/src/gui/styles/images/media-volume-16.png Binary files differnew file mode 100644 index 0000000000..ad258340f2 --- /dev/null +++ b/src/gui/styles/images/media-volume-16.png diff --git a/src/gui/styles/images/media-volume-muted-16.png b/src/gui/styles/images/media-volume-muted-16.png Binary files differnew file mode 100644 index 0000000000..06bded21e7 --- /dev/null +++ b/src/gui/styles/images/media-volume-muted-16.png diff --git a/src/gui/styles/images/networkdrive-128.png b/src/gui/styles/images/networkdrive-128.png Binary files differnew file mode 100644 index 0000000000..fd4a59c6bd --- /dev/null +++ b/src/gui/styles/images/networkdrive-128.png diff --git a/src/gui/styles/images/networkdrive-16.png b/src/gui/styles/images/networkdrive-16.png Binary files differnew file mode 100644 index 0000000000..1bc62f766a --- /dev/null +++ b/src/gui/styles/images/networkdrive-16.png diff --git a/src/gui/styles/images/networkdrive-32.png b/src/gui/styles/images/networkdrive-32.png Binary files differnew file mode 100644 index 0000000000..6a389dcae4 --- /dev/null +++ b/src/gui/styles/images/networkdrive-32.png diff --git a/src/gui/styles/images/newdirectory-128.png b/src/gui/styles/images/newdirectory-128.png Binary files differnew file mode 100644 index 0000000000..fdbee27688 --- /dev/null +++ b/src/gui/styles/images/newdirectory-128.png diff --git a/src/gui/styles/images/newdirectory-16.png b/src/gui/styles/images/newdirectory-16.png Binary files differnew file mode 100644 index 0000000000..6c9f80318b --- /dev/null +++ b/src/gui/styles/images/newdirectory-16.png diff --git a/src/gui/styles/images/newdirectory-32.png b/src/gui/styles/images/newdirectory-32.png Binary files differnew file mode 100644 index 0000000000..4fd0329216 --- /dev/null +++ b/src/gui/styles/images/newdirectory-32.png diff --git a/src/gui/styles/images/parentdir-128.png b/src/gui/styles/images/parentdir-128.png Binary files differnew file mode 100644 index 0000000000..84d14ab079 --- /dev/null +++ b/src/gui/styles/images/parentdir-128.png diff --git a/src/gui/styles/images/parentdir-16.png b/src/gui/styles/images/parentdir-16.png Binary files differnew file mode 100644 index 0000000000..665f8280f2 --- /dev/null +++ b/src/gui/styles/images/parentdir-16.png diff --git a/src/gui/styles/images/parentdir-32.png b/src/gui/styles/images/parentdir-32.png Binary files differnew file mode 100644 index 0000000000..44f3c4876d --- /dev/null +++ b/src/gui/styles/images/parentdir-32.png diff --git a/src/gui/styles/images/refresh-24.png b/src/gui/styles/images/refresh-24.png Binary files differnew file mode 100644 index 0000000000..4c9b72c489 --- /dev/null +++ b/src/gui/styles/images/refresh-24.png diff --git a/src/gui/styles/images/refresh-32.png b/src/gui/styles/images/refresh-32.png Binary files differnew file mode 100644 index 0000000000..eecde4b8f9 --- /dev/null +++ b/src/gui/styles/images/refresh-32.png diff --git a/src/gui/styles/images/right-128.png b/src/gui/styles/images/right-128.png Binary files differnew file mode 100644 index 0000000000..14b1cfd8eb --- /dev/null +++ b/src/gui/styles/images/right-128.png diff --git a/src/gui/styles/images/right-16.png b/src/gui/styles/images/right-16.png Binary files differnew file mode 100644 index 0000000000..81ca628ff6 --- /dev/null +++ b/src/gui/styles/images/right-16.png diff --git a/src/gui/styles/images/right-32.png b/src/gui/styles/images/right-32.png Binary files differnew file mode 100644 index 0000000000..0f6ba8608b --- /dev/null +++ b/src/gui/styles/images/right-32.png diff --git a/src/gui/styles/images/standardbutton-apply-128.png b/src/gui/styles/images/standardbutton-apply-128.png Binary files differnew file mode 100644 index 0000000000..85f07a57ef --- /dev/null +++ b/src/gui/styles/images/standardbutton-apply-128.png diff --git a/src/gui/styles/images/standardbutton-apply-16.png b/src/gui/styles/images/standardbutton-apply-16.png Binary files differnew file mode 100644 index 0000000000..8f11ce6504 --- /dev/null +++ b/src/gui/styles/images/standardbutton-apply-16.png diff --git a/src/gui/styles/images/standardbutton-apply-32.png b/src/gui/styles/images/standardbutton-apply-32.png Binary files differnew file mode 100644 index 0000000000..e8f7853a1e --- /dev/null +++ b/src/gui/styles/images/standardbutton-apply-32.png diff --git a/src/gui/styles/images/standardbutton-cancel-128.png b/src/gui/styles/images/standardbutton-cancel-128.png Binary files differnew file mode 100644 index 0000000000..16d857030f --- /dev/null +++ b/src/gui/styles/images/standardbutton-cancel-128.png diff --git a/src/gui/styles/images/standardbutton-cancel-16.png b/src/gui/styles/images/standardbutton-cancel-16.png Binary files differnew file mode 100644 index 0000000000..7bd25bd7c7 --- /dev/null +++ b/src/gui/styles/images/standardbutton-cancel-16.png diff --git a/src/gui/styles/images/standardbutton-cancel-32.png b/src/gui/styles/images/standardbutton-cancel-32.png Binary files differnew file mode 100644 index 0000000000..64a78727a1 --- /dev/null +++ b/src/gui/styles/images/standardbutton-cancel-32.png diff --git a/src/gui/styles/images/standardbutton-clear-128.png b/src/gui/styles/images/standardbutton-clear-128.png Binary files differnew file mode 100644 index 0000000000..107aea2234 --- /dev/null +++ b/src/gui/styles/images/standardbutton-clear-128.png diff --git a/src/gui/styles/images/standardbutton-clear-16.png b/src/gui/styles/images/standardbutton-clear-16.png Binary files differnew file mode 100644 index 0000000000..5359134c72 --- /dev/null +++ b/src/gui/styles/images/standardbutton-clear-16.png diff --git a/src/gui/styles/images/standardbutton-clear-32.png b/src/gui/styles/images/standardbutton-clear-32.png Binary files differnew file mode 100644 index 0000000000..8b85d6b7b3 --- /dev/null +++ b/src/gui/styles/images/standardbutton-clear-32.png diff --git a/src/gui/styles/images/standardbutton-close-128.png b/src/gui/styles/images/standardbutton-close-128.png Binary files differnew file mode 100644 index 0000000000..571aeae2bd --- /dev/null +++ b/src/gui/styles/images/standardbutton-close-128.png diff --git a/src/gui/styles/images/standardbutton-close-16.png b/src/gui/styles/images/standardbutton-close-16.png Binary files differnew file mode 100644 index 0000000000..e9e481987a --- /dev/null +++ b/src/gui/styles/images/standardbutton-close-16.png diff --git a/src/gui/styles/images/standardbutton-close-32.png b/src/gui/styles/images/standardbutton-close-32.png Binary files differnew file mode 100644 index 0000000000..47e5733062 --- /dev/null +++ b/src/gui/styles/images/standardbutton-close-32.png diff --git a/src/gui/styles/images/standardbutton-closetab-16.png b/src/gui/styles/images/standardbutton-closetab-16.png Binary files differnew file mode 100644 index 0000000000..540694eae3 --- /dev/null +++ b/src/gui/styles/images/standardbutton-closetab-16.png diff --git a/src/gui/styles/images/standardbutton-closetab-down-16.png b/src/gui/styles/images/standardbutton-closetab-down-16.png Binary files differnew file mode 100644 index 0000000000..ccec241652 --- /dev/null +++ b/src/gui/styles/images/standardbutton-closetab-down-16.png diff --git a/src/gui/styles/images/standardbutton-closetab-hover-16.png b/src/gui/styles/images/standardbutton-closetab-hover-16.png Binary files differnew file mode 100644 index 0000000000..b22a0ffaf0 --- /dev/null +++ b/src/gui/styles/images/standardbutton-closetab-hover-16.png diff --git a/src/gui/styles/images/standardbutton-delete-128.png b/src/gui/styles/images/standardbutton-delete-128.png Binary files differnew file mode 100644 index 0000000000..11947ba681 --- /dev/null +++ b/src/gui/styles/images/standardbutton-delete-128.png diff --git a/src/gui/styles/images/standardbutton-delete-16.png b/src/gui/styles/images/standardbutton-delete-16.png Binary files differnew file mode 100644 index 0000000000..63fe93fe98 --- /dev/null +++ b/src/gui/styles/images/standardbutton-delete-16.png diff --git a/src/gui/styles/images/standardbutton-delete-32.png b/src/gui/styles/images/standardbutton-delete-32.png Binary files differnew file mode 100644 index 0000000000..336d965d1c --- /dev/null +++ b/src/gui/styles/images/standardbutton-delete-32.png diff --git a/src/gui/styles/images/standardbutton-help-128.png b/src/gui/styles/images/standardbutton-help-128.png Binary files differnew file mode 100644 index 0000000000..aa38e6fdfb --- /dev/null +++ b/src/gui/styles/images/standardbutton-help-128.png diff --git a/src/gui/styles/images/standardbutton-help-16.png b/src/gui/styles/images/standardbutton-help-16.png Binary files differnew file mode 100644 index 0000000000..e8299418da --- /dev/null +++ b/src/gui/styles/images/standardbutton-help-16.png diff --git a/src/gui/styles/images/standardbutton-help-32.png b/src/gui/styles/images/standardbutton-help-32.png Binary files differnew file mode 100644 index 0000000000..310056a632 --- /dev/null +++ b/src/gui/styles/images/standardbutton-help-32.png diff --git a/src/gui/styles/images/standardbutton-no-128.png b/src/gui/styles/images/standardbutton-no-128.png Binary files differnew file mode 100644 index 0000000000..491c048ebd --- /dev/null +++ b/src/gui/styles/images/standardbutton-no-128.png diff --git a/src/gui/styles/images/standardbutton-no-16.png b/src/gui/styles/images/standardbutton-no-16.png Binary files differnew file mode 100644 index 0000000000..812d3f57dd --- /dev/null +++ b/src/gui/styles/images/standardbutton-no-16.png diff --git a/src/gui/styles/images/standardbutton-no-32.png b/src/gui/styles/images/standardbutton-no-32.png Binary files differnew file mode 100644 index 0000000000..9548d59196 --- /dev/null +++ b/src/gui/styles/images/standardbutton-no-32.png diff --git a/src/gui/styles/images/standardbutton-ok-128.png b/src/gui/styles/images/standardbutton-ok-128.png Binary files differnew file mode 100644 index 0000000000..63cc5279ae --- /dev/null +++ b/src/gui/styles/images/standardbutton-ok-128.png diff --git a/src/gui/styles/images/standardbutton-ok-16.png b/src/gui/styles/images/standardbutton-ok-16.png Binary files differnew file mode 100644 index 0000000000..fb4b4dbf96 --- /dev/null +++ b/src/gui/styles/images/standardbutton-ok-16.png diff --git a/src/gui/styles/images/standardbutton-ok-32.png b/src/gui/styles/images/standardbutton-ok-32.png Binary files differnew file mode 100644 index 0000000000..2dadd7a690 --- /dev/null +++ b/src/gui/styles/images/standardbutton-ok-32.png diff --git a/src/gui/styles/images/standardbutton-open-128.png b/src/gui/styles/images/standardbutton-open-128.png Binary files differnew file mode 100644 index 0000000000..8a052e829d --- /dev/null +++ b/src/gui/styles/images/standardbutton-open-128.png diff --git a/src/gui/styles/images/standardbutton-open-16.png b/src/gui/styles/images/standardbutton-open-16.png Binary files differnew file mode 100644 index 0000000000..08cdc2b91f --- /dev/null +++ b/src/gui/styles/images/standardbutton-open-16.png diff --git a/src/gui/styles/images/standardbutton-open-32.png b/src/gui/styles/images/standardbutton-open-32.png Binary files differnew file mode 100644 index 0000000000..db33c79852 --- /dev/null +++ b/src/gui/styles/images/standardbutton-open-32.png diff --git a/src/gui/styles/images/standardbutton-save-128.png b/src/gui/styles/images/standardbutton-save-128.png Binary files differnew file mode 100644 index 0000000000..fc6fd7ce1d --- /dev/null +++ b/src/gui/styles/images/standardbutton-save-128.png diff --git a/src/gui/styles/images/standardbutton-save-16.png b/src/gui/styles/images/standardbutton-save-16.png Binary files differnew file mode 100644 index 0000000000..dd4e228280 --- /dev/null +++ b/src/gui/styles/images/standardbutton-save-16.png diff --git a/src/gui/styles/images/standardbutton-save-32.png b/src/gui/styles/images/standardbutton-save-32.png Binary files differnew file mode 100644 index 0000000000..177678c963 --- /dev/null +++ b/src/gui/styles/images/standardbutton-save-32.png diff --git a/src/gui/styles/images/standardbutton-yes-128.png b/src/gui/styles/images/standardbutton-yes-128.png Binary files differnew file mode 100644 index 0000000000..79c8296016 --- /dev/null +++ b/src/gui/styles/images/standardbutton-yes-128.png diff --git a/src/gui/styles/images/standardbutton-yes-16.png b/src/gui/styles/images/standardbutton-yes-16.png Binary files differnew file mode 100644 index 0000000000..cc16dbbec3 --- /dev/null +++ b/src/gui/styles/images/standardbutton-yes-16.png diff --git a/src/gui/styles/images/standardbutton-yes-32.png b/src/gui/styles/images/standardbutton-yes-32.png Binary files differnew file mode 100644 index 0000000000..e3340c6453 --- /dev/null +++ b/src/gui/styles/images/standardbutton-yes-32.png diff --git a/src/gui/styles/images/stop-24.png b/src/gui/styles/images/stop-24.png Binary files differnew file mode 100644 index 0000000000..99856e9640 --- /dev/null +++ b/src/gui/styles/images/stop-24.png diff --git a/src/gui/styles/images/stop-32.png b/src/gui/styles/images/stop-32.png Binary files differnew file mode 100644 index 0000000000..4f4952bb2a --- /dev/null +++ b/src/gui/styles/images/stop-32.png diff --git a/src/gui/styles/images/trash-128.png b/src/gui/styles/images/trash-128.png Binary files differnew file mode 100644 index 0000000000..334fe5b6f3 --- /dev/null +++ b/src/gui/styles/images/trash-128.png diff --git a/src/gui/styles/images/trash-16.png b/src/gui/styles/images/trash-16.png Binary files differnew file mode 100644 index 0000000000..c471791ee8 --- /dev/null +++ b/src/gui/styles/images/trash-16.png diff --git a/src/gui/styles/images/trash-32.png b/src/gui/styles/images/trash-32.png Binary files differnew file mode 100644 index 0000000000..68625cf698 --- /dev/null +++ b/src/gui/styles/images/trash-32.png diff --git a/src/gui/styles/images/up-128.png b/src/gui/styles/images/up-128.png Binary files differnew file mode 100644 index 0000000000..c10df10677 --- /dev/null +++ b/src/gui/styles/images/up-128.png diff --git a/src/gui/styles/images/up-16.png b/src/gui/styles/images/up-16.png Binary files differnew file mode 100644 index 0000000000..33e939db8f --- /dev/null +++ b/src/gui/styles/images/up-16.png diff --git a/src/gui/styles/images/up-32.png b/src/gui/styles/images/up-32.png Binary files differnew file mode 100644 index 0000000000..d7157c9476 --- /dev/null +++ b/src/gui/styles/images/up-32.png diff --git a/src/gui/styles/images/viewdetailed-128.png b/src/gui/styles/images/viewdetailed-128.png Binary files differnew file mode 100644 index 0000000000..363937a857 --- /dev/null +++ b/src/gui/styles/images/viewdetailed-128.png diff --git a/src/gui/styles/images/viewdetailed-16.png b/src/gui/styles/images/viewdetailed-16.png Binary files differnew file mode 100644 index 0000000000..44a14b923a --- /dev/null +++ b/src/gui/styles/images/viewdetailed-16.png diff --git a/src/gui/styles/images/viewdetailed-32.png b/src/gui/styles/images/viewdetailed-32.png Binary files differnew file mode 100644 index 0000000000..fac1a3e683 --- /dev/null +++ b/src/gui/styles/images/viewdetailed-32.png diff --git a/src/gui/styles/images/viewlist-128.png b/src/gui/styles/images/viewlist-128.png Binary files differnew file mode 100644 index 0000000000..cc301059c1 --- /dev/null +++ b/src/gui/styles/images/viewlist-128.png diff --git a/src/gui/styles/images/viewlist-16.png b/src/gui/styles/images/viewlist-16.png Binary files differnew file mode 100644 index 0000000000..9132877ff6 --- /dev/null +++ b/src/gui/styles/images/viewlist-16.png diff --git a/src/gui/styles/images/viewlist-32.png b/src/gui/styles/images/viewlist-32.png Binary files differnew file mode 100644 index 0000000000..fae3c24536 --- /dev/null +++ b/src/gui/styles/images/viewlist-32.png diff --git a/src/gui/styles/qcdestyle.cpp b/src/gui/styles/qcdestyle.cpp new file mode 100644 index 0000000000..b58c41c1ae --- /dev/null +++ b/src/gui/styles/qcdestyle.cpp @@ -0,0 +1,305 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 <limits.h> + +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/gui/styles/qcdestyle.h b/src/gui/styles/qcdestyle.h new file mode 100644 index 0000000000..bb752d3064 --- /dev/null +++ b/src/gui/styles/qcdestyle.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QCDESTYLE_H +#define QCDESTYLE_H + +#include <QtGui/qmotifstyle.h> + +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/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp new file mode 100644 index 0000000000..468ada9484 --- /dev/null +++ b/src/gui/styles/qcleanlooksstyle.cpp @@ -0,0 +1,4945 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 <qcombobox.h> +#include <qpushbutton.h> +#include <qpainter.h> +#include <qdir.h> +#include <qhash.h> +#include <qstyleoption.h> +#include <qapplication.h> +#include <qmainwindow.h> +#include <qfont.h> +#include <qgroupbox.h> +#include <qprocess.h> +#include <qpixmapcache.h> +#include <qdialogbuttonbox.h> +#include <qscrollbar.h> +#include <qspinbox.h> +#include <qslider.h> +#include <qsplitter.h> +#include <qprogressbar.h> +#include <qtoolbar.h> +#include <qwizard.h> +#include <qlibrary.h> + +#define CL_MAX(a,b) (a)>(b) ? (a):(b) // ### qMin/qMax does not work for vc6 +#define CL_MIN(a,b) (a)<(b) ? (a):(b) // remove this when it is working + +QT_BEGIN_NAMESPACE + +static const bool UsePixmapCache = true; + +enum Direction { + TopDown, + FromLeft, + BottomUp, + FromRight +}; + +// from windows style +static const int windowsItemFrame = 2; // menu item frame width +static const int windowsSepHeight = 6; // separator item height +static const int windowsItemHMargin = 3; // menu item hor text margin +static const int windowsItemVMargin = 8; // 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 windowsCheckMarkHMargin = 2; // horiz. margins of check mark +static const int windowsRightBorder = 15; // right border on windows +static const int windowsCheckMarkWidth = 12; // checkmarks width 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", + + " ", + " % ", + " %. ", + " %.% ", + " %.. ", + " %.% %.. ", + " %..%..% ", + " %...% ", + " %..% ", + " %.% ", + " % ", + " ", + " "}; + +#ifdef Q_WS_X11 +extern "C" { + struct GConfClient; + struct GError; + typedef void (*Ptr_g_type_init)(); + typedef GConfClient* (*Ptr_gconf_client_get_default)(); + typedef char* (*Ptr_gconf_client_get_string)(GConfClient*, const char*, GError **); + typedef void (*Ptr_g_object_unref)(void *); + typedef void (*Ptr_g_error_free)(GError *); + typedef void (*Ptr_g_free)(void*); +} + +static Ptr_g_type_init p_g_type_init = 0; +static Ptr_gconf_client_get_default p_gconf_client_get_default = 0; +static Ptr_gconf_client_get_string p_gconf_client_get_string = 0; +static Ptr_g_object_unref p_g_object_unref = 0; +static Ptr_g_error_free p_g_error_free = 0; +static Ptr_g_free p_g_free = 0; +#endif + +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 < 1) + size = 1; + 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 QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size) +{ + QString tmp; + const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option); + tmp.sprintf("%s-%d-%d-%lld-%dx%d-%d", key.toLatin1().constData(), uint(option->state), + complexOption ? uint(complexOption->activeSubControls) : uint(0), + option->palette.cacheKey(), size.width(), size.height(), option->direction); +#ifndef QT_NO_SPINBOX + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { + tmp.append(QLatin1Char('-')); + tmp.append(QString::number(spinBox->buttonSymbols)); + tmp.append(QLatin1Char('-')); + tmp.append(QString::number(spinBox->stepEnabled)); + tmp.append(QLatin1Char('-')); + tmp.append(QLatin1Char(spinBox->frame ? '1' : '0')); + } +#endif // QT_NO_SPINBOX + return tmp; +} + +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(), + CL_MIN(255, (int)(option->palette.button().color().saturation()*1.9)), + CL_MIN(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)); + painter->drawLine(tmp.left() + 2, tmp.top(), tmp.right() - 2, tmp.top()); + painter->drawLine(tmp.left() + 2, tmp.bottom(), tmp.right() - 2, tmp.bottom()); + painter->drawLine(tmp.left(), tmp.top() + 2, tmp.left(), tmp.bottom() - 2); + painter->drawLine(tmp.right(), tmp.top() + 2, tmp.right(), tmp.bottom() - 2); + painter->drawPoint(tmp.left() + 1, tmp.top() + 1); + painter->drawPoint(tmp.right() - 1, tmp.top() + 1); + painter->drawPoint(tmp.left() + 1, tmp.bottom() - 1); + painter->drawPoint(tmp.right() - 1, tmp.bottom() - 1); + + 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(), + CL_MIN(255, (int)(button.saturation()*3.0)), + CL_MIN(255, (int)(button.value()*0.6))); + dark.setHsv(button.hue(), + CL_MIN(255, (int)(button.saturation()*1.9)), + CL_MIN(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<const QStyleOptionTabBarBase *>(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; + drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget); + } + return; + case PE_IndicatorHeaderArrow: + if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(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: + 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) + drawPrimitive(PE_PanelButtonCommand, option, painter, widget); + } else { + 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; + 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_LINEDIT + case PE_FrameLineEdit: + // fall through +#endif // QT_NO_LINEEDIT +#ifdef QT3_SUPPORT + if (widget && widget->inherits("Q3ToolBar")) { + 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)); + painter->drawPoint(r.right() - 1, r.top()); + painter->drawPoint(r.right(), r.top() + 1); + painter->drawPoint(r.right() - 1, r.bottom()); + painter->drawPoint(r.right(), r.bottom() - 1); + painter->drawPoint(r.left() + 1, r.top() ); + painter->drawPoint(r.left(), r.top() + 1); + painter->drawPoint(r.left() + 1, r.bottom() ); + painter->drawPoint(r.left(), r.bottom() - 1); + 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())); + painter->drawPoint(QPoint(r.right() - 1, r.bottom() - 1)); + painter->drawPoint(QPoint(r.right() - 1, r.top() + 1)); + painter->drawPoint(QPoint(r.left() + 1, r.bottom() - 1)); + painter->drawPoint(QPoint(r.left() + 1, r.top() + 1)); + 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<const QStyleOptionButton*>(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<const QStyleOptionFocusRect *>(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); + painter->drawRect(rect.left(), rect.top(), rect.width(), 1); // Top + painter->drawRect(rect.left(), rect.bottom(), rect.width(), 1); // Bottom + painter->drawRect(rect.left(), rect.top(), 1, rect.height()); // Left + painter->drawRect(rect.right(), rect.top(), 1, rect.height()); // Right + 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<const QStyleOptionButton*>(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)); + painter->drawLine(QPoint(r.left() + 2, r.top()), + QPoint(r.right() - 2, r.top())); + 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())); + painter->drawPoint(QPoint(r.right() - 1, r.bottom() - 1)); + painter->drawPoint(QPoint(r.right() - 1, r.top() + 1)); + painter->drawPoint(QPoint(r.left() + 1, r.bottom() - 1)); + painter->drawPoint(QPoint(r.left() + 1, r.top() + 1)); + 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(), + CL_MIN(255, (int)(buttonColor.saturation()*1.9)), + CL_MIN(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())); + p->drawPoint(QPoint(r.right() - 1, r.bottom() - 1)); + p->drawPoint(QPoint(r.right() - 1, r.top() + 1)); + p->drawPoint(QPoint(r.left() + 1, r.bottom() - 1)); + p->drawPoint(QPoint(r.left() + 1, r.top() + 1)); + + 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); + p->drawPoint(QPoint(r.right(), r.top() + 1)); + p->drawPoint(QPoint(r.right() - 1, r.top() )); + p->drawPoint(QPoint(r.right(), r.bottom() - 1)); + p->drawPoint(QPoint(r.right() - 1, r.bottom() )); + p->drawPoint(QPoint(r.left() + 1, r.bottom())); + p->drawPoint(QPoint(r.left(), r.bottom() - 1)); + p->drawPoint(QPoint(r.left() + 1, r.top())); + p->drawPoint(QPoint(r.left(), r.top() + 1)); + + 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)); + p->drawLine(r.topLeft() + QPoint(3, 0), r.topRight() - QPoint(3, 0)); + p->drawLine(r.bottomLeft() + QPoint(3, 0), r.bottomRight() - QPoint(3, 0)); + p->drawLine(r.topLeft() + QPoint(0, 3), r.bottomLeft() - QPoint(0, 3)); + p->drawLine(r.topRight() + QPoint(0, 3), r.bottomRight() - QPoint(0, 3)); + p->drawPoint(r.topRight() + QPoint(-2, 1)); + p->drawPoint(r.topRight() + QPoint(-1, 2)); + p->drawPoint(r.bottomRight() + QPoint(-1, -2)); + p->drawPoint(r.bottomRight() + QPoint(-2, -1)); + p->drawPoint(r.topLeft() + QPoint(1, 2)); + p->drawPoint(r.topLeft() + QPoint(2, 1)); + p->drawPoint(r.bottomLeft() + QPoint(1, -2)); + p->drawPoint(r.bottomLeft() + QPoint(2, -1)); + } + 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<const QStyleOptionTabWidgetFrame *>(option)) { + QColor borderColor = darkOutline.lighter(110); + QColor alphaCornerColor = mergedColors(borderColor, option->palette.background().color()); + QColor innerShadow = mergedColors(borderColor, option->palette.base().color()); + + int borderThickness = 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); + painter->drawPoint(leftBottomInnerCorner1); + painter->drawPoint(leftBottomInnerCorner2); + painter->drawPoint(rightBottomInnerCorner1); + painter->drawPoint(rightBottomInnerCorner2); + painter->drawPoint(leftTopInnerCorner1); + painter->drawPoint(leftTopInnerCorner2); + } +#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)) + drawPrimitive(PE_PanelButtonCommand, option, painter, widget); + QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On); + 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(), + CL_MIN(255, (int)(button.saturation()*1.9)), + CL_MIN(255, (int)(button.value()*0.7))); + QColor darkOutline; + darkOutline.setHsv(button.hue(), + CL_MIN(255, (int)(button.saturation()*2.0)), + CL_MIN(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(); + QColor highlightText = option->palette.highlightedText().color(); + + switch(element) { + case CE_RadioButton: //fall through + case CE_CheckBox: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(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<const QStyleOptionToolBar *>(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 (QApplication::layoutDirection() == 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<const QStyleOptionDockWidget *>(option)) { + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(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()); + 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<const QStyleOptionHeader *>(option)) { + QPixmap cache; + QString pixmapName = uniqueName(QLatin1String("headersection"), option, option->rect.size()); + pixmapName += QLatin1String("-") + QString::number(int(header->position)); + pixmapName += QLatin1String("-") + QString::number(int(header->orientation)); + QRect r = option->rect; + QColor gradientStopColor; + QColor gradientStartColor = option->palette.button().color(); + gradientStopColor.setHsv(gradientStartColor.hue(), + CL_MIN(255, (int)(gradientStartColor.saturation()*2)), + CL_MIN(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 (!UsePixmapCache || !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(); + if (UsePixmapCache) + 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)); + painter->drawLine(QPoint(rect.left() + 1, rect.top()), QPoint(rect.right() - 1, rect.top())); + painter->drawLine(QPoint(rect.left() + 1, rect.bottom()), QPoint(rect.right() - 1, rect.bottom())); + painter->drawLine(QPoint(rect.left(), rect.top() + 1), QPoint(rect.left(), rect.bottom() - 1)); + painter->drawLine(QPoint(rect.right(), rect.top() + 1), QPoint(rect.right(), rect.bottom() - 1)); + QColor alphaCorner = mergedColors(borderColor, option->palette.background().color()); + QColor innerShadow = mergedColors(borderColor, option->palette.base().color()); + + //corner smoothing + painter->setPen(alphaCorner); + painter->drawPoint(rect.topRight()); + painter->drawPoint(rect.topLeft()); + painter->drawPoint(rect.bottomRight()); + painter->drawPoint(rect.bottomLeft()); + + //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<const QStyleOptionProgressBar *>(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<const QStyleOptionProgressBarV2 *>(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; + m.translate(rect.height()-1, -1.0); + m.rotate(90.0); + painter->setTransform(m, true); + } + + int maxWidth = rect.width() - 4; + int minWidth = 4; + qint64 progress = (qint64)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 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; + + 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<const QStyleOptionMenuItem *>(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)); + painter->drawLine(QPoint(r.left(), r.top() + 1), QPoint(r.left(), r.bottom())); + painter->drawLine(QPoint(r.right(), r.top() + 1), QPoint(r.right(), r.bottom())); + painter->drawLine(QPoint(r.left() + 1, r.bottom()), QPoint(r.right() - 1, r.bottom())); + painter->drawLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top())); + + //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; + 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<const QStyleOptionMenuItem *>(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); + 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)); + painter->drawLine(QPoint(r.left(), r.top() + 1), QPoint(r.left(), r.bottom() - 1)); + painter->drawLine(QPoint(r.right(), r.top() + 1), QPoint(r.right(), r.bottom() - 1)); + painter->drawLine(QPoint(r.left() + 1, r.bottom()), QPoint(r.right() - 1, r.bottom())); + painter->drawLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top())); + } 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<const QComboBox*>(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 = pixelMetric(PM_SmallIconSize, option, widget); + QSize iconSize(smallIconSize, smallIconSize); +#ifndef QT_NO_COMBOBOX + if (const QComboBox *combo = qobject_cast<const QComboBox*>(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; + 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 && 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 = 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()); + 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<const QStyleOptionButton *>(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, -pixelMetric(PM_MenuButtonIndicator, button, widget), 0); + 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<const QMainWindow *>(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<const QStyleOptionTab *>(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 = 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 = 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(), + CL_MIN(255, (int)(button.saturation()*1.9)), + CL_MIN(255, (int)(button.value()*0.7))); + grooveColor.setHsv(button.hue(), + CL_MIN(255, (int)(button.saturation()*2.6)), + CL_MIN(255, (int)(button.value()*0.9))); + darkOutline.setHsv(button.hue(), + CL_MIN(255, (int)(button.saturation()*3.0)), + CL_MIN(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<const QStyleOptionSpinBox *>(option)) { + QPixmap cache; + QString pixmapName = uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size()); + if (!UsePixmapCache || !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 = subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxUp, widget); + QRect downRect = subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxDown, widget); + + int fw = spinBoxCopy.frame ? 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 + cachePainter.drawPoint(QPoint(r.right(), r.top() + 1)); + cachePainter.drawPoint(QPoint(r.right() - 1, r.top() )); + cachePainter.drawPoint(QPoint(r.right(), r.bottom() - 1)); + cachePainter.drawPoint(QPoint(r.right() - 1, r.bottom() )); + cachePainter.drawPoint(QPoint(r.left() + 1, r.bottom())); + cachePainter.drawPoint(QPoint(r.left(), r.bottom() - 1)); + cachePainter.drawPoint(QPoint(r.left() + 1, r.top())); + cachePainter.drawPoint(QPoint(r.left(), r.top() + 1)); + + // 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 + cachePainter.drawLine(QPoint(r.left() + 2, r.bottom()), QPoint(r.right()- 2, r.bottom())); + cachePainter.drawLine(QPoint(r.left() + 2, r.top()), QPoint(r.right() - 2, r.top())); + cachePainter.drawLine(QPoint(r.right(), r.top() + 2), QPoint(r.right(), r.bottom() - 2)); + cachePainter.drawLine(QPoint(r.left(), r.top() + 2), QPoint(r.left(), r.bottom() - 2)); + } + + // 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 + cachePainter.drawPoint(QPoint(r.left() + 1, r.bottom() - 1)); + cachePainter.drawPoint(QPoint(r.left() + 1, r.top() + 1)); + cachePainter.drawPoint(QPoint(r.right() - 1, r.bottom() - 1)); + cachePainter.drawPoint(QPoint(r.right() - 1, 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); + 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)); + cachePainter.drawLine(QPoint(r.left() + 2, r.bottom()), QPoint(r.right()- downRect.width() - 1, r.bottom())); + cachePainter.drawLine(QPoint(r.left() + 2, r.top()), QPoint(r.right() - downRect.width() - 1, r.top())); + cachePainter.drawLine(QPoint(r.right() - downRect.width() - 1, r.top() + 1), QPoint(r.right()- downRect.width() - 1, r.bottom() - 1)); + cachePainter.drawLine(QPoint(r.left(), r.top() + 2), QPoint(r.left(), r.bottom() - 2)); + 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(); + if (UsePixmapCache) + 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<const QStyleOptionTitleBar *>(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); + drawControl(CE_DockWidgetTitle, &dockwidget, painter, widget); + } else +#endif // QT3_SUPPORT + { + // Fill title bar gradient + QColor titlebarColor = QColor(active ? highlight: palette.background().color()); + QColor titleBarGradientStop(active ? highlight.darker(150): palette.background().color().darker(120)); + 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()); + painter->drawPoint(fullRect.left() + 4, fullRect.top() + 1); + painter->drawPoint(fullRect.left() + 3, fullRect.top() + 1); + painter->drawPoint(fullRect.left() + 2, fullRect.top() + 2); + painter->drawPoint(fullRect.left() + 1, fullRect.top() + 3); + painter->drawPoint(fullRect.left() + 1, fullRect.top() + 4); + + painter->drawLine(fullRect.right(), fullRect.top() + 4, fullRect.right(), fullRect.bottom()); + painter->drawPoint(fullRect.right() - 3, fullRect.top() + 1); + painter->drawPoint(fullRect.right() - 4, fullRect.top() + 1); + painter->drawPoint(fullRect.right() - 2, fullRect.top() + 2); + painter->drawPoint(fullRect.right() - 1, fullRect.top() + 3); + painter->drawPoint(fullRect.right() - 1, fullRect.top() + 4); + + // 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 = 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 = 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 = 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); + painter->drawPoint(maxButtonIconRect.topLeft()); + painter->drawPoint(maxButtonIconRect.topRight()); + painter->drawPoint(maxButtonIconRect.bottomLeft()); + painter->drawPoint(maxButtonIconRect.bottomRight()); + } + } + + // close button + if ((titleBar->subControls & SC_TitleBarCloseButton) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) { + QRect closeButtonRect = 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); + painter->drawLine(closeIconRect.left() + 1, closeIconRect.top(), + closeIconRect.right(), closeIconRect.bottom() - 1); + painter->drawLine(closeIconRect.left(), closeIconRect.top() + 1, + closeIconRect.right() - 1, closeIconRect.bottom()); + painter->drawLine(closeIconRect.right() - 1, closeIconRect.top(), + closeIconRect.left(), closeIconRect.bottom() - 1); + painter->drawLine(closeIconRect.right(), closeIconRect.top() + 1, + closeIconRect.left() + 1, closeIconRect.bottom()); + painter->drawPoint(closeIconRect.topLeft()); + painter->drawPoint(closeIconRect.topRight()); + painter->drawPoint(closeIconRect.bottomLeft()); + painter->drawPoint(closeIconRect.bottomRight()); + + 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 = 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); + painter->drawPoint(frontWindowRect.topLeft()); + painter->drawPoint(frontWindowRect.topRight()); + painter->drawPoint(frontWindowRect.bottomLeft()); + painter->drawPoint(frontWindowRect.bottomRight()); + + 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); + painter->drawPoint(backWindowRect.topLeft()); + painter->drawPoint(backWindowRect.topRight()); + painter->drawPoint(backWindowRect.bottomLeft()); + painter->drawPoint(backWindowRect.bottomRight()); + painter->restore(); + } + } + + // context help button + if (titleBar->subControls & SC_TitleBarContextHelpButton + && (titleBar->titleBarFlags & Qt::WindowContextHelpButtonHint)) { + QRect contextHelpButtonRect = 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 = 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 = 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 = 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(); + 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<const QStyleOptionSlider *>(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 rect = scrollBar->rect; + QRect scrollBarSubLine = subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget); + QRect scrollBarAddLine = subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget); + QRect scrollBarSlider = subControlRect(control, scrollBar, SC_ScrollBarSlider, widget); + QRect grooveRect = 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 = 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); + drawPrimitive(arrow, &arrowOpt, painter, widget); + + + // The AddLine (down/right) button + if (scrollBar->subControls & SC_ScrollBarAddLine) { + QString addLinePixmapName = 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); + 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<const QStyleOptionComboBox *>(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 = uniqueName(QLatin1String("combobox"), option, comboBox->rect.size()); + if (sunken) + pixmapName += QLatin1String("-sunken"); + if (comboBox->editable) + pixmapName += QLatin1String("-editable"); + if (isEnabled) + pixmapName += QLatin1String("-enabled"); + + if (!UsePixmapCache || !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 = subControlRect(CC_ComboBox, &comboBoxCopy, + SC_ComboBoxArrow, widget); + QRect editRect = 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; + } + + 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; + } + 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 && (option->state & State_KeyboardFocusChange)) && !comboBox->editable) { + QStyleOptionFocusRect focus; + focus.rect = subControlRect(CC_ComboBox, &comboBoxCopy, SC_ComboBoxEditField, widget) + .adjusted(0, 2, option->direction == Qt::RightToLeft ? 1 : -1, -2); + drawPrimitive(PE_FrameFocusRect, &focus, &cachePainter, widget); + } + cachePainter.end(); + if (UsePixmapCache) + 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<const QStyleOptionGroupBox *>(option)) { + QRect textRect = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget); + QRect checkBoxRect = 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 = 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)); + 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; + 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<const QStyleOptionSlider *>(option)) { + QRect groove = subControlRect(CC_Slider, option, SC_SliderGroove, widget); + QRect handle = subControlRect(CC_Slider, option, SC_SliderHandle, widget); + QRect ticks = 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 = uniqueName(QLatin1String("slider_groove"), option, groove.size()); + QRect pixmapRect(0, 0, groove.width(), groove.height()); + + // draw background groove + if (!UsePixmapCache || !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(); + if (UsePixmapCache) + QPixmapCache::insert(groovePixmapName, cache); + } + painter->drawPixmap(groove.topLeft(), cache); + + // draw blue groove highlight + QRect clipRect; + groovePixmapName += QLatin1String("_blue"); + if (!UsePixmapCache || !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(); + if (UsePixmapCache) + 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 = uniqueName(QLatin1String("slider_handle"), option, handle.size()); + if (!UsePixmapCache || !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); + handlePainter.drawLine(QPoint(r.left(), r.bottom() - 2), QPoint(r.left() + 2, r.bottom())); + handlePainter.drawLine(QPoint(r.left(), r.top() + 2), QPoint(r.left() + 2, r.top())); + handlePainter.drawLine(QPoint(r.right(), r.bottom() - 2), QPoint(r.right() - 2, r.bottom())); + handlePainter.drawLine(QPoint(r.right(), r.top() + 2), QPoint(r.right() - 2, r.top())); + 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(); + if (UsePixmapCache) + QPixmapCache::insert(handlePixmapName, cache); + } + + painter->drawPixmap(handle.topLeft(), cache); + + if (slider->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*slider); + fropt.rect = slider->rect; + drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + } + if (option->subControls & SC_SliderTickmarks) { + painter->setPen(darkOutline); + int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget); + int available = 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 = 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 + 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_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; + 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<const QStyleOptionButton *>(option)) { + if (!btn->text.isEmpty() && newSize.width() < 80) + newSize.setWidth(80); + if (!btn->icon.isNull() && btn->iconSize.height() > 16) + newSize -= QSize(0, 2); + } + if (const QPushButton *button = qobject_cast<const QPushButton *>(widget)) { + if (qobject_cast<const QDialogButtonBox *>(button->parentWidget())) { + if (newSize.height() < 32) + newSize.setHeight(32); + } + } + break; + case CT_GroupBox: + case CT_RadioButton: + case CT_CheckBox: + newSize += QSize(0, 1); + break; + case CT_ToolButton: +#ifndef QT_NO_TOOLBAR + if (widget && qobject_cast<QToolBar *>(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<const QStyleOptionMenuItem *>(option)) { + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + if (!menuItem->text.isEmpty()) { + newSize.setHeight(menuItem->fontMetrics.lineSpacing()); + } + } +#ifndef QT_NO_COMBOBOX + else if (!menuItem->icon.isNull()) { + if (const QComboBox *combo = qobject_cast<const QComboBox*>(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<const QStyleOptionComplex *>(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); +#ifdef Q_WS_X11 + Q_D(QCleanlooksStyle); + + QString dataDirs = QLatin1String(getenv("XDG_DATA_DIRS")); + + if (dataDirs.isEmpty()) + dataDirs = QLatin1String("/usr/local/share/:/usr/share/"); + + dataDirs.prepend(QDir::homePath() + QLatin1String("/:")); + d->iconDirs = dataDirs.split(QLatin1String(":")); +#endif +} + +/*! + \reimp +*/ +void QCleanlooksStyle::polish(QWidget *widget) +{ + QWindowsStyle::polish(widget); + if (qobject_cast<QAbstractButton*>(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast<QComboBox *>(widget) +#endif +#ifndef QT_NO_PROGRESSBAR + || qobject_cast<QProgressBar *>(widget) +#endif +#ifndef QT_NO_SCROLLBAR + || qobject_cast<QScrollBar *>(widget) +#endif +#ifndef QT_NO_SPLITTER + || qobject_cast<QSplitterHandle *>(widget) +#endif + || qobject_cast<QAbstractSlider *>(widget) +#ifndef QT_NO_SPINBOX + || qobject_cast<QAbstractSpinBox *>(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<QAbstractButton*>(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast<QComboBox *>(widget) +#endif +#ifndef QT_NO_PROGRESSBAR + || qobject_cast<QProgressBar *>(widget) +#endif +#ifndef QT_NO_SCROLLBAR + || qobject_cast<QScrollBar *>(widget) +#endif +#ifndef QT_NO_SPLITTER + || qobject_cast<QSplitterHandle *>(widget) +#endif + || qobject_cast<QAbstractSlider *>(widget) +#ifndef QT_NO_SPINBOX + || qobject_cast<QAbstractSpinBox *>(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<const QStyleOptionSlider *>(option)) { + int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget); + switch (subControl) { + case SC_SliderHandle: { + if (slider->orientation == Qt::Horizontal) { + rect.setHeight(pixelMetric(PM_SliderThickness)); + rect.setWidth(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(pixelMetric(PM_SliderThickness)); + rect.setHeight(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<const QStyleOptionSpinBox *>(option)) { + QSize bs; + int center = spinbox->rect.height() / 2; + int fw = spinbox->frame ? 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<const QStyleOptionGroupBox *>(option)) { + int topMargin = 0; + int topHeight = 0; + int verticalAlignment = 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<const QGroupBox *>(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 = pixelMetric(PM_IndicatorWidth, option, widget); + int indicatorHeight = 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 = 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<const QStyleOptionComboBox *>(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<const QStyleOptionTitleBar *>(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<const QStyleOptionComboBox *>(option)) + ret = !cmb->editable; + else + ret = 0; + break; + case SH_WindowFrame_Mask: + ret = 1; + if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask *>(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<const QStyleOptionDockWidgetV2*>(opt); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + if (verticalTitleBar) { + r.adjust(0, 0, 0, -4); + } else { + if (QApplication::layoutDirection() == 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; +} + +void QCleanlooksStylePrivate::lookupIconTheme() const +{ +#ifdef Q_WS_X11 + + if (themeName.isEmpty()) { + //resolve glib and gconf functions + p_g_type_init = (Ptr_g_type_init)QLibrary::resolve(QLatin1String("gobject-2.0"), 0, "g_type_init"); + p_gconf_client_get_default = (Ptr_gconf_client_get_default)QLibrary::resolve(QLatin1String("gconf-2"), 4, "gconf_client_get_default"); + p_gconf_client_get_string = (Ptr_gconf_client_get_string)QLibrary::resolve(QLatin1String("gconf-2"), 4, "gconf_client_get_string"); + p_g_object_unref = (Ptr_g_object_unref)QLibrary::resolve(QLatin1String("gobject-2.0"), 0, "g_object_unref"); + p_g_error_free = (Ptr_g_error_free)QLibrary::resolve(QLatin1String("glib-2.0"), 0, "g_error_free"); + p_g_free = (Ptr_g_free)QLibrary::resolve(QLatin1String("glib-2.0"), 0, "g_free"); + + if (p_g_type_init && + p_gconf_client_get_default && + p_gconf_client_get_string && + p_g_object_unref && + p_g_error_free && + p_g_free) { + + p_g_type_init(); + GConfClient* client = p_gconf_client_get_default(); + GError *err = 0; + char *str = p_gconf_client_get_string(client, "/desktop/gnome/interface/icon_theme", &err); + if (!err) { + themeName = QString::fromUtf8(str); + p_g_free(str); + } + p_g_object_unref(client); + if (err) + p_g_error_free (err); + } + if (themeName.isEmpty()) + themeName = QLatin1String("gnome"); + } +#endif +} + +/*! + \internal +*/ +QIcon QCleanlooksStyle::standardIconImplementation(StandardPixmap standardIcon, + const QStyleOption *option, + const QWidget *widget) const +{ +#ifdef Q_WS_X11 + Q_D(const QCleanlooksStyle); + if (!qApp->desktopSettingsAware()) + return QWindowsStyle::standardIconImplementation(standardIcon, option, widget); + QIcon icon; + QPixmap pixmap; + QPixmap link; + d->lookupIconTheme(); + switch (standardIcon) { + case SP_DirIcon: { + icon = QIcon(standardPixmap(standardIcon, option, widget)); + icon.addPixmap(standardPixmap(SP_DirClosedIcon, option, widget), + QIcon::Normal, QIcon::Off); + pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory.png")); + if (!pixmap.isNull()) + icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off); + pixmap = d->findIcon(48, QLatin1String("gnome-fs-directory.png")); + if (!pixmap.isNull()) + icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off); + pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory-accept.png")); + if (!pixmap.isNull()) + icon.addPixmap(pixmap, QIcon::Normal, QIcon::On); + pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory-accept.png")); + if (!pixmap.isNull()) + icon.addPixmap(pixmap, QIcon::Normal, QIcon::On); + } + break; + case SP_DirLinkIcon: + { + icon = QIcon(standardPixmap(standardIcon, option, widget)); + QPixmap link = d->findIcon(12, QLatin1String("emblem-symbolic-link.png")); + if (!link.isNull()) { + icon.addPixmap(standardPixmap(SP_DirLinkIcon, option, widget)); + pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory.png")); + if (!pixmap.isNull()) { + QPainter painter(&pixmap); + painter.drawPixmap(8, 8, 8, 8, link); + painter.end(); + icon.addPixmap(pixmap); + } + } + break; + } + case SP_FileIcon: + { + icon = d->createIcon(QLatin1String("unknown.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("gnome-fs-regular.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("stock_new.png")); + break; + } + case SP_DialogCloseButton: + { + icon = d->createIcon(QLatin1String("gtk-close.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("stock-close.png")); + break; + } + case SP_DirHomeIcon: + { + icon = d->createIcon(QLatin1String("folder_home.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("gnome_home.png")); + break; + } + case SP_DriveFDIcon: + { + icon = d->createIcon(QLatin1String("gnome-dev-floppy.png")); + break; + } + case SP_ComputerIcon: + { + icon = d->createIcon(QLatin1String("gnome-fs-client.png")); + break; + } + case SP_DesktopIcon: + { + icon = d->createIcon(QLatin1String("gnome-fs-desktop.png")); + break; + } + case SP_TrashIcon: + { + icon = d->createIcon(QLatin1String("gnome-fs-trash-empty.png")); + break; + } + case SP_DriveCDIcon: + case SP_DriveDVDIcon: + { + icon = d->createIcon(QLatin1String("gnome-dev-cdrom.png")); + break; + } + case SP_DriveHDIcon: + { + icon = d->createIcon(QLatin1String("gnome-dev-harddisk.png")); + break; + } + case SP_ArrowUp: + { + icon = d->createIcon(QLatin1String("stock_up.png")); + break; + } + case SP_ArrowDown: + { + icon = d->createIcon(QLatin1String("stock_down.png")); + break; + } + case SP_ArrowRight: + { + icon = d->createIcon(QLatin1String("stock_right.png")); + break; + } + case SP_ArrowLeft: + { + icon = d->createIcon(QLatin1String("stock_left.png")); + break; + } + case SP_BrowserReload: + { + icon = d->createIcon(QLatin1String("view-refresh.png")); + break; + } + case SP_BrowserStop: + { + pixmap = d->findIcon(24, QLatin1String("stop.png")); + break; + } + case SP_FileLinkIcon: + { + icon = QIcon(standardPixmap(standardIcon, option, widget)); + QPixmap link = d->findIcon(12, QLatin1String("emblem-symbolic-link.png")); + if (!link.isNull()) { + icon.addPixmap(standardPixmap(SP_FileLinkIcon,option, widget)); + pixmap = d->findIcon(16, QLatin1String("unknown.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(16, QLatin1String("stock_new.png")); + if (!pixmap.isNull()) { + QPainter painter(&pixmap); + painter.drawPixmap(8, 8, 8, 8, link); + painter.end(); + icon.addPixmap(pixmap); + } + } + break; + } + case SP_ArrowForward: + if (QApplication::layoutDirection() == Qt::RightToLeft) + return standardIconImplementation(SP_ArrowLeft, option, widget); + return standardIconImplementation(SP_ArrowRight, option, widget); + case SP_ArrowBack: + if (QApplication::layoutDirection() == Qt::RightToLeft) + return standardIconImplementation(SP_ArrowRight, option, widget); + return standardIconImplementation(SP_ArrowLeft, option, widget); + default: + icon = QIcon(standardPixmap(standardIcon, option, widget)); + } + if (!icon.isNull()) + return icon; +#endif // Q_WS_X11 + return QWindowsStyle::standardIconImplementation(standardIcon, option, widget); +} + +/*! + \reimp + */ +QPixmap QCleanlooksStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget) const +{ +#ifdef Q_WS_X11 + Q_D(const QCleanlooksStyle); + QPixmap pixmap; + if (!qApp->desktopSettingsAware()) + return QWindowsStyle::standardPixmap(standardPixmap, opt, widget); + d->lookupIconTheme(); +#ifndef QT_NO_IMAGEFORMAT_XPM + switch (standardPixmap) { + case SP_MessageBoxInformation: + { + pixmap = d->findIcon(48, QLatin1String("dialog-info.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(48, QLatin1String("stock_dialog-info.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MessageBoxWarning: + { + pixmap = d->findIcon(48, QLatin1String("dialog-warning.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(48, QLatin1String("stock_dialog-warning.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MessageBoxCritical: + { + pixmap = d->findIcon(48, QLatin1String("dialog-error.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(48, QLatin1String("stock_dialog-error.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MessageBoxQuestion: + { + pixmap = d->findIcon(48, QLatin1String("dialog-question.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DirHomeIcon: + { + pixmap = d->findIcon(16, QLatin1String("folder_home.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(16, QLatin1String("gnome_home.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DialogOpenButton: + case SP_DirOpenIcon: + { + pixmap = d->findIcon(24, QLatin1String("stock_open.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_FileIcon: + { + pixmap = d->findIcon(24, QLatin1String("unknown.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(24, QLatin1String("gnome-fs-regular.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(24, QLatin1String("stock_new.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_FileLinkIcon: + { + pixmap = d->findIcon(24, QLatin1String("emblem-symbolic-link.png")); + if (!pixmap.isNull()) { + QPixmap fileIcon = d->findIcon(24, QLatin1String("unknown.png")); + if (fileIcon.isNull()) + fileIcon = d->findIcon(24, QLatin1String("stock_new.png")); + if (!fileIcon.isNull()) { + QPainter painter(&fileIcon); + painter.setRenderHint(QPainter::SmoothPixmapTransform); + painter.drawPixmap(12, 12, 12, 12, pixmap); + return fileIcon; + } + } + break; + } + case SP_DirClosedIcon: + case SP_DirIcon: + { + pixmap = d->findIcon(24, QLatin1String("gnome-fs-directory.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DirLinkIcon: + { + pixmap = d->findIcon(24, QLatin1String("emblem-symbolic-link.png")); + if (!pixmap.isNull()) { + QPixmap dirIcon = d->findIcon(24, QLatin1String("gnome-fs-directory.png")); + if (!dirIcon.isNull()) { + QPainter painter(&dirIcon); + painter.setRenderHint(QPainter::SmoothPixmapTransform); + painter.drawPixmap(12, 12, 12, 12, pixmap); + return dirIcon; + } + } + break; + } + case SP_DriveFDIcon: + { + pixmap = d->findIcon(24, QLatin1String("gnome-dev-floppy.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_ComputerIcon: + { + pixmap = d->findIcon(24, QLatin1String("gnome-fs-client.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DesktopIcon: + { + pixmap = d->findIcon(24, QLatin1String("gnome-fs-desktop.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_TrashIcon: + { + pixmap = d->findIcon(24, QLatin1String("gnome-fs-trash-empty.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DriveCDIcon: + case SP_DriveDVDIcon: + { + pixmap = d->findIcon(24, QLatin1String("gnome-dev-cdrom.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DriveHDIcon: + { + pixmap = d->findIcon(24, QLatin1String("gnome-dev-harddisk.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_FileDialogToParent: + { + pixmap = d->findIcon(16, QLatin1String("stock_up.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_FileDialogNewFolder: + { + pixmap = d->findIcon(16, QLatin1String("stock_new-dir.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_ArrowUp: + { + pixmap = d->findIcon(16, QLatin1String("stock_up.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_ArrowDown: + { + pixmap = d->findIcon(16, QLatin1String("stock_down.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_ArrowRight: + { + pixmap = d->findIcon(16, QLatin1String("stock_right.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_ArrowLeft: + { + pixmap = d->findIcon(16, QLatin1String("stock_left.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DialogCloseButton: + { + pixmap = d->findIcon(24, QLatin1String("gtk-close.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(24, QLatin1String("stock-close.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DialogApplyButton: + { + pixmap = d->findIcon(24, QLatin1String("dialog-apply.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(24, QLatin1String("stock-apply.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DialogResetButton: + { + pixmap = d->findIcon(24, QLatin1String("gtk-clear.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DialogHelpButton: + { + pixmap = d->findIcon(24, QLatin1String("gtk-help.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DialogOkButton: + { + pixmap = d->findIcon(24, QLatin1String("dialog-ok.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(24, QLatin1String("stock-ok.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DialogCancelButton: + { + pixmap = d->findIcon(24, QLatin1String("dialog-cancel.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(24, QLatin1String("stock-cancel.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(24, QLatin1String("process-stop.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DialogSaveButton: + { + pixmap = d->findIcon(24, QLatin1String("stock_save.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_BrowserStop: + { + pixmap = d->findIcon(16, QLatin1String("process-stop.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_BrowserReload: + { + pixmap = d->findIcon(16, QLatin1String("view-refresh.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaPlay: + { + pixmap = d->findIcon(24, QLatin1String("media-playback-start.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaPause: + { + pixmap = d->findIcon(24, QLatin1String("media-playback-pause.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaStop: + { + pixmap = d->findIcon(24, QLatin1String("media-playback-stop.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaVolume: + { + pixmap = d->findIcon(16, QLatin1String("audio-volume-medium.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaVolumeMuted: + { + pixmap = d->findIcon(16, QLatin1String("audio-volume-muted.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaSeekForward: + { + pixmap = d->findIcon(24, QLatin1String("media-seek-forward.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaSeekBackward: + { + pixmap = d->findIcon(24, QLatin1String("media-seek-backward.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaSkipForward: + { + pixmap = d->findIcon(24, QLatin1String("media-skip-forward.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaSkipBackward: + { + pixmap = d->findIcon(24, QLatin1String("media-skip-backward.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_TitleBarMenuButton: + case SP_TitleBarShadeButton: + case SP_TitleBarUnshadeButton: + case SP_TitleBarMaxButton: + case SP_TitleBarContextHelpButton: + return QWindowsStyle::standardPixmap(standardPixmap, opt, widget); + 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 +#endif //Q_WS_X11 + return QWindowsStyle::standardPixmap(standardPixmap, opt, widget); +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_CLEANLOOKS || QT_PLUGIN diff --git a/src/gui/styles/qcleanlooksstyle.h b/src/gui/styles/qcleanlooksstyle.h new file mode 100644 index 0000000000..1da457e3f0 --- /dev/null +++ b/src/gui/styles/qcleanlooksstyle.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLEANLOOKSSTYLE_H +#define QCLEANLOOKSSTYLE_H + +#include <QtGui/qwindowsstyle.h> + +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/gui/styles/qcleanlooksstyle_p.h b/src/gui/styles/qcleanlooksstyle_p.h new file mode 100644 index 0000000000..dfc4441d3e --- /dev/null +++ b/src/gui/styles/qcleanlooksstyle_p.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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() { + } + + void lookupIconTheme() const; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_CLEANLOOKS + +#endif //QCLEANLOOKSSTYLE_P_H diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp new file mode 100644 index 0000000000..3cae08ab8c --- /dev/null +++ b/src/gui/styles/qcommonstyle.cpp @@ -0,0 +1,6357 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcommonstyle.h" +#include "qcommonstyle_p.h" + +#include <qfile.h> +#include <qapplication.h> +#include <qbitmap.h> +#include <qcache.h> +#include <qdockwidget.h> +#include <qdrawutil.h> +#include <qdialogbuttonbox.h> +#include <qformlayout.h> +#include <qgroupbox.h> +#include <qmath.h> +#include <qmenu.h> +#include <qpainter.h> +#include <qpaintengine.h> +#include <qpainterpath.h> +#include <qslider.h> +#include <qstyleoption.h> +#include <qtabbar.h> +#include <qtabwidget.h> +#include <qtoolbar.h> +#include <qtoolbutton.h> +#include <qrubberband.h> +#include <private/qapplication_p.h> +#include <private/qcommonstylepixmaps_p.h> +#include <private/qmath_p.h> +#include <qdebug.h> +#include <qtextformat.h> +#include <qwizard.h> +#include <qtabbar.h> +#include <qfileinfo.h> +#include <qdir.h> +#include <qsettings.h> +#include <qpixmapcache.h> + +#include <limits.h> + +#ifndef QT_NO_ITEMVIEWS +# include "private/qtextengine_p.h" +#endif + +#ifdef Q_WS_X11 +# include <private/qt_x11_p.h> +#endif + +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) +{ } + +/*! + \overload + + 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: + 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<const QStyleOptionFocusRect *>(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<QLineF> 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<const QStyleOptionFrame *>(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<QToolBar *>(widget->parentWidget())) + break; + if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)){ + qDrawShadePanel(p, frame->rect, frame->palette, false, frame->lineWidth, + &frame->palette.brush(QPalette::Button)); + + } + else if (const QStyleOptionToolBar *frame = qstyleoption_cast<const QStyleOptionToolBar *>(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<const QStyleOptionProgressBarV2 *>(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<const QStyleOptionQ3ListView *>(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<const QStyleOptionQ3ListView *>(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<const QStyleOptionHeader *>(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<const QStyleOptionTabBarBase *>(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 = 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); + 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: + drawPrimitive(PE_Frame, opt, p, widget); + break; +#ifndef QT_NO_GROUPBOX + case PE_FrameGroupBox: + if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) { + const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(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<const QStyleOptionFrame *>(opt)) { + int lw = frame->lineWidth; + if (lw <= 0) + lw = 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 (QApplication::layoutDirection() == 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: + 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 = 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 = 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 = pixelMetric(PM_ButtonShiftHorizontal); + bsy = 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<const QStyleOptionTab *>(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<const QStyleOptionFrame *>(opt)) { + p->fillRect(panel->rect.adjusted(panel->lineWidth, panel->lineWidth, -panel->lineWidth, -panel->lineWidth), + panel->palette.brush(QPalette::Base)); + + if (panel->lineWidth > 0) + drawPrimitive(PE_FrameLineEdit, panel, p, widget); + } + break; +#endif // QT_NO_LINEEDIT +#ifndef QT_NO_COLUMNVIEW + case PE_IndicatorColumnViewArrow: { + if (const QStyleOptionViewItem *viewOpt = qstyleoption_cast<const QStyleOptionViewItem *>(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<const QStyleOptionViewItemV4 *>(opt)) { + 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) && 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<const QStyleOptionViewItemV4 *>(opt)) { + 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)) { + 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 + + + +#ifdef Q_WS_X11 // These functions are used to parse the X11 freedesktop icon spec + +void QCommonStylePrivate::lookupIconTheme() const +{ + if (!themeName.isEmpty()) + return; + + QString dataDirs = QString::fromLocal8Bit(getenv("XDG_DATA_DIRS")); + if (dataDirs.isEmpty()) + dataDirs = QLatin1String("/usr/local/share/:/usr/share/"); + dataDirs += QLatin1Char(':') + QApplicationPrivate::kdeHome() + QLatin1String("/share"); + dataDirs.prepend(QDir::homePath() + QLatin1String("/:")); + QStringList kdeDirs = QString::fromLocal8Bit(getenv("KDEDIRS")).split(QLatin1Char(':')); + foreach (const QString &dirName, kdeDirs) + dataDirs.append(QLatin1String(":") + dirName + QLatin1String("/share")); + iconDirs = dataDirs.split(QLatin1Char(':')); + + QFileInfo fileInfo(QLatin1String("/usr/share/icons/default.kde")); + QDir dir(fileInfo.canonicalFilePath()); + int kdeVersion = qgetenv("KDE_SESSION_VERSION").toInt(); + QString kdeDefault = kdeVersion >= 4 ? QString::fromLatin1("oxygen") : QString::fromLatin1("crystalsvg"); + QString defaultTheme = fileInfo.exists() ? dir.dirName() : kdeDefault; + QSettings settings(QApplicationPrivate::kdeHome() + + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); + settings.beginGroup(QLatin1String("Icons")); + themeName = settings.value(QLatin1String("Theme"), defaultTheme).toString(); +} + +QIconTheme QCommonStylePrivate::parseIndexFile(const QString &themeName) const +{ + Q_Q(const QCommonStyle); + QIconTheme theme; + QFile themeIndex; + QStringList parents; + QHash <int, QString> dirList; + + for ( int i = 0 ; i < iconDirs.size() && !themeIndex.exists() ; ++i) { + QString contentDir = QLatin1String(iconDirs[i].startsWith(QDir::homePath()) ? + "/.icons/" : "/icons/"); + themeIndex.setFileName(iconDirs[i] + contentDir + + themeName + QLatin1String("/index.theme")); + } + + if (themeIndex.open(QIODevice::ReadOnly | QIODevice::Text)) { + + QTextStream in(&themeIndex); + + while (!in.atEnd()) { + + QString line = in.readLine(); + + if (line.startsWith(QLatin1String("Inherits="))) { + line = line.right(line.length() - 9); + parents = line.split(QLatin1Char(',')); + } + + if (line.startsWith(QLatin1String("["))) { + line = line.trimmed(); + line.chop(1); + QString dirName = line.right(line.length() - 1); + if (!in.atEnd()) { + line = in.readLine(); + int size; + if (line.startsWith(QLatin1String("Size="))) { + size = line.right(line.length() - 5).toInt(); + if (size) + dirList.insertMulti(size, dirName); + } + } + } + } + } + + if (q->inherits("QPlastiqueStyle")) { + QFileInfo fileInfo(QLatin1String("/usr/share/icons/default.kde")); + QDir dir(fileInfo.canonicalFilePath()); + QString defaultKDETheme = dir.exists() ? dir.dirName() : QString::fromLatin1("crystalsvg"); + if (!parents.contains(defaultKDETheme) && themeName != defaultKDETheme) + parents.append(defaultKDETheme); + } else if (parents.isEmpty() && themeName != QLatin1String("hicolor")) { + parents.append(QLatin1String("hicolor")); + } + theme = QIconTheme(dirList, parents); + return theme; +} + +QPixmap QCommonStylePrivate::findIconHelper(int size, + const QString &themeName, + const QString &iconName, + QStringList &visited) const +{ + QPixmap pixmap; + + if (!themeName.isEmpty()) { + + visited << themeName; + QIconTheme theme = themeList.value(themeName); + + if (!theme.isValid()) { + theme = parseIndexFile(themeName); + themeList.insert(themeName, theme); + } + + if (!theme.isValid()) + return QPixmap(); + + QList <QString> subDirs = theme.dirList().values(size); + + for ( int i = 0 ; i < iconDirs.size() ; ++i) { + for ( int j = 0 ; j < subDirs.size() ; ++j) { + QString contentDir = (iconDirs[i].startsWith(QDir::homePath())) ? + QLatin1String("/.icons/") : QLatin1String("/icons/"); + QString fileName = iconDirs[i] + contentDir + themeName + QLatin1Char('/') + subDirs[j] + QLatin1Char('/') + iconName; + QFile file(fileName); + if (file.exists()) + pixmap.load(fileName); + if (!pixmap.isNull()) + break; + } + } + + if (pixmap.isNull()) { + QStringList parents = theme.parents(); + //search recursively through inherited themes + for (int i = 0 ; pixmap.isNull() && i < parents.size() ; ++i) { + QString parentTheme = parents[i].trimmed(); + if (!visited.contains(parentTheme)) //guard against endless recursion + pixmap = findIconHelper(size, parentTheme, iconName, visited); + } + } + } + return pixmap; +} + +QPixmap QCommonStylePrivate::findIcon(int size, const QString &name) const +{ + QPixmap pixmap; + QString pixmapName = QLatin1String("$qt") + name + QString::number(size); + + if (QPixmapCache::find(pixmapName, pixmap)) + return pixmap; + + if (!themeName.isEmpty()) { + QStringList visited; + pixmap = findIconHelper(size, themeName, name, visited); + } + QPixmapCache::insert(pixmapName, pixmap); + return pixmap; +} + +QIcon QCommonStylePrivate::createIcon(const QString &name) const +{ + QIcon icon; + icon.addPixmap(findIcon(16, name)); + icon.addPixmap(findIcon(24, name)); + icon.addPixmap(findIcon(32, name)); + return icon; +} + +#endif //Q_WS_X11 + +#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 = QSizeF(widthUsed, height).toSize(); + 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<qreal>(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(int(x), int(y), elidedText); + p->restore(); + break; + } + line.draw(p, position); + } +} + +/* 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 */ +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) + 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 + +/*! + \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<const QStyleOptionButton *>(opt)) { + drawControl(CE_PushButtonBevel, btn, p, widget); + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); + drawControl(CE_PushButtonLabel, &subopt, p, widget); + if (btn->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*btn); + fropt.rect = subElementRect(SE_PushButtonFocusRect, btn, widget); + drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + break; + case CE_PushButtonBevel: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { + QRect br = btn->rect; + int dbi = pixelMetric(PM_ButtonDefaultIndicator, btn, widget); + if (btn->features & QStyleOptionButton::DefaultButton) + 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; + drawPrimitive(PE_PanelButtonCommand, &tmpBtn, p, widget); + } + if (btn->features & QStyleOptionButton::HasMenu) { + int mbi = 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); + drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); + } + } + break; + case CE_PushButtonLabel: + if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(opt)) { + QRect textRect = button->rect; + uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic; + if (!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(pixelMetric(PM_ButtonShiftHorizontal, opt, widget), + pixelMetric(PM_ButtonShiftVertical, opt, widget)); + p->drawPixmap(iconRect, pixmap); + } else { + tf |= Qt::AlignHCenter; + } + if (button->state & (State_On | State_Sunken)) + textRect.translate(pixelMetric(PM_ButtonShiftHorizontal, opt, widget), + pixelMetric(PM_ButtonShiftVertical, opt, widget)); + + if (button->features & QStyleOptionButton::HasMenu) { + int indicatorSize = 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); + } + 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<const QStyleOptionButton *>(opt)) { + bool isRadio = (element == CE_RadioButton); + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator + : SE_CheckBoxIndicator, btn, widget); + drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox, + &subopt, p, widget); + subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents + : SE_CheckBoxContents, btn, widget); + 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); + drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + break; + case CE_RadioButtonLabel: + case CE_CheckBoxLabel: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { + uint alignment = visualAlignment(btn->direction, Qt::AlignLeft | Qt::AlignVCenter); + + if (!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); + 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()){ + 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; + 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<const QStyleOptionMenuItem *>(opt)) { + uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip + | Qt::TextSingleLine; + if (!styleHint(SH_UnderlineShortcut, mbi, widget)) + alignment |= Qt::TextHideMnemonic; + QPixmap pix = mbi->icon.pixmap(pixelMetric(PM_SmallIconSize), (mbi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled); + if (!pix.isNull()) + drawItemPixmap(p,mbi->rect, alignment, pix); + else + 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<const QStyleOptionProgressBar *>(opt)) { + QStyleOptionProgressBarV2 subopt = *pb; + subopt.rect = subElementRect(SE_ProgressBarGroove, pb, widget); + drawControl(CE_ProgressBarGroove, &subopt, p, widget); + subopt.rect = subElementRect(SE_ProgressBarContents, pb, widget); + drawControl(CE_ProgressBarContents, &subopt, p, widget); + if (pb->textVisible) { + subopt.rect = subElementRect(SE_ProgressBarLabel, pb, widget); + drawControl(CE_ProgressBarLabel, &subopt, p, widget); + } + } + break; + case CE_ProgressBarGroove: + qDrawShadePanel(p, opt->rect, opt->palette, true, 1, + &opt->palette.brush(QPalette::Window)); + break; + case CE_ProgressBarLabel: + if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) { + bool vertical = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(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); + drawItemText(p, shadowRect, Qt::AlignCenter | Qt::TextSingleLine, shadowPalette, + pb->state & State_Enabled, pb->text, textRole); + } + 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<const QStyleOptionProgressBar *>(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<const QStyleOptionProgressBarV2 *>(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 = 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(); + 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(); + drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget); + } + } + } + break; +#endif // QT_NO_PROGRESSBAR + case CE_HeaderLabel: + if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { + QRect rect = header->rect; + if (!header->icon.isNull()) { + QPixmap pixmap + = header->icon.pixmap(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); + } + 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<const QStyleOptionToolButton *>(opt)) { + QRect rect = toolbutton->rect; + int shiftX = 0; + int shiftY = 0; + if (toolbutton->state & (State_Sunken | State_On)) { + shiftX = pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget); + shiftY = 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 (!styleHint(SH_UnderlineShortcut, opt, widget)) + alignment |= Qt::TextHideMnemonic; + rect.translate(shiftX, shiftY); + 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 (!styleHint(SH_UnderlineShortcut, opt, widget)) + alignment |= Qt::TextHideMnemonic; + + if (toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { + pr.setHeight(pmSize.height() + 6); + tr.adjust(0, pr.height(), 0, -3); + pr.translate(shiftX, shiftY); + if (!hasArrow) { + 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) { + 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); + 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 { + drawItemPixmap(p, rect, Qt::AlignCenter, pm); + } + } + } + } + break; +#endif // QT_NO_TOOLBUTTON +#ifndef QT_NO_TOOLBOX + case CE_ToolBoxTab: + if (const QStyleOptionToolBox *tb = qstyleoption_cast<const QStyleOptionToolBox *>(opt)) { + drawControl(CE_ToolBoxTabShape, tb, p, widget); + drawControl(CE_ToolBoxTabLabel, tb, p, widget); + } + break; + case CE_ToolBoxTabShape: + if (const QStyleOptionToolBox *tb = qstyleoption_cast<const QStyleOptionToolBox *>(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<const QStyleOptionTab *>(opt)) { + drawControl(CE_TabBarTabShape, tab, p, widget); + drawControl(CE_TabBarTabLabel, tab, p, widget); + } + break; + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) { + p->save(); + + QRect rect(tab->rect); + bool selected = tab->state & State_Selected; + bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab; + int tabOverlap = onlyOne ? 0 : 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<const QStyleOptionToolBox *>(opt)) { + bool enabled = tb->state & State_Enabled; + bool selected = tb->state & State_Selected; + QPixmap pm = tb->icon.pixmap(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 && 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 (!styleHint(QStyle::SH_UnderlineShortcut, tb, widget)) + alignment |= Qt::TextHideMnemonic; + 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; + drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, widget); + } + } + break; + case CE_TabBarTabLabel: + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) { + // ### consider merging this with SE_TabBarTabText + 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 (!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; + } + tr.setRect(0, 0, tr.height(), tr.width()); + QTransform m; + m.translate(newX, newY); + m.rotate(newRot); + p->setTransform(m, true); + } + tr = subElementRect(SE_TabBarTabText, opt, widget); + + if (!tabV2.icon.isNull()) { + QSize iconSize = tabV2.iconSize; + if (!iconSize.isValid()) { + int iconExtent = pixelMetric(PM_SmallIconSize); + iconSize = QSize(iconExtent, iconExtent); + } + QSize tabIconSize = tabV2.icon.actualSize(iconSize, + (tabV2.state & State_Enabled) ? QIcon::Normal + : QIcon::Disabled); + QPixmap tabIcon = tabV2.icon.pixmap(iconSize, + (tabV2.state & State_Enabled) ? QIcon::Normal + : QIcon::Disabled); + + int offset = 4; + int left = opt->rect.left(); + if (tabV2.leftButtonSize.isEmpty()) + offset += 2; + else + left += tabV2.leftButtonSize.width() + (6 + 2) + 2; + QRect iconRect = QRect(left + offset, tr.center().y() - tabIcon.height() / 2, + tabIconSize.width(), tabIconSize.height()); + if (!verticalTabs) + iconRect = visualRect(opt->direction, opt->rect, iconRect); + p->drawPixmap(iconRect.x(), iconRect.y(), tabIcon); + } + + 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<const QStyleOptionSizeGrip *>(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<const QStyleOptionRubberBand *>(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 (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<const QStyleOptionDockWidget *>(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<const QStyleOptionDockWidgetV2*>(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(); + 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<const QStyleOptionHeader *>(opt)) { + QRegion clipRegion = p->clipRegion(); + p->setClipRect(opt->rect); + drawControl(CE_HeaderSection, header, p, widget); + QStyleOptionHeader subopt = *header; + subopt.rect = subElementRect(SE_HeaderLabel, header, widget); + if (subopt.rect.isValid()) + drawControl(CE_HeaderLabel, &subopt, p, widget); + if (header->sortIndicator != QStyleOptionHeader::None) { + subopt.rect = subElementRect(SE_HeaderArrow, opt, widget); + 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<const QStyleOptionComboBox *>(opt)) { + QRect editRect = 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)); + 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) { + 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<const QStyleOptionToolBar *>(opt)) { + // Compatibility with styles that use PE_PanelToolBar + QStyleOptionFrame frame; + frame.QStyleOption::operator=(*toolBar); + frame.lineWidth = toolBar->lineWidth; + frame.midLineWidth = toolBar->midLineWidth; + drawPrimitive(PE_PanelToolBar, opt, p, widget); + + if (widget && qobject_cast<QToolBar *>(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<const QStyleOptionViewItemV4 *>(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 + drawPrimitive(PE_PanelItemViewItem, opt, p, widget); + + // draw the check mark + if (checkRect.isValid()) { + 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; + } + 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 = 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); + 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<const QStyleOptionFrameV3 *>(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 { + 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<const QStyleOptionButton *>(opt)) { + int dx1, dx2; + dx1 = pixelMetric(PM_DefaultFrameWidth, btn, widget); + if (btn->features & QStyleOptionButton::AutoDefaultButton) + dx1 += 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<const QStyleOptionButton *>(opt)) { + int dbw1 = 0, dbw2 = 0; + if (btn->features & QStyleOptionButton::AutoDefaultButton){ + dbw1 = pixelMetric(PM_ButtonDefaultIndicator, btn, widget); + dbw2 = dbw1 * 2; + } + + int dfw1 = 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 = pixelMetric(PM_IndicatorHeight, opt, widget); + r.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - h) / 2), + 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 = 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<const QStyleOptionButton *>(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 = pixelMetric(PM_ExclusiveIndicatorHeight, opt, widget); + r.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - h) / 2), + 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 = 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<const QStyleOptionButton *>(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<const QStyleOptionSlider *>(opt)) { + int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget); + int thickness = 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<const QStyleOptionProgressBar *>(opt)) { + int textw = 0; + bool vertical = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(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<const QStyleOptionQ3DockWindow *>(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<const QStyleOptionComboBox *>(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 = 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<const QStyleOptionHeader *>(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 = 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<const QStyleOptionTabWidgetFrame *>(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 (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 (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 (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 (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<const QStyleOptionTabWidgetFrame *>(opt)) { + QStyleOptionTab tabopt; + tabopt.shape = twf->shape; + int overlap = 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<const QStyleOptionTabWidgetFrame *>(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<const QStyleOptionTabWidgetFrame *>(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: + // ### consider merging this with CE_TabBarTabLabel + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(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; + if (verticalTabs) + tr.setRect(0, 0, tr.height(), tr.width()); + int verticalShift = pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget); + int horizontalShift = pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget); + if (tabV2.shape == QTabBar::RoundedSouth || tabV2.shape == QTabBar::TriangularSouth) + verticalShift = -verticalShift; + tr.adjust(0, 0, horizontalShift, verticalShift); + bool selected = tabV2.state & State_Selected; + if (selected) { + tr.setBottom(tr.bottom() - verticalShift); + tr.setRight(tr.right() - horizontalShift); + } + + // left widget + if (!tabV2.leftButtonSize.isEmpty()) { + tr.setLeft(tr.left() + 6 + 2 + + (verticalTabs ? tabV2.leftButtonSize.height() : tabV2.leftButtonSize.width())); + } + + // icon + if (!tabV2.icon.isNull()) { + QSize iconSize = tabV2.iconSize; + if (!iconSize.isValid()) { + int iconExtent = pixelMetric(PM_SmallIconSize); + iconSize = QSize(iconExtent, iconExtent); + } + QSize tabIconSize = tabV2.icon.actualSize(iconSize, + (tabV2.state & State_Enabled) ? QIcon::Normal + : QIcon::Disabled); + int offset = 4; + if (tabV2.leftButtonSize.isEmpty()) + offset += 2; + + QRect iconRect = QRect(tr.left() + offset, tr.center().y() - tabIconSize.height() / 2, + tabIconSize.width(), tabIconSize .height()); + if (!verticalTabs) + iconRect = visualRect(opt->direction, opt->rect, iconRect); + tr.setLeft(tr.left() + tabIconSize.width() + offset + 2); + } + + // right widget + if (!tabV2.rightButtonSize.isEmpty()) { + tr.setRight(tr.right() - 6 - 2 - + (verticalTabs ? tabV2.rightButtonSize.height() : tabV2.rightButtonSize.width())); + } + + if (!verticalTabs) + tr = visualRect(opt->direction, opt->rect, tr); + r = tr; + } + break; + case SE_TabBarTabLeftButton: + case SE_TabBarTabRightButton: + if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) { + bool selected = tab->state & State_Selected; + int verticalShift = pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget); + int horizontalShift = pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget); + + 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; + } + 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<int>(ceil(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(6 + tab->rect.x(), midHeight, w, h); + else + r = QRect(tab->rect.right() - 6 - w, midHeight, w, h); + r = visualRect(tab->direction, tab->rect, r); + } + if (verticalTabs) { + if (atTheTop) + r = QRect(midWidth, tr.y() + tab->rect.height() - 6 - h, w, h); + else + r = QRect(midWidth, tr.y() + 6, w, h); + } + } + + break; +#endif // QT_NO_TABWIDGET +#ifndef QT_NO_TABBAR + case SE_TabBarTearIndicator: + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(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<const QStyleOptionFrame *>(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<const QStyleOptionFrameV2 *>(opt)) { + int fw = 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<const QStyleOptionFrameV3 *>(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 = pixelMetric(PM_SmallIconSize, opt, widget); + int buttonMargin = pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget); + int margin = pixelMetric(QStyle::PM_DockWidgetTitleMargin, opt, widget); + QRect rect = opt->rect; + + const QStyleOptionDockWidget *dwOpt + = qstyleoption_cast<const QStyleOptionDockWidget*>(opt); + bool canClose = dwOpt == 0 ? true : dwOpt->closable; + bool canFloat = dwOpt == 0 ? false : dwOpt->floatable; + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(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<const QDockWidget*>(widget)) { + QIcon icon; + if (dw->isFloating()) + icon = dw->windowIcon(); + if (!icon.isNull() + && icon.cacheKey() != qApp->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<const QStyleOptionViewItemV4 *>(opt)) { + r = subElementRect(SE_CheckBoxIndicator, opt, widget); + break; + } + case SE_ItemViewItemDecoration: + case SE_ItemViewItemText: + case SE_ItemViewItemFocusRect: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) { + if (!d->isViewItemCached(*vopt)) { + d->viewItemLayout(vopt, &d->checkRect, &d->decorationRect, &d->displayRect, false); + if (d->cachedOption) + delete d->cachedOption; + 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 + default: + break; + } + return r; +} + +#ifndef QT_NO_DIAL +static 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 = atan(m) * rad_factor; + + if (p1.x() < p2.x()) + _angle = 180 - _angle; + else + _angle = -_angle; + } + return _angle; +} + +static int calcBigLineSize(int radius) +{ + int bigLineSize = radius / 6; + if (bigLineSize < 4) + bigLineSize = 4; + if (bigLineSize > radius / 2) + bigLineSize = radius / 2; + return bigLineSize; +} + +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 - 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; +} + +static QPolygonF calcLines(const QStyleOptionSlider *dial, const QWidget *) +{ + 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; + qreal yc = height / 2; + 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; +} +#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<const QStyleOptionSlider *>(opt)) { + if (slider->subControls == SC_SliderTickmarks) { + int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget); + int ticks = slider->tickPosition; + int thickness = pixelMetric(PM_SliderControlThickness, slider, widget); + int len = pixelMetric(PM_SliderLength, slider, widget); + int available = 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<const QStyleOptionSlider *>(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 = subControlRect(cc, &newScrollbar, SC_ScrollBarSubLine, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarSubLine)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + drawControl(CE_ScrollBarSubLine, &newScrollbar, p, widget); + } + } + if (scrollbar->subControls & SC_ScrollBarAddLine) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarAddLine, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarAddLine)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + drawControl(CE_ScrollBarAddLine, &newScrollbar, p, widget); + } + } + if (scrollbar->subControls & SC_ScrollBarSubPage) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarSubPage, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarSubPage)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + drawControl(CE_ScrollBarSubPage, &newScrollbar, p, widget); + } + } + if (scrollbar->subControls & SC_ScrollBarAddPage) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarAddPage, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarAddPage)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + drawControl(CE_ScrollBarAddPage, &newScrollbar, p, widget); + } + } + if (scrollbar->subControls & SC_ScrollBarFirst) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarFirst, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarFirst)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + drawControl(CE_ScrollBarFirst, &newScrollbar, p, widget); + } + } + if (scrollbar->subControls & SC_ScrollBarLast) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarLast, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarLast)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + drawControl(CE_ScrollBarLast, &newScrollbar, p, widget); + } + } + if (scrollbar->subControls & SC_ScrollBarSlider) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarSlider, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarSlider)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + 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); + drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + } + } + break; +#endif // QT_NO_SCROLLBAR +#ifdef QT3_SUPPORT + case CC_Q3ListView: + if (const QStyleOptionQ3ListView *lv = qstyleoption_cast<const QStyleOptionQ3ListView *>(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<const QStyleOptionSpinBox *>(opt)) { + QStyleOptionSpinBox copy = *sb; + PrimitiveElement pe; + + if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) { + QRect r = 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 = subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget); + drawPrimitive(PE_PanelButtonBevel, ©, p, widget); + copy.rect.adjust(3, 0, -4, 0); + 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 = subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget); + drawPrimitive(PE_PanelButtonBevel, ©, p, widget); + copy.rect.adjust(3, 0, -4, 0); + drawPrimitive(pe, ©, p, widget); + } + } + break; +#endif // QT_NO_SPINBOX +#ifndef QT_NO_TOOLBUTTON + case CC_ToolButton: + if (const QStyleOptionToolButton *toolbutton + = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) { + QRect button, menuarea; + button = subControlRect(cc, toolbutton, SC_ToolButton, widget); + menuarea = 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; + 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, -pixelMetric(QStyle::PM_MenuButtonIndicator, + toolbutton, widget), 0); + drawPrimitive(PE_FrameFocusRect, &fr, p, widget); + } + QStyleOptionToolButton label = *toolbutton; + label.state = bflags; + int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget); + label.rect = button.adjusted(fw, fw, -fw, -fw); + 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)) + drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); + drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget); + } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { + int mbi = 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); + drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); + } + } + break; +#endif // QT_NO_TOOLBUTTON + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(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 = 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 = 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<const QDockWidget *>(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; + drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + + p->save(); + if (down) + p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + pixelMetric(PM_ButtonShiftVertical, tb, widget)); + drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + + if (tb->subControls & SC_TitleBarMaxButton + && tb->titleBarFlags & Qt::WindowMaximizeButtonHint + && !(tb->titleBarState & Qt::WindowMaximized)) { + ir = 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; + drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + + p->save(); + if (down) + p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + pixelMetric(PM_ButtonShiftVertical, tb, widget)); + drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + + if (tb->subControls & SC_TitleBarMinButton + && tb->titleBarFlags & Qt::WindowMinimizeButtonHint + && !(tb->titleBarState & Qt::WindowMinimized)) { + ir = 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; + drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + + p->save(); + if (down) + p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + pixelMetric(PM_ButtonShiftVertical, tb, widget)); + 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 = 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; + drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + + p->save(); + if (down) + p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + pixelMetric(PM_ButtonShiftVertical, tb, widget)); + drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + + if (tb->subControls & SC_TitleBarShadeButton + && tb->titleBarFlags & Qt::WindowShadeButtonHint + && !(tb->titleBarState & Qt::WindowMinimized)) { + ir = 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; + drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + p->save(); + if (down) + p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + pixelMetric(PM_ButtonShiftVertical, tb, widget)); + drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + + if (tb->subControls & SC_TitleBarUnshadeButton + && tb->titleBarFlags & Qt::WindowShadeButtonHint + && tb->titleBarState & Qt::WindowMinimized) { + ir = 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; + drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + p->save(); + if (down) + p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + pixelMetric(PM_ButtonShiftVertical, tb, widget)); + drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + if (tb->subControls & SC_TitleBarContextHelpButton + && tb->titleBarFlags & Qt::WindowContextHelpButtonHint) { + ir = 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; + drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + p->save(); + if (down) + p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget), + pixelMetric(PM_ButtonShiftVertical, tb, widget)); + drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + if (tb->subControls & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) { + ir = subControlRect(CC_TitleBar, tb, SC_TitleBarSysMenu, widget); + if (!tb->icon.isNull()) { + tb->icon.paint(p, ir); + } else { + int iconSize = pixelMetric(PM_SmallIconSize, tb, widget); + pm = standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(iconSize, iconSize); + tool.rect = ir; + p->save(); + drawItemPixmap(p, ir, Qt::AlignCenter, pm); + p->restore(); + } + } + } + break; +#ifndef QT_NO_DIAL + case CC_Dial: + if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(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(calcLines(dial, widget)); // ### calcLines could be cached... + } + + if (dial->state & State_Enabled) { + p->setBrush(pal.brush(QPalette::ColorRole(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 = 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); + 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<const QStyleOptionGroupBox *>(opt)) { + // Draw frame + QRect textRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, widget); + QRect checkBoxRect = 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 = 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); + 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 (!styleHint(QStyle::SH_UnderlineShortcut, opt, widget)) + alignment |= Qt::TextHideMnemonic; + + 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; + drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + + // Draw checkbox + if (groupBox->subControls & SC_GroupBoxCheckBox) { + QStyleOptionButton box; + box.QStyleOption::operator=(*groupBox); + box.rect = checkBoxRect; + 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 = pixelMetric(PM_ButtonShiftHorizontal); + bsy = pixelMetric(PM_ButtonShiftVertical); + } else { + btnOpt.state |= State_Raised; + btnOpt.state &= ~State_Sunken; + bsx = 0; + bsy = 0; + } + btnOpt.rect = subControlRect(CC_MdiControls, opt, SC_MdiCloseButton, widget); + drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget); + QPixmap pm = standardIcon(SP_TitleBarCloseButton).pixmap(16, 16); + 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 = pixelMetric(PM_ButtonShiftHorizontal); + bsy = pixelMetric(PM_ButtonShiftVertical); + } else { + btnOpt.state |= State_Raised; + btnOpt.state &= ~State_Sunken; + bsx = 0; + bsy = 0; + } + btnOpt.rect = subControlRect(CC_MdiControls, opt, SC_MdiNormalButton, widget); + drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget); + QPixmap pm = standardIcon(SP_TitleBarNormalButton).pixmap(16, 16); + 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 = pixelMetric(PM_ButtonShiftHorizontal); + bsy = pixelMetric(PM_ButtonShiftVertical); + } else { + btnOpt.state |= State_Raised; + btnOpt.state &= ~State_Sunken; + bsx = 0; + bsy = 0; + } + btnOpt.rect = subControlRect(CC_MdiControls, opt, SC_MdiMinButton, widget); + drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget); + QPixmap pm = standardIcon(SP_TitleBarMinButton).pixmap(16, 16); + 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<const QStyleOptionSlider *>(opt)) { + QRect r = subControlRect(cc, slider, SC_SliderHandle, widget); + if (r.isValid() && r.contains(pt)) { + sc = SC_SliderHandle; + } else { + r = 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<const QStyleOptionSlider *>(opt)) { + QRect r; + uint ctrl = SC_ScrollBarAddLine; + while (ctrl <= SC_ScrollBarGroove) { + r = 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<const QStyleOptionToolButton *>(opt)) { + QRect r; + uint ctrl = SC_ToolButton; + while (ctrl <= SC_ToolButtonMenu) { + r = 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<const QStyleOptionQ3ListView *>(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<const QStyleOptionSpinBox *>(opt)) { + QRect r; + uint ctrl = SC_SpinBoxUp; + while (ctrl <= SC_SpinBoxEditField) { + r = 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<const QStyleOptionTitleBar *>(opt)) { + QRect r; + uint ctrl = SC_TitleBarSysMenu; + + while (ctrl <= SC_TitleBarLabel) { + r = 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<const QStyleOptionComboBox *>(opt)) { + QRect r; + uint ctrl = SC_ComboBoxArrow; // Start here and go down. + while (ctrl > 0) { + r = 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<const QStyleOptionGroupBox *>(opt)) { + QRect r; + uint ctrl = SC_GroupBoxCheckBox; + while (ctrl <= SC_GroupBoxFrame) { + r = 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 = 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<const QStyleOptionSlider *>(opt)) { + int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget); + int thickness = pixelMetric(PM_SliderControlThickness, slider, widget); + + switch (sc) { + 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) + 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<const QStyleOptionSlider *>(opt)) { + const QRect scrollBarRect = scrollbar->rect; + int sbextent = 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 = 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<const QStyleOptionSpinBox *>(opt)) { + QSize bs; + int fw = spinbox->frame ? 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<const QStyleOptionToolButton *>(opt)) { + int mbi = 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<const QStyleOptionComboBox *>(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<const QStyleOptionTitleBar *>(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<const QStyleOptionGroupBox *>(opt)) { + switch (sc) { + case SC_GroupBoxFrame: + // FALL THROUGH + case SC_GroupBoxContents: { + int topMargin = 0; + int topHeight = 0; + int verticalAlignment = 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 = 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 = pixelMetric(PM_IndicatorWidth, opt, widget); + int indicatorSpace = 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 = 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 = 5; + break; + case PM_DialogButtonsButtonWidth: + ret = 70; + break; + case PM_DialogButtonsButtonHeight: + ret = 30; + break; + case PM_CheckListControllerSize: + case PM_CheckListButtonSize: + ret = 16; + break; + case PM_TitleBarHeight: { + if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) { + if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool) { + ret = qMax(widget ? widget->fontMetrics().lineSpacing() : opt->fontMetrics.lineSpacing(), 16); +#ifndef QT_NO_DOCKWIDGET + } else if (qobject_cast<const QDockWidget*>(widget)) { + ret = qMax(widget->fontMetrics().lineSpacing(), 13); +#endif + } else { + ret = qMax(widget ? widget->fontMetrics().lineSpacing() : opt->fontMetrics.lineSpacing(), 18); + } + } else { + ret = 18; + } + + break; } + case PM_ScrollBarSliderMin: + ret = 9; + break; + + case PM_ButtonMargin: + ret = 6; + break; + + case PM_DockWidgetTitleBarButtonMargin: + ret = 2; + break; + + case PM_ButtonDefaultIndicator: + ret = 0; + break; + + case PM_MenuButtonIndicator: + ret = 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 = pixelMetric(PM_DefaultFrameWidth, opt, widget); + break; + + case PM_MdiSubWindowFrameWidth: + ret = 4; + break; + + case PM_MdiSubWindowMinimizedWidth: + ret = 196; + break; + +#ifndef QT_NO_SCROLLBAR + case PM_ScrollBarExtent: + if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { + int s = sb->orientation == Qt::Horizontal ? + QApplication::globalStrut().height() + : QApplication::globalStrut().width(); + ret = qMax(16, s); + } else { + ret = 16; + } + break; +#endif + case PM_MaximumDragDistance: + ret = -1; + break; + +#ifndef QT_NO_SLIDER + case PM_SliderThickness: + ret = 16; + break; + + case PM_SliderTickmarkOffset: + if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { + int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height() + : sl->rect.width(); + int thickness = 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<const QStyleOptionSlider *>(opt)) { + if (sl->orientation == Qt::Horizontal) + ret = sl->rect.width() - pixelMetric(PM_SliderLength, sl, widget); + else + ret = sl->rect.height() - pixelMetric(PM_SliderLength, sl, widget); + } else { + ret = 0; + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_DOCKWIDGET + case PM_DockWidgetSeparatorExtent: + ret = 6; + break; + + case PM_DockWidgetHandleExtent: + ret = 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 = 4; + break; + + case PM_ToolBarHandleExtent: + ret = 8; + break; + + case PM_ToolBarSeparatorExtent: + ret = 6; + break; + + case PM_ToolBarExtensionExtent: + ret = 12; + break; +#endif // QT_NO_TOOLBAR + +#ifndef QT_NO_TABBAR + case PM_TabBarTabOverlap: + ret = 3; + break; + + case PM_TabBarTabHSpace: + ret = 24; + break; + + case PM_TabBarTabShiftHorizontal: + ret = 0; + break; + + case PM_TabBarTabShiftVertical: + ret = 2; + break; + + case PM_TabBarTabVSpace: { + const QStyleOptionTab *tb = qstyleoption_cast<const QStyleOptionTab *>(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 = 13; + break; + + case PM_IndicatorHeight: + ret = 13; + break; + + case PM_ExclusiveIndicatorWidth: + ret = 12; + break; + + case PM_ExclusiveIndicatorHeight: + ret = 12; + break; + + case PM_MenuTearoffHeight: + ret = 10; + break; + + case PM_MenuScrollerHeight: + ret = 10; + break; + + case PM_MenuDesktopFrameWidth: + case PM_MenuHMargin: + case PM_MenuVMargin: + ret = 0; + break; + + case PM_HeaderMargin: + ret = 4; + break; + case PM_HeaderMarkSize: + ret = 32; + break; + case PM_HeaderGripMargin: + ret = 4; + break; + case PM_TabBarScrollButtonWidth: + ret = 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 = pixelMetric(isWindow ? PM_DefaultTopLevelMargin : PM_DefaultChildMargin); + } + break; + case PM_LayoutHorizontalSpacing: + case PM_LayoutVerticalSpacing: + ret = pixelMetric(PM_DefaultLayoutSpacing); + break; + + case PM_DefaultTopLevelMargin: + ret = 11; + break; + case PM_DefaultChildMargin: + ret = 9; + break; + case PM_DefaultLayoutSpacing: + ret = 6; + break; + + case PM_TabBarIconSize: + case PM_ToolBarIconSize: + case PM_ListViewIconSize: + ret = pixelMetric(PM_SmallIconSize, opt, widget); + break; + + case PM_ButtonIconSize: + case PM_SmallIconSize: + ret = 16; + break; + case PM_IconViewIconSize: + ret = pixelMetric(PM_LargeIconSize, opt, widget); + break; + + case PM_LargeIconSize: + ret = 32; + break; + + case PM_ToolTipLabelFrameWidth: + ret = 1; + break; + case PM_CheckBoxLabelSpacing: + case PM_RadioButtonLabelSpacing: + ret = 6; + break; + case PM_SizeGripSize: + ret = 13; + break; + case PM_MessageBoxIconSize: + ret = 32; + break; + case PM_TextCursorWidth: + ret = 1; + break; + case PM_TabBar_ScrollButtonOverlap: + ret = 1; + break; + case PM_TabCloseIndicatorWidth: + case PM_TabCloseIndicatorHeight: + ret = 16; + break; + case PM_ScrollView_ScrollBarSpacing: + ret = 2 * pixelMetric(PM_DefaultFrameWidth, opt, widget); + break; + case PM_SubMenuOverlap: + ret = -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<const QStyleOptionButton *>(opt)) { + int w = csz.width(), + h = csz.height(), + bm = pixelMetric(PM_ButtonMargin, btn, widget), + fw = pixelMetric(PM_DefaultFrameWidth, btn, widget) * 2; + w += bm + fw; + h += bm + fw; + if (btn->features & QStyleOptionButton::AutoDefaultButton){ + int dbw = 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<const QStyleOptionButton *>(opt)) { + bool isRadio = (ct == CT_RadioButton); + + int w = pixelMetric(isRadio ? PM_ExclusiveIndicatorWidth + : PM_IndicatorWidth, btn, widget); + int h = 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 + 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<const QStyleOptionMenuItem *>(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 = 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<const QStyleOptionComboBox *>(opt)) { + int fw = cmb->frame ? pixelMetric(PM_ComboBoxFrameWidth, opt, widget) * 2 : 0; + const int textMargins = 2*(pixelMetric(PM_FocusFrameHMargin) + 1); + // QItemDelegate::sizeHint expands the textMargins two times, thus the 2*textMargins... + int other = qMax(23, 2*textMargins + 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<const QStyleOptionHeader *>(opt)) { + bool nullIcon = hdr->icon.isNull(); + int margin = pixelMetric(QStyle::PM_HeaderMargin, hdr, widget); + int iconSize = nullIcon ? 0 : 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<const QStyleOptionFrame *>(opt)) + sz += QSize(2*f->lineWidth, 2*f->lineWidth); + break; +#ifndef QT_NO_GROUPBOX + case CT_GroupBox: + if (const QGroupBox *grb = static_cast<const QGroupBox *>(widget)) + sz += QSize(!grb->isFlat() ? 16 : 0, 0); + break; +#endif // QT_NO_GROUPBOX + case CT_MdiControls: + if (const QStyleOptionComplex *styleOpt = qstyleoption_cast<const QStyleOptionComplex *>(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<const QStyleOptionViewItemV4 *>(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<QStyleHintReturnMask*>(hret)) { + mask->region = widget->rect(); + int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin), + hmargin = 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<const QStyleOptionRubberBand *>(opt)) { + ret = 0; + if (rbOpt->shape == QRubberBand::Rectangle) { + ret = true; + if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) { + mask->region = opt->rect; + int margin = 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 = false; + 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: + 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<QStyleHintReturnVariant*>(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; + default: + ret = 0; + break; + } + + return ret; +} + +/*! \reimp */ +QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, + const QWidget *widget) const +{ +#ifdef QT_NO_IMAGEFORMAT_PNG + Q_UNUSED(option); + Q_UNUSED(widget); + Q_UNUSED(sp); +#else +#ifdef Q_WS_X11 + Q_D(const QCommonStyle); + QPixmap pixmap; + if (qApp->desktopSettingsAware()) { + d->lookupIconTheme(); + switch (sp) { + case SP_DirHomeIcon: + { + pixmap = d->findIcon(16, QLatin1String("folder_home.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MessageBoxInformation: + { + pixmap = d->findIcon(32, QLatin1String("messagebox_info.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MessageBoxWarning: + { + pixmap = d->findIcon(32, QLatin1String("messagebox_warning.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MessageBoxCritical: + { + pixmap = d->findIcon(32, QLatin1String("messagebox_critical.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MessageBoxQuestion: + { + pixmap = d->findIcon(32, QLatin1String("help.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DialogOpenButton: + case SP_DirOpenIcon: + { + pixmap = d->findIcon(16, QLatin1String("folder-open.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(16, QLatin1String("folder_open.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_FileIcon: + { + pixmap = d->findIcon(16, QLatin1String("text-x-generic.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(16, QLatin1String("empty.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_FileLinkIcon: + { + pixmap = d->findIcon(16, QLatin1String("link_overlay.png")); + if (!pixmap.isNull()) { + QPixmap fileIcon = d->findIcon(16, QLatin1String("text-x-generic.png")); + if (fileIcon.isNull()) + fileIcon = d->findIcon(16, QLatin1String("empty.png")); + if (!fileIcon.isNull()) { + QPainter painter(&fileIcon); + painter.drawPixmap(0, 0, 16, 16, pixmap); + return fileIcon; + } + } + break; + } + case SP_DirClosedIcon: + case SP_DirIcon: + { + pixmap = d->findIcon(16, QLatin1String("folder.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DirLinkIcon: + { + pixmap = d->findIcon(16, QLatin1String("link_overlay.png")); + if (!pixmap.isNull()) { + QPixmap dirIcon = d->findIcon(16, QLatin1String("folder.png")); + if (!dirIcon.isNull()) { + QPainter painter(&dirIcon); + painter.drawPixmap(0, 0, 16, 16, pixmap); + return dirIcon; + } + } + break; + } + case SP_DriveFDIcon: + { + pixmap = d->findIcon(16, QLatin1String("media-floppy.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(16, QLatin1String("3floppy_unmount.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_ComputerIcon: + { + pixmap = d->findIcon(16, QLatin1String("computer.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(16, QLatin1String("system.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DesktopIcon: + { + pixmap = d->findIcon(16, QLatin1String("user-desktop.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(16, QLatin1String("desktop.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_TrashIcon: + { + pixmap = d->findIcon(16, QLatin1String("user-trash.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(16, QLatin1String("trashcan_empty.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DriveCDIcon: + case SP_DriveDVDIcon: + { + pixmap = d->findIcon(16, QLatin1String("media-optical.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(16, QLatin1String("cdrom_unmount.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_DriveHDIcon: + { + pixmap = d->findIcon(16, QLatin1String("drive-harddisk.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(16, QLatin1String("hdd_unmount.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_FileDialogToParent: + { + pixmap = d->findIcon(32, QLatin1String("go-up.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(32, QLatin1String("up.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_FileDialogNewFolder: + { + pixmap = d->findIcon(16, QLatin1String("folder_new.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_ArrowUp: + { + pixmap = d->findIcon(32, QLatin1String("go-up.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(32, QLatin1String("up.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_ArrowDown: + { + pixmap = d->findIcon(32, QLatin1String("go-down.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(32, QLatin1String("down.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_ArrowRight: + { + pixmap = d->findIcon(32, QLatin1String("go-next.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(32, QLatin1String("forward.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_ArrowLeft: + { + pixmap = d->findIcon(32, QLatin1String("go-previous.png")); + if (pixmap.isNull()) + pixmap = d->findIcon(32, QLatin1String("back.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_FileDialogDetailedView: + { + pixmap = d->findIcon(16, QLatin1String("view_detailed.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + + case SP_FileDialogListView: + { + pixmap = d->findIcon(16, QLatin1String("view_icon.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_BrowserReload: + { + pixmap = d->findIcon(32, QLatin1String("reload.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_BrowserStop: + { + pixmap = d->findIcon(32, QLatin1String("stop.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaPlay: + { + pixmap = d->findIcon(16, QLatin1String("player_play.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaPause: + { + pixmap = d->findIcon(16, QLatin1String("player_pause.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaStop: + { + pixmap = d->findIcon(16, QLatin1String("player_stop.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaSeekForward: + { + pixmap = d->findIcon(16, QLatin1String("player_fwd.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaSeekBackward: + { + pixmap = d->findIcon(16, QLatin1String("player_rew.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaSkipForward: + { + pixmap = d->findIcon(16, QLatin1String("player_end.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + case SP_MediaSkipBackward: + { + pixmap = d->findIcon(16, QLatin1String("player_start.png")); + if (!pixmap.isNull()) + return pixmap; + break; + } + + default: + break; + } + } +#endif //Q_WS_X11 +#endif //QT_NO_IMAGEFORMAT_PNG + switch (sp) { +#ifndef QT_NO_IMAGEFORMAT_XPM + case SP_ToolBarHorizontalExtensionButton: + if (QApplication::layoutDirection() == Qt::RightToLeft) { + 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 (QApplication::layoutDirection() == Qt::RightToLeft) + return standardPixmap(SP_ArrowLeft, option, widget); + return standardPixmap(SP_ArrowRight, option, widget); + case SP_ArrowBack: + if (QApplication::layoutDirection() == Qt::RightToLeft) + return standardPixmap(SP_ArrowRight, option, widget); + return 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 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 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; +#ifdef Q_WS_X11 + Q_D(const QCommonStyle); + if (qApp->desktopSettingsAware()) { + d->lookupIconTheme(); + QPixmap pixmap; + switch (standardIcon) { + case SP_DirHomeIcon: + { + icon = d->createIcon(QLatin1String("folder_home.png")); + break; + } + case SP_MessageBoxInformation: + { + icon = d->createIcon(QLatin1String("dialog-information.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("messagebox_info.png")); + break; + } + case SP_MessageBoxWarning: + { + icon = d->createIcon(QLatin1String("dialog-warning.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("messagebox_warning.png")); + break; + } + case SP_MessageBoxCritical: + { + icon = d->createIcon(QLatin1String("dialog-error.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("messagebox_critical.png")); + break; + } + case SP_MessageBoxQuestion: + { + icon = d->createIcon(QLatin1String("help.png")); + break; + } + case SP_DialogOpenButton: + case SP_DirOpenIcon: + { + icon = d->createIcon(QLatin1String("folder-open.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("folder_open.png")); + break; + } + case SP_FileIcon: + { + icon = d->createIcon(QLatin1String("text-x-generic.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("empty.png")); + break; + } + case SP_DirClosedIcon: + case SP_DirIcon: + { + icon = d->createIcon(QLatin1String("folder.png")); + break; + } + case SP_DriveFDIcon: + { + icon = d->createIcon(QLatin1String("floppy_unmount.png")); + break; + } + case SP_ComputerIcon: + { + icon = d->createIcon(QLatin1String("computer.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("system.png")); + break; + } + case SP_DesktopIcon: + { + icon = d->createIcon(QLatin1String("user-desktop.png")); + break; + } + case SP_TrashIcon: + { + icon = d->createIcon(QLatin1String("user-trash.png")); + break; + } + case SP_DriveCDIcon: + case SP_DriveDVDIcon: + { + icon = d->createIcon(QLatin1String("media-optical.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("cdrom_unmount.png")); + break; + } + case SP_DriveHDIcon: + { + icon = d->createIcon(QLatin1String("drive-harddisk.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("hdd_unmount.png")); + break; + } + case SP_FileDialogToParent: + { + icon = d->createIcon(QLatin1String("go-up.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("up.png")); + break; + } + case SP_FileDialogNewFolder: + { + icon = d->createIcon(QLatin1String("folder_new.png")); + break; + } + case SP_ArrowUp: + { + icon = d->createIcon(QLatin1String("go-up.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("up.png")); + break; + } + case SP_ArrowDown: + { + icon = d->createIcon(QLatin1String("go-down.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("down.png")); + break; + } + case SP_ArrowRight: + { + icon = d->createIcon(QLatin1String("go-next.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("forward.png")); + break; + } + case SP_ArrowLeft: + { + icon = d->createIcon(QLatin1String("go-previous.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("back.png")); + break; + } + case SP_FileDialogDetailedView: + { + icon = d->createIcon(QLatin1String("view-list-details.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("view_detailed.png")); + break; + } + case SP_FileDialogListView: + { + icon = d->createIcon(QLatin1String("view-list-icons.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("view_icon.png")); + break; + } + case SP_BrowserReload: + { + icon = d->createIcon(QLatin1String("view-refresh.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("reload.png")); + break; + } + case SP_BrowserStop: + { + icon = d->createIcon(QLatin1String("process-stop.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("stop.png")); + break; + } + case SP_MediaPlay: + { + icon = d->createIcon(QLatin1String("media-playback-start.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("player_play.png")); + break; + } + case SP_MediaPause: + { + icon = d->createIcon(QLatin1String("media-playback-pause.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("player_pause.png")); + break; + } + case SP_MediaStop: + { + icon = d->createIcon(QLatin1String("media-playback-stop.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("player_stop.png")); + break; + } + case SP_MediaSeekForward: + { + icon = d->createIcon(QLatin1String("media-skip-forward.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("player_fwd.png")); + break; + } + case SP_MediaSeekBackward: + { + icon = d->createIcon(QLatin1String("media-skip-backward.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("player_rew.png")); + break; + } + case SP_MediaSkipForward: + { + icon = d->createIcon(QLatin1String("media-skip-forward.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("player_end.png")); + break; + } + case SP_MediaSkipBackward: + { + icon = d->createIcon(QLatin1String("media-skip-backward.png")); + if (icon.isNull()) + icon = d->createIcon(QLatin1String("player_start.png")); + break; + } + + case SP_FileLinkIcon: { + icon = QIcon(standardPixmap(standardIcon, option, widget)); + QPixmap pixmap = d->findIcon(32, QLatin1String("link_overlay.png")); + if (!pixmap.isNull()) { + QPixmap fileIcon = d->findIcon(32, QLatin1String("text-x-generic.png")); + if (fileIcon.isNull()) + fileIcon = d->findIcon(32, QLatin1String("empty.png")); + if (!fileIcon.isNull()) { + QPainter painter(&fileIcon); + painter.drawPixmap(0, 0, 32, 32, pixmap); + icon.addPixmap(fileIcon); + } + } + } + break; + case SP_DirLinkIcon: { + icon = QIcon(standardPixmap(standardIcon, option, widget)); + QPixmap pixmap = d->findIcon(32, QLatin1String("link_overlay.png")); + if (!pixmap.isNull()) { + QPixmap fileIcon = d->findIcon(32, QLatin1String("folder.png")); + if (!fileIcon.isNull()) { + QPainter painter(&fileIcon); + painter.drawPixmap(0, 0, 32, 32, pixmap); + icon.addPixmap(fileIcon); + } + } + } + break; + default: + break; + } + if (!icon.isNull()) + return icon; + } +#endif//Q_WS_X11 + + switch (standardIcon) { +#ifndef QT_NO_IMAGEFORMAT_PNG + case SP_FileDialogNewFolder: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-128.png")); + 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")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-128.png")); + break; + case SP_FileDialogInfoView: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-128.png")); + break; + case SP_FileDialogContentsView: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-128.png")); + break; + case SP_FileDialogListView: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-128.png")); + break; + case SP_DialogOkButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-128.png")); + break; + case SP_DialogCancelButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-128.png")); + break; + case SP_DialogHelpButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-128.png")); + break; + case SP_DialogOpenButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-128.png")); + break; + case SP_DialogSaveButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-128.png")); + break; + case SP_DialogCloseButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-128.png")); + break; + case SP_DialogApplyButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-128.png")); + break; + case SP_DialogResetButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-128.png")); + break; + case SP_DialogDiscardButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-128.png")); + break; + case SP_DialogYesButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-128.png")); + break; + case SP_DialogNoButton: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-128.png")); + break; + case SP_ArrowForward: + if (QApplication::layoutDirection() == Qt::RightToLeft) + return standardIconImplementation(SP_ArrowLeft, option, widget); + return standardIconImplementation(SP_ArrowRight, option, widget); + case SP_ArrowBack: + if (QApplication::layoutDirection() == Qt::RightToLeft) + 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")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-128.png")); + break; + case SP_ArrowRight: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-128.png")); + break; + case SP_ArrowUp: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-128.png")); + break; + case SP_ArrowDown: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-128.png")); + 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")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-128.png")); + break; + case SP_DriveDVDIcon: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-128.png")); + break; + case SP_FileIcon: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-128.png")); + break; + case SP_FileLinkIcon: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-128.png")); + break; + case SP_TrashIcon: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-32.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-128.png")); + break; + case SP_BrowserReload: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-24.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-32.png")); + break; + case SP_BrowserStop: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/stop-24.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/stop-32.png")); + break; + case SP_MediaPlay: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-32.png")); + break; + case SP_MediaPause: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-32.png")); + break; + case SP_MediaStop: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-32.png")); + break; + case SP_MediaSeekForward: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-32.png")); + break; + case SP_MediaSeekBackward: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-32.png")); + break; + case SP_MediaSkipForward: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-32.png")); + break; + case SP_MediaSkipBackward: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-16.png")); + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-32.png")); + break; + case SP_MediaVolume: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-16.png")); + break; + case SP_MediaVolumeMuted: + icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-muted-16.png")); + break; +#endif // QT_NO_IMAGEFORMAT_PNG + default: + icon.addPixmap(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; y<im.height(); ++y) { + QRgb *scanLine = (QRgb*)im.scanLine(y); + for (int x=0; x<im.width(); ++x) { + QRgb pixel = *scanLine; + // Calculate color table index, taking intensity adjustment + // and a magic offset into account. + uint ci = uint(qGray(pixel)/3 + (130 - intensity / 3)); + *scanLine = qRgba(reds[ci], greens[ci], blues[ci], qAlpha(pixel)); + ++scanLine; + } + } + + return QPixmap::fromImage(im); + } + case QIcon::Selected: { + QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); + QColor color = opt->palette.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/gui/styles/qcommonstyle.h b/src/gui/styles/qcommonstyle.h new file mode 100644 index 0000000000..367afc080e --- /dev/null +++ b/src/gui/styles/qcommonstyle.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOMMONSTYLE_H +#define QCOMMONSTYLE_H + +#include <QtGui/qstyle.h> + +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/gui/styles/qcommonstyle_p.h b/src/gui/styles/qcommonstyle_p.h new file mode 100644 index 0000000000..a941706792 --- /dev/null +++ b/src/gui/styles/qcommonstyle_p.h @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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; + +#ifdef Q_WS_X11 +class QIconTheme +{ +public: + QIconTheme(QHash <int, QString> dirList, QStringList parents) : + _dirList(dirList), _parents(parents), _valid(true){ } + QIconTheme() : _valid(false){ } + + QHash <int, QString> dirList() {return _dirList;} + QStringList parents() {return _parents;} + bool isValid() {return _valid;} + +private: + QHash <int, QString> _dirList; + QStringList _parents; + bool _valid; +}; +#endif + +// 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; + +//icon detection on X11 +#ifdef Q_WS_X11 + void lookupIconTheme() const; + QIcon createIcon(const QString &) const; + QPixmap findIcon(int size, const QString &) const; + QPixmap findIconHelper(int size, const QString &, const QString &, QStringList &visited) const; + QIconTheme parseIndexFile(const QString &themeName) const; + mutable QString themeName; + mutable QStringList iconDirs; + mutable QHash <QString, QIconTheme> themeList; +#endif + +}; + +QT_END_NAMESPACE + +#endif //QCOMMONSTYLE_P_H diff --git a/src/gui/styles/qcommonstylepixmaps_p.h b/src/gui/styles/qcommonstylepixmaps_p.h new file mode 100644 index 0000000000..c4adb7686a --- /dev/null +++ b/src/gui/styles/qcommonstylepixmaps_p.h @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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/gui/styles/qgtkpainter.cpp b/src/gui/styles/qgtkpainter.cpp new file mode 100644 index 0000000000..3d47b80b9b --- /dev/null +++ b/src/gui/styles/qgtkpainter.cpp @@ -0,0 +1,705 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgtkpainter_p.h" + +#include <QtCore/qglobal.h> +#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 <QtGui/QWidget> +#include <QtGui/QStyleOption> +#include <QtGui/QPixmapCache> + +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 = QGtk::gdk_pixmap_new((GdkDrawable*)(m_window->window), \ + rect.width(), rect.height(), -1); \ + if (!pixmap) \ + return; \ + style = QGtk::gtk_style_attach (style, m_window->window); \ + QGtk::gdk_draw_rectangle(pixmap, m_alpha ? style->black_gc : *style->bg_gc, true, \ + 0, 0, rect.width(), rect.height()); \ + draw_func; \ + GdkPixbuf *imgb = QGtk::gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, rect.width(), rect.height());\ + if (!imgb) \ + return; \ + imgb = QGtk::gdk_pixbuf_get_from_drawable(imgb, pixmap, NULL, 0, 0, 0, 0, \ + rect.width(), rect.height()); \ + uchar* bdata = (uchar*)QGtk::gdk_pixbuf_get_pixels(imgb); \ + if (m_alpha) { \ + QGtk::gdk_draw_rectangle(pixmap, style->white_gc, true, 0, 0, rect.width(), rect.height()); \ + draw_func; \ + GdkPixbuf *imgw = QGtk::gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, rect. \ + width(), rect.height()); \ + if (!imgw) \ + return; \ + imgw = QGtk::gdk_pixbuf_get_from_drawable(imgw, pixmap, NULL, 0, 0, 0, 0, \ + rect.width(), rect.height()); \ + uchar* wdata = (uchar*)QGtk::gdk_pixbuf_get_pixels(imgw); \ + cache = renderTheme(bdata, wdata, rect); \ + QGtk::gdk_pixbuf_unref(imgw); \ + } else { \ + cache = renderTheme(bdata, 0, rect); \ + } \ + QGtk::gdk_drawable_unref(pixmap); \ + QGtk::gdk_pixbuf_unref(imgb); \ + } + +QGtkPainter::QGtkPainter(QPainter *_painter) + : m_window(QGtk::gtkWidget(QLatin1String("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 = QString(QLS("%0-%1-%2-%3x%4-%5")).arg(key).arg(uint(state)).arg(shadow) + .arg(size.width()).arg(size.height()).arg(quintptr(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 = QGtk::gtkStyle(); + GtkIconSet* iconSet = QGtk::gtk_icon_factory_lookup_default (iconName); + GdkPixbuf* icon = QGtk::gtk_icon_set_render_icon(iconSet, + style, + GTK_TEXT_DIR_LTR, + GTK_STATE_NORMAL, + size, + NULL, + "button"); + uchar* data = (uchar*)QGtk::gdk_pixbuf_get_pixels(icon); + int width = QGtk::gdk_pixbuf_get_width(icon); + int height = QGtk::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]; + } + + QGtk::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 gapExtras = QString(QLS("s %0 w %1 g %2")).arg(gap_side).arg(width).arg(x); + QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget) + gapExtras; + + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtk::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(QGtk::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 hLineExtras = QString(QLS("%0 %1 %2")).arg(x1).arg(x2).arg(y); + QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget) + + hLineExtras + pmKey; + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtk::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 vLineExtras = QString(QLS("%0 %1 %2")).arg(y1).arg(y2).arg(x); + QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), + gtkWidget) + vLineExtras +pmKey; + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtk::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) + QString::number(expander_state) + pmKey; + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtk::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(QGtk::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(QGtk::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()) + + QString::number((int)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(QGtk::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()) + + QString::number(orientation); + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtk::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(QGtk::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(QGtk::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(QGtk::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); + pixmapName += QString::number(gap_pos); + + if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { + DRAW_TO_CACHE(QGtk::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(QGtk::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(QGtk::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/gui/styles/qgtkpainter_p.h b/src/gui/styles/qgtkpainter_p.h new file mode 100644 index 0000000000..dc0bc98d1c --- /dev/null +++ b/src/gui/styles/qgtkpainter_p.h @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 <QtCore/qglobal.h> +#if !defined(QT_NO_STYLE_GTK) + +#include "gtksymbols_p.h" +#include <QtGui/QCleanlooksStyle> +#include <QtGui/QPainter> +#include <QtGui/QPalette> +#include <QtGui/QFont> + +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/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp new file mode 100644 index 0000000000..103e97f8ea --- /dev/null +++ b/src/gui/styles/qgtkstyle.cpp @@ -0,0 +1,3280 @@ +/******* ********************************************************************* +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgtkstyle.h" + +#if !defined(QT_NO_STYLE_GTK) + +#include <private/qapplication_p.h> +#include <QtCore/QLibrary> +#include <QtCore/QSettings> +#include <QtGui/QDialogButtonBox> +#include <QtGui/QStatusBar> +#include <QtGui/QLineEdit> +#include <QtGui/QWidget> +#include <QtGui/QListView> +#include <QtGui/QApplication> +#include <QtGui/QStyleOption> +#include <QtGui/QPushButton> +#include <QtGui/QPainter> +#include <QtGui/QMainWindow> +#include <QtGui/QToolBar> +#include <QtGui/QHeaderView> +#include <QtGui/QMenuBar> +#include <QtGui/QComboBox> +#include <QtGui/QSpinBox> +#include <QtGui/QScrollBar> +#include <QtGui/QAbstractButton> +#include <QtGui/QToolButton> +#include <QtGui/QGroupBox> +#include <QtGui/QRadioButton> +#include <QtGui/QCheckBox> +#include <QtGui/QTreeView> +#include <qpixmapcache.h> +#undef signals // Collides with GTK stymbols +#include "qgtkpainter_p.h" + +#include <private/qcleanlooksstyle_p.h> + + +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; + +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", + " ", + " @@@@@@@@@ ", + "@+ +@", + "@ #@@@# @", + "@ @ @ @", + "@ #@@@# @ @", + "@ @ @ @ @", + "@ @ @@@ @", + "@ @ @ @", + "@ #@@@@ @", + "@+ +@", + " @@@@@@@@@ ", + " " + }; + + +class QGtkStylePrivate : public QCleanlooksStylePrivate +{ + Q_DECLARE_PUBLIC(QGtkStyle) +public: + QGtkStylePrivate() + : QCleanlooksStylePrivate() + {} +}; + +static const int groupBoxBottomMargin = 2; // space below the groupbox +static const int groupBoxTitleMargin = 6; // space between contents and title +static const int groupBoxTopMargin = 2; +static bool UsePixmapCache = true; + +// Get size of the arrow controls in a GtkSpinButton +static int spinboxArrowSize() +{ + const int MIN_ARROW_WIDTH = 6; + GtkWidget *spinButton = QGtk::gtkWidget(QLS("GtkSpinButton")); + GtkStyle *style = spinButton->style; + gint size = QGtk::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; +} + +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; +} + +// Note this is different from uniqueName as used in QGtkPainter +static QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size) +{ + QString tmp; + const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option); + tmp.sprintf("%s-%d-%d-%d-%lld-%dx%d", key.toLatin1().constData(), uint(option->state), + option->direction, complexOption ? uint(complexOption->activeSubControls) : uint(0), + option->palette.cacheKey(), size.width(), size.height()); + return tmp; +} + +/*! + \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() +{ + QGtk::initGtkWidgets(); +} + +/*! + Destroys the QGtkStyle object. +*/ +QGtkStyle::~QGtkStyle() +{ +} + +/*! + \reimp +*/ +QPalette QGtkStyle::standardPalette() const +{ + QPalette palette = QCleanlooksStyle::standardPalette(); + if (QGtk::isThemeAvailable()) { + GtkStyle *style = QGtk::gtkStyle(); + GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + GtkWidget *gtkEntry = QGtk::gtkWidget(QLS("GtkEntry")); + + GdkColor gdkBg, gdkBase, gdkText, gdkForeground, gdkSbg, gdkSfg; + QColor bg, base, text, fg, highlight, highlightText; + 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]; + 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); + + 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 = QGtk::gtkWidget(QLS("GtkTreeView")); + GdkColor *gtkAltBase = NULL; + QGtk::gtk_widget_style_get(gtkTreeView, "odd-row-color", >kAltBase, NULL); + if (gtkAltBase) { + alternateRowColor = QColor(gtkAltBase->red>>8, gtkAltBase->green>>8, gtkAltBase->blue>>8); + QGtk::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); + style = QGtk::gtk_rc_get_style_by_paths(QGtk::gtk_settings_get_default(), "gtk-tooltips", "GtkWindow", Q_GTK_TYPE_WINDOW); + 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) +{ + // QCleanlooksStyle will alter the palette, hence we do + // not want to polish the palette unless we are using it as + // the fallback + if (!QGtk::isThemeAvailable()) + QCleanlooksStyle::polish(palette); + else + palette = standardPalette(); +} + +/*! + \reimp +*/ +void QGtkStyle::polish(QApplication *app) +{ + 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() && QGtk::isThemeAvailable()) { + QApplicationPrivate::setSystemPalette(standardPalette()); + QApplicationPrivate::setSystemFont(QGtk::getThemeFont()); + if (!QGtk::isKDE4Session()) { + qt_filedialog_open_filename_hook = &QGtk::openFilename; + qt_filedialog_save_filename_hook = &QGtk::saveFilename; + qt_filedialog_open_filenames_hook = &QGtk::openFilenames; + qt_filedialog_existing_directory_hook = &QGtk::openDirectory; + } + } +} + +/*! + \reimp +*/ +void QGtkStyle::unpolish(QApplication *app) +{ + QCleanlooksStyle::unpolish(app); + QPixmapCache::clear(); + + if (app->desktopSettingsAware() && QGtk::isThemeAvailable() + && !QGtk::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; + } +} + +/*! + \reimp +*/ +void QGtkStyle::polish(QWidget *widget) +{ + QCleanlooksStyle::polish(widget); + if (!QGtk::isThemeAvailable()) + return; + + if (qobject_cast<QAbstractButton*>(widget) + || qobject_cast<QToolButton*>(widget) + || qobject_cast<QComboBox*>(widget) + || qobject_cast<QGroupBox*>(widget) + || qobject_cast<QScrollBar*>(widget) + || qobject_cast<QSlider*>(widget) + || qobject_cast<QAbstractSpinBox*>(widget) + || qobject_cast<QSpinBox*>(widget) + || qobject_cast<QHeaderView*>(widget)) + widget->setAttribute(Qt::WA_Hover); + else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) + tree->viewport()->setAttribute(Qt::WA_Hover); + + QGtk::applyGtkSystemPalette(widget); +} + +/*! + \reimp +*/ +void QGtkStyle::unpolish(QWidget *widget) +{ + QCleanlooksStyle::unpolish(widget); +} + +/*! + \reimp +*/ +int QGtkStyle::pixelMetric(PixelMetric metric, + + const QStyleOption *option, + const QWidget *widget) const +{ + if (!QGtk::isThemeAvailable()) + return QCleanlooksStyle::pixelMetric(metric, option, widget); + + switch (metric) { + 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 = QGtk::gtkWidget(QLS("GtkButton")); + guint horizontal_shift; + QGtk::gtk_widget_style_get(gtkButton, "child-displacement-x", &horizontal_shift, NULL); + return horizontal_shift; + } + + case PM_ButtonShiftVertical: { + GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + guint vertical_shift; + QGtk::gtk_widget_style_get(gtkButton, "child-displacement-y", &vertical_shift, NULL); + return vertical_shift; + } + + case PM_MenuBarPanelWidth: + return 0; + + case PM_MenuPanelWidth: { + GtkWidget *gtkMenu = QGtk::gtkWidget(QLS("GtkMenu")); + guint horizontal_padding = 0; + // horizontal-padding is used by Maemo to get thicker borders + if (!QGtk::gtk_check_version(2, 10, 0)) + QGtk::gtk_widget_style_get(gtkMenu, "horizontal-padding", &horizontal_padding, NULL); + int padding = qMax<int>(gtkMenu->style->xthickness, horizontal_padding); + return padding; + } + + case PM_ButtonIconSize: { + int retVal = 24; + GtkSettings *settings = QGtk::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 = QGtk::gtkWidget(QLS("GtkHScale")); + gint val; + QGtk::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 = QGtk::gtkWidget(QLS("GtkHScrollbar")); + QGtk::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; + QGtk::gtk_widget_style_get(QGtk::gtkWidget(QLS("GtkHScale")), "slider-length", &val, NULL); + return val; + + case PM_ExclusiveIndicatorWidth: + case PM_ExclusiveIndicatorHeight: + case PM_IndicatorWidth: + case PM_IndicatorHeight: { + GtkWidget *gtkCheckButton = QGtk::gtkWidget(QLS("GtkCheckButton")); + gint size, spacing; + QGtk::gtk_widget_style_get(gtkCheckButton, "indicator-spacing", &spacing, "indicator-size", &size, NULL); + return size + 2 * spacing; + } + + case PM_MenuBarVMargin: { + GtkWidget *gtkMenubar = QGtk::gtkWidget(QLS("GtkMenuBar")); + return qMax(0, gtkMenubar->style->ythickness); + } + case PM_ScrollView_ScrollBarSpacing: + { + gint spacing = 3; + GtkWidget *gtkScrollWindow = QGtk::gtkWidget(QLS("GtkScrolledWindow")); + Q_ASSERT(gtkScrollWindow); + QGtk::gtk_widget_style_get(gtkScrollWindow, "scrollbar-spacing", &spacing, NULL); + return spacing; + } + case PM_SubMenuOverlap: { + gint offset = 0; + GtkWidget *gtkMenu = QGtk::gtkWidget(QLS("GtkMenu")); + QGtk::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 +{ + if (!QGtk::isThemeAvailable()) + return QCleanlooksStyle::styleHint(hint, option, widget, returnData); + + switch (hint) { + + case SH_DialogButtonLayout: { + int ret = QDialogButtonBox::GnomeLayout; + gboolean alternateOrder = 0; + GtkSettings *settings = QGtk::gtk_settings_get_default(); + g_object_get(settings, "gtk-alternative-button-order", &alternateOrder, NULL); + + if (alternateOrder) + ret = QDialogButtonBox::WinLayout; + + return ret; + } + + break; + + case SH_SpinControls_DisableOnBounds: + return int(true); + + case SH_DitherDisabledText: + return int(false); + + case SH_ComboBox_Popup: { + GtkWidget *gtkComboBox = QGtk::gtkWidget(QLS("GtkComboBox")); + gboolean appears_as_list; + QGtk::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 = QGtk::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 (!QGtk::gtk_check_version(2, 12, 0)) { + GtkWidget *gtkScrollWindow = QGtk::gtkWidget(QLS("GtkScrolledWindow")); + QGtk::gtk_widget_style_get(gtkScrollWindow, "scrollbars-within-bevel", &scrollbars_within_bevel, NULL); + } + return !scrollbars_within_bevel; + } + + default: + return QCleanlooksStyle::styleHint(hint, option, widget, returnData); + } +} + +/*! + \reimp +*/ +void QGtkStyle::drawPrimitive(PrimitiveElement element, + + const QStyleOption *option, + QPainter *painter, + const QWidget *widget) const +{ + if (!QGtk::isThemeAvailable()) { + QCleanlooksStyle::drawPrimitive(element, option, painter, widget); + return; + } + + GtkStyle* style = QGtk::gtkStyle(); + QGtkPainter gtkPainter(painter); + + switch (element) { + + case PE_PanelTipLabel: { + GtkWidget *gtkWindow = QGtk::gtkWidget(QLS("GtkWindow")); // The Murrine Engine currently assumes a widget is passed + style = QGtk::gtk_rc_get_style_by_paths(QGtk::gtk_settings_get_default(), "gtk-tooltips", "GtkWindow", Q_GTK_TYPE_WINDOW); + 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 = QGtk::gtkWidget(QLS("GtkStatusbar.GtkFrame")); + QGtk::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<const QStyleOptionHeader *>(option)) { + GtkWidget *gtkTreeHeader = QGtk::gtkWidget(QLS("GtkTreeView.GtkButton")); + GtkStateType state = gtkPainter.gtkState(option); + style = gtkTreeHeader->style; + GtkArrowType type = GTK_ARROW_UP; + QRect r = header->rect; + QImage arrow; + 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<const QAbstractItemView*>(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<const QTabBar*>(widget)) + frameRect.adjust(-1, 1, 1, 1); + + 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, 10, 10); + rect.moveCenter(option->rect.center()); + rect.translate(2, 0); + GtkExpanderStyle openState = GTK_EXPANDER_EXPANDED; + GtkExpanderStyle closedState = GTK_EXPANDER_COLLAPSED; + GtkWidget *gtkExpander = QGtk::gtkWidget(QLS("GtkExpander")); + guint expanderSize; + QGtk::gtk_widget_style_get(gtkExpander, "expander-size", &expanderSize, NULL); + // Note CleanIce will crash unless a GtkExpander is provided + // but providing the expander will enforce the expander-size, which we + // don't neccessarily have room for + 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(expanderSize <= 10 ? gtkExpander : NULL, "expander", rect, state, + option->state & State_Open ? openState : closedState , gtkExpander->style); + } + break; + case PE_PanelItemViewItem: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) { + if (vopt->state & State_Selected) { + QLinearGradient gradient; + gradient.setStart(option->rect.left(), option->rect.top()); + gradient.setFinalStop(option->rect.left(), option->rect.bottom()); + gradient.setColorAt(0, option->palette.highlight().color().lighter(105)); + gradient.setColorAt(0.5, option->palette.highlight().color().lighter(101)); + gradient.setColorAt(0.51, option->palette.highlight().color().darker(101)); + gradient.setColorAt(1, option->palette.highlight().color().darker(105)); + painter->fillRect(option->rect, gradient); + } 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); + } + } + } + break; + case PE_IndicatorToolBarSeparator: + { + const int margin = 6; + GtkWidget *gtkSeparator = QGtk::gtkWidget(QLS("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 = QGtk::gtkWidget(QLS("GtkToolbar")); + GtkShadowType shadow_type; + QGtk::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 = pixelMetric(PM_ButtonShiftHorizontal); + bsy = 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 = QGtk::gtkWidget(QLS("GtkArrow")); + GdkColor color = fromQColor(arrowColor); + QGtk::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 + QGtk::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 = QGtk::gtkWidget(QLS("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<const QToolBar *>(widget)) { + GtkWidget *gtkMenubar = QGtk::gtkWidget(QLS("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 = QGtk::gtkWidget(QLS("GtkEntry")); + + if (option->state & State_HasFocus) + GTK_WIDGET_SET_FLAGS(gtkEntry, GTK_HAS_FOCUS); + else + GTK_WIDGET_UNSET_FLAGS(gtkEntry, GTK_HAS_FOCUS); + + gboolean interior_focus; + gint focus_line_width; + QRect rect = option->rect; + QGtk::gtk_widget_style_get(gtkEntry, + "interior-focus", &interior_focus, + "focus-line-width", &focus_line_width, NULL); + + if (!interior_focus && option->state & State_HasFocus) + rect.adjust(focus_line_width, focus_line_width, -focus_line_width, -focus_line_width); + + 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")); + } + break; + + case PE_PanelLineEdit: + if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) { + GtkWidget *gtkEntry = QGtk::gtkWidget(QLS("GtkEntry")); + if (panel->lineWidth > 0) + 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().color()); + 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<const QStyleOptionTabWidgetFrame*>(option)) { + GtkWidget *gtkNotebook = QGtk::gtkWidget(QLS("GtkNotebook")); + style = gtkPainter.getStyle(gtkNotebook); + gtkPainter.setAlphaSupport(false); + GtkShadowType shadow = GTK_SHADOW_OUT; + GtkStateType state = GTK_STATE_NORMAL; // Only state supported by gtknotebook + if (const QTabWidget *tabwidget = qobject_cast<const QTabWidget*>(widget)) { + // We should introduce QStyleOptionTabWidgetFrameV2 to obtain this information + // No gap if we do not show the actual tabs + QTabBar *tabBar = tabwidget->findChild<QTabBar*>(); + if (tabwidget->count() > 0 && tabBar->isVisible()) { + QRect tabRect = tabBar->tabRect(tabBar->currentIndex()); + int begin = 0, size = 0; + GtkPositionType frameType = GTK_POS_TOP; + QTabBar::Shape shape = frame->shape; + if (shape == QTabBar::RoundedNorth || shape == QTabBar::RoundedSouth) { + begin = option->direction == Qt::LeftToRight ? + frame->leftCornerWidgetSize.width() + tabRect.left() : + frame->rect.width() - frame->tabBarSize.width() + tabRect.left() + - frame->rightCornerWidgetSize.width(); + size = tabRect.width(); + frameType = (shape == QTabBar::RoundedNorth) ? GTK_POS_TOP : GTK_POS_BOTTOM; + } else { + begin = frame->leftCornerWidgetSize.height() + tabRect.top(); + size = tabRect.height(); + frameType = (shape == QTabBar::RoundedWest) ? GTK_POS_LEFT : GTK_POS_RIGHT; + } + gtkPainter.paintBoxGap(gtkNotebook, "notebook", option->rect, state, shadow, frameType, + begin, size, style); + break; // done + } + } + // Note this is only the fallback option + gtkPainter.paintBox(gtkNotebook, "notebook", option->rect, state, shadow, style); + } + break; + + case PE_PanelButtonCommand: { + bool isDefault = false; + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton*>(option)) + isDefault = btn->features & QStyleOptionButton::DefaultButton; + + GtkStateType state = gtkPainter.gtkState(option); + if (option->state & State_On || option->state & State_Sunken) + state = GTK_STATE_ACTIVE; + GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + gint focusWidth, focusPad; + gboolean interiorFocus = false; + QGtk::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()); + } else + GTK_WIDGET_UNSET_FLAGS(gtkButton, GTK_HAS_DEFAULT); + + bool hasFocus = option->state & State_HasFocus; + + if (hasFocus) { + key += QLS("def"); + GTK_WIDGET_SET_FLAGS(gtkButton, GTK_HAS_FOCUS); + + } else { + GTK_WIDGET_UNSET_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); + } + 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 = QGtk::gtkWidget(QLS("GtkRadioButton")); + gint spacing; + QGtk::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 = QGtk::gtkWidget(QLS("GtkCheckButton")); + gtkPainter.paintOption(gtkCheckButton , buttonRect, state, shadow, gtkRadioButton->style, QLS("radiobutton")); + + } + 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 = QGtk::gtkWidget(QLS("GtkCheckButton")); + + // Some styles such as aero-clone assume they can paint in the spacing area + gtkPainter.setClipRect(option->rect); + + QGtk::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, + QLS("checkbutton")); + } + break; + +#ifndef QT_NO_TABBAR + + case PE_FrameTabBarBase: + if (const QStyleOptionTabBarBase *tbb + = qstyleoption_cast<const QStyleOptionTabBarBase *>(option)) { + QRect tabRect = tbb->rect; + QRegion region(tabRect); + 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 +{ + if (!QGtk::isThemeAvailable()) { + QCleanlooksStyle::drawComplexControl(control, option, painter, widget); + return; + } + + GtkStyle* style = QGtk::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); + + QPalette palette = option->palette; + + switch (control) { + + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(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<const QStyleOptionGroupBox *>(option)) { + QRect textRect = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget); + QRect checkBoxRect = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxCheckBox, widget); + // Draw title + + if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) { + // Draw prelight background + GtkWidget *gtkCheckButton = QGtk::gtkWidget(QLS("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 (!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; + 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<const QStyleOptionComboBox *>(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); + QColor buttonShadow = option->palette.dark().color(); + GtkStateType state = gtkPainter.gtkState(option); + int appears_as_list = !styleHint(QStyle::SH_ComboBox_Popup, comboBox, widget); + QPixmap cache; + QString pixmapName; + QStyleOptionComboBox comboBoxCopy = *comboBox; + comboBoxCopy.rect = option->rect; + + bool reverse = (option->direction == Qt::RightToLeft); + QRect rect = option->rect; + QRect arrowButtonRect = subControlRect(CC_ComboBox, &comboBoxCopy, + SC_ComboBoxArrow, widget); + QRect editRect = subControlRect(CC_ComboBox, &comboBoxCopy, + SC_ComboBoxEditField, widget); + + GtkShadowType shadow = (option->state & State_Sunken || option->state & State_On ) ? + GTK_SHADOW_IN : GTK_SHADOW_OUT; + QString comboBoxPath = QLS(comboBox->editable ? "GtkComboBoxEntry" : "GtkComboBox"); + + // We use the gtk widget to position arrows and separators for us + GtkWidget *gtkCombo = QGtk::gtkWidget(comboBoxPath); + GtkAllocation geometry = {0, 0, option->rect.width(), option->rect.height()}; + QGtk::gtk_widget_set_direction(gtkCombo, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + QGtk::gtk_widget_size_allocate(gtkCombo, &geometry); + + QString buttonPath = comboBoxPath + QLS(".GtkToggleButton"); + GtkWidget *gtkToggleButton = QGtk::gtkWidget(buttonPath); + QGtk::gtk_widget_set_direction(gtkToggleButton, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + if (gtkToggleButton && (appears_as_list || comboBox->editable)) { + // 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; + QString entryPath = QLS(comboBox->editable ? "GtkComboBoxEntry.GtkEntry" : "GtkComboBox.GtkFrame"); + GtkWidget *gtkEntry = QGtk::gtkWidget(entryPath); + QGtk::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()); + + // Required for inner blue highlight with clearlooks + if (focus) { + GTK_WIDGET_SET_FLAGS(gtkEntry, GTK_HAS_FOCUS); + GTK_WIDGET_SET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS); + + } else { + GTK_WIDGET_UNSET_FLAGS(gtkEntry, GTK_HAS_FOCUS); + GTK_WIDGET_UNSET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS); + } + + // 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); + 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, style, entryPath + QString::number(focus)); + } + + gtkCachedPainter.paintShadow(gtkEntry, comboBox->editable ? "entry" : "frame", frameRect, frameState, + GTK_SHADOW_IN, gtkEntry->style, entryPath + + QString::number(focus) + QString::number(comboBox->editable) + + QString::number(option->direction)); + } + + 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; + + QRect buttonrect = QRect(gtkToggleButton->allocation.x, gtkToggleButton->allocation.y, + gtkToggleButton->allocation.width, gtkToggleButton->allocation.height); + + Q_ASSERT(gtkToggleButton); + gtkCachedPainter.paintBox( gtkToggleButton, "button", arrowButtonRect, buttonState, + shadow, gtkToggleButton->style, buttonPath + + QString::number(focus) + QString::number(option->direction)); + + } 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); + + } else { + GTK_WIDGET_UNSET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS); + } + + gtkCachedPainter.paintBox(gtkToggleButton, "button", + buttonRect, state, + shadow, gtkToggleButton->style, + buttonPath + QString::number(focus)); + // Draw the separator between label and arrows + QString vSeparatorPath = buttonPath + QLS(".GtkHBox.GtkVSeparator"); + + if (GtkWidget *gtkVSeparator = QGtk::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); + + + gint interiorFocus = true; + QGtk::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))) + 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; + + QString arrowPath = comboBoxPath + QLS(appears_as_list ? ".GtkToggleButton.GtkArrow" + : ".GtkToggleButton.GtkHBox.GtkArrow"); + + GtkWidget *gtkArrow = QGtk::gtkWidget(arrowPath); + gfloat scale = 0.7; + gint minSize = 15; + QRect arrowWidgetRect; + + if (gtkArrow && !QGtk::gtk_check_version(2, 12, 0)) { + QGtk::gtk_widget_style_get(gtkArrow, "arrow-scaling", &scale, NULL); + QGtk::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<int>(arrowSize * scale), static_cast<int>(arrowSize * scale)); + + arrowRect.moveCenter(arrowWidgetRect.center()); + + if (sunken) { + int xoff, yoff; + GtkWidget *gtkButton = QGtk::gtkWidget(comboBoxPath + QLS(".GtkToggleButton")); + QGtk::gtk_widget_style_get(gtkButton, "child-displacement-x", &xoff, NULL); + QGtk::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 + 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<const QStyleOptionToolButton *>(option)) { + QRect button, menuarea; + button = subControlRect(control, toolbutton, SC_ToolButton, widget); + menuarea = 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; + 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 = subControlRect(CC_ToolButton, toolbutton, SC_ToolButton, widget); + fr.rect.adjust(1, 1, -1, -1); + drawPrimitive(PE_FrameFocusRect, &fr, painter, widget); + } + + QStyleOptionToolButton label = *toolbutton; + label.state = bflags; + GtkWidget *gtkButton = QGtk::gtkWidget(QLS("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); + 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)) + drawPrimitive(PE_IndicatorButtonDropDown, &tool, painter, widget); + + 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); + drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget); + } + } + break; + +#endif // QT_NO_TOOLBUTTON +#ifndef QT_NO_SCROLLBAR + + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) { + GtkWidget *gtkHScrollBar = QGtk::gtkWidget(QLS("GtkHScrollbar")); + GtkWidget *gtkVScrollBar = QGtk::gtkWidget(QLS("GtkVScrollbar")); + + // Fill background in case the scrollbar is partially transparent + painter->fillRect(option->rect, option->palette.background()); + + QRect rect = scrollBar->rect; + QRect scrollBarSubLine = subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget); + QRect scrollBarAddLine = subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget); + QRect scrollBarSlider = subControlRect(control, scrollBar, SC_ScrollBarSlider, widget); + QRect grooveRect = 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 stepper_size = 14; + gint trough_border = 1; + if (!QGtk::gtk_check_version(2, 10, 0)) { + QGtk::gtk_widget_style_get((GtkWidget*)(scrollbarWidget), + "trough-border", &trough_border, + "trough-side-details", &trough_side_details, + "trough-under-steppers", &trough_under_steppers, + "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; + GtkObject *adjustment = QGtk::gtk_adjustment_new(fakePos, 0, maximum, 0, 0, 0); + + if (horizontal) + QGtk::gtk_range_set_adjustment((GtkRange*)(gtkHScrollBar), (GtkAdjustment*)(adjustment)); + else + QGtk::gtk_range_set_adjustment((GtkRange*)(gtkVScrollBar), (GtkAdjustment*)(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 (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<const QStyleOptionSpinBox *>(option)) { + GtkWidget *gtkSpinButton = QGtk::gtkWidget(QLS("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); + + //### Move this to subControlRect + QRect upRect = subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget); + upRect.setTop(option->rect.top()); + + if (reverse) + upRect.setLeft(option->rect.left()); + else + upRect.setRight(option->rect.right()); + + QRect editRect = subControlRect(CC_SpinBox, option, SC_SpinBoxEditField, widget); + QRect downRect = subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget); + downRect.setBottom(option->rect.bottom()); + + if (reverse) + downRect.setLeft(option->rect.left()); + else + downRect.setRight(option->rect.right()); + + QRect buttonRect = upRect | downRect; + QRect editArea = option->rect; + + 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); + + if (option->state & State_HasFocus) + GTK_WIDGET_SET_FLAGS(gtkSpinButton, GTK_HAS_FOCUS); + else + GTK_WIDGET_UNSET_FLAGS(gtkSpinButton, GTK_HAS_FOCUS); + + QString key; + + if (option->state & State_HasFocus) + key = QLS("f"); + + 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); + 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 (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 { + int size = spinboxArrowSize(); + 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<const QStyleOptionSlider *>(option)) { + GtkWidget *hScaleWidget = QGtk::gtkWidget(QLS("GtkHScale")); + GtkWidget *vScaleWidget = QGtk::gtkWidget(QLS("GtkVScale")); + + QRect groove = subControlRect(CC_Slider, option, SC_SliderGroove, widget); + QRect handle = subControlRect(CC_Slider, option, SC_SliderHandle, widget); + QRect ticks = 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); + + GtkWidget *scaleWidget = horizontal ? hScaleWidget : vScaleWidget; + style = scaleWidget->style; + + if ((option->subControls & SC_SliderGroove) && groove.isValid()) { + GtkObject *adjustment = QGtk::gtk_adjustment_new(slider->sliderPosition, + slider->minimum, + slider->maximum, + slider->singleStep, + slider->singleStep, + slider->pageStep); + int outerSize; + QGtk::gtk_range_set_adjustment ((GtkRange*)(scaleWidget), (GtkAdjustment*)(adjustment)); + QGtk::gtk_range_set_inverted((GtkRange*)(scaleWidget), !horizontal); + QGtk::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); + + gtkPainter.paintBox( scaleWidget, "trough", grooveRect, state, + GTK_SHADOW_IN, style, QString(QLS("p%0")).arg(slider->sliderPosition)); + + gboolean trough_side_details = false; // Indicates if the upper or lower scale background differs + if (!QGtk::gtk_check_version(2, 10, 0)) + QGtk::gtk_widget_style_get((GtkWidget*)(scaleWidget), "trough-side-details", &trough_side_details, NULL); + + if (trough_side_details && horizontal) { //### Vertical sliders look broken with this for some reason + QRect lowerGroove = grooveRect; + lowerGroove.setRight(handle.center().x()); + 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 = pixelMetric(PM_SliderTickmarkOffset, option, widget); + int available = 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 = 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); + } + 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 +{ + if (!QGtk::isThemeAvailable()) { + QCleanlooksStyle::drawControl(element, option, painter, widget); + return; + } + + GtkStyle* style = QGtk::gtkStyle(); + QGtkPainter gtkPainter(painter); + + switch (element) { + case CE_ProgressBarLabel: + if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { + GtkWidget *gtkProgressBar = QGtk::gtkWidget(QLS("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<const QStyleOptionProgressBarV2 *>(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 = static_cast<int>((bar->progress - qint64(bar->minimum)) / + qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * rect.width()); + 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<const QStyleOptionButton *>(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), + pixelMetric(PM_ButtonShiftVertical, option, widget)); + + 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() + 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 = QGtk::gtkWidget(QLS("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); + 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<const QStyleOptionButton *>(option)) { + bool isRadio = (element == CE_RadioButton); + + // Draw prelight background + GtkWidget *gtkRadioButton = QGtk::gtkWidget(QLS("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); + 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; + 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); + drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + } + break; + +#ifndef QT_NO_COMBOBOX + + case CE_ComboBoxLabel: + if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { + QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget); + bool appearsAsList = !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)); + + 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 = QGtk::gtkWidget(QLS("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); + + 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<const QStyleOptionDockWidget *>(option)) { + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(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()); + 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<const QStyleOptionHeader *>(option)) { + Q_UNUSED(header); + GtkWidget *gtkTreeView = QGtk::gtkWidget(QLS("GtkTreeView")); + // Get the middle column + GtkTreeViewColumn *column = QGtk::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 = QGtk::gtkWidget(QLS("GtkStatusbar.GtkFrame")); + QRect gripRect = option->rect.adjusted(0, 0, -gtkStatusbar->style->xthickness, -gtkStatusbar->style->ythickness); + gtkPainter.paintResizeGrip( gtkStatusbar, "window", 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 = QGtk::gtkWidget(QLS("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; + QGtk::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<const QStyleOptionMenuItem *>(option)) { + GtkWidget *gtkMenubarItem = QGtk::gtkWidget(QLS("GtkMenuBar.GtkMenuItem")); + GtkWidget *gtkMenubar = QGtk::gtkWidget(QLS("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; + QGtk::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; + QGtk::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 (!QCleanlooksStyle::styleHint(SH_UnderlineShortcut, mbi, widget)) + alignment |= Qt::TextHideMnemonic; + + drawItemText(painter, item.rect, alignment, item.palette, mbi->state & State_Enabled, mbi->text, textRole); + } + } + painter->restore(); + break; + + case CE_Splitter: { + GtkWidget *gtkWindow = QGtk::gtkWidget(QLS("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<const QStyleOptionToolBar *>(option)) { + // Reserve the beveled appearance only for mainwindow toolbars + if (!(widget && qobject_cast<const QMainWindow*> (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 = QGtk::gtkWidget(QLS("GtkToolbar")); + GtkShadowType shadow_type = GTK_SHADOW_NONE; + QGtk::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<const QStyleOptionMenuItem *>(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 *gtkMenu = QGtk::gtkWidget(QLS("GtkMenu")); + GtkWidget *gtkMenuItem = menuItem->checked ? QGtk::gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")) : + QGtk::gtkWidget(QLS("GtkMenu.GtkMenuItem")); + + style = gtkPainter.getStyle(gtkMenuItem); + QColor borderColor = option->palette.background().color().darker(160); + QColor shadow = option->palette.dark().color(); + + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + GtkWidget *gtkMenuSeparator = QGtk::gtkWidget(QLS("GtkMenu.GtkSeparatorMenuItem")); + painter->setPen(shadow.lighter(106)); + gboolean wide_separators = 0; + gint separator_height = 0; + guint horizontal_padding = 3; + if (!QGtk::gtk_check_version(2, 10, 0)) { + QGtk::gtk_widget_style_get(gtkMenuSeparator, + "wide-separators", &wide_separators, + "separator-height", &separator_height, + "horizontal-padding", &horizontal_padding, + NULL); + } + if (wide_separators) + gtkPainter.paintBox( gtkMenuSeparator, "hseparator", + option->rect.adjusted(0, 0, 0, -1), GTK_STATE_NORMAL, GTK_SHADOW_NONE, gtkMenu->style); + else + gtkPainter.paintHline( gtkMenuSeparator, "hseparator", + menuItem->rect, GTK_STATE_NORMAL, gtkMenu->style, + option->rect.left() + horizontal_padding, option->rect.width() - 2*horizontal_padding, 2); + painter->restore(); + break; + } + + bool selected = menuItem->state & State_Selected && menuItem->state & State_Enabled; + + if (selected) { + QRect rect = option->rect.adjusted(0, 0, -1, -1); + 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; + QGtk::gtk_widget_style_get(QGtk::gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")), "indicator-size", &checkSize, NULL); + + int checkcol = qMax(menuItem->maxIconWidth, qMax(20, checkSize)); + +#ifndef QT_NO_COMBOBOX + + if (qobject_cast<const QComboBox*>(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, 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 = pixelMetric(PM_SmallIconSize, option, widget); + QSize iconSize(smallIconSize, smallIconSize); + +#ifndef QT_NO_COMBOBOX + if (const QComboBox *combo = qobject_cast<const QComboBox*>(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 (!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; + 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]; + QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + QColor disabledTextColor = QColor(gdkDText.red>>8, gdkDText.green>>8, gdkDText.blue>>8); + QColor highlightedTextColor = QColor(gdkHText.red>>8, gdkHText.green>>8, gdkHText.blue>>8); + + 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; + 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; + + // 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 + QPoint buttonShift(pixelMetric(PM_ButtonShiftHorizontal, option, widget), + pixelMetric(PM_ButtonShiftVertical, option, widget)); + + QFontMetrics fm(menuitem->font); + int arrow_size = fm.ascent() + fm.descent() - 2 * gtkMenuItem->style->ythickness; + gfloat arrow_scaling = 0.8; + + // "arrow-scaling" is actually hardcoded and fails on hardy (see gtk+-2.12/gtkmenuitem.c) + // though the current documentation states otherwise + int horizontal_padding; + QGtk::gtk_widget_style_get(gtkMenuItem, "horizontal-padding", &horizontal_padding, NULL); + + const int dim = static_cast<int>(arrow_size * arrow_scaling); + 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<const QStyleOptionButton *>(option)) { + GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + drawControl(CE_PushButtonBevel, btn, painter, widget); + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); + gint interiorFocus = true; + QGtk::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 + 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); + + drawControl(CE_PushButtonLabel, &subopt, painter, widget); + } + break; + +#ifndef QT_NO_TABBAR + + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) { + GtkWidget *gtkNotebook = QGtk::gtkWidget(QLS("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 first = tab->position == QStyleOptionTab::Beginning || tab->position == QStyleOptionTab::OnlyOneTab; + bool last = tab->position == QStyleOptionTab::End || tab->position == QStyleOptionTab::OnlyOneTab; + bool selected = (tab->state & State_Selected); + 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<const QStyleOptionProgressBar *>(option)) { + Q_UNUSED(bar); + GtkWidget *gtkProgressBar = QGtk::gtkWidget(QLS("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<const QStyleOptionProgressBar *>(option)) { + GtkStateType state = option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE; + GtkWidget *gtkProgressBar = QGtk::gtkWidget(QLS("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<const QStyleOptionProgressBarV2 *>(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; + m.translate(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; + + GtkObject *adjustment = QGtk::gtk_adjustment_new(fakePos, 0, maximum, 0, 0, 0); + QGtk::gtk_progress_set_adjustment((GtkProgress*)(gtkProgressBar), (GtkAdjustment*)(adjustment)); + + 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 +{ + QRect rect = QWindowsStyle::subControlRect(control, option, subControl, widget); + if (!QGtk::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<const QStyleOptionSlider *>(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<const QStyleOptionGroupBox *>(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<const QGroupBox *>(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 = pixelMetric(PM_IndicatorWidth, option, widget); + int indicatorHeight = 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<const QStyleOptionSpinBox *>(option)) { + GtkWidget *gtkSpinButton = QGtk::gtkWidget(QLS("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(spinboxArrowSize()); + 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<const QStyleOptionComboBox *>(option)) { + // We employ the gtk widget to position arrows and separators for us + QString comboBoxPath = box->editable ? QLS("GtkComboBoxEntry") : QLS("GtkComboBox"); + GtkWidget *gtkCombo = QGtk::gtkWidget(comboBoxPath); + QGtk::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())}; + QGtk::gtk_widget_size_allocate(gtkCombo, &geometry); + int appears_as_list = !styleHint(QStyle::SH_ComboBox_Popup, option, widget); + QString arrowPath = comboBoxPath + QLS(".GtkToggleButton"); + + if (!box->editable && !appears_as_list) + arrowPath += QLS(".GtkHBox.GtkArrow"); + + GtkWidget *arrowWidget = QGtk::gtkWidget(arrowPath); + if (!arrowWidget) + return QCleanlooksStyle::subControlRect(control, option, subControl, widget); + + QRect buttonRect(arrowWidget->allocation.x, 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 +{ + + QSize newSize = QCleanlooksStyle::sizeFromContents(type, option, size, widget); + if (!QGtk::isThemeAvailable()) + return newSize; + + switch (type) { + + case CT_ToolButton: + if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { + GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + newSize = size + QSize(2 * gtkButton->style->xthickness, 1 + 2 * gtkButton->style->ythickness); + if (widget && qobject_cast<QToolBar *>(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<const QStyleOptionMenuItem *>(option)) { + int textMargin = 8; + + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + GtkWidget *gtkMenuSeparator = QGtk::gtkWidget(QLS("GtkMenu.GtkSeparatorMenuItem")); + gboolean wide_separators; + gint separator_height; + QGtk::gtk_widget_style_get(gtkMenuSeparator, + "wide-separators", &wide_separators, + "separator-height", &separator_height, + NULL); + newSize = QSize(size.width(), wide_separators ? separator_height - 1 : 7 ); + + break; + } + + GtkWidget *gtkMenuItem = QGtk::gtkWidget(QLS("GtkMenu.GtkMenuItem")); + GtkStyle* style = gtkMenuItem->style; + newSize += QSize(textMargin + style->xthickness - 2, style->ythickness - 4); + + // Cleanlooks assumes a check column of 20 pixels so we need to + // expand it a bit + gint checkSize; + QGtk::gtk_widget_style_get(QGtk::gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")), "indicator-size", &checkSize, NULL); + newSize.setHeight(qMax(newSize.height(), checkSize + 2)); + newSize.setWidth(newSize.width() + qMax(0, checkSize - 20)); + } + + break; + + case CT_Menu: + // This is evil, but QMenu adds 1 pixel too much + newSize -= QSize(0, 1); + + break; + + case CT_SpinBox: + // QSpinBox does some nasty things that depends on CT_LineEdit + newSize = size + QSize(0, -QGtk::gtkWidget(QLS("GtkSpinButton"))->style->ythickness * 2 + 2); + break; + + case CT_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { + GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + gint focusPadding, focusWidth; + QGtk::gtk_widget_style_get(gtkButton, "focus-padding", &focusPadding, NULL); + QGtk::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 = QGtk::gtkWidget(QLS("GtkHButtonBox")); + gint minWidth = 85, minHeight = 0; + QGtk::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 = QGtk::gtkWidget(QLS("GtkHScale")); + newSize = size + QSize(2*gtkSlider->style->xthickness, 2*gtkSlider->style->ythickness); + } + break; + + case CT_MenuBarItem://cleanlooks adds 2 pixels + newSize = QWindowsStyle::sizeFromContents(type, option, size, widget) + QSize(0, 1); + break; + + case CT_LineEdit: { + GtkWidget *gtkEntry = QGtk::gtkWidget(QLS("GtkEntry")); + newSize = size + QSize(2*gtkEntry->style->xthickness, 2*gtkEntry->style->ythickness); + } + break; + + case CT_ItemViewItem: + newSize += QSize(0, 2); + break; + + case CT_ComboBox: + if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { + GtkWidget *gtkCombo = QGtk::gtkWidget(QLS("GtkComboBox")); + QRect arrowButtonRect = 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<QToolBar *>(widget->parentWidget()))) + newSize += QSize(0, 3); + } + 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<const QStyleOptionTab *>(option)) { + if (!tab->icon.isNull()) + newSize += QSize(6, 0); + } + newSize += QSize(1, 0); + break; + + default: + break; + } + + return newSize; +} + +/*! \reimp */ +QPixmap QGtkStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, + const QWidget *widget) const +{ + if (!QGtk::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 QPixmap(); +} + +/*! \reimp */ +QRect QGtkStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const +{ + QRect r = QCleanlooksStyle::subElementRect(element, option, widget); + switch (element) { + case SE_ProgressBarLabel: + case SE_ProgressBarContents: + case SE_ProgressBarGroove: + return option->rect; + 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/gui/styles/qgtkstyle.h b/src/gui/styles/qgtkstyle.h new file mode 100644 index 0000000000..b7d5bcf09c --- /dev/null +++ b/src/gui/styles/qgtkstyle.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGTKSTYLE_H +#define QGTKSTYLE_H + +#include <QtGui/QCleanlooksStyle> +#include <QtGui/QPalette> +#include <QtGui/QFont> + +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(); + + 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); +}; + + +#endif //!defined(QT_NO_STYLE_QGTK) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif //QGTKSTYLE_H diff --git a/src/gui/styles/qmacstyle_mac.h b/src/gui/styles/qmacstyle_mac.h new file mode 100644 index 0000000000..f043a66731 --- /dev/null +++ b/src/gui/styles/qmacstyle_mac.h @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMACSTYLE_MAC_H +#define QMACSTYLE_MAC_H + +#include <QtGui/qwindowsstyle.h> + +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 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; +}; + +#endif // Q_WS_MAC + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMACSTYLE_H diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm new file mode 100644 index 0000000000..a3f5cfe2de --- /dev/null +++ b/src/gui/styles/qmacstyle_mac.mm @@ -0,0 +1,6394 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmacstyle_mac.h" + +#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) +#define QMAC_QAQUASTYLE_SIZE_CONSTRAIN +//#define DEBUG_SIZE_CONSTRAINT + +#include <private/qcombobox_p.h> +#include <private/qmacstylepixmaps_mac_p.h> +#include <private/qpaintengine_mac_p.h> +#include <private/qpainter_p.h> +#include <private/qprintengine_mac_p.h> +#include <qapplication.h> +#include <qbitmap.h> +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qdialogbuttonbox.h> +#include <qdockwidget.h> +#include <qevent.h> +#include <qfocusframe.h> +#include <qformlayout.h> +#include <qgroupbox.h> +#include <qhash.h> +#include <qheaderview.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qlistview.h> +#include <qmainwindow.h> +#include <qmap.h> +#include <qmenubar.h> +#include <qpaintdevice.h> +#include <qpainter.h> +#include <qpixmapcache.h> +#include <qpointer.h> +#include <qprogressbar.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qrubberband.h> +#include <qsizegrip.h> +#include <qspinbox.h> +#include <qsplitter.h> +#include <qstyleoption.h> +#include <qtextedit.h> +#include <qtextstream.h> +#include <qtoolbar.h> +#include <qtoolbutton.h> +#include <qtreeview.h> +#include <qtableview.h> +#include <qwizard.h> +#include <qdebug.h> +#include <qlibrary.h> +#include <qdatetimeedit.h> +#include <QtGui/qgraphicsproxywidget.h> +#include <QtGui/qgraphicsview.h> +#include <private/qt_cocoa_helpers_mac_p.h> + +QT_BEGIN_NAMESPACE + +extern QRegion qt_mac_convert_mac_region(RgnHandle); //qregion_mac.cpp +extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); // qapplication.cpp + +// The following constants are used for adjusting the size +// of push buttons so that they are drawn inside their bounds. +static const int PushButtonLeftOffset = 6; +static const int PushButtonTopOffset = 4; +static const int PushButtonRightOffset = 12; +static const int PushButtonBottomOffset = 12; +static const int MiniButtonH = 26; +static const int SmallButtonH = 30; +static const int BevelButtonW = 50; +static const int BevelButtonH = 22; +static const int 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); + + +// Resolve these at run-time, since the functions was moved in Leopard. +typedef HIRect * (*PtrHIShapeGetBounds)(HIShapeRef, HIRect *); +static PtrHIShapeGetBounds ptrHIShapeGetBounds = 0; + +static bool isVerticalTabs(const QTabBar::Shape shape) { + return (shape == QTabBar::RoundedEast + || shape == QTabBar::TriangularEast + || shape == QTabBar::RoundedWest + || shape == QTabBar::TriangularWest); +} + +static int closeButtonSize = 12; + +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) { + p->fillRect(rect, QColor(151, 151, 151)); + } else { + QLinearGradient gradient(rect.topLeft(), rect.bottomLeft()); + gradient.setColorAt(0, QColor(207, 207, 207)); + gradient.setColorAt(0.5, QColor(206, 206, 206)); + gradient.setColorAt(1, QColor(201, 201, 201)); + 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(0, 0, width, 0); + p->setPen(borderTop); + p->drawLine(0, 1, width, 1); + + // center block + QRect centralRect(0, 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(0, height - 2, width, height - 2); + p->setPen(borderBottom); + p->drawLine(0, height - 1, width, height - 1); +} + +/* + 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) + +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<const QTreeView *>(widget->parentWidget()) +#ifdef QT3_SUPPORT + || widget->parentWidget()->inherits("Q3ListView") +#endif + )); +} + +QString qt_mac_removeMnemonics(const QString &original) +{ + // copied from qt_format_text (to be bug-for-bug compatible). + QString returnText(original.size(), 0); + int finalDest = 0; + int currPos = 0; + int l = original.length(); + while (l) { + if (original.at(currPos) == 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; +} + +class QMacStylePrivate : public QObject +{ + Q_OBJECT + +public: + QMacStylePrivate(QMacStyle *style); + + // 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; + + void drawPantherTab(const QStyleOptionTab *tab, QPainter *p, const QWidget *w = 0) 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<QPushButton> defaultButton; //default push buttons + int timerID; + QList<QPointer<QWidget> > progressBars; //existing progress bars that need animation + + struct ButtonState { + int frame; + enum { ButtonDark, ButtonLight } dir; + } buttonState; + UInt8 progressFrame; + QPointer<QFocusFrame> focusWidget; + CFAbsoluteTime defaultButtonStart; + QMacStyle *q; + bool mouseDown; +}; + +QT_BEGIN_INCLUDE_NAMESPACE +#include "qmacstyle_mac.moc" +QT_END_INCLUDE_NAMESPACE + +/***************************************************************************** + External functions + *****************************************************************************/ +extern CGContextRef qt_mac_cg_context(const QPaintDevice *); //qpaintdevice_mac.cpp +extern QPixmap qt_mac_convert_iconref(const IconRef, int, int); //qpixmap_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 macSpinBoxSep = 5; // distance between spinwidget and the lineedit +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() +{ +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) + return 1; +#endif + return 0; +} + +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<const QPushButton *>(widg)) + ct = QStyle::CT_PushButton; + else if (qobject_cast<const QRadioButton *>(widg)) + ct = QStyle::CT_RadioButton; + else if (qobject_cast<const QCheckBox *>(widg)) + ct = QStyle::CT_CheckBox; + else if (qobject_cast<const QComboBox *>(widg)) + ct = QStyle::CT_ComboBox; + else if (qobject_cast<const QToolButton *>(widg)) + ct = QStyle::CT_ToolButton; + else if (qobject_cast<const QSlider *>(widg)) + ct = QStyle::CT_Slider; + else if (qobject_cast<const QProgressBar *>(widg)) + ct = QStyle::CT_ProgressBar; + else if (qobject_cast<const QLineEdit *>(widg)) + ct = QStyle::CT_LineEdit; + else if (qobject_cast<const QHeaderView *>(widg) +#ifdef QT3_SUPPORT + || widg->inherits("Q3Header") +#endif + ) + ct = QStyle::CT_HeaderSection; + else if (qobject_cast<const QMenuBar *>(widg) +#ifdef QT3_SUPPORT + || widg->inherits("Q3MenuBar") +#endif + ) + ct = QStyle::CT_MenuBar; + else if (qobject_cast<const QSizeGrip *>(widg)) + ct = QStyle::CT_SizeGrip; + else + return ret; + } + + switch (ct) { + case QStyle::CT_PushButton: { + const QPushButton *psh = static_cast<const QPushButton *>(widg); + 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); + } + +#if 0 //Not sure we are applying the rules correctly for RadioButtons/CheckBoxes --Sam + } else if (ct == QStyle::CT_RadioButton) { + QRadioButton *rdo = static_cast<QRadioButton *>(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 = static_cast<const QToolButton *>(widg); + 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 { + 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 = static_cast<const QSlider *>(widg); + 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); + } + } + 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<const QProgressBar *>(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<QComboBox *>(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 (sz == QAquaSizeLarge && 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<QDockWidget *>(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 += PushButtonTopOffset; + outerBounds.size.height -= PushButtonBottomOffset; + } else if (bdi->kind == kThemePushButtonMini) { + outerBounds.origin.y += 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(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->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() >= BevelButtonW && btn->rect.height() >= BevelButtonH){ + if (widget && widget->testAttribute(Qt::WA_MacVariableSize)) { + if (btn->rect.height() <= MiniButtonH){ + if (contentFitsInPushButton(btn, bdi, kThemePushButtonMini)) + bdi->kind = kThemePushButtonMini; + } else if (btn->rect.height() <= SmallButtonH){ + if (contentFitsInPushButton(btn, bdi, kThemePushButtonSmall)) + bdi->kind = kThemePushButtonSmall; + } else if (contentFitsInPushButton(btn, bdi, kThemePushButton)) { + bdi->kind = kThemePushButton; + } + } else { + bdi->kind = kThemePushButton; + } + } + } + } +} + +/** + 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) + && QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { + 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<PtrHIShapeGetBounds>(library.resolve("HIShapeGetBounds")); + } + +} + +bool QMacStylePrivate::animatable(QMacStylePrivate::Animates as, const QWidget *w) const +{ + if (as == AquaPushButton) { + QPushButton *pb = const_cast<QPushButton *>(static_cast<const QPushButton *>(w)); + if (w->window()->isActiveWindow() && pb && !mouseDown) { + if (static_cast<const QPushButton *>(w) != defaultButton) { + // Changed on its own, update the value. + const_cast<QMacStylePrivate *>(this)->stopAnimate(as, defaultButton); + const_cast<QMacStylePrivate *>(this)->startAnimate(as, pb); + } + return true; + } + } else if (as == AquaProgressBar) { + if (progressBars.contains((const_cast<QWidget *>(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<QPushButton *>(w); + else if (as == AquaProgressBar) + progressBars.append(w); + startAnimationTimer(); +} + +void QMacStylePrivate::startAnimationTimer() +{ + if ((defaultButton || !progressBars.isEmpty()) && timerID <= -1) + timerID = startTimer(animateSpeed(AquaListViewItemOpen)); +} + +enum { TabNormalLeft, TabNormalMid, TabNormalRight, TabSelectedActiveLeft, + TabSelectedActiveMid, TabSelectedActiveRight, TabSelectedInactiveLeft, + TabSelectedInactiveMid, TabSelectedInactiveRight, TabSelectedActiveGraphiteLeft, + TabSelectedActiveGraphiteMid, TabSelectedActiveGraphiteRight, + TabPressedLeft, TabPressedMid, TabPressedRight }; + +static const char * const * const PantherTabXpms[] = { + qt_mac_tabnrm_left, + qt_mac_tabnrm_mid, + qt_mac_tabnrm_right, + qt_mac_tabselected_active_left, + qt_mac_tabselected_active_mid, + qt_mac_tabselected_active_right, + qt_mac_tabselected_inactive_left, + qt_mac_tabselected_inactive_mid, + qt_mac_tabselected_inactive_right, + qt_mac_tab_selected_active_graph_left, + qt_mac_tab_selected_active_graph_mid, + qt_mac_tab_selected_active_graph_right, + qt_mac_tab_press_left, + qt_mac_tab_press_mid, + qt_mac_tab_press_right}; + +void QMacStylePrivate::drawPantherTab(const QStyleOptionTab *tabOpt, QPainter *p, + const QWidget *) const +{ + QString tabKey = QLatin1String("$qt_mac_style_tab_"); + int pantherTabStart; + int pantherTabMid; + int pantherTabEnd; + + ThemeTabDirection ttd = getTabDirection(tabOpt->shape); + + if (tabOpt->state & QStyle::State_Selected) { + if (!(tabOpt->state & QStyle::State_Active)) { + pantherTabStart = TabSelectedInactiveLeft; + } else { + // Draw into a pixmap to determine which version we use, Aqua or Graphite. + QPixmap tabPix(20, 20); + QPainter pixPainter(&tabPix); + HIThemeTabDrawInfo tdi; + tdi.version = 0; + tdi.style = kThemeTabFront; + tdi.direction = kThemeTabNorth; + tdi.size = kHIThemeTabSizeNormal; + tdi.adornment = kHIThemeTabAdornmentNone; + HIRect inRect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); + HIThemeDrawTab(&inRect, &tdi, QMacCGContext(&pixPainter), kHIThemeOrientationNormal, 0); + pixPainter.end(); + const QRgb GraphiteColor = 0xffa7b0ba; + QRgb pmColor = tabPix.toImage().pixel(10, 10); + if (qAbs(qRed(pmColor) - qRed(GraphiteColor)) < 3 && + qAbs(qGreen(pmColor) - qGreen(GraphiteColor)) < 3 + && qAbs(qBlue(pmColor) - qBlue(GraphiteColor)) < 3) + pantherTabStart = TabSelectedActiveGraphiteLeft; + else + pantherTabStart = TabSelectedActiveLeft; + } + } else if (tabOpt->state & QStyle::State_Sunken) { + pantherTabStart = TabPressedLeft; + } else { + pantherTabStart = TabNormalLeft; + } + + + bool doLine; + bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; + + QStyleOptionTab::TabPosition tp = tabOpt->position; + if (ttd == kThemeTabWest + || ((ttd == kThemeTabNorth || ttd == kThemeTabSouth) + && tabOpt->direction == Qt::RightToLeft)) { + if (tp == QStyleOptionTab::Beginning) + tp = QStyleOptionTab::End; + else if (tp == QStyleOptionTab::End) + tp = QStyleOptionTab::Beginning; + } + + switch (tp) { + default: // Stupid GCC, being overly pedantic + case QStyleOptionTab::Beginning: + doLine = false; + pantherTabMid = pantherTabEnd = pantherTabStart + 1; + break; + case QStyleOptionTab::Middle: + doLine = true; + pantherTabMid = pantherTabEnd = ++pantherTabStart; + break; + case QStyleOptionTab::End: + doLine = true; + pantherTabMid = ++pantherTabStart; + pantherTabEnd = pantherTabMid + 1; + break; + case QStyleOptionTab::OnlyOneTab: + doLine = false; + pantherTabMid = pantherTabStart + 1; + pantherTabEnd = pantherTabMid + 1; + break; + } + + QPixmap pmStart; + if (!QPixmapCache::find(tabKey + QString::number(pantherTabStart), pmStart)) { + pmStart = QPixmap(PantherTabXpms[pantherTabStart]); + QPixmapCache::insert(tabKey + QString::number(pantherTabStart), pmStart); + } + + QPixmap pmMid; + if (!QPixmapCache::find(tabKey + QString::number(pantherTabMid), pmMid)) { + pmMid = QPixmap(PantherTabXpms[pantherTabMid]); + QPixmapCache::insert(tabKey + QString::number(pantherTabMid), pmMid); + } + + QPixmap pmEnd; + if (!QPixmapCache::find(tabKey + QString::number(pantherTabEnd), pmEnd)) { + pmEnd = QPixmap(PantherTabXpms[pantherTabEnd]); + QPixmapCache::insert(tabKey + QString::number(pantherTabEnd), pmEnd); + } + QRect tr = tabOpt->rect; + if (verticalTabs) { + p->save(); + int newX, newY, newRot; + if (tabOpt->shape == QTabBar::RoundedEast || tabOpt->shape == QTabBar::TriangularEast) { + newX = tr.width(); + newY = tr.y(); + newRot = 90; + } else { + newX = 0; + newY = tr.y() + tr.height(); + newRot = -90; + } + tr.setRect(0, 0, tr.height(), tr.width()); + QMatrix m; + if (ttd == kThemeTabEast) { + // It's lame but Apple inverts these on the East side. + m.scale(-1, 1); + m.translate(-tabOpt->rect.width(), 0); + } + m.translate(newX, newY); + m.rotate(newRot); + p->setMatrix(m, true); + } + + int x = tr.x(); + int y = tr.y(); + int endX = x + tr.width() - pmEnd.width(); + + p->drawPixmap(x, y, pmStart.width(), tr.height(), pmStart); + if (doLine) { + QPen oldPen = p->pen(); + p->setPen(QColor(0, 0, 0, 0x35)); + p->drawLine(x, y + (verticalTabs ? 0 : 1), x, tr.height() - 2); + } + + for (x = x + pmStart.width(); x < endX; x += pmMid.width()) + p->drawPixmap(x, y, pmMid.width(), tr.height(), pmMid); + p->drawPixmap(endX, y, pmEnd.width(), tr.height(), pmEnd); + if (verticalTabs) + p->restore(); +} + +bool QMacStylePrivate::addWidget(QWidget *w) +{ + //already knew of it + if (static_cast<QPushButton*>(w) == defaultButton + || progressBars.contains(static_cast<QProgressBar*>(w))) + return false; + + if (QPushButton *btn = qobject_cast<QPushButton *>(w)) { + btn->installEventFilter(this); + if (btn->isDefault() || (btn->autoDefault() && btn->hasFocus())) + startAnimate(AquaPushButton, btn); + return true; + } else { + bool isProgressBar = (qobject_cast<QProgressBar *>(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<QPushButton *>(w); + if (btn && btn == defaultButton) { + stopAnimate(AquaPushButton, btn); + } else if (qobject_cast<QProgressBar *>(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<QProgressBar *>(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<QProgressBar *>(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<QPushButton *>(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<QMouseEvent *>(e)->button() == Qt::LeftButton) + mouseDown = true; + stopAnimate(AquaPushButton, btn); + break; + case QEvent::MouseButtonRelease: + if (static_cast<QMouseEvent *>(e)->button() == Qt::LeftButton) + mouseDown = false; + // fall through + case QEvent::FocusOut: + case QEvent::Show: + case QEvent::WindowActivate: { + QList<QPushButton *> list = qFindChildren<QPushButton *>(btn->window()); + 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<const QStyleOptionComboBox *>(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<QRgb *>(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<QRgb *>(colorlessImage.scanLine(y)); + const QRgb *activeScanLine = reinterpret_cast<const QRgb *>(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); +} + +/*! + \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 +*/ + +/*! + Constructs a QMacStyle object. +*/ +QMacStyle::QMacStyle() + : QWindowsStyle() +{ + d = new QMacStylePrivate(this); +} + +/*! + Destructs a QMacStyle object. +*/ +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); +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { + QMacCGContext cg(&px); + HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationNormal); + const CGRect cgRect = CGRectMake(0, 0, px.width(), px.height()); + CGContextFillRect(cg, cgRect); + } else +#endif + { +#ifndef QT_MAC_NO_QUICKDRAW + QMacSavedPortInfo port(&px); + SetThemeBackground(kThemeBrushDialogBackgroundActive, px.depth(), true); + const Rect qdRect = { 0, 0, px.width(), px.height() }; + EraseRect(&qdRect); +#endif + } + 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 QPoint &offset, const QBrush &brush) +{ +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) + QPoint dummy; + const QPaintDevice *target = painter->device(); + const QPaintDevice *redirected = QPainter::redirected(target, &dummy); + const bool usePainter = redirected && redirected != target; + const QRegion translated = rgn.translated(offset); + + if (!usePainter && QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 && qt_mac_backgroundPattern + && qt_mac_backgroundPattern->cacheKey() == brush.texture().cacheKey()) { + + painter->setClipRegion(translated); + + CGContextRef cg = qt_mac_cg_context(target); + CGContextSaveGState(cg); + HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationInverted); + + const QVector<QRect> &rects = translated.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 +#endif + { + const QRect rect(translated.boundingRect()); + painter->setClipRegion(translated); + painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); + } +} + +/*! \reimp */ +void QMacStyle::polish(QPalette &pal) +{ + if (qt_mac_backgroundPattern == 0) + 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)); + } +} + +/*! \reimp */ +void QMacStyle::polish(QApplication *) +{ +} + +/*! \reimp */ +void QMacStyle::unpolish(QApplication *) +{ +} + +/*! \reimp */ +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<QMenu*>(w) || qobject_cast<QComboBoxPrivateContainer *>(w)) { + w->setWindowOpacity(0.94); + if (!w->testAttribute(Qt::WA_SetPalette)) { + QPixmap px(64, 64); + HIThemeMenuDrawInfo mtinfo; + mtinfo.version = qt_mac_hitheme_version; + mtinfo.menuType = kThemeMenuTypePopUp; + HIRect rect = CGRectMake(0, 0, px.width(), px.height()); + HIThemeDrawMenuBackground(&rect, &mtinfo, QCFType<CGContextRef>(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); + } + } + + // Adjust the lineedit of the editable combo box + if (QSysInfo::MacintoshVersion == QSysInfo::MV_10_3) { + if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(w)) { + if (qobject_cast<QComboBox *>(lineEdit->parentWidget()) + && !lineEdit->testAttribute(Qt::WA_SetFont)) { + QFont font = lineEdit->font(); + font.setPointSize(font.pointSize() - 1); + lineEdit->setFont(font); + } + } + } + + if (QTabBar *tb = qobject_cast<QTabBar*>(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<QRubberBand*>(w)) { + rubber->setWindowOpacity(0.25); + rubber->setAttribute(Qt::WA_PaintOnScreen, false); + rubber->setAttribute(Qt::WA_NoSystemBackground, false); + } +} + +/*! \reimp */ +void QMacStyle::unpolish(QWidget* w) +{ + d->removeWidget(w); + if ((qobject_cast<QMenu*>(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<QComboBox *>(w)) { + if (!combo->isEditable()) { + if (QWidget *widget = combo->findChild<QComboBoxPrivateContainer *>()) + widget->setWindowOpacity(1.0); + } + } + + if (QRubberBand *rubber = ::qobject_cast<QRubberBand*>(w)) { + rubber->setWindowOpacity(1.0); + rubber->setAttribute(Qt::WA_PaintOnScreen, true); + rubber->setAttribute(Qt::WA_NoSystemBackground, true); + } + + if (QFocusFrame *frame = qobject_cast<QFocusFrame *>(w)) { + frame->setAttribute(Qt::WA_NoSystemBackground, true); + frame->setAutoFillBackground(true); + } + QWindowsStyle::unpolish(w); +} + +/*! \reimp */ +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 = 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<const QMainWindow*>(widget->parentWidget()) + && static_cast<QMainWindow *>(widget->parentWidget())->centralWidget() == widget)) + && (qobject_cast<const QAbstractScrollArea *>(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<const QStyleOptionComboBox *>(opt) != 0) + ret = 0; + else + ret = QWindowsStyle::pixelMetric(metric, opt, widget); + break; + case PM_MaximumDragDistance: + ret = -1; + break; + case PM_ScrollBarSliderMin: + ret = 24; + break; + case PM_SpinBoxFrameWidth: + GetThemeMetric(kThemeMetricEditTextFrameOutset, &ret); + ret += 2; + 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<const QStyleOptionTitleBar *>(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<HIShapeRef> region; + HIRect hirect = qt_hirectForQRect(tb->rect); + if (hirect.size.width == -1) + hirect.size.width = 100; + if (hirect.size.height == -1) + 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: +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3) && 0 + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3) { + GetThemeMetric(kThemeMetricMiniScrollBarWidth, &ret); + break; + } +#endif + 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_MessageBoxIconSize: + ret = 64; + 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; + default: + ret = QWindowsStyle::pixelMetric(metric, opt, widget); + break; + } + return ret; +} + +/*! \reimp */ +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; +} + +/*! \reimp */ +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<const QStyleOptionTabBarBaseV2 *>(opt)) { + ret = opt2->documentMode ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; + } else { + ret = QEvent::MouseButtonRelease; + } + break; + case SH_ComboBox_Popup: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(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<const QTabWidget*>(w)) { + if (tab->documentMode()) { + ret = Qt::AlignLeft; + break; + } + } + if (const QTabBar *tab = qobject_cast<const QTabBar*>(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<QStyleHintReturnMask*>(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); + 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<QStyleHintReturnMask *>(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<QStyleHintReturnMask*>(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<QMenu *>(w->parentWidget())) + mdi.menuType = kThemeMenuTypeHierarchical; + else + mdi.menuType = kThemeMenuTypePopUp; + QCFType<HIShapeRef> 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; +} + +/*! \reimp */ +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); +} + + +/*! \reimp */ +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); +} +/*! + \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. +*/ + +/*! + \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() +*/ +void QMacStyle::setFocusRectPolicy(QWidget *w, FocusRectPolicy policy) +{ + switch (policy) { + case FocusDefault: + break; + case FocusEnabled: + case FocusDisabled: + w->setAttribute(Qt::WA_MacShowFocusRect, policy == FocusEnabled); + break; + } +} + +/*! + \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() +*/ +QMacStyle::FocusRectPolicy QMacStyle::focusRectPolicy(const QWidget *w) +{ + return w->testAttribute(Qt::WA_MacShowFocusRect) ? FocusEnabled : FocusDisabled; +} + +/*! + \obsolete + + Call QWidget::setAttribute() with Qt::WA_MacMiniSize, Qt::WA_MacSmallSize, + or Qt::WA_MacNormalSize instead. +*/ +void QMacStyle::setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy) +{ + QWidget *wadget = const_cast<QWidget *>(widget); + wadget->setAttribute(Qt::WA_MacNormalSize, policy == SizeLarge); + wadget->setAttribute(Qt::WA_MacSmallSize, policy == SizeSmall); + wadget->setAttribute(Qt::WA_MacMiniSize, policy == SizeMini); +} + +/*! + \obsolete + + Call QWidget::testAttribute() with Qt::WA_MacMiniSize, Qt::WA_MacSmallSize, + or Qt::WA_MacNormalSize instead. +*/ +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; +} + +/*! \reimp */ +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<const QStyleOptionTabBarBaseV2 *>(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; + } + 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<const QStyleOptionFrame *>(opt)) { + const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(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<QGroupBox *>(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<qreal>() << 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<const QStyleOptionHeader *>(opt)) { + // In HITheme, up is down, down is up and hamburgers eat people. + if (header->sortIndicator != QStyleOptionHeader::None) + 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<QLineF> 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); + HIThemeDrawButton(&hirect, &bi, cg, kHIThemeOrientationNormal, 0); + break; } + case PE_Frame: { + QPen oldPen = p->pen(); + QPen newPen; + newPen.setBrush(opt->palette.dark()); + p->setPen(newPen); + p->drawRect(opt->rect.adjusted(0, 0, -1, -1)); + p->setPen(oldPen); + break; } + case PE_FrameLineEdit: + if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(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 = 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); + break; + case PE_FrameTabWidget: + if (const QStyleOptionTabWidgetFrame *twf + = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { + HIRect hirect = qt_hirectForQRect(twf->rect); +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { + HIThemeTabPaneDrawInfo tpdi; + tpdi.version = qt_mac_hitheme_tab_version(); + tpdi.state = tds; + tpdi.direction = getTabDirection(twf->shape); + tpdi.size = kHIThemeTabSizeNormal; + if (tpdi.version == 1) { + tpdi.kind = kHIThemeTabKindNormal; + tpdi.adornment = kHIThemeTabPaneAdornmentNormal; + } + HIThemeDrawTabPane(&hirect, &tpdi, cg, kHIThemeOrientationNormal); + } else +#endif + { + HIThemeGroupBoxDrawInfo gdi; + gdi.version = qt_mac_hitheme_version; + gdi.state = tds; + gdi.kind = kHIThemeGroupBoxKindSecondary; + HIThemeDrawGroupBox(&hirect, &gdi, cg, kHIThemeOrientationNormal); + } + } + break; + case PE_PanelScrollAreaCorner: { + const QBrush brush(qApp->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: + QCommonStyle::drawPrimitive(pe, opt, p, w); + 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<QMainWindow *>(w->parent()) == 0 || + qobject_cast<QMainWindow *>(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); +} + + + +/*! \reimp */ +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<const QStyleOptionHeader *>(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: + break; + case QStyleOptionHeader::Middle: + case QStyleOptionHeader::End: + ir.adjust(-1, 0, 0, 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<const QTableView *>(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<const QStyleOptionHeader *>(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(pixelMetric(PM_SmallIconSize), mode); + + QRect pixr = header->rect; + pixr.setY(header->rect.center().y() - (pixmap.height() - 1) / 2); + drawItemPixmap(p, pixr, Qt::AlignVCenter, pixmap); + textr.translate(pixmap.width() + 2, 0); + } + + 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<const QStyleOptionToolButton *>(opt)) { + QStyleOptionToolButton myTb = *tb; + myTb.state &= ~State_AutoRaise; + if (w && qobject_cast<QToolBar *>(w->parentWidget())) { + QRect cr = tb->rect; + int shiftX = 0; + int shiftY = 0; + if (tb->state & (State_Sunken | State_On)) { + shiftX = pixelMetric(PM_ButtonShiftHorizontal, tb, w); + shiftY = 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->state & State_Sunken + && !(tb->features & QStyleOptionToolButton::Arrow)) { + Qt::ToolButtonStyle tbstyle = tb->toolButtonStyle; + if (tb->icon.isNull() && !tb->text.isEmpty()) + tbstyle = Qt::ToolButtonTextOnly; + + switch (tbstyle) { + case Qt::ToolButtonTextOnly: + drawItemText(p, cr, Qt::AlignCenter, tb->palette, + tb->state & State_Enabled, tb->text); + 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) { + int alignment = 0; + if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { + 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; + } + cr.translate(shiftX, shiftY); + drawItemText(p, cr, alignment, tb->palette, + tb->state & State_Enabled, tb->text); + cr.adjust(0, 3, 0, -3); // the drop shadow + drawItemText(p, cr, alignment, tb->palette, + tb->state & State_Enabled, tb->text); + } + pr.translate(shiftX, shiftY); + pixmap = darkenPixmap(pixmap); + drawItemPixmap(p, pr, Qt::AlignCenter, pixmap); + break; } + } + } 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<const QStyleOptionButton *>(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 += PushButtonLeftOffset; + newRect.origin.y += PushButtonTopOffset; + newRect.size.width -= PushButtonRightOffset; + newRect.size.height -= PushButtonBottomOffset; + } else if (bdi.kind == kThemePushButtonMini) { + newRect.origin.x += PushButtonLeftOffset - 2; + newRect.origin.y += PushButtonTopOffset; + newRect.size.width -= PushButtonRightOffset - 4; + } + HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); + + if (btn->features & QStyleOptionButton::HasMenu) { + int mbi = pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); + QRect ir = btn->rect; + HIRect arrowRect = CGRectMake(ir.right() - mbi - 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<const QStyleOptionButton *>(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 += 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() + 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); + drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap); + int newOffset = iconDestRect.x() + iconDestRect.width() + + PushButtonContentPadding - textRect.x(); + textRect.adjust(newOffset, 0, newOffset, 0); + } + // Draw the text: + if (hasText) { + textRect = visualRect(btn->direction, freeContentRect, textRect); + 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<const QStyleOptionComboBox *>(opt)) { + QStyleOptionComboBox comboCopy = *cb; + comboCopy.direction = Qt::LeftToRight; + QWindowsStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w); + } + break; + case CE_TabBarTabShape: + if (const QStyleOptionTabV3 *tabOpt = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) { + if (tabOpt->documentMode) { + p->save(); + QRect tabRect = tabOpt->rect; + drawTabShape(p, tabOpt); + p->restore(); + return; + } + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) + if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_3) { + 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; + + if ((!verticalTabs && tabRect.height() > 21 || verticalTabs && tabRect.width() > 21)) { + d->drawPantherTab(tabOpt, p, w); + break; + } + + 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; + } + } + switch (tp) { + case QStyleOptionTab::Beginning: + tdi.position = kHIThemeTabPositionFirst; + if (sp != QStyleOptionTab::NextIsSelected) + tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator; + break; + case QStyleOptionTab::Middle: + tdi.position = kHIThemeTabPositionMiddle; + if (selected) + tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator; + if (sp != QStyleOptionTab::NextIsSelected) // 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; + } + HIRect hirect = qt_hirectForQRect(tabRect); + HIThemeDrawTab(&hirect, &tdi, cg, kHIThemeOrientationNormal, 0); + } else +#endif + { + d->drawPantherTab(tabOpt, p, w); + } + } + break; + case CE_TabBarTabLabel: + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(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; + 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<const QDockWidget *>(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<HIShapeRef> 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<const QStyleOptionDockWidget *>(opt)) { + if (!dwOpt->title.isEmpty()) { + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(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 = pixelMetric(PM_FocusFrameHMargin, opt, w) + 1; + int yOff = 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<const QStyleOptionMenuItem *>(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 = pixelMetric(PM_SmallIconSize); + QSize iconSize(smallIconSize, smallIconSize); + if (const QComboBox *comboBox = qobject_cast<const QComboBox *>(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; + if (mi->state & QStyle::State_Mini) + myFont.setPointSize(mi->font.pointSize()); + 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<const QStyleOptionMenuItem *>(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<const QStyleOptionMenuItem *>(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; + HIRect hirect = qt_hirectForQRect(mi->rect); + HIThemeDrawMenuBarBackground(&menuRect, &bdi, cg, kHIThemeOrientationNormal); + } + + if (!mi->icon.isNull()) { + drawItemPixmap(p, mi->rect, + Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip + | Qt::TextSingleLine, + mi->icon.pixmap(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<const QStyleOptionMenuItem *>(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<const QStyleOptionProgressBar *>(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<const QStyleOptionProgressBarV2 *>(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; + HIThemeDrawTrack(&tdi, 0, cg, kHIThemeOrientationNormal); + } + 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<const QStyleOptionRubberBand *>(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<QMainWindow *>(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); + } +} +/*! \reimp */ +QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, + const QWidget *widget) const +{ + QRect rect; + int controlSize = getControlSize(opt, widget); + + switch (sr) { + case SE_ToolBoxTabContents: + rect = QCommonStyle::subElementRect(sr, opt, widget); + break; + case SE_PushButtonContents: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(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<const QStyleOptionHeader *>(opt)) { + rect = QWindowsStyle::subElementRect(sr, opt, widget); + if (widget && widget->height() <= qt_mac_aqua_get_metric(kThemeMetricListHeaderHeight)){ + // We need to allow the text a bit more space when the header is as + // small as kThemeMetricListHeaderHeight, otherwise it gets clipped: + rect.setY(0); + rect.setHeight(widget->height()); + } + if (opt->direction == Qt::RightToLeft) + rect.adjust(15, 0, -20, 0); + } + 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<HIShapeRef> shape; + HIRect outRect; + HIThemeGetButtonShape(&inRect, &bdi, &shape); + ptrHIShapeGetBounds(shape, &outRect); + rect = QRect(int(outRect.origin.x), int(outRect.origin.y), + int(contentRect.origin.x - outRect.origin.x), int(outRect.size.height)); + break; + } + case SE_TabWidgetLeftCorner: + if (const QStyleOptionTabWidgetFrame *twf + = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(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<const QStyleOptionTabWidgetFrame *>(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<const QStyleOptionTabWidgetFrame *>(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<const QComboBox*>(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<QToolBar *>(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<const QStyleOptionButton *>(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<const QStyleOptionSlider *>(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<const QFrame *>(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<const QStyleOptionGroupBox *>(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<const QStyleOptionTabWidgetFrame *>(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); +} + +/*! \reimp */ +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<const QStyleOptionSlider *>(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 + && (!slider->upsideDown + || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 + && slider->upsideDown))); + 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<HIShapeRef> 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 scrollBarLenght = (slider->orientation == Qt::Horizontal) + ? slider->rect.width() : slider->rect.height(); + const QMacStyle::WidgetSizePolicy sizePolicy = widgetSizePolicy(widget); + if (scrollBarLenght < scrollButtonsCutoffSize(thumbIndicatorCutoff, sizePolicy)) + tdi.attributes &= ~kThemeTrackShowThumb; + if (scrollBarLenght < scrollButtonsCutoffSize(scrollButtonsCutoff, sizePolicy)) + tdi.enableState = kThemeTrackNothingToScroll; + } + + 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<const QStyleOptionQ3ListView *>(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; + drawPrimitive(PE_IndicatorBranch, &treeOpt, p, widget); + } + y += item.totalHeight; + } + } + } + break; + case CC_SpinBox: + if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { + QStyleOptionSpinBox newSB = *sb; + if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) { + SInt32 frame_size; + GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size); + + QRect lineeditRect = 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: + case QAquaSizeSmall: + if (aquaSize == QAquaSizeMini) + bdi.kind = kThemeIncDecButtonMini; + else + 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 = subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, + widget); + updown |= 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)); + + // HIThemeGetButtonBackgroundBounds offsets non-focused normal sized + // buttons by one in de y direction, account for that here. + if (bdi.adornment == kThemeAdornmentNone && bdi.kind == kThemeIncDecButton) + off_rct.adjust(0, 1, 0, 0); + + // Adjust the rect for small buttos also. + if (bdi.adornment == kThemeAdornmentFocus && bdi.kind == kThemeIncDecButtonSmall) + off_rct.adjust(0, 0, 0, -1); + + newRect = qt_hirectForQRect(updown, off_rct); + HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); + } + } + break; + case CC_ComboBox: + if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(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<const QStyleOptionTitleBar *>(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<HIShapeRef> 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; + 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<HIShapeRef> titleRegion2; + HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleProxyIconRgn, + &titleRegion2); + ptrHIShapeGetBounds(titleRegion2, &tmpRect); + if (tmpRect.size.width != 1) { + int iconExtent = pixelMetric(PM_SmallIconSize); + iw = titlebar->icon.actualSize(QSize(iconExtent, iconExtent)).width(); + } + } + if (!titlebar->text.isEmpty()) { + p->save(); + QCFType<HIShapeRef> 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(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<const QStyleOptionGroupBox *>(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 = 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<const QStyleOptionToolButton *>(opt)) { + if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) { + if (tb->subControls & SC_ToolButtonMenu) { + QStyleOption arrowOpt(0); + arrowOpt.rect = 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; + drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); + } else if (tb->features & QStyleOptionToolButton::HasMenu) { + drawToolbarButtonArrow(tb->rect, tds, cg); + } + if (tb->state & State_On) { + 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); + } + drawControl(CE_ToolButtonLabel, opt, p, widget); + } else { + ThemeButtonKind bkind = kThemeBevelButton; + switch (d->aquaSizeConstrain(opt, widget)) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + bkind = kThemeBevelButton; + break; + case QAquaSizeMini: +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3) && 0 + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3) { + bkind = kThemeMiniBevelButton; + break; + } +#endif + case QAquaSizeSmall: + bkind = kThemeSmallBevelButton; + break; + } + + QRect button, menuarea; + button = subControlRect(cc, tb, SC_ToolButton, widget); + menuarea = 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 = subControlRect(CC_ToolButton, tb, SC_ToolButton, widget); + int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget); + QStyleOptionToolButton label = *tb; + label.rect = buttonRect.adjusted(fw, fw, -fw, -fw); + drawControl(CE_ToolButtonLabel, &label, p, widget); + } + } + break; + default: + QWindowsStyle::drawComplexControl(cc, opt, p, widget); + break; + } +} + +/*! \reimp */ +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<const QStyleOptionComboBox *>(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<const QStyleOptionSlider *>(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<const QStyleOptionSlider *>(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 scrollBarLenght = (sb->orientation == Qt::Horizontal) + ? sb->rect.width() : sb->rect.height(); + if (scrollBarLenght < 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<const QStyleOptionTitleBar *>(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; +} + +/*! \reimp */ +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<const QStyleOptionSlider *>(opt)) { + HIThemeTrackDrawInfo tdi; + d->getSliderInfo(cc, slider, &tdi, widget); + HIRect macRect; + QCFType<HIShapeRef> 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 + && (!slider->upsideDown + || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 + && slider->upsideDown)) + ) { + 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<const QStyleOptionTitleBar *>(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, pixelMetric(PM_TitleBarHeight, + titlebar, widget)); + if (wrc != kWindowGlobalPortRgn) { + QCFType<HIShapeRef> 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<const QStyleOptionComboBox *>(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<const QDateTimeEdit *>(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.width() - ret.width() - ret.x()); + break; } + case SC_ComboBoxListBoxPopup:{ + if (combo->editable) { + HIRect inner = QMacStylePrivate::comboboxInnerBounds(qt_hirectForQRect(combo->rect), bdi.kind); + QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); + ret.adjust(qRound(inner.origin.x), 0, qRound(inner.origin.x + inner.size.width), editRect.y() + editRect.height() + 2); + } else { + QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); + ret.adjust(4 - 11, 1, editRect.width() + 10 + 11, 1); + } + break; } + default: + break; + } + } + break; + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(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 = int(width); + h = int(height); + } else { + QFontMetrics fm = groupBox->fontMetrics; + if (!checkable && !fontIsSet) + fm = QFontMetrics(qt_app_fonts_hash()->value("QSmallFont", QFont())); + h = fm.height(); + tw = fm.size(Qt::TextShowMnemonic, groupBox->text).width(); + } + ret.setHeight(h); + + QRect labelRect = alignedRect(groupBox->direction, groupBox->textAlignment, + QSize(tw, h), ret); + int indicatorWidth = 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, 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 = -fm.height(); + } + + ret = opt->rect.adjusted(0, 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<const QStyleOptionSpinBox *>(opt)) { + const int spinner_w = 14, + fw = pixelMetric(PM_SpinBoxFrameWidth, spin, widget); + switch (sc) { + case SC_SpinBoxUp: + case SC_SpinBoxDown: { + if (spin->buttonSymbols == QAbstractSpinBox::NoButtons) + break; + const int frameWidth = pixelMetric(PM_SpinBoxFrameWidth, spin, widget); + const int spinner_w = 18; + const int y = frameWidth; + const int x = spin->rect.width() - spinner_w + frameWidth; + 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; + QAquaWidgetSize aquaSize = d->aquaSizeConstrain(opt, widget); + switch (aquaSize) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + bdi.kind = kThemeIncDecButton; + break; + case QAquaSizeMini: + case QAquaSizeSmall: + if (aquaSize == QAquaSizeMini) + bdi.kind = kThemeIncDecButtonMini; + else + bdi.kind = kThemeIncDecButtonSmall; + 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(-1, -2); // hack: position the buttons correctly (weird that we need this) + ret = visualRect(spin->direction, spin->rect, ret); + break; + } + case SC_SpinBoxEditField: + ret.setRect(fw, fw, + spin->rect.width() - spinner_w - fw * 2 - macSpinBoxSep + 1, + 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<QToolBar*>(widget->parentWidget())) { + ret.adjust(-1, 0, 0, 0); + } + break; + default: + ret = QWindowsStyle::subControlRect(cc, opt, sc, widget); + break; + } + return ret; +} + +/*! \reimp */ +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: + sz.setWidth(sz.width() + macSpinBoxSep); + sz.setHeight(sz.height() - 3); // hack to work around horrible sizeHint() code in QAbstractSpinBox + break; + case QStyle::CT_TabBarTab: + if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) { + bool newStyleTabs = +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) + QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 ? true : +#endif + false; + 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(); + if (newStyleTabs) { + int defaultTabHeight; + int defaultExtraSpace = 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)); + } + } else { + SInt32 tabh = sz.height(); + SInt32 overlap = 0; + switch (AquaSize) { + default: + case QAquaSizeUnknown: + case QAquaSizeLarge: + GetThemeMetric(kThemeLargeTabHeight, &tabh); + GetThemeMetric(kThemeMetricTabFrameOverlap, &overlap); + break; + case QAquaSizeMini: + GetThemeMetric(kThemeMetricMiniTabHeight, &tabh); + GetThemeMetric(kThemeMetricMiniTabFrameOverlap, &overlap); + break; + case QAquaSizeSmall: + GetThemeMetric(kThemeSmallTabHeight, &tabh); + GetThemeMetric(kThemeMetricSmallTabFrameOverlap, &overlap); + break; + } + tabh += overlap; + if (sz.height() < tabh) + sz.rheight() = tabh; + } + } + 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() += PushButtonLeftOffset + PushButtonRightOffset + 12; + sz.rheight() += PushButtonTopOffset + PushButtonBottomOffset; + break; + case QStyle::CT_MenuItem: + if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) { + int maxpmw = mi->maxIconWidth; + const QComboBox *comboBox = qobject_cast<const QComboBox *>(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 = 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: + 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 (styleHint(SH_Menu_Mask, &myOption, widget, &menuMask)) { + sz = menuMask.region.boundingRect().size(); + } + break; } + case CT_HeaderSection:{ + const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(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<const QStyleOptionSlider *>(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; + 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<const QStyleOptionComboBox *>(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<const QStyleOptionButton *>(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; +} + +/*! + \reimp +*/ +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); +} + +/*! + \reimp +*/ +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<QGraphicsView *>(focusWidget)) { + QGraphicsItem *focusItem = graphicsView->scene() ? graphicsView->scene()->focusItem() : 0; + if (focusItem && focusItem->type() == QGraphicsProxyWidget::Type) { + QGraphicsProxyWidget *proxy = static_cast<QGraphicsProxyWidget *>(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<QMainWindow *>(top)) { + QWidget *central = static_cast<QMainWindow *>(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; +} + +void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayIcon, QIcon *retIcon, QStyle::StandardPixmap standardIcon = QStyle::SP_CustomBase) +{ + int size = 16; + while (size <= 128) { + + const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size); + QPixmap mainIcon; + if (standardIcon >= QStyle::SP_CustomBase) { + mainIcon = qt_mac_convert_iconref(icon, size, size); + } else if (QPixmapCache::find(cacheKey, mainIcon) == false) { + mainIcon = qt_mac_convert_iconref(icon, size, size); + QPixmapCache::insert(cacheKey, mainIcon); + } + + if (overlayIcon) { + int littleSize = size / 2; + QPixmap overlayPix = qt_mac_convert_iconref(overlayIcon, littleSize, littleSize); + QPainter painter(&mainIcon); + painter.drawPixmap(size - littleSize, size - littleSize, overlayPix); + } + + retIcon->addPixmap(mainIcon); + size += size; // 16 -> 32 -> 64 -> 128 + } +} + +/*! + \internal +*/ +QIcon QMacStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt, + const QWidget *widget) const +{ + OSType iconType = 0; + switch (standardIcon) { + case QStyle::SP_MessageBoxQuestion: + case QStyle::SP_MessageBoxInformation: + case QStyle::SP_MessageBoxWarning: + case QStyle::SP_MessageBoxCritical: + iconType = kGenericApplicationIcon; + break; + case SP_DesktopIcon: + iconType = kDesktopIcon; + break; + case SP_TrashIcon: + iconType = kTrashIcon; + break; +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) + case SP_ComputerIcon: + iconType = kComputerIcon; + break; +#endif + 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_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; + } + break; + case SP_DirIcon: { + // A rather special case + QIcon closeIcon = QStyle::standardIcon(SP_DirClosedIcon, opt, widget); + QIcon openIcon = QStyle::standardIcon(SP_DirOpenIcon, opt, 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; + } + return QWindowsStyle::standardIconImplementation(standardIcon, opt, widget); +} + +/*! + \internal +*/ +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/gui/styles/qmacstylepixmaps_mac_p.h b/src/gui/styles/qmacstylepixmaps_mac_p.h new file mode 100644 index 0000000000..0754508046 --- /dev/null +++ b/src/gui/styles/qmacstylepixmaps_mac_p.h @@ -0,0 +1,1467 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// 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_tabnrm_left[]={ +"6 22 71 2", +"#a c #5f5f5f", +"## c #6d6d6d", +".c c #737373", +".d c #757575", +".b c #7c7c7c", +".n c #7d7d7d", +".r c #828282", +".f c #838383", +"#. c #878787", +".7 c #8c8c8c", +".v c #8e8e8e", +".4 c #939393", +".1 c #969696", +".j c #979797", +".a c #9a9a9a", +".6 c #9b9b9b", +".A c #a0a0a0", +".Z c #a6a6a6", +".C c #aaaaaa", +".3 c #aeaeae", +".E c #afafaf", +".J c #b3b3b3", +".8 c #b7b7b7", +".o c #b8b8b8", +".g c #b9b9b9", +".P c #bcbcbc", +".R c #bfbfbf", +".T c #c2c2c2", +".s c #c4c4c4", +"#e c #c6c6c6", +".V c #c7c7c7", +".w c #c9c9c9", +".B c #cacaca", +"#d c #cbcbcb", +".z c #cecece", +".F c #cfcfcf", +".5 c #d1d1d1", +"#c c #d3d3d3", +".K c #d4d4d4", +".G c #d5d5d5", +".Q c #d6d6d6", +".S c #d8d8d8", +".U c #dadada", +".2 c #dbdbdb", +".L c #dcdcdc", +".H c #dedede", +".I c #dfdfdf", +".M c #e0e0e0", +".X c #e1e1e1", +".D c #e2e2e2", +"#b c #e3e3e3", +".O c #e4e4e4", +".N c #e6e6e6", +".9 c #e7e7e7", +".e c #e8e8e8", +".# c #e9e9e9", +".t c #ebebeb", +"Qt c #ececec", +".p c #ededed", +".x c #eeeeee", +".y c #efefef", +".u c #f1f1f1", +".k c #f2f2f2", +".q c #f3f3f3", +".W c #f6f6f6", +".l c #f7f7f7", +".m c #f8f8f8", +".Y c #f9f9f9", +".h c #fcfcfc", +".i c #fdfdfd", +".0 c #ffffff", +"Qt.#.a.b.c.d", +".e.f.gQt.h.i", +".j.a.k.l.m.m", +".n.o.p.k.q.q", +".r.s.t.u.u.u", +".v.w.t.x.y.y", +".a.z.#.p.x.x", +".A.B.#.t.x.p", +".C.B.D.t.x.x", +".E.F.G.H.I.I", +".J.K.L.M.N.O", +".P.Q.D.#.e.#", +".R.S.O.p.x.p", +".T.U.#.u.u.k", +".V.I.t.q.W.W", +".P.X.k.W.Y.Y", +".Z.M.u.Y.0.0", +".1.2.l.0.0.0", +".3.4.m.0.0.0", +".5.6.7.8.9.0", +".X.5.3#.###a", +".O#b.L#c#d#e"}; + +static const char *const qt_mac_tabnrm_mid[]={ +"6 22 18 1", +"n c #585858", +". c #777777", +"p c #c2c2c2", +"o c #c3c3c3", +"g c #dedede", +"h c #e5e5e5", +"i c #e8e8e8", +"f c #ededed", +"e c #eeeeee", +"d c #efefef", +"c c #f1f1f1", +"b c #f3f3f3", +"j c #f6f6f6", +"a c #f8f8f8", +"k c #f9f9f9", +"# c #fdfdfd", +"l c #fefefe", +"m c #ffffff", +"......", +"######", +"aaaaaa", +"bbbbbb", +"cccccc", +"dddddd", +"eeeeee", +"ffffff", +"eeeeee", +"gggggg", +"hhhhhh", +"iiiiii", +"eeeeee", +"cccccc", +"jjjjjj", +"kkkkkk", +"llllll", +"mmmmmm", +"mmmmmm", +"mmmmmm", +"nnnnnn", +"oppooo"}; + +static const char *const qt_mac_tabnrm_right[]={ +"6 22 70 2", +".9 c #5f5f5f", +"#. c #6d6d6d", +".# c #747474", +"Qt c #757575", +".a c #7c7c7c", +".p c #7d7d7d", +".t c #828282", +".h c #838383", +"## c #888888", +".6 c #8c8c8c", +".x c #8e8e8e", +".3 c #929292", +".2 c #969696", +".l c #979797", +".b c #9a9a9a", +".7 c #9b9b9b", +".A c #a0a0a0", +".0 c #a6a6a6", +".C c #aaaaaa", +"#a c #aeaeae", +".H c #afafaf", +".N c #b3b3b3", +".5 c #b7b7b7", +".o c #b8b8b8", +".g c #b9b9b9", +".Q c #bcbcbc", +".S c #bfbfbf", +".U c #c2c2c2", +".s c #c4c4c4", +"#b c #c6c6c6", +".W c #c7c7c7", +".w c #c9c9c9", +".z c #cacaca", +".y c #cecece", +".G c #cfcfcf", +".8 c #d1d1d1", +"#c c #d3d3d3", +".M c #d4d4d4", +".F c #d5d5d5", +".P c #d6d6d6", +".R c #d8d8d8", +".T c #dadada", +".1 c #dbdbdb", +".L c #dcdcdc", +".E c #dedede", +".D c #dfdfdf", +".K c #e0e0e0", +".Y c #e1e1e1", +".B c #e2e2e2", +".I c #e4e4e4", +"#d c #e5e5e5", +".J c #e6e6e6", +".4 c #e7e7e7", +".O c #e8e8e8", +".c c #e9e9e9", +".r c #ebebeb", +".d c #ececec", +".n c #ededed", +".v c #eeeeee", +".u c #efefef", +".q c #f1f1f1", +".k c #f2f2f2", +".m c #f3f3f3", +".V c #f6f6f6", +".j c #f7f7f7", +".i c #f8f8f8", +".X c #f9f9f9", +".f c #fcfcfc", +".e c #fdfdfd", +".Z c #ffffff", +"Qt.#.a.b.c.d", +".e.f.d.g.h.c", +".i.i.j.k.b.l", +".m.m.k.n.o.p", +".q.q.q.r.s.t", +".u.u.v.r.w.x", +".v.v.n.c.y.b", +".n.v.r.c.z.A", +".v.v.r.B.z.C", +".D.D.E.F.G.H", +".I.J.K.L.M.N", +".c.O.c.B.P.Q", +".n.v.n.I.R.S", +".k.q.q.c.T.U", +".V.V.m.r.D.W", +".X.X.V.k.Y.Q", +".Z.Z.X.q.K.0", +".Z.Z.Z.j.1.2", +".Z.Z.Z.i.3.H", +".Z.4.5.6.7.8", +".9#.###a.8.B", +"#b.z#c.L.I#d"}; + +static const char *const qt_mac_tabselected_active_left[]={ +"6 22 130 2", +".d c #000069", +".C c #0042b4", +".I c #0157bb", +".w c #0c28a0", +".l c #101094", +".O c #1163c4", +".c c #1a1a6e", +".U c #1e6ec9", +".r c #214eb7", +".x c #256cc9", +".0 c #2877ce", +".6 c #347fd1", +".D c #3981d2", +"#a c #3a81d2", +"#g c #418ad7", +".J c #4288d4", +".q c #45459b", +".V c #458cd5", +".g c #46469f", +".P c #4a8dd7", +".1 c #4a90db", +"#m c #4b91db", +"#s c #4e91dc", +"#y c #4f8dcd", +".7 c #5195df", +".b c #525280", +"#E c #5984b2", +"#b c #5b9be1", +"#R c #5c7e9f", +".2 c #5d9de6", +"#5 c #5f5f5f", +"#Y c #627c8d", +"#h c #65a4e7", +".3 c #65a6e8", +".8 c #67a6eb", +"#n c #69a6e8", +"#c c #6cabed", +"#4 c #6d6d6d", +".4 c #6dacee", +".5 c #6eabee", +"#K c #6f87a1", +"#L c #70aff1", +".9 c #70aff2", +"#t c #71aced", +"#z c #72afee", +"#F c #72afef", +".f c #757592", +"#i c #75b3f4", +"#d c #75b4f3", +"#Z c #77a6b3", +"#. c #77b1f4", +"## c #7ab4f4", +".W c #7cb0e7", +"#o c #7cb8f9", +"#f c #80bdf9", +"#e c #81bbf9", +"#j c #81bbfc", +"#u c #86c1ff", +"#3 c #878787", +"#k c #89c2fd", +"#A c #89c3ff", +".Q c #8bb9e8", +"#l c #8bc4ff", +"#p c #8bc6ff", +"#G c #8dc7ff", +".K c #8ebae8", +"#S c #8ecbff", +"#q c #91c8ff", +"#M c #92ccff", +"#v c #93ccff", +".k c #9494b0", +"#r c #94caff", +".E c #96bde8", +".X c #96c3ee", +"#w c #96cfff", +"#B c #97cfff", +".Y c #99c4ee", +"#x c #99d0ff", +".a c #9a9aa4", +"#X c #9b9b9b", +".s c #9bbee8", +".R c #9bc4ee", +".T c #9cc5ee", +".Z c #9dc7ef", +"#C c #9dd3ff", +".y c #9ec3e8", +".L c #9ec3ed", +".M c #9ec5ed", +"#H c #9ed6ff", +".S c #9fc5ee", +"#D c #a1d7ff", +".N c #a3c8ed", +"#N c #a3daff", +".F c #a5c8ed", +".G c #a7c9ed", +"#J c #a7ddff", +"#I c #a7deff", +".H c #a8caee", +"#T c #a8e0ff", +"#0 c #a8e2e6", +".z c #a9caed", +"#O c #abe3ff", +".A c #adcbed", +"#P c #ade3ff", +"#Q c #aeaeae", +".m c #afbbe7", +".B c #afccee", +"#U c #b0e9ff", +".t c #b3d1ed", +"#V c #b5ebff", +".u c #bad4ee", +".v c #bbd4ef", +".h c #bfc2e8", +"#1 c #bffdff", +"a# c #c6c6c6", +"a. c #cbcbcb", +".n c #cbddf2", +".o c #cce0f3", +".p c #cfe1f4", +"#W c #d1d1d1", +"#9 c #d3d3d3", +"#8 c #dcdcdc", +"#2 c #e1e1e1", +"#7 c #e3e3e3", +"#6 c #e4e4e4", +".i c #e6e9f6", +".e c #e8e8e8", +".# c #e9e9e9", +".j c #e9edf8", +"Qt c #ececec", +"Qt.#.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.F.G.H", +".I.J.K.L.M.N", +".O.P.Q.R.S.T", +".U.V.W.X.Y.Z", +".0.1.2.3.4.5", +".6.7.8.9#.##", +"#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#F#G#H#I#J", +"#K#L#M#N#O#P", +"#Q#R#S#T#U#V", +"#W#X#Y#Z#0#1", +"#2#W#Q#3#4#5", +"#6#7#8#9a.a#"}; + +static const char *const qt_mac_tabselected_active_mid[]={ +"6 22 23 1", +". c #00006d", +"s c #585858", +"h c #70adef", +"i c #7bb5f5", +"j c #83bcf9", +"k c #8bc3ff", +"l c #93c9ff", +"m c #9ad1ff", +"f c #9ec5ef", +"g c #9ec7f0", +"n c #a0d6ff", +"e c #a2c7ed", +"d c #a8caee", +"o c #a8deff", +"p c #ade2ff", +"c c #afceee", +"q c #b6ecff", +"b c #bbd5f0", +"r c #c1feff", +"u c #c2c2c2", +"t c #c3c3c3", +"a c #cfe1f3", +"# c #e9edf8", +"......", +"######", +"aaaaaa", +"bbbbbb", +"cccccc", +"dddddd", +"eeeeee", +"ffffff", +"gggggg", +"hhhhhh", +"iiiiii", +"jjjjjj", +"kkkkkk", +"llllll", +"mmmmmm", +"nnnnnn", +"oooooo", +"pppppp", +"qqqqqq", +"rrrrrr", +"ssssss", +"ttttuu"}; + +static const char *const qt_mac_tabselected_active_right[]={ +"6 22 128 2", +"Qt c #000069", +".G c #0042b4", +".M c #0157bb", +".A c #0c28a0", +".n c #101094", +".S c #1163c4", +".# c #1b1b6e", +".Y c #1e6ec9", +".t c #214eb7", +".z c #256cc9", +".4 c #2877ce", +"#. c #347fd1", +".F c #3981d2", +"#e c #3a81d2", +"#k c #418ad7", +".L c #4288d4", +".u c #45459b", +".X c #458cd5", +".h c #46469f", +".R c #4a8dd7", +".3 c #4a90db", +"#q c #4b91db", +"#w c #4e91dc", +"#C c #4f8dcd", +".9 c #5195df", +".a c #525280", +"#I c #5984b2", +"#T c #5b7d9f", +"#d c #5b9be1", +".2 c #5d9de6", +"#1 c #5f5f5f", +"#Y c #627c8d", +"#j c #65a4e7", +".1 c #65a6e8", +".8 c #67a6eb", +"#p c #69a6e8", +"#c c #6cabed", +"#2 c #6d6d6d", +".0 c #6dacee", +".Z c #6eabee", +"#O c #6f87a1", +"#N c #70aff1", +".7 c #70aff2", +"#v c #71aced", +"#B c #72afee", +"#H c #72afef", +".i c #757592", +"#i c #75b3f4", +"#b c #75b4f3", +"#X c #77a6b3", +".6 c #77b1f4", +".5 c #7ab4f4", +".W c #7cb0e7", +"#o c #7cb8f9", +"## c #80bdf9", +"#a c #81bbf9", +"#h c #81bbfc", +"#u c #86c1ff", +"#3 c #888888", +"#g c #89c2fd", +"#A c #89c3ff", +".Q c #8bb9e8", +"#f c #8bc4ff", +"#n c #8bc6ff", +"#G c #8dc7ff", +".K c #8ebae8", +"#S c #8ecbff", +"#m c #91c8ff", +"#M c #92ccff", +"#t c #93ccff", +".o c #9494b0", +"#l c #94caff", +".E c #96bde8", +".V c #96c3ee", +"#s c #96cfff", +"#z c #97cfff", +".U c #99c4ee", +"#r c #99d0ff", +".b c #9a9aa4", +"#Z c #9b9b9b", +".s c #9bbee8", +".P c #9bc4ee", +".N c #9cc5ee", +".T c #9dc7ef", +"#y c #9dd3ff", +".y c #9ec3e8", +".J c #9ec3ed", +".I c #9ec5ed", +"#F c #9ed6ff", +".O c #9fc5ee", +"#x c #a1d7ff", +".H c #a3c8ed", +"#L c #a3daff", +".D c #a5c8ed", +".C c #a7c9ed", +"#D c #a7ddff", +"#E c #a7deff", +".B c #a8caee", +"#R c #a8e0ff", +"#W c #a8e2e6", +".x c #a9caed", +"#K c #abe3ff", +".w c #adcbed", +"#J c #ade3ff", +"#U c #aeaeae", +".m c #afbbe7", +".v c #afccee", +"#Q c #b0e9ff", +".r c #b3d1ed", +"#P c #b5ebff", +".q c #bad4ee", +".p c #bbd4ef", +".g c #bfc2e8", +"#V c #bffdff", +"#5 c #c6c6c6", +"#6 c #cacaca", +".l c #cbddf2", +".k c #cce0f3", +".j c #cfe1f4", +"#0 c #d1d1d1", +"#7 c #d3d3d3", +"#8 c #dcdcdc", +"#4 c #e2e2e2", +"#9 c #e4e4e4", +".f c #e6e9f6", +".c c #e9e9e9", +".e c #e9edf8", +".d c #ececec", +"Qt.#.a.b.c.d", +".e.f.g.h.i.c", +".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.0.1.2.3.4", +".5.6.7.8.9#.", +"###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#F#G#H#I", +"#J#K#L#M#N#O", +"#P#Q#R#S#T#U", +"#V#W#X#Y#Z#0", +"#1#2#3#U#0#4", +"#5#6#7#8#9#9"}; + +static const char *const qt_mac_tabselected_inactive_left[]={ +"6 22 64 1", +"9 c #656565", +"8 c #737373", +"c c #767676", +"b c #808080", +"n c #818181", +"q c #828282", +"e c #888888", +"7 c #8b8b8b", +"u c #8d8d8d", +"3 c #939393", +"k c #979797", +"0 c #989898", +"j c #9b9b9b", +"A c #9d9d9d", +"a c #9e9e9e", +"4 c #9f9f9f", +"Y c #a3a3a3", +"C c #a6a6a6", +"E c #aaaaaa", +"J c #aeaeae", +"6 c #b0b0b0", +"2 c #b1b1b1", +"o c #b2b2b2", +"f c #b3b3b3", +"O c #b6b6b6", +"Q c #b9b9b9", +"S c #bbbbbb", +"r c #bdbdbd", +"U c #c0c0c0", +"v c #c2c2c2", +"B c #c3c3c3", +"y c #c6c6c6", +"F c #c7c7c7", +"K c #cccccc", +"G c #cdcdcd", +"R c #cfcfcf", +"T c #d1d1d1", +"1 c #d2d2d2", +"L c #d3d3d3", +"H c #d5d5d5", +"I c #d6d6d6", +"W c #d7d7d7", +"D c #d8d8d8", +"N c #dadada", +"M c #dcdcdc", +"5 c #dddddd", +"P c #dedede", +"z c #dfdfdf", +"s c #e0e0e0", +"g c #e1e1e1", +"p c #e2e2e2", +"w c #e3e3e3", +"x c #e4e4e4", +"t c #e6e6e6", +"l c #e7e7e7", +"d c #e8e8e8", +"# c #e9e9e9", +"V c #eaeaea", +"m c #ebebeb", +". c #ececec", +"X c #ededed", +"h c #f0f0f0", +"i c #f1f1f1", +"Z c #f2f2f2", +".#abcc", +"defghi", +"jklm..", +"nopldd", +"qrsttt", +"uvswxx", +"kyzpww", +"ABzswp", +"CBDsww", +"EFGHII", +"JKLIMN", +"OGDzPz", +"QRNpwp", +"STzttl", +"UIsdVV", +"OWlVXX", +"YItXZZ", +"01mZZZ", +"23.ZZZ", +"T4uo5Z", +"gT6789", +"xwMLKF"}; + +static const char *const qt_mac_tabselected_inactive_mid[]={ +"6 22 17 1", +"m c #5f5f5f", +". c #787878", +"o c #c3c3c3", +"n c #c4c4c4", +"g c #d5d5d5", +"h c #dbdbdb", +"i c #dedede", +"f c #e2e2e2", +"e c #e3e3e3", +"d c #e4e4e4", +"c c #e6e6e6", +"b c #e8e8e8", +"j c #eaeaea", +"a c #ececec", +"k c #ededed", +"# c #f1f1f1", +"l c #f2f2f2", +"......", +"######", +"aaaaaa", +"bbbbbb", +"cccccc", +"dddddd", +"eeeeee", +"ffffff", +"eeeeee", +"gggggg", +"hhhhhh", +"iiiiii", +"eeeeee", +"cccccc", +"jjjjjj", +"kkkkkk", +"llllll", +"llllll", +"llllll", +"llllll", +"mmmmmm", +"nnnnno"}; + +static const char *const qt_mac_tabselected_inactive_right[]={ +"6 22 65 2", +".6 c #656565", +".7 c #737373", +"Qt c #767676", +".# c #808080", +".p c #818181", +".t c #828282", +".h c #888888", +".8 c #8c8c8c", +".x c #8d8d8d", +".2 c #929292", +".k c #979797", +".1 c #989898", +".l c #9b9b9b", +".B c #9d9d9d", +".a c #9e9e9e", +".5 c #9f9f9f", +".Z c #a3a3a3", +".D c #a6a6a6", +".I c #aaaaaa", +".N c #aeaeae", +".9 c #b0b0b0", +".3 c #b1b1b1", +".o c #b2b2b2", +".g c #b3b3b3", +".P c #b6b6b6", +".R c #b9b9b9", +".T c #bbbbbb", +".s c #bdbdbd", +".V c #c0c0c0", +".w c #c2c2c2", +".A c #c3c3c3", +".z c #c6c6c6", +".H c #c7c7c7", +"#. c #cbcbcb", +".M c #cccccc", +".G c #cdcdcd", +".Q c #cfcfcf", +".S c #d1d1d1", +".0 c #d2d2d2", +".L c #d3d3d3", +".F c #d5d5d5", +".E c #d6d6d6", +".X c #d7d7d7", +".C c #d8d8d8", +".J c #dadada", +".K c #dcdcdc", +".4 c #dddddd", +".O c #dedede", +".y c #dfdfdf", +".r c #e0e0e0", +".f c #e1e1e1", +".n c #e2e2e2", +".v c #e3e3e3", +".u c #e4e4e4", +".q c #e6e6e6", +".j c #e7e7e7", +".m c #e8e8e8", +".b c #e9e9e9", +".U c #eaeaea", +".i c #ebebeb", +".c c #ececec", +".W c #ededed", +".e c #f0f0f0", +".d c #f1f1f1", +".Y c #f2f2f2", +"QtQt.#.a.b.c", +".d.e.f.g.h.b", +".c.c.i.j.k.l", +".m.m.j.n.o.p", +".q.q.q.r.s.t", +".u.u.v.r.w.x", +".v.v.n.y.z.k", +".n.v.r.y.A.B", +".v.v.r.C.A.D", +".E.E.F.G.H.I", +".J.K.E.L.M.N", +".y.O.y.C.G.P", +".n.v.n.J.Q.R", +".j.q.q.y.S.T", +".U.U.m.r.E.V", +".W.W.U.j.X.P", +".Y.Y.W.q.E.Z", +".Y.Y.Y.i.0.1", +".Y.Y.Y.c.2.3", +".Y.4.o.x.5.S", +".6.7.8.9.S.n", +".H#..L.K.u.u"}; + +static const char * const qt_mac_tab_selected_active_graph_left[]={ +"6 22 126 2", +".d c #15283d", +".c c #283348", +".w c #374459", +".l c #435364", +".B c #465568", +".q c #4d5367", +".b c #525763", +".H c #536271", +".N c #5d6a79", +"#1 c #5f5f5f", +".T c #647181", +"#N c #656e77", +".r c #677282", +"#B c #687380", +"#U c #697077", +".Z c #6c7885", +".5 c #6c7988", +"#0 c #6d6d6d", +"#H c #6f767f", +".x c #727e8a", +"## c #757f8d", +".f c #76767d", +"#v c #76838f", +"#e c #778292", +"#k c #7b8694", +".U c #7b8794", +".C c #7b8795", +".O c #7c8893", +".I c #7d8896", +".g c #7e8895", +".0 c #7e8b99", +"#q c #818c98", +".6 c #85909e", +"#Z c #878787", +"#a c #8a96a3", +"#f c #8d99a7", +".1 c #8e99a6", +"#V c #929ca5", +"#l c #939daa", +".k c #949499", +".7 c #96a0ad", +".2 c #98a3af", +"#r c #99a5b0", +".a c #9a9a9b", +"#I c #9aa4b1", +"#T c #9b9b9b", +".3 c #9ba6b1", +"#b c #9ba6b3", +".8 c #9ca7b4", +".4 c #9da6b1", +"#w c #9da7b5", +"#C c #9ea9b5", +".V c #a0a9b4", +"#g c #a0abb8", +"#. c #a3acb8", +".9 c #a4adba", +"#c c #a6afbc", +"#m c #a8b1bd", +"#d c #a9b3bf", +".J c #abb3bc", +".P c #adb4bb", +"#h c #adb8c3", +"#M c #aeaeae", +"#j c #aeb8c4", +".W c #b0b8c2", +"#i c #b0bac6", +".D c #b3bac3", +"#x c #b3bcc8", +"#n c #b3bdc9", +".Q c #b4bac2", +"#D c #b5bfc9", +".y c #b6bdc5", +"#o c #b6becb", +"#s c #b7c2ce", +".K c #b8bdc6", +".X c #b8bfc8", +"#p c #b8c1ce", +".S c #b9bec7", +".R c #b9bfc8", +".Y c #b9c1c7", +".M c #b9c1c8", +"#J c #bac5cf", +".L c #bbbfc8", +"#O c #bbc7d4", +".s c #bcc3ca", +"#t c #bcc5d1", +"#u c #bcc6d2", +".E c #bdc3ca", +"#y c #bdc7d2", +".G c #bec3cb", +".F c #bec5cb", +".z c #c2c7ce", +"#E c #c2cad6", +".A c #c3c9d0", +"#z c #c3ccd7", +"#A c #c3ced7", +".m c #c5c9d0", +"#7 c #c6c6c6", +"#K c #c7d2dd", +".t c #c8ced3", +"#F c #c8d3de", +"#G c #c9d3df", +"#6 c #cbcbcb", +".u c #cbd1d6", +".v c #ccd2d7", +".h c #ced2d6", +"#W c #ced8e4", +"#L c #d0dae3", +"#S c #d1d1d1", +"#P c #d1dbe6", +"#5 c #d3d3d3", +".n c #d5dadc", +"#Q c #d5deea", +".o c #d7dbdf", +"#R c #d7e1ec", +".p c #dadde0", +"#4 c #dcdcdc", +".i c #e0e2e6", +"#Y c #e1e1e1", +"#3 c #e3e3e3", +"#2 c #e4e4e4", +".j c #e6e8ea", +".e c #e8e8e8", +".# c #e9e9e9", +"#X c #e9f4ff", +"Qt c #ececec", +"Qt.#.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.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.0.1.2.3.4", +".5.6.7.8.9#.", +"###a#b#c#d#d", +"#e#f#g#h#i#j", +"#k#l#m#n#o#p", +"#q#r#h#s#t#u", +"#v#w#x#y#z#A", +"#B#C#D#E#F#G", +"#H#I#J#K#L#L", +"#M#N#O#P#Q#R", +"#S#T#U#V#W#X", +"#Y#S#M#Z#0#1", +"#2#3#4#5#6#7"}; + +static const char * const qt_mac_tab_selected_active_graph_mid[]={ +"6 22 41 1", +". c #15273d", +"# c #16283e", +"a c #17293e", +"b c #192a3f", +"c c #1a2b40", +"K c #585858", +"p c #9ea8b4", +"q c #a4adb9", +"r c #aab4bf", +"s c #afb9c6", +"o c #b6bcc6", +"n c #b8bec6", +"t c #b8c2ce", +"m c #bbc2c8", +"u c #bbc5d0", +"l c #bec4cb", +"v c #bfcad4", +"L c #c2c2c2", +"k c #c2c9ce", +"M c #c3c3c3", +"w c #c7d1dd", +"i c #cad0d5", +"j c #cbd0d5", +"x c #ccd5e1", +"y c #cdd6e2", +"z c #ced6e2", +"A c #d5dfeb", +"B c #d6e0ec", +"C c #d7e1ed", +"e c #d8dbe0", +"f c #d8dce0", +"g c #d9dce0", +"D c #d9e2ee", +"h c #dadce0", +"E c #dae2ef", +"d c #e7e9eb", +"J c #e9f2ff", +"I c #eaf3ff", +"H c #ebf5ff", +"G c #ecf6ff", +"F c #edf6ff", +"..#abc", +"dddddd", +"eeefgh", +"iiiiij", +"kkkkkk", +"llllll", +"mmmmmm", +"nnnnnn", +"oooooo", +"pppppp", +"qqqqqq", +"rrrrrr", +"ssssss", +"tttttt", +"uuuuuu", +"vvvvvv", +"wwwwww", +"xxxxyz", +"AABCDE", +"FFGHIJ", +"KKKKKK", +"LLLLMM"}; + +static const char * const qt_mac_tab_selected_active_graph_right[]={ +"6 22 124 2", +"Qt c #15283d", +".# c #293448", +".z c #374459", +".n c #435364", +".F c #465568", +".u c #4d5367", +".a c #525763", +".L c #536271", +".R c #5d6a79", +"#X c #5f5f5f", +"#P c #646d77", +".X c #647181", +".t c #677282", +"#F c #687380", +"#U c #697077", +".3 c #6c7885", +".9 c #6c7988", +"#Y c #6d6d6d", +"#K c #6f767f", +".y c #727e8a", +"#c c #757f8d", +".i c #76767d", +"#z c #76838f", +"#i c #778292", +"#o c #7b8694", +".W c #7b8794", +".E c #7b8795", +".Q c #7c8893", +".K c #7d8896", +".h c #7e8895", +".2 c #7e8b99", +"#t c #818c98", +".8 c #85909e", +"#Z c #888888", +"#b c #8a96a3", +"#h c #8d99a7", +".1 c #8e99a6", +"#T c #929ca5", +"#n c #939daa", +".o c #949499", +".7 c #96a0ad", +".0 c #98a3af", +"#s c #99a5b0", +".b c #9a9a9b", +"#J c #9aa4b1", +"#V c #9b9b9b", +".Z c #9ba6b1", +"#a c #9ba6b3", +".6 c #9ca7b4", +".Y c #9da6b1", +"#y c #9da7b5", +"#E c #9ea9b5", +".V c #a0a9b4", +"#g c #a0abb8", +".4 c #a3acb8", +".5 c #a4adba", +"## c #a6afbc", +"#m c #a8b1bd", +"#. c #a9b3bf", +".J c #abb3bc", +".P c #adb4bb", +"#f c #adb8c3", +"#Q c #aeaeae", +"#d c #aeb8c4", +".U c #b0b8c2", +"#e c #b0bac6", +".D c #b3bac3", +"#x c #b3bcc8", +"#l c #b3bdc9", +".O c #b4bac2", +"#D c #b5bfc9", +".x c #b6bdc5", +"#k c #b6becb", +"#r c #b7c2ce", +".I c #b8bdc6", +".T c #b8bfc8", +"#j c #b8c1ce", +".M c #b9bec7", +".N c #b9bfc8", +".S c #b9c1c7", +".G c #b9c1c8", +"#I c #bac5cf", +".H c #bbbfc8", +"#O c #bbc7d4", +".s c #bcc3ca", +"#q c #bcc5d1", +"#p c #bcc6d2", +".C c #bdc3ca", +"#w c #bdc7d2", +".A c #bec3cb", +".B c #bec5cb", +".w c #c2c7ce", +"#C c #c2cad6", +".v c #c3c9d0", +"#v c #c3ccd7", +"#u c #c3ced7", +".m c #c5c9d0", +"#1 c #c6c6c6", +"#H c #c7d2dd", +".r c #c8ced3", +"#B c #c8d3de", +"#A c #c9d3df", +"#2 c #cacaca", +".q c #cbd1d6", +".p c #ccd2d7", +".g c #ced2d6", +"#S c #ced8e4", +"#G c #d0dae3", +"#W c #d1d1d1", +"#N c #d1dbe6", +"#3 c #d3d3d3", +".l c #d5dadc", +"#M c #d5deea", +".k c #d7dbdf", +"#L c #d7e1ec", +".j c #dadde0", +"#4 c #dcdcdc", +".f c #e0e2e6", +"#0 c #e2e2e2", +"#5 c #e4e4e4", +".e c #e6e8ea", +".c c #e9e9e9", +"#R c #e9f4ff", +".d c #ececec", +"Qt.#.a.b.c.d", +".e.f.g.h.i.c", +".j.k.l.m.n.o", +".p.q.r.s.t.u", +".v.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.0.1.2.3", +".4.5.6.7.8.9", +"#.#.###a#b#c", +"#d#e#f#g#h#i", +"#j#k#l#m#n#o", +"#p#q#r#f#s#t", +"#u#v#w#x#y#z", +"#A#B#C#D#E#F", +"#G#G#H#I#J#K", +"#L#M#N#O#P#Q", +"#R#S#T#U#V#W", +"#X#Y#Z#Q#W#0", +"#1#2#3#4#5#5"}; + +static const char * const qt_mac_tab_press_left[]={ +"6 22 65 2", +".8 c #5c5c5c", +".c c #696969", +".d c #6a6a6a", +".b c #767676", +".f c #7e7e7e", +".t c #808080", +".4 c #828282", +".7 c #838383", +".2 c #888888", +".k c #8b8b8b", +".0 c #8c8c8c", +".z c #909090", +".j c #919191", +".a c #959595", +".Y c #989898", +".B c #999999", +".D c #9e9e9e", +".I c #a1a1a1", +".n c #a6a6a6", +".g c #a7a7a7", +".6 c #a8a8a8", +".O c #aaaaaa", +".1 c #ababab", +".R c #acacac", +".T c #afafaf", +".q c #b1b1b1", +".V c #b3b3b3", +".u c #b5b5b5", +".A c #b6b6b6", +".x c #bababa", +".E c #bbbbbb", +"#. c #bebebe", +".J c #bfbfbf", +".F c #c0c0c0", +".P c #c1c1c1", +".S c #c3c3c3", +".U c #c5c5c5", +".K c #c6c6c6", +".G c #c8c8c8", +".H c #c9c9c9", +".L c #cacaca", +".X c #cbcbcb", +".C c #cccccc", +".3 c #cdcdcd", +".N c #cecece", +".M c #cfcfcf", +".5 c #d0d0d0", +".Q c #d1d1d1", +".y c #d2d2d2", +".r c #d4d4d4", +".h c #d5d5d5", +".o c #d6d6d6", +".v c #d7d7d7", +".w c #d8d8d8", +".s c #d9d9d9", +".l c #dadada", +".p c #dbdbdb", +".9 c #dcdcdc", +".W c #dedede", +".m c #dfdfdf", +".e c #e0e0e0", +".# c #e1e1e1", +".i c #e3e3e3", +"Qt c #e4e4e4", +".Z c #e6e6e6", +"Qt.#.a.b.c.d", +".e.f.g.h.iQt", +".j.k.l.m.e.e", +".b.n.o.l.p.p", +".b.q.r.s.s.s", +".t.u.r.v.w.w", +".k.x.y.o.v.v", +".z.A.y.r.v.o", +".B.A.C.r.v.v", +".D.E.F.G.H.H", +".I.J.K.L.M.N", +".O.P.C.y.Q.y", +".R.S.N.o.v.o", +".T.U.y.s.s.l", +".V.H.r.p.W.W", +".O.X.l.W.#.#", +".Y.L.s.#.Z.Z", +".0.K.m.Z.Z.Z", +".1.2.e.Z.Z.Z", +".3.Y.4.n.5.Z", +".s.H.6.7.d.8", +".9.l.r.L.S#."}; + +static const char * const qt_mac_tab_press_mid[]={ +"7 22 19 1", +"o c #555555", +". c #6b6b6b", +"p c #bbbbbb", +"q c #bcbcbc", +"g c #c8c8c8", +"h c #cecece", +"i c #d1d1d1", +"f c #d6d6d6", +"e c #d7d7d7", +"d c #d8d8d8", +"c c #d9d9d9", +"j c #dadada", +"b c #dbdbdb", +"k c #dedede", +"a c #e0e0e0", +"l c #e1e1e1", +"# c #e4e4e4", +"m c #e5e5e5", +"n c #e6e6e6", +".......", +"#######", +"aaaaaaa", +"bbbbbbb", +"ccccccc", +"ddddddd", +"eeeeeee", +"fffffff", +"eeeeeee", +"ggggggg", +"hhhhhhh", +"iiiiiii", +"eeeeeee", +"jjjjjjj", +"kkkkkkk", +"lllllll", +"mmmmmmm", +"nnnnnnn", +"nnnnnnn", +"nnnnnnn", +"ooooooo", +"ppppqqq"}; + +static const char * const qt_mac_tab_press_right[]={ +"6 22 64 1", +"5 c #5c5c5c", +". c #6a6a6a", +"# c #767676", +"g c #7e7e7e", +"v c #808080", +"3 c #828282", +"6 c #848484", +"0 c #888888", +"k c #8b8b8b", +"Z c #8c8c8c", +"z c #909090", +"l c #919191", +"a c #959595", +"Y c #989898", +"B c #999999", +"G c #9e9e9e", +"M c #a1a1a1", +"o c #a6a6a6", +"f c #a7a7a7", +"7 c #a8a8a8", +"P c #aaaaaa", +"1 c #ababab", +"R c #acacac", +"T c #afafaf", +"r c #b1b1b1", +"V c #b3b3b3", +"u c #b5b5b5", +"y c #b6b6b6", +"x c #bababa", +"F c #bbbbbb", +"8 c #bebebe", +"L c #bfbfbf", +"E c #c0c0c0", +"O c #c1c1c1", +"9 c #c2c2c2", +"Q c #c3c3c3", +"S c #c5c5c5", +"K c #c6c6c6", +"D c #c8c8c8", +"C c #c9c9c9", +"J c #cacaca", +"W c #cbcbcb", +"A c #cccccc", +"4 c #cdcdcd", +"H c #cecece", +"I c #cfcfcf", +"2 c #d0d0d0", +"N c #d1d1d1", +"w c #d2d2d2", +"q c #d4d4d4", +"e c #d5d5d5", +"n c #d6d6d6", +"t c #d7d7d7", +"s c #d8d8d8", +"p c #d9d9d9", +"j c #dadada", +"m c #dbdbdb", +"U c #dedede", +"i c #dfdfdf", +"h c #e0e0e0", +"b c #e1e1e1", +"d c #e3e3e3", +"c c #e4e4e4", +"X c #e6e6e6", +"..#abc", +"cdefgb", +"hhijkl", +"mmjno#", +"pppqr#", +"sstquv", +"ttnwxk", +"ntqwyz", +"ttqAyB", +"CCDEFG", +"HIJKLM", +"wNwAOP", +"ntnHQR", +"jppwST", +"UUmqCV", +"bbUjWP", +"XXbpJY", +"XXXiKZ", +"XXXh01", +"X2o3Y4", +"5.67Cj", +"89Jqmm"}; + +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"}; diff --git a/src/gui/styles/qmotifstyle.cpp b/src/gui/styles/qmotifstyle.cpp new file mode 100644 index 0000000000..7d4fab8d89 --- /dev/null +++ b/src/gui/styles/qmotifstyle.cpp @@ -0,0 +1,2719 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 <limits.h> +#include <QtGui/qgraphicsproxywidget.h> +#include <QtGui/qgraphicsview.h> + +#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<QProgressBar *>(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<QProgressBar *>(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<QProgressBar *>(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<QProgressBar *>(widget)) + widget->removeEventFilter(this); +#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<const QStyleOptionQ3ListView *>(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, pixelMetric(PM_DefaultFrameWidth)); + break; + case PE_FrameFocusRect: + if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(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)), + 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, + pixelMetric(PM_DefaultFrameWidth), &fill); + } + if (!(opt->state & State_Enabled) && 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) && 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<dim/2-2 ; i++) { + bTop.putPoints(i*2+4, 2, 2+i*2,2+i, 5+i*2, 2+i); + bBot.putPoints(i*2+4, 2, 2+i*2,dim-3-i, 5+i*2,dim-3-i); + } + if (dim & 1) // odd number size: extra line + bBot.putPoints(dim-1, 2, dim-3,dim/2, dim-1,dim/2); + if (dim > 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) && styleHint(SH_DitherDisabledText)) + p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern)); + break; } + + case PE_IndicatorDockWidgetResizeHandle: { + const int motifOffset = 10; + int sw = 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 = 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<const QStyleOptionProgressBarV2 *>(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; + 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; + drawPrimitive(pe, &arrowOpt, p, widget); + if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText)) { + int fw = 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()); + drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget); + p->restore(); + if (!(opt->state & State_Enabled) && 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<const QStyleOptionButton *>(opt)) { + bool isRadio = (element == CE_RadioButton); + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator + : SE_CheckBoxIndicator, btn, widget); + drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox, + &subopt, p, widget); + subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents + : SE_CheckBoxContents, btn, widget); + 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); + drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + break; + case CE_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { + drawControl(CE_PushButtonBevel, btn, p, widget); + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); + 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); + drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + break; + case CE_PushButtonBevel: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { + int diw, x1, y1, x2, y2; + p->setPen(opt->palette.foreground().color()); + p->setBrush(QBrush(opt->palette.button().color(), Qt::NoBrush)); + diw = 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()); + drawPrimitive(PE_PanelButtonCommand, &newOpt, p, widget); + } + if (btn->features & QStyleOptionButton::HasMenu) { + int mbi = 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); + drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); + } + break; + } + +#ifndef QT_NO_TABBAR + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) { + const int default_frame = 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<const QStyleOptionProgressBar *>(opt)) { + QTransform oldMatrix = p->transform(); + QRect rect = pb->rect; + bool vertical = false; + bool invert = false; + bool bottomToTop = false; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(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 = 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<const QStyleOptionMenuItem *>(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)); + 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.lineSpacing() / 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); + drawPrimitive(PE_IndicatorRadioButton, &newMenuItem, p, widget); + } else { + newMenuItem.rect.setRect(xvis + 5, y + motifItemFrame + mh / 4, 9, 9); + 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) && 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) && 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); + 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)), + 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<const QStyleOptionProgressBar *>(opt)) { + QRect rect = pb->rect; + bool vertical = false; + bool inverted = false; + + // Get extra style options if version 2 + const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(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<const QStyleOptionToolButton *>(opt)) { + QRect button, menuarea; + button = subControlRect(cc, toolbutton, SC_ToolButton, widget); + menuarea = 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; + 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); + drawPrimitive(PE_FrameFocusRect, &fr, p, widget); + } + QStyleOptionToolButton label = *toolbutton; + label.state = bflags; + int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget); + label.rect = button.adjusted(fw, fw, -fw, -fw); + 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)) + drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); + drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget); + } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { + int mbi = 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); + drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); + } + } + break; +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { + QStyleOptionSpinBox copy = *spinbox; + PrimitiveElement pe; + + if (spinbox->frame && (spinbox->subControls & SC_SpinBoxFrame)) { + QRect r = subControlRect(CC_SpinBox, spinbox, SC_SpinBoxFrame, widget); + qDrawShadePanel(p, r, opt->palette, false, pixelMetric(PM_SpinBoxFrameWidth)); + + int fw = pixelMetric(QStyle::PM_DefaultFrameWidth); + r = 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; + 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 = subControlRect(CC_SpinBox, spinbox, SC_SpinBoxUp, widget); + 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 = subControlRect(CC_SpinBox, spinbox, SC_SpinBoxDown, widget); + drawPrimitive(pe, ©, p, widget); + } + } + break; +#endif // QT_NO_SPINBOX +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { + QRect groove = subControlRect(CC_Slider, opt, SC_SliderGroove, widget), + handle = subControlRect(CC_Slider, opt, SC_SliderHandle, widget); + + if ((opt->subControls & SC_SliderGroove) && groove.isValid()) { + qDrawShadePanel(p, groove, opt->palette, true, 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); + 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()); + 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) && 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 = 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<const QStyleOptionComboBox *>(opt)) { + if (opt->subControls & SC_ComboBoxArrow) { + int awh, ax, ay, sh, sy, dh, ew; + int fw = cb->frame ? pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0; + + if (cb->frame) { + QStyleOptionButton btn; + btn.QStyleOption::operator=(*cb); + btn.state |= QStyle::State_Raised; + 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; + 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(); + drawPrimitive(PE_FrameFocusRect, &focus, p, widget); + } + } + + if (opt->subControls & SC_ComboBoxEditField) { + if (cb->editable) { + QRect er = 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, + pixelMetric(PM_DefaultFrameWidth, opt, widget), + &opt->palette.brush((opt->state & State_Enabled) ? QPalette::Mid : QPalette::Window)); + + if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(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<const QStyleOptionQ3ListView *>(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 = 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 * pixelMetric(PM_DefaultFrameWidth); + break; +#ifndef QT_NO_SLIDER + case PM_SliderControlThickness: + if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(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<const QStyleOptionSlider *>(opt)) { + if (sl->orientation == Qt::Horizontal) + ret = sl->rect.width() - pixelMetric(PM_SliderLength, opt, widget) - 2 * pixelMetric(PM_DefaultFrameWidth, opt, widget); + else + ret = sl->rect.height() - pixelMetric(PM_SliderLength, opt, widget) - 2 * 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<const QStyleOptionSpinBox *>(opt)) { + int fw = spinbox->frame ? 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<const QStyleOptionSlider *>(opt)) { + if (sc == SC_SliderHandle) { + int tickOffset = pixelMetric(PM_SliderTickmarkOffset, opt, widget); + int thickness = pixelMetric(PM_SliderControlThickness, opt, widget); + bool horizontal = slider->orientation == Qt::Horizontal; + int len = pixelMetric(PM_SliderLength, opt, widget); + int motifBorder = 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<const QStyleOptionSlider *>(opt)) { + int dfw = 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<const QStyleOptionComboBox *>(opt)) { + switch (sc) { + case SC_ComboBoxArrow: { + int ew, awh, sh, dh, ax, ay, sy; + int fw = cb->frame ? 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 ? 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_Splitter: + sz = QSize(10, 10); + break; + + 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<const QStyleOptionButton *>(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<const QStyleOptionMenuItem *>(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.lineSpacing(); + } + + // 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 = 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<const QStyleOptionQ3DockWindow *>(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<const QStyleOptionProgressBar *>(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<QGraphicsView *>(focusWidget)) { + QGraphicsItem *focusItem = graphicsView->scene() ? graphicsView->scene()->focusItem() : 0; + if (focusItem && focusItem->type() == QGraphicsProxyWidget::Type) { + QGraphicsProxyWidget *proxy = static_cast<QGraphicsProxyWidget *>(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; + 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/gui/styles/qmotifstyle.h b/src/gui/styles/qmotifstyle.h new file mode 100644 index 0000000000..e244dba68e --- /dev/null +++ b/src/gui/styles/qmotifstyle.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMOTIFSTYLE_H +#define QMOTIFSTYLE_H + +#include <QtGui/qcommonstyle.h> +#include <QtCore/qpointer.h> + +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<QFocusFrame> 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/gui/styles/qmotifstyle_p.h b/src/gui/styles/qmotifstyle_p.h new file mode 100644 index 0000000000..b42e0d959c --- /dev/null +++ b/src/gui/styles/qmotifstyle_p.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMOTIFSTYLE_P_H +#define QMOTIFSTYLE_P_H +#include <qlist.h> +#include <qdatetime.h> +#include <qprogressbar.h> +#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<QProgressBar *> bars; + int animationFps; + int animateTimer; + QTime startTime; + int animateStep; +#endif // QT_NO_PROGRESSBAR +}; + +QT_END_NAMESPACE + +#endif //QMOTIFSTYLE_P_H diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp new file mode 100644 index 0000000000..24d77486ff --- /dev/null +++ b/src/gui/styles/qplastiquestyle.cpp @@ -0,0 +1,6024 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplastiquestyle.h" + +#if !defined(QT_NO_STYLE_PLASTIQUE) || defined(QT_PLUGIN) + +static bool UsePixmapCache = true; +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 <qapplication.h> +#include <qbitmap.h> +#include <qabstractitemview.h> +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qdatetime.h> +#include <qdebug.h> +#include <qdialogbuttonbox.h> +#include <qformlayout.h> +#include <qgroupbox.h> +#include <qimage.h> +#include <qlineedit.h> +#include <qmainwindow.h> +#include <qmenu.h> +#include <qmenubar.h> +#include <qpainter.h> +#include <qpaintengine.h> +#include <qpainterpath.h> +#include <qpalette.h> +#include <qpen.h> +#include <qpixmap.h> +#include <qpixmapcache.h> +#include <qprogressbar.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qscrollbar.h> +#include <qspinbox.h> +#include <qsplitter.h> +#include <qstyleoption.h> +#include <qtextedit.h> +#include <qtoolbar.h> +#include <qtoolbox.h> +#include <qtoolbutton.h> +#include <qworkspace.h> +#include <qprocess.h> +#include <qvarlengtharray.h> +#include <limits.h> + +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 windowsCheckMarkHMargin = 2; // horiz. margins of check mark +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<const QLinearGradient *>(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<QGradientStop> it(stops); + QColor tmpColor; + while (it.hasNext()) { + it.next(); + tmpColor = it.value().second; + tmpColor.setAlphaF(alpha * tmpColor.alphaF()); + it.setValue(QPair<qreal, QColor>(it.value().first, tmpColor)); + } + + switch (gradient->type()) { + case QGradient::RadialGradient: { + QRadialGradient grad = *static_cast<const QRadialGradient *>(gradient); + grad.setStops(stops); + *brush = QBrush(grad); + break; + } + case QGradient::ConicalGradient: { + QConicalGradient grad = *static_cast<const QConicalGradient *>(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<const QLinearGradient *>(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 = QString::fromLatin1("qbrushtexture-alpha-%1-%2").arg(alpha).arg(texture.cacheKey()); + if (UsePixmapCache && !QPixmapCache::find(name, pixmap)) { + QImage image = texture.toImage(); + QRgb *rgb = reinterpret_cast<QRgb *>(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<QGradientStop> it(stops); + while (it.hasNext()) { + it.next(); + it.setValue(QPair<qreal, QColor>(it.value().first, it.value().second.lighter(light))); + } + + switch (gradient->type()) { + case QGradient::RadialGradient: { + QRadialGradient grad = *static_cast<const QRadialGradient *>(gradient); + grad.setStops(stops); + brush = QBrush(grad); + break; + } + case QGradient::ConicalGradient: { + QConicalGradient grad = *static_cast<const QConicalGradient *>(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<const QLinearGradient *>(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 = QString::fromLatin1("qbrushtexture-light-%1-%2").arg(light).arg(texture.cacheKey()); + if (UsePixmapCache && !QPixmapCache::find(name, pixmap)) { + QImage image = texture.toImage(); + QRgb *rgb = reinterpret_cast<QRgb *>(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<QGradientStop> it(stops); + while (it.hasNext()) { + it.next(); + it.setValue(QPair<qreal, QColor>(it.value().first, it.value().second.darker(dark))); + } + + switch (gradient->type()) { + case QGradient::RadialGradient: { + QRadialGradient grad = *static_cast<const QRadialGradient *>(gradient); + grad.setStops(stops); + brush = QBrush(grad); + break; + } + case QGradient::ConicalGradient: { + QConicalGradient grad = *static_cast<const QConicalGradient *>(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<const QLinearGradient *>(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 = QString::fromLatin1("qbrushtexture-dark-%1-%2").arg(dark).arg(brush.texture().cacheKey()); + if (UsePixmapCache && !QPixmapCache::find(name, pixmap)) { + QImage image = texture.toImage(); + QRgb *rgb = reinterpret_cast<QRgb *>(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 QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size) +{ + QString tmp; + const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option); + tmp.sprintf("%s-%d-%d-%d-%lld-%dx%d", key.toLatin1().constData(), uint(option->state), + option->direction, complexOption ? uint(complexOption->activeSubControls) : uint(0), + option->palette.cacheKey(), size.width(), size.height()); + return tmp; +} + +static void qt_plastique_draw_gradient(QPainter *painter, const QRect &rect, const QColor &gradientStart, + const QColor &gradientStop) +{ + QString gradientName; + gradientName.sprintf("%dx%d-%x-%x", rect.width(), rect.height(), gradientStart.rgba(), gradientStop.rgba()); + QPixmap cache; + QPainter *p = painter; + QRect r = rect; + + bool doPixmapCache = UsePixmapCache + && 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<QProgressBar *> bars; + int progressBarAnimateTimer; + QTime timer; +#endif +}; + +/*! + \internal + */ +QPlastiqueStylePrivate::QPlastiqueStylePrivate() : + QWindowsStylePrivate() +#ifndef QT_NO_PROGRESSBAR + , progressBarAnimateTimer(0) +#endif +{ + if (!qgetenv("QT_STYLE_NO_PIXMAPCACHE").isNull()) + UsePixmapCache = false; +} + +/*! + \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 = qFindChild<QLineEdit *>(widget)) + 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 |= QStyle::State_Sunken; + 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 gradientStartColor = option->palette.button().color().lighter(104); + QColor gradientStopColor = option->palette.button().color().darker(105); + QColor baseGradientStartColor = option->palette.base().color().darker(101); + QColor baseGradientStopColor = option->palette.base().color().darker(106); + QColor highlightedGradientStartColor = option->palette.button().color().lighter(101); + QColor highlightedGradientStopColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 85); + QColor highlightedBaseGradientStartColor = option->palette.base().color(); + QColor highlightedBaseGradientStopColor = mergedColors(option->palette.base().color().darker(105), option->palette.highlight().color(), 70); + 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 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 alphaInnerColor = mergedColors(highlightedLightInnerBorderColor, gradientStartColor); + QColor alphaInnerColorNoHover = mergedColors(borderColor, gradientStartColor); + QColor alphaTextColor = mergedColors(option->palette.background().color(), option->palette.text().color()); + QColor alphaLightTextColor = mergedColors(option->palette.background().color().lighter(250), option->palette.text().color().lighter(250)); + QColor lightShadow = option->palette.button().color().lighter(105); + QColor shadowGradientStartColor = option->palette.button().color().darker(115); + QColor shadow = shadowGradientStartColor; + + switch (element) { + case PE_IndicatorButtonDropDown: + 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<const QStyleOptionTabWidgetFrame *>(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 = 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<QLine, 4> lines; + QVarLengthArray<QPoint, 8> 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<const QStyleOptionTabBarBase *>(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<const QStyleOptionFrame *>(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); + 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<const QStyleOptionFrame *>(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_COMBOBOX + if (qobject_cast<const QComboBox *>(widget->parentWidget())) + break; +#endif +#ifndef QT_NO_SPINBOX + if (qobject_cast<const QAbstractSpinBox *>(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<const QMainWindow *>(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 = uniqueName(QLatin1String("toolbarhandle"), option, rect.size()); + if (!UsePixmapCache || !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(); + if (UsePixmapCache) + 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<const QStyleOptionButton *>(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<const QStyleOptionButton *>(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<const QStyleOptionButton *>(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; + drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget); + break; + } + case PE_FrameWindow: { + painter->save(); + bool active = (option->state & State_Active); + int titleBarStop = option->rect.top() + 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); + qt_plastique_draw_gradient(painter, gradientRect, baseGradientStartColor, baseGradientStopColor); + // 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<const QStyleOptionTab *>(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 + QRect adjustedRect; + bool atEnd = (tab->position == QStyleOptionTab::End) || onlyTab; + bool atBeginning = ((tab->position == QStyleOptionTab::Beginning) || onlyTab) + && !leftCornerWidget; + bool reverseShadow = false; + + int borderThickness = 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<QPoint, 6> 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<QLine, 3> lines; + QVarLengthArray<QPoint, 7> 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<const QStyleOptionProgressBar *>(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<const QStyleOptionProgressBar *>(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<const QStyleOptionProgressBarV2 *>(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); + } + + double vc6_workaround = ((bar->progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * rect.width()); + int progressIndicatorPos = int(vc6_workaround); + + 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<const QStyleOptionProgressBar *>(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<const QStyleOptionProgressBarV2 *>(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; + m.translate(rect.height()-1, 0); + m.rotate(90.0); + painter->setTransform(m, true); + } + + int maxWidth = rect.width() - 4; + int minWidth = 4; + qint64 progress = qMax<qint64>(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<QLine, 4> lines; + QVarLengthArray<QPoint, 8> 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 = uniqueName(QLatin1String("progressBarContents"), + option, rect.size()); + QPixmap cache; + if ((!UsePixmapCache || !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; + } + + if (UsePixmapCache) + 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<const QStyleOptionHeader *>(option)) { + QPixmap cache; + QString pixmapName = uniqueName(QLatin1String("headersection"), option, option->rect.size()); + pixmapName += QLatin1String("-") + QString::number(int(header->position)); + pixmapName += QLatin1String("-") + QString::number(int(header->orientation)); + + if (!UsePixmapCache || !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(); + if (UsePixmapCache) + 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<const QStyleOptionMenuItem *>(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); + 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; + 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; + 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()); + 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 = uniqueName(QLatin1String("menubaritem"), option, option->rect.size()); + if (!UsePixmapCache || !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(); + if (UsePixmapCache) + QPixmapCache::insert(pixmapName, cache); + } + painter->drawPixmap(option->rect.topLeft(), cache); + } else { + painter->fillRect(option->rect, option->palette.background()); + } + + if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(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<const QMainWindow *>(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<const QStyleOptionToolBox *>(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<const QStyleOptionDockWidget *>(option)) { + painter->save(); + + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(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(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<const QStyleOptionToolBar *>(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<const QStyleOptionSlider *>(option)) { + + bool horizontal = scrollBar->orientation == Qt::Horizontal; + bool reverse = scrollBar->direction == Qt::RightToLeft; + bool sunken = scrollBar->state & State_Sunken; + + QString addLinePixmapName = uniqueName(QLatin1String("scrollbar_addline"), option, option->rect.size()); + QPixmap cache; + if (!UsePixmapCache || !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(); + if (UsePixmapCache) + QPixmapCache::insert(addLinePixmapName, cache); + } + painter->drawPixmap(option->rect.topLeft(), cache); + } + break; + case CE_ScrollBarSubPage: + case CE_ScrollBarAddPage: + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) { + bool sunken = scrollBar->state & State_Sunken; + bool horizontal = scrollBar->orientation == Qt::Horizontal; + + QString groovePixmapName = uniqueName(QLatin1String("scrollbar_groove"), option, option->rect.size()); + if (sunken) + groovePixmapName += QLatin1String("-sunken"); + if (element == CE_ScrollBarAddPage) + groovePixmapName += QLatin1String("-addpage"); + + QPixmap cache; + if (!UsePixmapCache || !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(); + if (UsePixmapCache) + QPixmapCache::insert(groovePixmapName, cache); + } + painter->drawPixmap(option->rect.topLeft(), cache); + } + break; + case CE_ScrollBarSubLine: + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(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 = 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 = uniqueName(QLatin1String("scrollbar_subline"), option, button1.size()); + QPixmap cache; + if (!UsePixmapCache || !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(); + if (UsePixmapCache) + QPixmapCache::insert(subLinePixmapName, cache); + } + painter->drawPixmap(button1.topLeft(), cache); + painter->drawPixmap(button2.topLeft(), cache); + } + break; + case CE_ScrollBarSlider: + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) { + bool horizontal = scrollBar->orientation == Qt::Horizontal; + bool isEnabled = scrollBar->state & State_Enabled; + + // The slider + if (option->rect.isValid()) { + QString sliderPixmapName = uniqueName(QLatin1String("scrollbar_slider"), option, option->rect.size()); + if (horizontal) + sliderPixmapName += QLatin1String("-horizontal"); + + QPixmap cache; + if (!UsePixmapCache || !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 = 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 + if (UsePixmapCache) + 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<const QStyleOptionComboBox *>(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 = 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(QApplication::layoutDirection(), + Qt::AlignLeft | Qt::AlignVCenter, + iconRect.size(), editRect); + painter->fillRect(iconRect, option->palette.brush(QPalette::Base)); + 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<const QStyleOptionSlider *>(option)) { + QRect grooveRegion = subControlRect(CC_Slider, option, SC_SliderGroove, widget); + QRect handle = subControlRect(CC_Slider, option, SC_SliderHandle, widget); + QRect ticks = 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 = 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 (!UsePixmapCache || !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(); + if (UsePixmapCache) + 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); + drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + } + + if (option->subControls & SC_SliderTickmarks) { + QPen oldPen = painter->pen(); + painter->setPen(borderColor); + int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget); + int available = 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 = pixelMetric(PM_SliderLength, slider, widget); + QVarLengthArray<QLine, 32> 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<const QStyleOptionSpinBox *>(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 = subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget); + QRect downRect = 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<QPoint, 4> 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, + 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<const QStyleOptionComboBox *>(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, + 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; + } + 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) && (option->state & State_KeyboardFocusChange)) && !comboBox->editable) { + QStyleOptionFocusRect focus; + focus.rect = subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget) + .adjusted(-2, 0, 2, 0); + drawPrimitive(PE_FrameFocusRect, &focus, painter, widget); + } + + painter->setPen(oldPen); + } + break; +#endif // QT_NO_COMBOBOX + case CC_TitleBar: + if (const QStyleOptionTitleBar *titleBar = qstyleoption_cast<const QStyleOptionTitleBar *>(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; + 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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(); + drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm); + painter->restore(); + } + } + painter->restore(); + } + break; + 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<const QStyleOptionSlider *>(option)) { + int tickSize = 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<const QStyleOptionSlider *>(option)) { + int scrollBarExtent = pixelMetric(PM_ScrollBarExtent, option, widget); + int scrollBarSliderMinimum = 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<const QStyleOptionMenuItem *>(option)) { + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) + newSize.setHeight(menuItem->text.isEmpty() ? 2 : menuItem->fontMetrics.lineSpacing()); + } + 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<const QStyleOptionSlider *>(option)) { + int tickSize = 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<const QStyleOptionSlider *>(option)) { + int scrollBarExtent = pixelMetric(PM_ScrollBarExtent, scrollBar, widget); + int sliderMaxLength = ((scrollBar->orientation == Qt::Horizontal) ? + scrollBar->rect.width() : scrollBar->rect.height()) - (scrollBarExtent * 3); + int sliderMinLength = 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<const QStyleOptionSpinBox *>(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<const QStyleOptionComboBox *>(option)) { + int frameWidth = 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<const QStyleOptionTitleBar *>(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<QStyleHintReturnMask *>(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<const QStyleOptionTitleBar *>(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; + 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<const QStyleOptionSlider *>(option)) { + QRect slider = subControlRect(control, scrollBar, SC_ScrollBarSlider, widget); + if (slider.contains(pos)) { + ret = SC_ScrollBarSlider; + break; + } + + QRect scrollBarAddLine = subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget); + if (scrollBarAddLine.contains(pos)) { + ret = SC_ScrollBarAddLine; + break; + } + + QRect scrollBarSubPage = subControlRect(control, scrollBar, SC_ScrollBarSubPage, widget); + if (scrollBarSubPage.contains(pos)) { + ret = SC_ScrollBarSubPage; + break; + } + + QRect scrollBarAddPage = subControlRect(control, scrollBar, SC_ScrollBarAddPage, widget); + if (scrollBarAddPage.contains(pos)) { + ret = SC_ScrollBarAddPage; + break; + } + + QRect scrollBarSubLine = 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_ToolBarIconSize: + ret = 24; + 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<const QStyleOptionSlider *>(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<const QMenu *>(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().lineSpacing(), 20); + } else +#endif + ret = qMax(widget ? widget->fontMetrics().lineSpacing() : + (option ? option->fontMetrics.lineSpacing() : 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<QPushButton *>(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast<QComboBox *>(widget) +#endif +#ifndef QT_NO_SPINBOX + || qobject_cast<QAbstractSpinBox *>(widget) +#endif + || qobject_cast<QCheckBox *>(widget) +#ifndef QT_NO_GROUPBOX + || qobject_cast<QGroupBox *>(widget) +#endif + || qobject_cast<QRadioButton *>(widget) +#ifndef QT_NO_SPLITTER + || qobject_cast<QSplitterHandle *>(widget) +#endif +#ifndef QT_NO_TABBAR + || qobject_cast<QTabBar *>(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<QMenuBar *>(widget) +#endif +#ifdef QT3_SUPPORT + || widget->inherits("Q3ToolBar") +#endif +#ifndef QT_NO_TOOLBAR + || qobject_cast<QToolBar *>(widget) + || (widget && qobject_cast<QToolBar *>(widget->parent())) +#endif + ) { + widget->setBackgroundRole(QPalette::Window); + } + +#ifndef QT_NO_PROGRESSBAR + if (AnimateBusyProgressBar && qobject_cast<QProgressBar *>(widget)) + widget->installEventFilter(this); +#endif + +#if defined QPlastique_MaskButtons + if (qobject_cast<QPushButton *>(widget) || qobject_cast<QToolButton *>(widget)) + widget->installEventFilter(this); +#endif +} + +/*! + \reimp +*/ +void QPlastiqueStyle::unpolish(QWidget *widget) +{ + if (qobject_cast<QPushButton *>(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast<QComboBox *>(widget) +#endif +#ifndef QT_NO_SPINBOX + || qobject_cast<QAbstractSpinBox *>(widget) +#endif + || qobject_cast<QCheckBox *>(widget) +#ifndef QT_NO_GROUPBOX + || qobject_cast<QGroupBox *>(widget) +#endif +#ifndef QT_NO_SPLITTER + || qobject_cast<QSplitterHandle *>(widget) +#endif +#ifndef QT_NO_TABBAR + || qobject_cast<QTabBar *>(widget) +#endif + || qobject_cast<QRadioButton *>(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<QMenuBar *>(widget) +#endif +#ifndef QT_NO_TOOLBOX + || qobject_cast<QToolBox *>(widget) +#endif +#ifdef QT3_SUPPORT + || widget->inherits("Q3ToolBar") +#endif +#ifndef QT_NO_TOOLBAR + || qobject_cast<QToolBar *>(widget) + || (widget && qobject_cast<QToolBar *>(widget->parent())) +#endif + ) { + widget->setBackgroundRole(QPalette::Button); + } + +#ifndef QT_NO_PROGRESSBAR + if (AnimateBusyProgressBar && qobject_cast<QProgressBar *>(widget)) { + Q_D(QPlastiqueStyle); + widget->removeEventFilter(this); + d->bars.removeAll(static_cast<QProgressBar*>(widget)); + } +#endif + +#if defined QPlastique_MaskButtons + if (qobject_cast<QPushButton *>(widget) || qobject_cast<QToolButton *>(widget)) + widget->removeEventFilter(this); +#endif +} + +/*! + \reimp +*/ +void QPlastiqueStyle::polish(QApplication *app) +{ + QWindowsStyle::polish(app); +} + +/*! + \reimp +*/ +void QPlastiqueStyle::polish(QPalette &pal) +{ + QWindowsStyle::polish(pal); + pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110)); +#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<QProgressBar *>(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<QProgressBar*>(watched)); + if (d->bars.isEmpty()) { + killTimer(d->progressBarAnimateTimer); + d->progressBarAnimateTimer = 0; + } + } + break; +#if defined QPlastique_MaskButtons + case QEvent::Resize: + if (qobject_cast<QPushButton *>(watched) || qobject_cast<QToolButton *>(watched)) { + QWidget *widget = qobject_cast<QWidget *>(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/gui/styles/qplastiquestyle.h b/src/gui/styles/qplastiquestyle.h new file mode 100644 index 0000000000..7e236b8b20 --- /dev/null +++ b/src/gui/styles/qplastiquestyle.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLASTIQUESTYLE_H +#define QPLASTIQUESTYLE_H + +#include <QtGui/qwindowsstyle.h> + +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/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp new file mode 100644 index 0000000000..58dcb9874e --- /dev/null +++ b/src/gui/styles/qs60style.cpp @@ -0,0 +1,2451 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qs60style_p.h" +#include "qapplication.h" +#include "qpainter.h" +#include "qstyleoption.h" +#include "qresizeevent" +#include "qpixmapcache" +#include "qlistview.h" +#include "qcalendarwidget.h" +#include "qtabbar.h" +#include "qlistwidget.h" +#include "qmenu.h" +#include "qpushbutton.h" +#include "qmenubar.h" +#include "qtablewidget.h" +#include "private/qcombobox_p.h" +#include "private/qwidget_p.h" +#include "qscrollbar.h" +#include "qlist.h" +#include "qtableview.h" +#include "qheaderview.h" +#include "qtreeview.h" +#include "qdialog.h" +#include "qmessagebox.h" +#include "qerrormessage.h" + +#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN) + +QT_BEGIN_NAMESPACE + +// from text/qfont.cpp +extern Q_GUI_EXPORT int qt_defaultDpiY(); + +const QS60StylePrivate::SkinElementFlags QS60StylePrivate::KDefaultSkinElementFlags = + SkinElementFlags(SF_PointNorth | SF_StateEnabled); + +static const QByteArray propertyKeyLayouts = "layouts"; +static const QByteArray propertyKeyCurrentlayout = "currentlayout"; + +#if defined(QT_S60STYLE_LAYOUTDATA_SIMULATED) +const layoutHeader QS60StylePrivate::m_layoutHeaders[] = { +// *** generated layout data *** +{240,320,1,12,true,QLatin1String("QVGA Landscape Mirrored")}, +{240,320,1,12,false,QLatin1String("QVGA Landscape")}, +{320,240,1,12,true,QLatin1String("QVGA Portrait Mirrored")}, +{320,240,1,12,false,QLatin1String("QVGA Portrait")}, +{360,640,1,12,true,QLatin1String("NHD Landscape Mirrored")}, +{360,640,1,12,false,QLatin1String("NHD Landscape")}, +{640,360,1,12,true,QLatin1String("NHD Portrait Mirrored")}, +{640,360,1,12,false,QLatin1String("NHD Portrait")}, +{352,800,1,9,true,QLatin1String("E90 Landscape Mirrored")}, +{352,800,1,9,false,QLatin1String("E90 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,1,0,0,-1,8,15,22,15,15,7,198,-909,-909,-909,19,15,2,0,0,21,-909,21,-909,4,4,1,-909,-909,0,2,0,0,13,23,17,17,21,21,2,115,21,0,-909,-909,-909,-909,0,0,15,4,-909,0,0,-909,-909,-909,-909,-909,-909,37,21,51,27,51,4,4,5,3,15,-909,5,58,12,5,0,7,4,4,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1}, +{5,0,-909,0,0,1,0,0,-1,8,15,22,15,15,7,198,-909,-909,-909,19,15,2,0,0,21,-909,21,-909,4,4,1,-909,-909,0,2,0,0,13,23,17,17,21,21,2,115,21,0,-909,-909,-909,-909,0,0,15,5,-909,0,0,-909,-909,-909,-909,-909,-909,37,21,51,27,51,4,4,5,3,15,-909,5,58,12,5,0,4,4,7,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1}, +{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,-909,27,-909,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,4,-909,0,0,-909,-909,-909,-909,-909,-909,37,21,65,27,65,4,4,5,3,15,-909,5,58,13,5,0,7,4,4,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1}, +{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,-909,27,-909,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,5,-909,0,0,-909,-909,-909,-909,-909,-909,37,21,65,27,65,4,4,5,3,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1}, +{7,0,-909,0,0,2,0,0,-1,20,53,28,19,19,9,258,-909,-909,-909,29,19,26,0,0,32,-909,72,-909,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,5,-909,0,0,-909,-909,-909,-909,-909,-909,87,27,77,35,77,5,5,6,3,19,-909,7,74,19,7,0,8,5,5,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1}, +{7,0,-909,0,0,2,0,0,-1,20,53,28,19,19,9,258,-909,-909,-909,29,19,26,0,0,32,-909,72,-909,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,7,-909,0,0,-909,-909,-909,-909,-909,-909,87,27,77,35,77,5,5,6,3,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1}, +{7,0,-909,0,0,2,0,0,-1,20,52,28,19,19,9,258,-909,-909,-909,29,19,6,0,0,32,-909,60,-909,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,5,-909,0,0,-909,-909,-909,-909,-909,-909,87,27,98,35,98,5,5,6,3,19,-909,7,74,22,7,0,8,5,5,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1}, +{7,0,-909,0,0,2,0,0,-1,20,52,28,19,19,9,258,-909,-909,-909,29,19,6,0,0,32,-909,60,-909,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,7,-909,0,0,-909,-909,-909,-909,-909,-909,87,27,98,35,98,5,5,6,3,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1}, +{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,-909,32,-909,5,5,2,-909,-909,0,2,8,0,16,16,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,5,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,34,7,0,2,2,3,0,1,1,-909,2,-909,-909,-909,-909,7,7,3,1}, +{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,-909,32,-909,5,5,2,-909,-909,0,2,8,0,16,16,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,34,7,0,3,2,2,0,1,1,-909,2,-909,-909,-909,-909,7,7,3,1} + +// *** End of generated data *** +}; + +const short *QS60StylePrivate::m_pmPointer = QS60StylePrivate::data[0]; +#endif // defined(QT_S60STYLE_LAYOUTDATA_SIMULATED) + +bool QS60StylePrivate::m_backgroundValid = false; + +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_OptionsMenu, QS60StyleEnums::SP_QsnFrPopupCenter}, + {SE_SettingsList, QS60StyleEnums::SP_QsnFrSetOptCenter}, + {SE_TableItem, QS60StyleEnums::SP_QsnFrCaleCenter}, + {SE_TableHeaderItem, QS60StyleEnums::SP_QsnFrCaleHeadingCenter}, + {SE_ToolTip, QS60StyleEnums::SP_QsnFrPopupPreviewCenter} +}; +static const int frameElementsCount = + int(sizeof(QS60StylePrivate::m_frameElementsData)/sizeof(QS60StylePrivate::m_frameElementsData[0])); + +const int KNotFound = -1; + +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(), 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.setWidth(qMin(rect.width() / 2 - 1, startRect.width())); + endRect = startRect.translated(rect.width() - startRect.width(), 0); + middleRect.adjust(startRect.width(), 0, -startRect.width(), 0); + } else { + startRect.setHeight(qMin(rect.height() / 2 - 1, startRect.height())); + endRect = startRect.translated(0, rect.height() - startRect.height()); + middleRect.adjust(0, startRect.height(), 0, -startRect.height()); + } + +#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, SkinElementFlags flags) +{ + QPixmap result; + const QString cacheKey = + QString::fromLatin1("S60Style: SkinParts=%1 QSize=%2|%3 SkinElementFlags=%4") + .arg((int)part).arg(size.width()).arg(size.height()).arg((int)flags); + if (!QPixmapCache::find(cacheKey, result)) { + result = QS60StylePrivate::part(part, size, 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::refreshUI() +{ + foreach (QWidget *topLevelWidget, QApplication::allWidgets()) { + topLevelWidget->updateGeometry(); + QCoreApplication::postEvent(topLevelWidget, new QResizeEvent(topLevelWidget->size(), topLevelWidget->size())); + } +} + +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_QgnIndiSliderEdit, painter, rect, flags | SF_PointNorth); + break; + case SE_SliderHandleVertical: + drawPart(QS60StyleEnums::SP_QgnIndiSliderEdit, painter, rect, flags | SF_PointEast); + 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_OptionsMenu: + drawFrame(SF_OptionsMenu, 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; + default: + break; + } +} + +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: + break; + case QS60StyleEnums::SP_QgnIndiSliderEdit: + result.scale(pixelMetric(QStyle::PM_SliderLength), + pixelMetric(QStyle::PM_SliderControlThickness), Qt::IgnoreAspectRatio); + break; + case QS60StyleEnums::SP_QsnCpScrollBgBottom: + case QS60StyleEnums::SP_QsnCpScrollBgMiddle: + case QS60StyleEnums::SP_QsnCpScrollBgTop: + case QS60StyleEnums::SP_QsnCpScrollHandleBottom: + case QS60StyleEnums::SP_QsnCpScrollHandleMiddle: + case QS60StyleEnums::SP_QsnCpScrollHandleTop: + result.setHeight(pixelMetric(QStyle::PM_ScrollBarExtent)); + result.setWidth(pixelMetric(QStyle::PM_ScrollBarExtent)); + 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_Custom_FrameCornerWidth)); + // Falltrough intended... + case 4: /* SideT */ + case 3: /* SideB */ + result.setHeight(pixelMetric(PM_Custom_FrameCornerHeight)); + break; + case 2: /* SideL */ + case 1: /* SideR */ + result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth)); + break; + case 0: /* center */ + default: + break; + } + } + break; + } + if (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest)) { + const int temp = result.width(); + result.setWidth(result.height()); + result.setHeight(temp); + } + return result; +} + + +void QS60StylePrivate::drawSkinPart(QS60StyleEnums::SkinParts part, + QPainter *painter, const QRect &rect, SkinElementFlags flags) +{ + drawPart(part, painter, rect, flags); +} + +void QS60StylePrivate::setStyleProperty(const char *name, const QVariant &value) +{ + if (name == propertyKeyCurrentlayout) { +#if !defined(QT_WS_S60) || defined(QT_S60STYLE_LAYOUTDATA_SIMULATED) + static const QStringList layouts = styleProperty(propertyKeyLayouts).toStringList(); + const QString layout = value.toString(); + Q_ASSERT(layouts.contains(layout)); + const int layoutIndex = layouts.indexOf(layout); + setCurrentLayout(layoutIndex); + QApplication::setLayoutDirection(m_layoutHeaders[layoutIndex].mirroring ? Qt::RightToLeft : Qt::LeftToRight); + clearCaches(); + refreshUI(); + return; +#else + qFatal("Cannot set static layout. Dynamic layouts are used!"); +#endif + } +} + +// Since S60Style has 'button' and 'tooltip' as a graphic, we don't have any native color which to use +// for QPalette::Button and QPalette::ToolTipBase. Therefore we need to guesstimate +// this by calculating average rgb values for button pixels. +// Returns Qt::black if there is an issue with the graphics (image is NULL, or no bits() found). +QColor QS60StylePrivate::colorFromFrameGraphics(QS60StylePrivate::SkinFrameElements frame) const +{ + const bool cachedColorExists = m_colorCache.contains(frame); + if (!cachedColorExists) { + const int frameCornerWidth = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth); + const int frameCornerHeight = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerHeight); + Q_ASSERT(2*frameCornerWidth<32); + Q_ASSERT(2*frameCornerHeight<32); + + const QImage frameImage = QS60StylePrivate::frame(frame, QSize(32,32)).toImage(); + if (frameImage.isNull()) + return Qt::black; + + const QRgb *pixelRgb = (const QRgb*)frameImage.bits(); + const int pixels = frameImage.numBytes()/sizeof(QRgb); + const int bytesPerLine = frameImage.bytesPerLine(); + Q_ASSERT(bytesPerLine); + const int rows = frameImage.numBytes()/(sizeof(QRgb)*bytesPerLine); + + 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()-frameCornerHeight*frameImage.width()-1; + 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); + m_colorCache.insert(frame, frameColor); + return !estimations ? Qt::black : frameColor; + } else { + return m_colorCache.value(frame); + } + +} + +int QS60StylePrivate::focusRectPenWidth() +{ + return pixelMetric(QS60Style::PM_DefaultFrameWidth); +} + +void QS60StylePrivate::setThemePalette(QWidget *widget) const +{ + QPalette widgetPalette = QPalette(Qt::white); + + // basic colors + widgetPalette.setColor(QPalette::WindowText, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0)); + widgetPalette.setColor(QPalette::ButtonText, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0)); + widgetPalette.setColor(QPalette::Text, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0)); + widgetPalette.setColor(QPalette::ToolTipText, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 55, 0)); + widgetPalette.setColor(QPalette::BrightText, widgetPalette.color(QPalette::WindowText).lighter()); + widgetPalette.setColor(QPalette::HighlightedText, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0)); + widgetPalette.setColor(QPalette::Link, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnHighlightColors, 3, 0)); + widgetPalette.setColor(QPalette::LinkVisited, widgetPalette.color(QPalette::Link).darker()); + widgetPalette.setColor(QPalette::Highlight, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnHighlightColors, 2, 0)); + // set these as transparent so that styled full screen theme background is visible + widgetPalette.setColor(QPalette::AlternateBase, Qt::transparent); + widgetPalette.setColor(QPalette::Window, Qt::transparent); + widgetPalette.setColor(QPalette::Base, Qt::transparent); + // set button and tooltipbase based on pixel colors + QColor buttonColor = colorFromFrameGraphics(QS60StylePrivate::SF_ButtonNormal); + widgetPalette.setColor(QPalette::Button, buttonColor ); + widgetPalette.setColor(QPalette::Light, widgetPalette.color(QPalette::Button).lighter()); + widgetPalette.setColor(QPalette::Dark, widgetPalette.color(QPalette::Button).darker()); + widgetPalette.setColor(QPalette::Midlight, widgetPalette.color(QPalette::Button).lighter(125)); + widgetPalette.setColor(QPalette::Mid, widgetPalette.color(QPalette::Button).darker(150)); + widgetPalette.setColor(QPalette::Shadow, Qt::black); + QColor toolTipColor = colorFromFrameGraphics(QS60StylePrivate::SF_ToolTip); + widgetPalette.setColor(QPalette::ToolTipBase, toolTipColor ); + + // widget specific colors + if (QSlider *slider = qobject_cast<QSlider *>(widget)){ + widgetPalette.setColor(QPalette::All, QPalette::WindowText, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 8, 0)); + } else if (QPushButton *button = qobject_cast<QPushButton *>(widget)){ + widgetPalette.setColor(QPalette::Active, QPalette::ButtonText, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0)); + widgetPalette.setColor(QPalette::Inactive, QPalette::ButtonText, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0)); + } else if (QHeaderView *table = qobject_cast<QHeaderView *>(widget)){ + widgetPalette.setColor(QPalette::Active, QPalette::ButtonText, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 23, 0)); + } else if (QMenuBar *menuBar = qobject_cast<QMenuBar *>(widget)){ + widgetPalette.setColor(QPalette::All, QPalette::ButtonText, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 8, 0)); + } else if (QTabBar *tabBar = qobject_cast<QTabBar *>(widget)){ + widgetPalette.setColor(QPalette::Active, QPalette::WindowText, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 4, 0)); + } else if (QTableView *table = qobject_cast<QTableView *>(widget)){ + widgetPalette.setColor(QPalette::All, QPalette::Text, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 22, 0)); + } + + if (widget) + widget->setPalette(widgetPalette); +} + +void QS60Style::polish(QWidget *widget) +{ + Q_D(const QS60Style); + QCommonStyle::polish(widget); + + if (QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(widget)){ + scrollArea->viewport()->setAutoFillBackground(false); + } + + if (false +#ifndef QT_NO_SCROLLBAR + || qobject_cast<QScrollBar *>(widget) +#endif + ) { + widget->setAttribute(Qt::WA_OpaquePaintEvent, false); + } + if (QS60StylePrivate::isSkinnableDialog(widget)) { + widget->setAttribute(Qt::WA_StyledBackground); + } else if (false +#ifndef QT_NO_MENU + || qobject_cast<const QMenu *> (widget) +#endif // QT_NO_MENU + ) { + widget->setAttribute(Qt::WA_StyledBackground); + } else if (false +#ifndef QT_NO_COMBOBOX + || qobject_cast<const QComboBoxListView *>(widget) +#endif //QT_NO_COMBOBOX + ) { + widget->setAttribute(Qt::WA_StyledBackground); + } + + if (widget){ + d->setThemePalette(widget); + } + +} + +void QS60Style::unpolish(QWidget *widget) +{ + if (QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(widget)){ + scrollArea->viewport()->setAutoFillBackground(true); + } + + if (false +#ifndef QT_NO_SCROLLBAR + || qobject_cast<QScrollBar *>(widget) +#endif + ) { + widget->setAttribute(Qt::WA_OpaquePaintEvent); + } + if (QS60StylePrivate::isSkinnableDialog(widget)) { + widget->setAttribute(Qt::WA_StyledBackground, false); + } else if (false +#ifndef QT_NO_MENU + || qobject_cast<const QMenu *> (widget) +#endif // QT_NO_MENU + ) { + widget->setAttribute(Qt::WA_StyledBackground, false); + } else if (false +#ifndef QT_NO_COMBOBOX + || qobject_cast<const QComboBoxListView *>(widget) +#endif //QT_NO_COMBOBOX + ) { + widget->setAttribute(Qt::WA_StyledBackground, false); + } + + if (widget) { + widget->setPalette(QPalette()); + } + + QCommonStyle::unpolish(widget); +} + +QVariant QS60StylePrivate::styleProperty(const char *name) const +{ + if (name == propertyKeyLayouts) { +#if !defined(QT_WS_S60) || defined(QT_S60STYLE_LAYOUTDATA_SIMULATED) + static QStringList layouts; + if (layouts.isEmpty()) + for (int i = 0; i < QS60StylePrivate::m_numberOfLayouts; i++) + layouts.append(QS60StylePrivate::m_layoutHeaders[i].layoutName); + return layouts; +#else + qFatal("Cannot return list of 'canned' static layouts. Dynamic layouts are used!"); +#endif + } + return QVariant(); +} + +QFont QS60StylePrivate::s60Font( + QS60StyleEnums::FontCategories fontCategory, int pointSize) 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<QS60StyleEnums::FontCategories, int> key(fontCategory, actualPointSize); + if (!m_mappedFontsCache.contains(key)) { + result = s60Font_specific(fontCategory, actualPointSize); + m_mappedFontsCache.insert(key, result); + } else { + result = m_mappedFontsCache.value(key); + if (result.pointSize() != actualPointSize) + result.setPointSize(actualPointSize); + } + return result; +} + +//todo: you could pass a reason to clear cache here, so that we could +// deduce whether or not the specific cache needs to be cleared +void QS60StylePrivate::clearCaches() +{ + m_colorCache.clear(); + m_mappedFontsCache.clear(); + QPixmapCache::clear(); + m_backgroundValid = false; +} + +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::isSkinnableDialog(const QWidget *widget) +{ + return (qobject_cast<const QMessageBox *> (widget) || + qobject_cast<const QErrorMessage *> (widget)); +} + +#if !defined(QT_WS_S60) || defined(QT_S60STYLE_LAYOUTDATA_SIMULATED) +void QS60StylePrivate::setCurrentLayout(int index) +{ + m_pmPointer = data[index]; +} +#endif + +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; +} + +/*! + \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 +*/ + +/*! + Constructs a QS60Style object. +*/ +QS60Style::QS60Style() + : QCommonStyle(*new QS60StylePrivate) +{ +} + +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<const QStyleOptionSlider *>(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 QS60StylePrivate::SkinElements handleElement = + horizontal ? QS60StylePrivate::SE_ScrollBarHandleHorizontal : 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<const QStyleOptionSlider *>(option)) { + + // The groove is just a centered line. Maybe a qgn_graf_line_* at some point + const QRect sliderGroove = subControlRect(control, optionSlider, SC_SliderGroove, widget); + 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(); + + const QRect sliderHandle = subControlRect(control, optionSlider, SC_SliderHandle, widget); + const QS60StylePrivate::SkinElements handleElement = + horizontal ? QS60StylePrivate::SE_SliderHandleHorizontal : QS60StylePrivate::SE_SliderHandleVertical; + QS60StylePrivate::drawSkinElement(handleElement, painter, sliderHandle, flags); + + if (optionSlider->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*optionSlider); + fropt.rect = subElementRect(SE_SliderFocusRect, optionSlider, widget); + drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + } + break; +#endif // QT_NO_SLIDER +#ifndef QT_NO_COMBOBOX + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(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 + //todo: why calc rect here for button? Is there no suitable SE_xxx for that? + QStyleOptionFrame buttonOption; + buttonOption.QStyleOption::operator=(*cmb); + const int maxHeight = cmbxFrame.height(); + const int maxWidth = cmbxFrame.width() - cmbxEditField.width(); + const int topLeftPoint = direction ? cmbxEditField.right()+1 : cmbxEditField.left()+1-maxWidth; + const QRect buttonRect(topLeftPoint, cmbxEditField.top(), maxWidth, maxHeight); + buttonOption.rect = buttonRect; + buttonOption.state = cmb->state & (State_Enabled | State_MouseOver); + drawPrimitive(PE_PanelButtonCommand, &buttonOption, painter, widget); + // todo: we could draw qgn_prop_set_button skin item here + + // draw label background - label itself is drawn separately + const QS60StylePrivate::SkinElements skinElement = QS60StylePrivate::SE_FrameLineEdit; + QS60StylePrivate::drawSkinElement(skinElement, painter, cmbxEditField, flags); + + if (sub & SC_ComboBoxArrow) { + const int iconRectWidth = buttonOption.rect.width()>>1; + const int nudgeWidth =iconRectWidth>>1; + + // Draw the little arrow + const QRect arrowRect(((buttonOption.rect.left()+buttonOption.rect.right())>>1) - nudgeWidth, + buttonOption.rect.center().y()-(buttonOption.rect.height()>>2)+nudgeWidth, iconRectWidth, iconRectWidth); + + painter->save(); + painter->setPen(option->palette.buttonText().color()); + drawPrimitive(PE_IndicatorSpinDown, &buttonOption, painter, widget); + painter->restore(); + } + + if (cmb->subControls & SC_ComboBoxEditField) { + if (cmb->state & State_HasFocus && !cmb->editable) { + QStyleOptionFocusRect focus; + focus.QStyleOption::operator=(*cmb); + focus.rect = cmbxEditField; + focus.state |= State_FocusAtBorder; + focus.backgroundColor = cmb->palette.highlight().color(); + drawPrimitive(PE_FrameFocusRect, &focus, painter, widget); + } + } + } + break; +#endif // QT_NO_COMBOBOX +#ifndef QT_NO_TOOLBUTTON + case CC_ToolButton: + if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { + const State bflags = toolBtn->state; + const QRect button(subControlRect(control, toolBtn, SC_ToolButton, widget)); + QStyleOptionToolButton label = *toolBtn; + + if (sub&SC_ToolButton) { + QStyleOption tool(0); + tool.palette = toolBtn->palette; + if (bflags & (State_Sunken | State_On | State_Raised)) { + tool.rect = button; + tool.state = bflags; + drawPrimitive(PE_PanelButtonTool, &tool, painter, widget); + } + } + if (toolBtn->state & State_HasFocus) { + QStyleOptionFocusRect fr; + fr.QStyleOption::operator=(*toolBtn); + const int frameWidth = pixelMetric(PM_DefaultFrameWidth, option, widget); + fr.rect.adjust(frameWidth, frameWidth, -frameWidth, -frameWidth); + drawPrimitive(PE_FrameFocusRect, &fr, painter, widget); + } + + if (toolBtn->features & QStyleOptionToolButton::Arrow) { + QStyle::PrimitiveElement pe; + switch (toolBtn->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: + break; } + label.rect = button; + drawPrimitive(pe, &label, painter, widget); + } + + if (toolBtn->text.length()>0 || + !toolBtn->icon.isNull()) { + const int frameWidth = pixelMetric(PM_DefaultFrameWidth, option, widget); + label.rect = button.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth); + drawControl(CE_ToolButtonLabel, &label, painter, widget); + } + } + break; +#endif //QT_NO_TOOLBUTTON +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { + QStyleOptionSpinBox copy = *spinBox; + + // Let the base class draw the wole thing except the qDrawWinPanel 'frame' with Windows95-look + copy.frame = false; + QCommonStyle::drawComplexControl(control, ©, painter, widget); + } + break; +#endif //QT_NO_SPINBOX +#ifndef QT_NO_GROUPBOX + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(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 & 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); + drawPrimitive(PE_FrameGroupBox, &frame, painter, widget); + } + + // Draw title + if ((groupBox->subControls & QStyle::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(QStyle::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(); + + 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); + } + } + break; + +#endif //QT_NO_GROUPBOX + + //todo: remove non-used complex widgets in final version + case CC_TitleBar: +#ifdef QT3_SUPPORT + case CC_Q3ListView: +#endif //QT3_SUPPORT +#ifndef QT_NO_DIAL + case CC_Dial: +#endif //QT_NO_DIAL +#ifndef QT_NO_WORKSPACE + case CC_MdiControls: +#endif //QT_NO_WORKSPACE + 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_PushButtonBevel: + { + const bool isPressed = option->state & QStyle::State_Sunken; + const QS60StylePrivate::SkinElements skinElement = + isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal; + QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags); + } + break; + case CE_PushButtonLabel: + if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) { + QStyleOptionButton optionButton = *button; + int margins = 2*QS60StylePrivate::pixelMetric(QStyle::PM_ButtonMargin); + // make sure that margins do not take too much space from button + if (margins > optionButton.rect.height()/3) // TODO: (?) Remove this when s60Fonts are set by polish(QWidget*) + margins = optionButton.rect.height()/3; + const QFont suggestedFont = d->s60Font( + QS60StyleEnums::FC_Primary, painter->font().pointSizeF()); + painter->save(); + painter->setFont(suggestedFont); + QCommonStyle::drawControl(element, &optionButton, painter, widget); + painter->restore(); + } + break; + case CE_CheckBoxLabel: + if (const QStyleOptionButton *checkBox = qstyleoption_cast<const QStyleOptionButton *>(option)) { + QStyleOptionButton optionCheckBox = *checkBox; + QCommonStyle::drawControl(element, &optionCheckBox, painter, widget); + } + break; + case CE_RadioButtonLabel: + if (const QStyleOptionButton *radioButton = qstyleoption_cast<const QStyleOptionButton *>(option)) { + QStyleOptionButton optionRadioButton = *radioButton; + QCommonStyle::drawControl(element, &optionRadioButton, painter, widget); + } + break; +#ifndef QT_NO_TOOLBUTTON + case CE_ToolButtonLabel: + if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { + QStyleOptionToolButton optionToolButton = *toolBtn; + QCommonStyle::drawControl(element, &optionToolButton, painter, widget); + } + break; +#endif //QT_NO_TOOLBUTTON + case CE_HeaderLabel: + if (const QStyleOptionHeader *headerLabel = qstyleoption_cast<const QStyleOptionHeader *>(option)) { + QStyleOptionHeader optionHeaderLabel = *headerLabel; + // Adjust font according S60 Look-and-Feel + const QFont suggestedFont = d->s60Font( + QS60StyleEnums::FC_Secondary, painter->font().pointSizeF()); + painter->save(); + painter->setFont(suggestedFont); + QCommonStyle::drawControl(element, &optionHeaderLabel, painter, widget); + painter->restore(); + } + break; +#ifndef QT_NO_COMBOBOX + case CE_ComboBoxLabel: + if (const QStyleOptionComboBox *comboBox = qstyleoption_cast<const QStyleOptionComboBox *>(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); + 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() + 4); + 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.translate(-4 - comboBox->iconSize.width(), 0); + else + editRect.translate(comboBox->iconSize.width() + 4, 0); + } + if (!comboBox->currentText.isEmpty() && !comboBox->editable) { + QCommonStyle::drawItemText(painter, + editRect.adjusted(QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth), 0, -1, 0), + visualAlignment(comboBox->direction, Qt::AlignLeft | Qt::AlignVCenter), + comboBox->palette, comboBox->state & State_Enabled, comboBox->currentText); + } + painter->restore(); + } + break; +#endif //QT_NO_COMBOBOX +#ifndef QT_NO_ITEMVIEWS + case CE_ItemViewItem: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) { + QStyleOptionViewItemV4 voptAdj = *vopt; + painter->save(); + + painter->setClipRect(voptAdj.rect); + const bool isSelected = (voptAdj.state & QStyle::State_HasFocus); + + bool isVisible = false; + int scrollBarWidth = 0; + QList<QScrollBar *> scrollBars = qFindChildren<QScrollBar *>(widget); + for (int i = 0; i < scrollBars.size(); ++i) { + QScrollBar *scrollBar = scrollBars.at(i); + if (scrollBar && scrollBar->orientation() == Qt::Vertical) { + isVisible = scrollBar->isVisible(); + scrollBarWidth = scrollBar->size().width(); + break; + } + } + + int rightValue = widget ? widget->contentsRect().right() : 0; + + if (isVisible) + 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); + + // draw the background + const QStyleOptionViewItemV4 *tableOption = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option); + const QTableView *table = qobject_cast<const QTableView *>(widget); + if (table && tableOption) { + const QModelIndex indexCurrent = tableOption->index; + // Draw cell background only once - for the first cell + //todo: calc area based on viewport only so that 1000x1000 table doesn't get ridiculously big background + //todo: try to do this only once. For some reason, if I try to + //if ( indexCurrent.column() == 2 && indexCurrent.row() == 2 ) { + QStyleOptionViewItemV4 voptAdj2 = voptAdj2; + const QModelIndex index = table->model()->index(0,0); + const QModelIndex indexLast = table->model()->index( + table->model()->rowCount()-1,table->model()->columnCount()-1); + voptAdj2.rect = QRect( table->visualRect(index).topLeft(), table->visualRect(indexLast).bottomRight()); + drawPrimitive(PE_PanelItemViewItem, &voptAdj2, painter, widget); + //} + } + + // draw the focus rect + if (isSelected) + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags); + + // draw the icon + const QIcon::Mode mode = !(voptAdj.state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled; + const QIcon::State state = voptAdj.state & QStyle::State_Open ? QIcon::On : QIcon::Off; + voptAdj.icon.paint(painter, iconRect, voptAdj.decorationAlignment, mode, state); + + // Draw selection check mark. Show check mark only in multi selection modes. + if (const QListView *listView = (qobject_cast<const QListView *>(widget))) { + const bool singleSelection = + listView && + (listView->selectionMode() == QAbstractItemView::SingleSelection || + listView->selectionMode() == QAbstractItemView::NoSelection); + QRect selectionRect = subElementRect(SE_ItemViewItemCheckIndicator, &voptAdj, widget); + if (voptAdj.state & QStyle::State_Selected && + !singleSelection) { + QStyleOptionViewItemV4 option(voptAdj); + option.rect = selectionRect; + // Draw selection mark. + drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, painter, widget); + if ( textRect.right() > selectionRect.left() ) + textRect.setRight(selectionRect.left()); + } + else if (singleSelection && + voptAdj.features & QStyleOptionViewItemV2::HasCheckIndicator) { + // draw the check mark + if (selectionRect.isValid()) { + QStyleOptionViewItemV4 option(*vopt); + option.rect = selectionRect; + 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; + } + drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, painter, widget); + } + } + } + + // draw the text + if (!voptAdj.text.isEmpty()) { + const QStyleOptionViewItemV4 *tableOption = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option); + if (isSelected) { + if (qobject_cast<const QTableView *>(widget) && tableOption) + voptAdj.palette.setColor(QPalette::Text, QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0)); + else + voptAdj.palette.setColor(QPalette::Text, QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0)); + } + 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<const QStyleOptionTabV3 *>(option)) { + QStyleOptionTabV3 optionTabAdj = *optionTab; + const bool isSelected = optionTab->state & QStyle::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(QStyle::PM_DefaultFrameWidth); + const int tabOverlap = + QS60StylePrivate::pixelMetric(QStyle::PM_TabBarTabOverlap) - borderThickness; + //todo: draw navi wipe behind tabbar - must be drawn with first draw + //QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableHeaderItem, painter, windowRect, flags); + + if (skinElement==QS60StylePrivate::SE_TabBarTabEastInactive|| + skinElement==QS60StylePrivate::SE_TabBarTabEastActive|| + skinElement==QS60StylePrivate::SE_TabBarTabWestInactive|| + skinElement==QS60StylePrivate::SE_TabBarTabWestActive){ + optionTabAdj.rect.adjust(0, 0, 0, tabOverlap); + } else { + if (directionMirrored) + optionTabAdj.rect.adjust(-tabOverlap, 0, 0, 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<const QStyleOptionTabV3 *>(option)) { + QStyleOptionTabV3 optionTab = *tab; + QRect tr = optionTab.rect; + const bool directionMirrored = (optionTab.direction == Qt::RightToLeft); + const int borderThickness = QS60StylePrivate::pixelMetric(QStyle::PM_DefaultFrameWidth); + const int tabOverlap = + QS60StylePrivate::pixelMetric(QStyle::PM_TabBarTabOverlap) - borderThickness; + const QRect windowRect = painter->window(); + + 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() * 0.72); + painter->setFont(f); + + if (option->state & QStyle::State_Selected){ + optionTab.palette.setColor(QPalette::Active, QPalette::WindowText, + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 3, option)); + } + + bool verticalTabs = optionTab.shape == QTabBar::RoundedEast + || optionTab.shape == QTabBar::RoundedWest + || optionTab.shape == QTabBar::TriangularEast + || optionTab.shape == QTabBar::TriangularWest; + bool selected = optionTab.state & State_Selected; + if (verticalTabs) { + painter->save(); + int newX, newY, newRot; + if (optionTab.shape == QTabBar::RoundedEast || optionTab.shape == QTabBar::TriangularEast) { + newX = tr.width(); + newY = tr.y(); + newRot = 90; + } else { + newX = 0; + newY = tr.y() + tr.height(); + newRot = -90; + } + tr.setRect(0, 0, tr.height(), tr.width()); + QTransform m; + m.translate(newX, newY); + m.rotate(newRot); + painter->setTransform(m, true); + } + tr.adjust(0, 0, pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget), + pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget)); + + if (selected) { + tr.setBottom(tr.bottom() - pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget)); + tr.setRight(tr.right() - pixelMetric(QStyle::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; + int iconExtent = pixelMetric(PM_TabBarIconSize); + if (iconSize.height() > iconExtent || iconSize.width() > iconExtent) + 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); + } + + QCommonStyle::drawItemText(painter, tr, alignment, optionTab.palette, tab->state & State_Enabled, tab->text, QPalette::WindowText); + if (verticalTabs) + painter->restore(); + + if (optionTab.state & State_HasFocus) { + const int OFFSET = 1 + pixelMetric(PM_DefaultFrameWidth); + const int x1 = optionTab.rect.left(); + const int x2 = optionTab.rect.right() - 1; + + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*tab); + fropt.rect.setRect(x1 + 1 + OFFSET, optionTab.rect.y() + OFFSET, + x2 - x1 - 2*OFFSET, optionTab.rect.height() - 2*OFFSET); + drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + + painter->restore(); + } + break; +#endif // QT_NO_TABBAR +#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBarContents: + if (const QStyleOptionProgressBarV2 *optionProgressBar = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) { + QRect progressRect = optionProgressBar->rect; + const qreal progressFactor = (optionProgressBar->minimum == optionProgressBar->maximum) ? 1.0 + : (qreal)optionProgressBar->progress / optionProgressBar->maximum; + 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(1, 0, -1, 0); + } else { + progressRect.adjust(0, 1, 0, -1); + 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<const QStyleOptionProgressBarV2 *>(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<const QStyleOptionProgressBarV2 *>(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_MENUBAR + case CE_MenuBarItem: + if (const QStyleOptionMenuItem *menuBarItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { + QStyleOptionMenuItem optionMenuBarItem = *menuBarItem; + QCommonStyle::drawControl(element, &optionMenuBarItem, painter, widget); + } + break; +#endif //QT_NO_MENUBAR +#ifndef QT_NO_MENU + case CE_MenuItem: + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { + QStyleOptionMenuItem optionMenuItem = *menuItem; + const bool enabled = optionMenuItem.state & State_Enabled; + const bool checkable = optionMenuItem.checkType != QStyleOptionMenuItem::NotCheckable; + + 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); + bool drawSubMenuIndicator = false; + + switch(menuItem->menuItemType) { + case QStyleOptionMenuItem::Scroller: + case QStyleOptionMenuItem::Separator: + return; // no separators or scrollers in S60 menus + case QStyleOptionMenuItem::SubMenu: + drawSubMenuIndicator = true; + break; + default: + break; + } + + if ((option->state & State_Selected) && (option->state & State_Enabled)) + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags); + + //todo: move the vertical spacing stuff into subElementRect + const int vSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutVerticalSpacing); + QStyleOptionMenuItem optionCheckBox; + if (checkable){ + QRect checkBoxRect = optionMenuItem.rect; + checkBoxRect.setWidth(pixelMetric(PM_IndicatorWidth)); + checkBoxRect.setHeight(pixelMetric(PM_IndicatorHeight)); + optionCheckBox.QStyleOption::operator=(*menuItem); + optionCheckBox.rect = checkBoxRect; + const int moveByX = checkBoxRect.width()+vSpacing; + if (optionMenuItem.direction == Qt::LeftToRight) { + textRect.translate(moveByX,0); + iconRect.translate(moveByX, 0); + iconRect.setWidth(iconRect.width()+vSpacing); + textRect.setWidth(textRect.width()-moveByX-vSpacing); + } else { + textRect.setWidth(textRect.width()-moveByX); + iconRect.setWidth(iconRect.width()+vSpacing); + iconRect.translate(-optionCheckBox.rect.width()-vSpacing, 0); + optionCheckBox.rect.translate(textRect.width()+iconRect.width(),0); + } + 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(QStyle::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; + QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnIndiSubMenu, painter, arrowOptions.rect, + (flags | QS60StylePrivate::SF_ColorSkinned | arrowDirection)); + } + + //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); + QCommonStyle::drawItemText(painter, textRect, text_flags, + optionMenuItem.palette, enabled, + optionMenuItem.text, QPalette::Text); + painter->restore(); + } else { + QCommonStyle::drawItemText(painter, textRect, text_flags, + optionMenuItem.palette, enabled, + optionMenuItem.text, QPalette::Text); + } + } + break; +#endif //QT_NO_MENU + + //todo: remove non-used widgets in final version + case CE_MenuEmptyArea: +#ifndef QT_NO_MENUBAR + case CE_MenuBarEmptyArea: + break; +#endif //QT_NO_MENUBAR + + case CE_HeaderSection: + if ( const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(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_Custom_BoldLineWidth) + : linePen.width()+QS60StylePrivate::pixelMetric(PM_Custom_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(); + } + break; + + case CE_HeaderEmptyArea: + { + QS60StylePrivate::SkinElementFlags adjFlags = flags; + QRect mtyRect = option->rect; + if (option->state & QStyle::State_Horizontal) { + mtyRect.adjust(-2,-2,2,-2); + } else { + if ( option->direction == Qt::LeftToRight ) { + mtyRect.adjust(-2,-2,0,2); + adjFlags |= QS60StylePrivate::SF_PointWest; + } else { + mtyRect.adjust(2,2,0,-2); + adjFlags |= QS60StylePrivate::SF_PointEast; + } + } + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableHeaderItem, painter, mtyRect, adjFlags); + } + break; + case CE_Header: + if ( const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { + QS60StylePrivate::SkinElementFlags adjFlags = flags; + QRect mtyRect = header->rect; + QRect parentRect = widget->parentWidget()->rect(); + if (header->orientation == Qt::Horizontal) { + mtyRect.adjust(-2,-2,2,-2); + } else { + if ( header->direction == Qt::LeftToRight ) { + mtyRect.adjust(-2,-2,0,2); + adjFlags |= QS60StylePrivate::SF_PointWest; + } else { + mtyRect.adjust(2,2,0,-2); + adjFlags |= QS60StylePrivate::SF_PointEast; + } + } + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableHeaderItem, painter, mtyRect, adjFlags); + QCommonStyle::drawControl(element, header, painter, widget); + } + break; + case CE_ShapedFrame: + case CE_MenuVMargin: + case CE_MenuHMargin: +#ifndef QT_NO_MENU + case CE_MenuScroller: + case CE_MenuTearoff: +#endif //QT_NO_MENU + + case CE_PushButton: + case CE_CheckBox: + case CE_RadioButton: +#ifndef QT_NO_TABBAR + case CE_TabBarTab: +#endif //QT_NO_TABBAR +#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBar: +#endif // QT_NO_PROGRESSBAR + case CE_Q3DockWindowEmptyArea: +#ifndef QT_NO_SIZEGRIP + case CE_SizeGrip: +#endif //QT_NO_SIZEGRIP + case CE_Splitter: +#ifndef QT_NO_RUBBERBAND + case CE_RubberBand: +#endif //QT_NO_RUBBERBAND +#ifndef QT_NO_DOCKWIDGET + case CE_DockWidgetTitle: +#endif //QT_NO_DOCKWIDGET + case CE_ScrollBarAddLine: + case CE_ScrollBarSubLine: + case CE_ScrollBarAddPage: + case CE_ScrollBarSubPage: + case CE_ScrollBarSlider: + case CE_ScrollBarFirst: + case CE_ScrollBarLast: + case CE_FocusFrame: +#ifndef QT_NO_TOOLBAR + case CE_ToolBar: +#endif //QT_NO_TOOLBAR +#ifndef QT_NO_TOOLBOX + case CE_ToolBoxTab: + case CE_ToolBoxTabShape: + case CE_ToolBoxTabLabel: +#endif //QT_NO_TOOLBOX + case CE_ColumnViewGrip: + 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; + switch (element) { +#ifndef QT_NO_LINEEDIT + case PE_PanelLineEdit: + if (const QStyleOptionFrame *lineEdit = qstyleoption_cast<const QStyleOptionFrame *>(option)) { +#ifndef QT_NO_COMBOBOX + if (widget && qobject_cast<const QComboBox *>(widget->parentWidget())) + break; +#endif + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_FrameLineEdit, + painter, option->rect, flags); + + if (lineEdit->state & State_HasFocus) + drawPrimitive(PE_FrameFocusRect, lineEdit, painter, widget); + } + break; +#endif // QT_NO_LINEEDIT + case PE_IndicatorCheckBox: + { + const QRect indicatorRect = option->rect; + // Draw checkbox indicator as color skinned graphics. + const QS60StyleEnums::SkinParts skinPart = (option->state & QStyle::State_On) ? + QS60StyleEnums::SP_QgnIndiCheckboxOn : QS60StyleEnums::SP_QgnIndiCheckboxOff; + QS60StylePrivate::drawSkinPart(skinPart, painter, indicatorRect, + (flags | QS60StylePrivate::SF_ColorSkinned)); + } + break; + case PE_IndicatorViewItemCheck: + if (const QListView *listItem = (qobject_cast<const QListView *>(widget))) { + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) { + const bool checkBoxVisible = vopt->features & QStyleOptionViewItemV2::HasCheckIndicator; + const bool singleSelection = listItem->selectionMode() == + QAbstractItemView::SingleSelection || listItem->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 & QStyle::State_Selected) { + QS60StyleEnums::SkinParts skinPart = QS60StyleEnums::SP_QgnIndiMarkedAdd; + QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, + (flags | QS60StylePrivate::SF_ColorSkinned)); + } + } + } + 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,0,-newY); + + // Draw radiobutton indicator as color skinned graphics. + QS60StyleEnums::SkinParts skinPart = (option->state & QStyle::State_On) ? + QS60StyleEnums::SP_QgnIndiRadiobuttOn : QS60StyleEnums::SP_QgnIndiRadiobuttOff; + QS60StylePrivate::drawSkinPart(skinPart, painter, buttonRect, + (flags | QS60StylePrivate::SF_ColorSkinned)); + } + break; + case PE_PanelButtonCommand: + case PE_PanelButtonTool: + case PE_PanelButtonBevel: + case PE_FrameButtonBevel: + { + const bool isPressed = option->state & QStyle::State_Sunken; + const QS60StylePrivate::SkinElements skinElement = + isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal; + QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags); + } + break; +#ifndef QT_NO_TOOLBUTTON + case PE_IndicatorArrowDown: + case PE_IndicatorArrowLeft: + case PE_IndicatorArrowRight: + case PE_IndicatorArrowUp: + { + if (option->rect.width() <= 1 || option->rect.height() <= 1) + break; + QRect r = option->rect; + int size = qMin(r.height(), r.width()); + int border = size/5; + int sqsize = 2*(size>>1); + QImage image(sqsize, sqsize, QImage::Format_ARGB32); + image.fill(Qt::transparent); + QPainter imagePainter(&image); + + QPolygon a; + int halfsqsize = sqsize>>1; + int borderlessSqSize = sqsize - border; + switch (element) { + case PE_IndicatorArrowUp: + a.setPoints(3, border, halfsqsize, halfsqsize, border, borderlessSqSize, halfsqsize); + break; + case PE_IndicatorArrowDown: + a.setPoints(3, border, halfsqsize, halfsqsize, borderlessSqSize, borderlessSqSize, halfsqsize); + break; + case PE_IndicatorArrowRight: + a.setPoints(3, borderlessSqSize, halfsqsize, halfsqsize, border, halfsqsize, borderlessSqSize); + break; + case PE_IndicatorArrowLeft: + a.setPoints(3, border, halfsqsize, halfsqsize, border, halfsqsize, borderlessSqSize); + break; + default: + break; + } + + int bsx = 0; + int bsy = 0; + + if (option->state & State_Sunken) { + bsx = pixelMetric(PM_ButtonShiftHorizontal); + bsy = pixelMetric(PM_ButtonShiftVertical); + } + + QRect bounds = a.boundingRect(); + int sx = halfsqsize - bounds.center().x() - 1; + int sy = halfsqsize - bounds.center().y() - 1; + QPalette themeColor = option->palette; + imagePainter.translate(sx + bsx, sy + bsy); + imagePainter.setPen(themeColor.buttonText().color()); + + if (!(option->state & State_Enabled)) { + imagePainter.translate(1, 1); + imagePainter.setPen(themeColor.light().color()); + imagePainter.drawPolygon(a); + imagePainter.translate(-1, -1); + imagePainter.setPen(themeColor.mid().color()); + } + imagePainter.drawPolygon(a); + imagePainter.end(); + int xOffset = r.x() + ((r.width() - size)>>1); + int yOffset = r.y() + ((r.height() - size)>>1); + + painter->drawImage(xOffset, yOffset, image); + } + break; +#endif //QT_NO_TOOLBUTTON +#ifndef QT_NO_SPINBOX + case PE_IndicatorSpinDown: + case PE_IndicatorSpinUp: + case PE_IndicatorSpinMinus: + case PE_IndicatorSpinPlus: + { + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { + QStyleOptionSpinBox optionSpinBox = *spinBox; + if (element==PE_IndicatorSpinDown || element==PE_IndicatorSpinUp) + optionSpinBox.rect.adjust(2,2,-2,-2); + QCommonStyle::drawPrimitive(element, &optionSpinBox, painter, widget); + } else if (const QStyleOptionFrame *cmb = qstyleoption_cast<const QStyleOptionFrame *>(option)) { + // We want to draw down arrow here for comboboxes as well. + QStyleOptionFrame comboBox = *cmb; + comboBox.rect.adjust(0,2,0,-2); + QCommonStyle::drawPrimitive(element, &comboBox, painter, widget); + } + } + break; +#endif //QT_NO_SPINBOX + case PE_FrameFocusRect: + if (!(widget && qobject_cast<const QCalendarWidget *>(widget->parent())) || + qobject_cast<const QComboBoxListView *>(widget)) { + // no focus selection for touch + if (option->state & State_HasFocus && !QS60StylePrivate::isTouchSupported()) { + painter->save(); + const int penWidth = QS60StylePrivate::focusRectPenWidth(); +#ifdef QT_KEYPAD_NAVIGATION + const Qt::PenStyle penStyle = widget->hasEditFocus() ? Qt::SolidLine :Qt::DotLine; + const qreal opacity = widget->hasEditFocus() ? 0.6 : 0.4; +#else + const Qt::PenStyle penStyle = Qt::SolidLine; + const qreal opacity = 0.5; +#endif + painter->setPen(QPen(option->palette.color(QPalette::Text), penWidth, penStyle)); + painter->setRenderHint(QPainter::Antialiasing); + painter->setOpacity(opacity); + // Because of Qts coordinate system, we need to tweak the rect by .5 pixels, otherwise it gets blurred. + const qreal rectAdjustment = penWidth % 2?.5:0; + // Also we try to stay inside the option->rect, with penWidth > 1. Therefore these +1/-1 + const QRectF adjustedRect = QRectF(option->rect).adjusted( + rectAdjustment + penWidth - 1, + rectAdjustment + penWidth - 1, + -rectAdjustment - penWidth + 1, + -rectAdjustment - penWidth + 1); + painter->drawRoundedRect(adjustedRect, penWidth * 1.5, penWidth * 1.5); + painter->restore(); + } + } + break; + + case PE_Widget: + if (QS60StylePrivate::isSkinnableDialog(widget) || + qobject_cast<const QComboBoxListView *>(widget) || + qobject_cast<const QMenu *> (widget)) { + QS60StylePrivate::SkinElements skinElement = QS60StylePrivate::SE_OptionsMenu; + QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags); + } + break; + case PE_FrameWindow: + case PE_FrameTabWidget: + { + if (const QStyleOptionTabWidgetFrame *tabFrame = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) { + QStyleOptionTabWidgetFrame optionTabFrame = *tabFrame; + + const QColor baseColor(QS60StylePrivate::lighterColor( + QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 3, option))); + const QPalette tabPalette(baseColor); + optionTabFrame.palette = tabPalette; + QCommonStyle::drawPrimitive(element, &optionTabFrame, painter, widget); + } + } + break; + + case PE_IndicatorHeaderArrow: + if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(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<const QStyleOptionFrameV2 *>(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: + if (const QStyleOptionFrameV3 *frame = qstyleoption_cast<const QStyleOptionFrameV3 *>(option)) + drawPrimitive(PE_FrameFocusRect, frame, painter, widget); + break; + +#ifndef QT_NO_ITEMVIEWS + case PE_PanelItemViewItem: + case PE_PanelItemViewRow: // ### Qt 5: remove + if (qobject_cast<const QTableView *>(widget) && qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableItem, painter, option->rect, flags); + break; +#endif //QT_NO_ITEMVIEWS + + case PE_IndicatorMenuCheckMark: + if (const QStyleOptionMenuItem *checkBox = qstyleoption_cast<const QStyleOptionMenuItem *>(option)){ + QStyleOptionMenuItem optionCheckBox = *checkBox; + if (optionCheckBox.checked) + optionCheckBox.state = (optionCheckBox.state | State_On); + drawPrimitive(PE_IndicatorCheckBox, &optionCheckBox, painter, widget); + } + break; + + case PE_PanelMenuBar: + case PE_FrameMenu: + break; //disable frame in menu + + // todo: items are below with #ifdefs "just in case". in final version, remove all non-required cases + case PE_FrameLineEdit: + case PE_IndicatorBranch: + case PE_IndicatorButtonDropDown: + case PE_IndicatorDockWidgetResizeHandle: + case PE_PanelTipLabel: + case PE_PanelScrollAreaCorner: + +#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: + case PE_IndicatorToolBarHandle: + case PE_IndicatorToolBarSeparator: +#endif //QT_NO_TOOLBAR +#ifndef QT_NO_COLUMNVIEW + case PE_IndicatorColumnViewArrow: + case PE_IndicatorItemViewItemDrop: +#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: + QCommonStyle::drawPrimitive(element, option, painter, widget); + } +} + +/*! + \reimp - sets the default colors +*/ +void QS60Style::drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette & palette, bool enabled, const QString &text, QPalette::ColorRole textRole) const +{ + QPalette override = palette; + QCommonStyle::drawItemText(painter, rectangle, alignment, override, enabled, text, textRole); +} + +/*! + \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); + + if (metric == PM_SubMenuOverlap && widget){ + const int widgetWidth = widget->width(); + const QMenu *menu = qobject_cast<const QMenu *>(widget); + if (menu && menu->activeAction() && menu->activeAction()->menu()) { + const int menuWidth = menu->activeAction()->menu()->sizeHint().width(); + metricValue = -menuWidth; + } + } + 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_LineEdit: + if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt)) + sz += QSize(2*f->lineWidth, 4*f->lineWidth); + break; + default: + sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); + break; + } + return sz; +} +/*! \reimp */ +int QS60Style::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *widget, + QStyleHintReturn *hret) const +{ + int retValue = -1; + switch (sh) { + case SH_Table_GridLineColor: { + QColor lineColor = QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors,2,0); + retValue = lineColor.rgb(); + } + break; + case SH_GroupBox_TextLabelColor: { + QColor groupBoxTxtColor = QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors,6,0); + retValue = groupBoxTxtColor.rgb(); + } + 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; + break; + default: + break; + } + if (retValue == -1) + retValue = QCommonStyle::styleHint(sh, opt, widget, hret); + 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<const QStyleOptionSlider *>(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); + + 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_ScrollBarSubLine: // top/left button + case SC_ScrollBarAddLine: // bottom/right button + break; + 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; + default: + break; + } + ret = visualRect(scrollbarOption->direction, scrollBarRect, ret); + } + break; +#endif // QT_NO_SCROLLBAR + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { + const int frameThickness = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0; + const int buttonMargin = 2; //spinbox->frame ? /*QS60StylePrivate::pixelMetric(QStyle::PM_ButtonMargin)*/2 : 0; + const int buttonWidth = + QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize) + 2*buttonMargin; + //todo: buttonMargin commented out as WAY too big in pixel metrics + QSize buttonSize; + buttonSize.setHeight(qMax(8, spinbox->rect.height()/2 - frameThickness)); + buttonSize.setWidth(buttonWidth); + buttonSize = buttonSize.expandedTo(QApplication::globalStrut()); + + const int y = frameThickness + spinbox->rect.y(); + const int x = spinbox->rect.x() + spinbox->rect.width() - frameThickness - buttonSize.width(); + + switch (scontrol) { + case SC_SpinBoxUp: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + ret = QRect(x, y, buttonWidth, buttonSize.height()); + break; + case SC_SpinBoxDown: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + ret = QRect(x, y + buttonSize.height(), buttonWidth, 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<const QStyleOptionComboBox *>(option)) { + ret = cmb->rect; + const int width = cmb->rect.width(); + const int height = cmb->rect.height(); + //todo: buttonMargin commented out as WAY too big in pixel metrics + const int buttonMargin = cmb->frame ? /*QS60StylePrivate::pixelMetric(QStyle::PM_ButtonMargin)*/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 buttonWidth = QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize); + int xposMod = (cmb->rect.x()) + width - buttonMargin - buttonWidth; + const int ypos = cmb->rect.y(); + + QSize buttonSize; + buttonSize.setHeight(qMax(8, (cmb->rect.height()>>1) - frameThickness)); //minimum of 8 pixels + buttonSize.setWidth(buttonWidth+2*buttonMargin); + buttonSize = buttonSize.expandedTo(QApplication::globalStrut()); + switch (scontrol) { + case SC_ComboBoxArrow: + ret.setRect(xposMod, ypos + buttonMargin, buttonWidth, height - 2*buttonMargin); + break; + case SC_ComboBoxEditField: { + const int withFrameX = cmb->rect.x() + cmb->rect.width() - frameThickness - buttonSize.width(); + ret = QRect( + frameThickness, + frameThickness, + withFrameX - frameThickness, + cmb->rect.height() - 2*frameThickness); + } + break; + default: + break; + } + } + break; + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(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(QStyle::PM_LayoutHorizontalSpacing); + const int bottomMargin = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutBottomMargin); + 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; + default: + ret = QCommonStyle::subControlRect(control, option, scontrol, widget); + } + return ret; +} + +QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, const QWidget *widget) const +{ + QRect ret; + switch (element) { + case SE_LineEditContents: { + // in S60 the input text box doesn't start from line Edit's TL, but + // a bit indented. + // todo: Should we NOT do this for combo boxes and spin boxes? + QRect lineEditRect = opt->rect; + int adjustment = opt->rect.height()>>2; + lineEditRect.adjust(adjustment,0,0,0); + ret = lineEditRect; + } + break; + case SE_TabBarTearIndicator: + ret = QRect(0,0,0,0); + break; + case SE_TabWidgetTabBar: + if (const QStyleOptionTabWidgetFrame *optionTab = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { + ret = QCommonStyle::subElementRect(element, opt, widget); + + if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { + const int tabOverlapNoBorder = + QS60StylePrivate::pixelMetric(QStyle::PM_TabBarTabOverlap); + const int tabOverlap = + tabOverlapNoBorder-QS60StylePrivate::pixelMetric(QStyle::PM_DefaultFrameWidth); + const QTabWidget *tab = qobject_cast<const QTabWidget *>(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<const QStyleOptionViewItemV4 *>(opt)) { + const QListWidget *listItem = qobject_cast<const QListWidget *>(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(QStyle::PM_LayoutVerticalSpacing); + //const int horizontalSpacing = QS60StylePrivate::pixelMetric(QStyle::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<const QStyleOptionMenuItem *>(opt)) { + const bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable; + const bool subMenu = menuItem->menuItemType == QStyleOptionMenuItem::SubMenu; + int indicatorWidth = checkable ? + pixelMetric(PM_ListViewIconSize, opt, widget) : + pixelMetric(PM_SmallIconSize, opt, widget); + ret = menuItem->rect; + const int verticalSpacing = + QS60StylePrivate::pixelMetric(QStyle::PM_LayoutVerticalSpacing); + + if (element == SE_ItemViewItemDecoration) { + if (menuItem->direction == Qt::RightToLeft) + ret.translate(ret.width()-indicatorWidth, 0); + ret.setWidth(indicatorWidth); + } else { + ret = menuItem->rect; + if (!menuItem->icon.isNull()) + if (menuItem->direction == Qt::LeftToRight) + ret.adjust(indicatorWidth, 0, 0, 0); + else + ret.adjust(0, 0, -indicatorWidth, 0); + + // Make room for submenu indicator + if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu){ + // submenu indicator is very small, so lets halve the rect + indicatorWidth = indicatorWidth >> 1; + if (menuItem->direction == Qt::LeftToRight) + ret.adjust(0,0,-indicatorWidth,0); + else + ret.adjust(indicatorWidth,0,0,0); + } + } + } + break; + case SE_ItemViewItemCheckIndicator: + { + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) { + const QListWidget *listItem = qobject_cast<const QListWidget *>(widget); + + const bool singleSelection = listItem && + (listItem->selectionMode() == QAbstractItemView::SingleSelection || + listItem->selectionMode() == QAbstractItemView::NoSelection); + const bool checkBoxOnly = (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator) && + listItem && + singleSelection; + + // Selection check mark rect. + const int indicatorWidth = QS60StylePrivate::pixelMetric(QStyle::PM_IndicatorWidth); + const int indicatorHeight = QS60StylePrivate::pixelMetric(QStyle::PM_IndicatorHeight); + const int spacing = QS60StylePrivate::pixelMetric(QStyle::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 + 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); + } + } + } + break; + case SE_HeaderLabel: + ret = QCommonStyle::subElementRect(element, opt, widget); + if (qstyleoption_cast<const QStyleOptionHeader *>(opt)) { + // Subtract area needed for line + if (opt->state & State_Horizontal) + ret.setHeight(ret.height() - QS60StylePrivate::pixelMetric(PM_Custom_BoldLineWidth)); + else + ret.setWidth(ret.width() - QS60StylePrivate::pixelMetric(PM_Custom_ThinLineWidth)); + } + ret = visualRect(opt->direction, opt->rect, ret); + break; + case SE_FrameContents: + if (QS60StylePrivate::isTouchSupported()) { + return QCommonStyle::subElementRect(element, opt, widget); + } else if (const QStyleOptionFrameV2 *f = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt)) { + // We shrink the frame contents by focusFrameWidth, so that we can draw the frame around it in keypad navigation mode. + const int frameWidth = QS60StylePrivate::focusRectPenWidth(); + ret = opt->rect.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth); + ret = visualRect(opt->direction, opt->rect, ret); + } + break; + default: + ret = QCommonStyle::subElementRect(element, opt, widget); + } + return ret; +} + +void QS60Style::setStyleProperty(const char *name, const QVariant &value) +{ + Q_D(QS60Style); + d->setStyleProperty_specific(name, value); +} + +QVariant QS60Style::styleProperty(const char *name) const +{ + Q_D(const QS60Style); + return d->styleProperty_specific(name); +} + +QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon, + const QStyleOption * option, const QWidget * widget) const +{ + const int iconDimension = QS60StylePrivate::pixelMetric(QStyle::PM_ToolBarIconSize); + const QRect iconSize = (!option) ? QRect(0,0,iconDimension,iconDimension) : option->rect; + QS60StyleEnums::SkinParts part; + QS60StylePrivate::SkinElementFlags adjustedFlags; + if (option) + adjustedFlags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled; + + switch(standardIcon) + { + case QStyle::SP_MessageBoxWarning: + part = QS60StyleEnums::SP_QgnNoteWarning; + break; + case QStyle::SP_MessageBoxInformation: + part = QS60StyleEnums::SP_QgnNoteInfo; + break; + case QStyle::SP_MessageBoxCritical: + part = QS60StyleEnums::SP_QgnNoteError; + break; + case QStyle::SP_MessageBoxQuestion: + part = QS60StyleEnums::SP_QgnNoteQuery; + break; + case QStyle::SP_ArrowRight: + part = QS60StyleEnums::SP_QgnIndiNaviArrowRight; + break; + case QStyle::SP_ArrowLeft: + part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft; + break; + case QStyle::SP_ArrowUp: + part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft; + adjustedFlags |= QS60StylePrivate::SF_PointEast; + break; + case QStyle::SP_ArrowDown: + part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft; + adjustedFlags |= QS60StylePrivate::SF_PointWest; + break; + case QStyle::SP_ArrowBack: + if (QApplication::layoutDirection() == Qt::RightToLeft) + return QS60Style::standardIcon(SP_ArrowRight, option, widget); + return QS60Style::standardIcon(SP_ArrowLeft, option, widget); + case QStyle::SP_ArrowForward: + if (QApplication::layoutDirection() == Qt::RightToLeft) + return QS60Style::standardIcon(SP_ArrowLeft, option, widget); + return QS60Style::standardIcon(SP_ArrowRight, option, widget); + case QStyle::SP_ComputerIcon: + part = QS60StyleEnums::SP_QgnPropPhoneMemcLarge; + break; + case QStyle::SP_DirClosedIcon: + part = QS60StyleEnums::SP_QgnPropFolderSmall; + break; + case QStyle::SP_DirOpenIcon: + part = QS60StyleEnums::SP_QgnPropFolderCurrent; + break; + case QStyle::SP_DirIcon: + part = QS60StyleEnums::SP_QgnPropFolderSmall; + break; + case QStyle::SP_FileDialogNewFolder: + part = QS60StyleEnums::SP_QgnPropFolderSmallNew; + break; + case QStyle::SP_FileIcon: + part = QS60StyleEnums::SP_QgnPropFileSmall; + break; + case QStyle::SP_TrashIcon: + part = QS60StyleEnums::SP_QgnNoteErased; + break; + default: + return QCommonStyle::standardIconImplementation(standardIcon, option, widget); + } + const QS60StylePrivate::SkinElementFlags flags = adjustedFlags; + const QPixmap cachedPixMap(QS60StylePrivate::cachedPart(part, iconSize.size(), flags)); + return cachedPixMap.isNull() ? + QCommonStyle::standardIconImplementation(standardIcon, option, widget) : QIcon(cachedPixMap); +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_S60 || QT_PLUGIN diff --git a/src/gui/styles/qs60style.h b/src/gui/styles/qs60style.h new file mode 100644 index 0000000000..253eb617be --- /dev/null +++ b/src/gui/styles/qs60style.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef QS60STYLE_H +#define QS60STYLE_H + +#include <QtGui/qcommonstyle.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_STYLE_S60) + +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; + void drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) 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 setStyleProperty(const char *name, const QVariant &value); + QVariant styleProperty(const char *name) const; + +#ifndef Q_WS_S60 + static QStringList partKeys(); + static QStringList colorListKeys(); + void setS60Theme(const QHash<QString, QPicture> &parts, + const QHash<QPair<QString , int>, QColor> &colors); +#endif // !Q_WS_S60 + +#ifdef Q_WS_S60 +public slots: + void handleDynamicLayoutVariantSwitch(); + void handleSkinChange(); +#endif // Q_WS_S60 + +protected slots: + QIcon standardIconImplementation( + StandardPixmap standardIcon, const QStyleOption * option = 0, const QWidget * widget = 0 ) const; + +private: + Q_DISABLE_COPY(QS60Style) + friend class QStyleFactory; +}; + +#endif // QT_NO_STYLE_S60 + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QS60STYLE_H diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h new file mode 100644 index 0000000000..c11d89ab8f --- /dev/null +++ b/src/gui/styles/qs60style_p.h @@ -0,0 +1,368 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef QS60STYLE_P_H +#define QS60STYLE_P_H + +#include "qs60style.h" +#include "qcommonstyle_p.h" +#include <QtCore/qhash.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. +// + +QT_BEGIN_NAMESPACE + +const int MAX_NON_CUSTOM_PIXELMETRICS = 92; +const int CUSTOMVALUESCOUNT = 4; +enum { + PM_Custom_FrameCornerWidth = MAX_NON_CUSTOM_PIXELMETRICS, + PM_Custom_FrameCornerHeight, + PM_Custom_BoldLineWidth, + PM_Custom_ThinLineWidth + }; +const int MAX_PIXELMETRICS = MAX_NON_CUSTOM_PIXELMETRICS + CUSTOMVALUESCOUNT; + +typedef struct { + unsigned short height; + unsigned short width; + int major_version; + int minor_version; + bool mirroring; // TODO: (nice to have) Use Qt::LayoutDirection + QString 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 look-and-feel font categories + enum FontCategories { + FC_Undefined, + FC_Primary, + FC_Secondary, + FC_Title, + FC_PrimarySmall, + FC_Digital + }; + + enum SkinParts { + SP_QgnGrafBarFrameCenter, + SP_QgnGrafBarFrameSideL, + SP_QgnGrafBarFrameSideR, + SP_QgnGrafBarProgress, + SP_QgnGrafTabActiveL, + SP_QgnGrafTabActiveM, + SP_QgnGrafTabActiveR, + SP_QgnGrafTabPassiveL, + SP_QgnGrafTabPassiveM, + SP_QgnGrafTabPassiveR, + SP_QgnIndiCheckboxOff, + SP_QgnIndiCheckboxOn, + SP_QgnIndiMarkedAdd, + SP_QgnIndiNaviArrowLeft, + SP_QgnIndiNaviArrowRight, + SP_QgnIndiRadiobuttOff, + SP_QgnIndiRadiobuttOn, + SP_QgnIndiSliderEdit, + 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_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_QsnFrCaleGSideT, + SP_QsnFrCaleGSideB, + SP_QsnFrCaleGSideL, + SP_QsnFrCaleGSideR, + 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 + }; + + enum ColorLists { + CL_QsnHighlightColors, + CL_QsnIconColors, + CL_QsnLineColors, + CL_QsnOtherColors, + CL_QsnParentColors, + CL_QsnTextColors + }; +}; + +// 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_TabBarTabEastActive, + SE_TabBarTabEastInactive, + SE_TabBarTabNorthActive, + SE_TabBarTabNorthInactive, + SE_TabBarTabSouthActive, + SE_TabBarTabSouthInactive, + SE_TabBarTabWestActive, + SE_TabBarTabWestInactive, + SE_ListHighlight, + SE_OptionsMenu, + SE_SettingsList, + SE_TableItem, + SE_TableHeaderItem, + SE_ToolTip //own graphic available on 3.2+ releases + }; + + enum SkinFrameElements { + SF_ButtonNormal, + SF_ButtonPressed, + SF_FrameLineEdit, + SF_ListHighlight, + SF_OptionsMenu, + SF_SettingsList, + SF_TableItem, + SF_TableHeaderItem, + SF_ToolTip + }; + + 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, + }; + 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); + // sets style property + void setStyleProperty(const char *name, const QVariant &value); + // sets specific style property + void setStyleProperty_specific(const char *name, const QVariant &value); + // gets style property + QVariant styleProperty(const char *name) const; + // gets specific style property + QVariant styleProperty_specific(const char *name) const; + // 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); + static QColor lighterColor(const QColor &baseColor); + static bool isSkinnableDialog(const QWidget *widget); + // gets layout + static const QHash<QStyle::PixelMetric, int> &s60StyleLayout(); + + QFont s60Font(QS60StyleEnums::FontCategories fontCategory, + int pointSize = -1) const; + void clearCaches(); + static QPixmap backgroundTexture(); + + static bool isTouchSupported(); + // calculates average color based on button skin graphics (minus borders). + QColor colorFromFrameGraphics(QS60StylePrivate::SkinFrameElements frame) const; + void setThemePalette(QWidget *widget) const; + + static int focusRectPenWidth(); + +#if defined(QT_S60STYLE_LAYOUTDATA_SIMULATED) + 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; +#endif // defined(QT_S60STYLE_LAYOUTDATA_SIMULATED) + + mutable QHash<QPair<QS60StyleEnums::FontCategories , int>, QFont> m_mappedFontsCache; + mutable QHash<QS60StylePrivate::SkinFrameElements, QColor> m_colorCache; + + // 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); + +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 QSize partSize(QS60StyleEnums::SkinParts part, + SkinElementFlags flags = KDefaultSkinElementFlags); + static QPixmap part(QS60StyleEnums::SkinParts part, const QSize &size, + SkinElementFlags flags = KDefaultSkinElementFlags); + static QPixmap cachedPart(QS60StyleEnums::SkinParts part, const QSize &size, + SkinElementFlags flags = KDefaultSkinElementFlags); + static QPixmap cachedFrame(SkinFrameElements frame, const QSize &size, + SkinElementFlags flags = KDefaultSkinElementFlags); + + static QFont s60Font_specific(QS60StyleEnums::FontCategories fontCategory, int pointSize); + + static void refreshUI(); + + static QSize screenSize(); + + static bool m_backgroundValid; + const static SkinElementFlags KDefaultSkinElementFlags; +}; + +QT_END_NAMESPACE + +#endif // QS60STYLE_P_H diff --git a/src/gui/styles/qs60style_simulated.cpp b/src/gui/styles/qs60style_simulated.cpp new file mode 100644 index 0000000000..68f0b70fc6 --- /dev/null +++ b/src/gui/styles/qs60style_simulated.cpp @@ -0,0 +1,269 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_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" + +#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN) + +QT_BEGIN_NAMESPACE + +class QS60StyleModeSpecifics +{ +public: + static QPixmap skinnedGraphics(QS60StyleEnums::SkinParts stylepart, + const QSize &size, QS60StylePrivate::SkinElementFlags flags); + static QHash<QString, QPicture> m_partPictures; + static QHash<QPair<QString , int>, QColor> m_colors; +}; +QHash<QString, QPicture> QS60StyleModeSpecifics::m_partPictures; +QHash<QPair<QString , int>, QColor> QS60StyleModeSpecifics::m_colors; + +QS60StylePrivate::QS60StylePrivate() +{ + setCurrentLayout(0); +} + +QS60StylePrivate::~QS60StylePrivate() +{ +} + +short QS60StylePrivate::pixelMetric(int metric) +{ + Q_ASSERT(metric < MAX_PIXELMETRICS); + const short returnValue = m_pmPointer[metric]; + if (returnValue==-909) + return -1; + return returnValue; +} + +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<QString, int>(listKey, index)), + option + ); +} + +QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part, const QSize &size, + QS60StylePrivate::SkinElementFlags flags) +{ + 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<QPicture *>(&partPicture)->play(&resultPainter); + resultPainter.end(); + + QPixmap result = QPixmap::fromImage(partImage); + if (flags & SF_StateDisabled) { + // TODO: fix this + QStyleOption opt; +// opt.palette = q->standardPalette(); + 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); + + QImage result(size, QImage::Format_ARGB32); + 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 QPixmap::fromImage(result); +} + +void QS60StylePrivate::setStyleProperty_specific(const char *name, const QVariant &value) +{ + setStyleProperty(name, value); +} + +QVariant QS60StylePrivate::styleProperty_specific(const char *name) const +{ + return styleProperty(name); +} + +bool QS60StylePrivate::isTouchSupported() +{ +#ifdef QT_KEYPAD_NAVIGATION + return !QApplication::keypadNavigationEnabled(); +#else + return true; +#endif +} + +QFont QS60StylePrivate::s60Font_specific(QS60StyleEnums::FontCategories fontCategory, int pointSize) +{ + QFont result; + 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; +} + +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<QString, QPicture> &parts, + const QHash<QPair<QString , int>, QColor> &colors) +{ + QS60StyleModeSpecifics::m_partPictures = parts; + QS60StyleModeSpecifics::m_colors = colors; +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_S60 || QT_PLUGIN diff --git a/src/gui/styles/qs60style_symbian.cpp b/src/gui/styles/qs60style_symbian.cpp new file mode 100644 index 0000000000..a1e7800cb3 --- /dev/null +++ b/src/gui/styles/qs60style_symbian.cpp @@ -0,0 +1,980 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qs60style.h" +#include "qs60style_p.h" +#include "qpainter.h" +#include "qstyleoption.h" +#include "qstyle.h" +#include "private/qwindowsurface_s60_p.h" +#include "private/qt_s60_p.h" +#include "private/qcore_symbian_p.h" +#include "qapplication.h" + +#include <w32std.h> +#include <aknsconstants.h> +#include <aknconsts.h> +#include <aknsitemid.h> +#include <aknsutils.h> +#include <aknsdrawutils.h> +#include <aknsskininstance.h> +#include <aknsbasicbackgroundcontrolcontext.h> +#include <avkon.mbg> +#include <AknFontAccess.h> +#include <AknLayoutFont.h> +#include <aknutils.h> + +#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN) + +QT_BEGIN_NAMESPACE + +enum TDrawType { + EDrawIcon, + EDrawBackground, + ENoDraw +}; + +enum TSupportRelease { + ES60_3_1 = 0x0001, + ES60_3_2 = 0x0002, + ES60_5_0 = 0x0004, + // Add all new releases here + ES60_AllReleases = ES60_3_1 | ES60_3_2 | ES60_5_0 +}; + +typedef struct { + const TAknsItemID &skinID; + TDrawType drawType; + int supportInfo; + int fallbackGraphicID; + int newMajorSkinId; + int newMinorSkinId; +} partMapEntry; + +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, QS60StylePrivate::SkinElementFlags flags); + static QColor colorValue(const TAknsItemID &colorGroup, int colorIndex); + static QPixmap fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask, QS60StylePrivate::SkinElementFlags flags, QImage::Format format); + +private: + static QPixmap createSkinnedGraphicsL(QS60StyleEnums::SkinParts part, + const QSize &size, QS60StylePrivate::SkinElementFlags flags); + static QPixmap createSkinnedGraphicsL(QS60StylePrivate::SkinFrameElements frameElement, const QSize &size, QS60StylePrivate::SkinElementFlags flags); + static QPixmap colorSkinnedGraphicsL(const QS60StyleEnums::SkinParts &stylepart, + const QSize &size, QS60StylePrivate::SkinElementFlags flags); + static void frameIdAndCenterId(QS60StylePrivate::SkinFrameElements frameElement, TAknsItemID &frameId, TAknsItemID ¢erId); + static void checkAndUnCompressBitmapL(CFbsBitmap*& aOriginalBitmap); + static void checkAndUnCompressBitmap(CFbsBitmap*& aOriginalBitmap); + static void unCompressBitmapL(const TRect& aTrgRect, CFbsBitmap* aTrgBitmap, CFbsBitmap* aSrcBitmap); + static void colorGroupAndIndex(QS60StyleEnums::SkinParts skinID, + TAknsItemID &colorGroup, int colorIndex); + static bool checkSupport(const int supportedRelease); + static TAknsItemID checkAndUpdateReleaseSpecificGraphics(int part); + // Array to match the skin ID, fallback graphics and Qt widget graphics. + static const partMapEntry m_partMap[]; +}; + +const partMapEntry QS60StyleModeSpecifics::m_partMap[] = { + /* SP_QgnGrafBarFrameCenter */ {KAknsIIDQgnGrafBarFrameCenter, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_graf_bar_frame_center ,-1,-1}, + /* SP_QgnGrafBarFrameSideL */ {KAknsIIDQgnGrafBarFrameSideL, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_graf_bar_frame_side_l ,-1,-1}, + /* SP_QgnGrafBarFrameSideR */ {KAknsIIDQgnGrafBarFrameSideR, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_graf_bar_frame_side_r ,-1,-1}, + /* SP_QgnGrafBarProgress */ {KAknsIIDQgnGrafBarProgress, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_graf_bar_progress ,-1,-1}, + /* SP_QgnGrafTabActiveL */ {KAknsIIDQgnGrafTabActiveL, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_graf_tab_active_l ,-1,-1}, + /* SP_QgnGrafTabActiveM */ {KAknsIIDQgnGrafTabActiveM, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_graf_tab_active_m ,-1,-1}, + /* SP_QgnGrafTabActiveR */ {KAknsIIDQgnGrafTabActiveR, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_graf_tab_active_r ,-1,-1}, + /* SP_QgnGrafTabPassiveL */ {KAknsIIDQgnGrafTabPassiveL, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_graf_tab_passive_l ,-1,-1}, + /* SP_QgnGrafTabPassiveM */ {KAknsIIDQgnGrafTabPassiveM, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_graf_tab_passive_m ,-1,-1}, + /* SP_QgnGrafTabPassiveR */ {KAknsIIDQgnGrafTabPassiveR, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_graf_tab_passive_r ,-1,-1}, + /* SP_QgnIndiCheckboxOff */ {KAknsIIDQgnIndiCheckboxOff, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_indi_checkbox_off ,-1,-1}, + /* SP_QgnIndiCheckboxOn */ {KAknsIIDQgnIndiCheckboxOn, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_indi_checkbox_on ,-1,-1}, + /* SP_QgnIndiMarkedAdd */ {KAknsIIDQgnIndiMarkedAdd, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_indi_marked_add ,-1,-1}, + /* SP_QgnIndiNaviArrowLeft */ {KAknsIIDQgnGrafScrollArrowLeft, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_indi_navi_arrow_left ,-1,-1}, + /* SP_QgnIndiNaviArrowRight */ {KAknsIIDQgnGrafScrollArrowRight, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_indi_navi_arrow_right ,-1,-1}, + /* SP_QgnIndiRadiobuttOff */ {KAknsIIDQgnIndiRadiobuttOff, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_indi_radiobutt_off ,-1,-1}, + /* SP_QgnIndiRadiobuttOn */ {KAknsIIDQgnIndiRadiobuttOn, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_indi_radiobutt_on ,-1,-1}, + /* SP_QgnIndiSliderEdit */ {KAknsIIDQgnIndiSliderEdit, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_indi_slider_edit ,-1,-1}, + /* SP_QgnIndiSubMenu */ {KAknsIIDQgnIndiSubmenu, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_indi_submenu ,-1,-1}, + /* SP_QgnNoteErased */ {KAknsIIDQgnNoteErased, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_note_erased ,-1,-1}, + /* SP_QgnNoteError */ {KAknsIIDQgnNoteError, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_note_error ,-1,-1}, + /* SP_QgnNoteInfo */ {KAknsIIDQgnNoteInfo, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_note_info ,-1,-1}, + /* SP_QgnNoteOk */ {KAknsIIDQgnNoteOk, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_note_ok ,-1,-1}, + /* SP_QgnNoteQuery */ {KAknsIIDQgnNoteQuery, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_note_query ,-1,-1}, + /* SP_QgnNoteWarning */ {KAknsIIDQgnNoteWarning, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_note_warning ,-1,-1}, + /* SP_QgnPropFileSmall */ {KAknsIIDQgnPropFileSmall, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_prop_file_small ,-1,-1}, + /* SP_QgnPropFolderCurrent */ {KAknsIIDQgnPropFolderCurrent, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_prop_folder_current ,-1,-1}, + /* SP_QgnPropFolderSmall */ {KAknsIIDQgnPropFolderSmall, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_prop_folder_small ,-1,-1}, + /* SP_QgnPropFolderSmallNew */ {KAknsIIDQgnPropFolderSmallNew, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_prop_folder_small_new ,-1,-1}, + /* SP_QgnPropPhoneMemcLarge */ {KAknsIIDQgnPropPhoneMemcLarge, EDrawIcon, ES60_AllReleases, EMbmAvkonQgn_prop_phone_memc_large ,-1,-1}, + +// No fallback graphics for screen elements (it is guaranteed that the root skin contains these). + /* SP_QsnBgScreen */ {KAknsIIDQsnBgScreen, EDrawBackground, ES60_AllReleases, -1,-1,-1}, + + /* SP_QsnCpScrollBgBottom */ {KAknsIIDQsnCpScrollBgBottom, EDrawIcon, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnCpScrollBgMiddle */ {KAknsIIDQsnCpScrollBgMiddle, EDrawIcon, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnCpScrollBgTop */ {KAknsIIDQsnCpScrollBgTop, EDrawIcon, ES60_AllReleases, -1,-1,-1}, + + /* SP_QsnCpScrollHandleBottom */ {KAknsIIDQsnCpScrollHandleBottom, EDrawIcon, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnCpScrollHandleMiddle */ {KAknsIIDQsnCpScrollHandleMiddle, EDrawIcon, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnCpScrollHandleTop */ {KAknsIIDQsnCpScrollHandleTop, EDrawIcon, ES60_AllReleases, -1,-1,-1}, + + /* SP_QsnFrButtonTbCornerTl */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbCornerTr */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbCornerBl */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbCornerBr */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbSideT */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbSideB */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbSideL */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbSideR */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbCenter */ {KAknsIIDQsnFrButtonTbCenter, ENoDraw, ES60_AllReleases, -1,-1,-1}, + + /* SP_QsnFrButtonTbCornerTlPressed */{KAknsIIDQsnFrButtonTbCornerTlPressed, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbCornerTrPressed */{KAknsIIDQsnFrButtonTbCornerTrPressed, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbCornerBlPressed */{KAknsIIDQsnFrButtonTbCornerBlPressed, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbCornerBrPressed */{KAknsIIDQsnFrButtonTbCornerBrPressed, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbSideTPressed */ {KAknsIIDQsnFrButtonTbSideTPressed, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbSideBPressed */ {KAknsIIDQsnFrButtonTbSideBPressed, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbSideLPressed */ {KAknsIIDQsnFrButtonTbSideLPressed, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbSideRPressed */ {KAknsIIDQsnFrButtonTbSideRPressed, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrButtonTbCenterPressed */ {KAknsIIDQsnFrButtonTbCenterPressed, ENoDraw, ES60_AllReleases, -1,-1,-1}, + + /* SP_QsnFrCaleCornerTl */ {KAknsIIDQsnFrCaleCornerTl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleCornerTr */ {KAknsIIDQsnFrCaleCornerTr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleCornerBl */ {KAknsIIDQsnFrCaleCornerBl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleCornerBr */ {KAknsIIDQsnFrCaleCornerBr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleGSideT */ {KAknsIIDQsnFrCaleSideT, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleGSideB */ {KAknsIIDQsnFrCaleSideB, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleGSideL */ {KAknsIIDQsnFrCaleSideL, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleGSideR */ {KAknsIIDQsnFrCaleSideR, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleCenter */ {KAknsIIDQsnFrCaleCenter, ENoDraw, ES60_AllReleases, -1,-1,-1}, + + /* SP_QsnFrCaleHeadingCornerTl */ {KAknsIIDQsnFrCaleHeadingCornerTl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleHeadingCornerTr */ {KAknsIIDQsnFrCaleHeadingCornerTr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleHeadingCornerBl */ {KAknsIIDQsnFrCaleHeadingCornerBl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleHeadingCornerBr */ {KAknsIIDQsnFrCaleHeadingCornerBr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleHeadingSideT */ {KAknsIIDQsnFrCaleHeadingSideT, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleHeadingSideB */ {KAknsIIDQsnFrCaleHeadingSideB, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleHeadingSideL */ {KAknsIIDQsnFrCaleHeadingSideL, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleHeadingSideR */ {KAknsIIDQsnFrCaleHeadingSideR, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrCaleHeadingCenter */ {KAknsIIDQsnFrCaleHeadingCenter, ENoDraw, ES60_AllReleases, -1,-1,-1}, + + /* SP_QsnFrInputCornerTl */ {KAknsIIDQsnFrInputCornerTl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrInputCornerTr */ {KAknsIIDQsnFrInputCornerTr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrInputCornerBl */ {KAknsIIDQsnFrInputCornerBl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrInputCornerBr */ {KAknsIIDQsnFrInputCornerBr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrInputSideT */ {KAknsIIDQsnFrInputSideT, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrInputSideB */ {KAknsIIDQsnFrInputSideB, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrInputSideL */ {KAknsIIDQsnFrInputSideL, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrInputSideR */ {KAknsIIDQsnFrInputSideR, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrInputCenter */ {KAknsIIDQsnFrInputCenter, ENoDraw, ES60_AllReleases, -1,-1,-1}, + + /* SP_QsnFrListCornerTl */ {KAknsIIDQsnFrListCornerTl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrListCornerTr */ {KAknsIIDQsnFrListCornerTr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrListCornerBl */ {KAknsIIDQsnFrListCornerBl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrListCornerBr */ {KAknsIIDQsnFrListCornerBr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrListSideT */ {KAknsIIDQsnFrListSideT, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrListSideB */ {KAknsIIDQsnFrListSideB, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrListSideL */ {KAknsIIDQsnFrListSideL, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrListSideR */ {KAknsIIDQsnFrListSideR, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrListCenter */ {KAknsIIDQsnFrListCenter, ENoDraw, ES60_AllReleases, -1,-1,-1}, + + /* SP_QsnFrPopupCornerTl */ {KAknsIIDQsnFrPopupCornerTl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrPopupCornerTr */ {KAknsIIDQsnFrPopupCornerTr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrPopupCornerBl */ {KAknsIIDQsnFrPopupCornerBl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrPopupCornerBr */ {KAknsIIDQsnFrPopupCornerBr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrPopupSideT */ {KAknsIIDQsnFrPopupSideT, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrPopupSideB */ {KAknsIIDQsnFrPopupSideB, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrPopupSideL */ {KAknsIIDQsnFrPopupSideL, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrPopupSideR */ {KAknsIIDQsnFrPopupSideR, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrPopupCenter */ {KAknsIIDQsnFrPopupCenter, ENoDraw, ES60_AllReleases, -1,-1,-1}, + + + /* SP_QsnFrPopupPreviewCornerTl */ {KAknsIIDQsnFrPopupCornerTl, ENoDraw, ES60_3_1, -1, EAknsMajorSkin, 0x19c5}, + /* SP_QsnFrPopupPreviewCornerTr */ {KAknsIIDQsnFrPopupCornerTr, ENoDraw, ES60_3_1, -1, EAknsMajorSkin, 0x19c6}, + /* SP_QsnFrPopupPreviewCornerBl */ {KAknsIIDQsnFrPopupCornerBl, ENoDraw, ES60_3_1, -1, EAknsMajorSkin, 0x19c3}, + /* SP_QsnFrPopupPreviewCornerBr */ {KAknsIIDQsnFrPopupCornerBr, ENoDraw, ES60_3_1, -1, EAknsMajorSkin, 0x19c4}, + /* SP_QsnFrPopupPreviewSideT */ {KAknsIIDQsnFrPopupSideT, ENoDraw, ES60_3_1, -1, EAknsMajorSkin, 0x19ca}, + /* SP_QsnFrPopupPreviewSideB */ {KAknsIIDQsnFrPopupSideB, ENoDraw, ES60_3_1, -1, EAknsMajorSkin, 0x19c7}, + /* SP_QsnFrPopupPreviewSideL */ {KAknsIIDQsnFrPopupSideL, ENoDraw, ES60_3_1, -1, EAknsMajorSkin, 0x19c8}, + /* SP_QsnFrPopupPreviewSideR */ {KAknsIIDQsnFrPopupSideR, ENoDraw, ES60_3_1, -1, EAknsMajorSkin, 0x19c9}, + /* SP_QsnFrPopupPreviewCenter */ {KAknsIIDQsnFrPopupCenter, ENoDraw, ES60_3_1, -1, EAknsMajorSkin, 0x19c2}, + + /* SP_QsnFrSetOptCornerTl */ {KAknsIIDQsnFrSetOptCornerTl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrSetOptCornerTr */ {KAknsIIDQsnFrSetOptCornerTr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrSetOptCornerBl */ {KAknsIIDQsnFrSetOptCornerBl, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrSetOptCornerBr */ {KAknsIIDQsnFrSetOptCornerBr, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrSetOptSideT */ {KAknsIIDQsnFrSetOptSideT, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrSetOptSideB */ {KAknsIIDQsnFrSetOptSideB, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrSetOptSideL */ {KAknsIIDQsnFrSetOptSideL, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrSetOptSideR */ {KAknsIIDQsnFrSetOptSideR, ENoDraw, ES60_AllReleases, -1,-1,-1}, + /* SP_QsnFrSetOptCenter */ {KAknsIIDQsnFrSetOptCenter, ENoDraw, ES60_AllReleases, -1,-1,-1}, +}; + +QPixmap QS60StyleModeSpecifics::skinnedGraphics( + QS60StyleEnums::SkinParts stylepart, const QSize &size, + QS60StylePrivate::SkinElementFlags flags) +{ + QPixmap themedImage; + TRAPD( error, { + const QPixmap skinnedImage = createSkinnedGraphicsL(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, { + const QPixmap skinnedImage = createSkinnedGraphicsL(frame, size, flags); + themedImage = skinnedImage; + }); + if (error) + return themedImage = QPixmap(); + return themedImage; +} + +QPixmap QS60StyleModeSpecifics::colorSkinnedGraphics( + const QS60StyleEnums::SkinParts &stylepart, + const QSize &size, QS60StylePrivate::SkinElementFlags flags) +{ + QPixmap colorGraphics; + TRAPD(error, colorGraphics = colorSkinnedGraphicsL(stylepart, size, flags)); + return error ? QPixmap() : colorGraphics; +} + +QPixmap QS60StyleModeSpecifics::colorSkinnedGraphicsL( + const QS60StyleEnums::SkinParts &stylepart, + const QSize &size, QS60StylePrivate::SkinElementFlags flags) +{ + const int stylepartIndex = (int)stylepart; + const TAknsItemID skinId = m_partMap[stylepartIndex].skinID; + const TInt fallbackGraphicID = m_partMap[stylepartIndex].fallbackGraphicID; + TAknsItemID colorGroup = KAknsIIDQsnIconColors; + int colorIndex = 0; + colorGroupAndIndex(stylepart, colorGroup, colorIndex); + + 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, KAvkonBitmapFile, fallbackGraphicID , fallbackGraphicsMaskID, KRgbBlack); + User::LeaveIfError(AknIconUtils::SetSize(icon, targetSize, EAspectRatioNotPreserved)); + User::LeaveIfError(AknIconUtils::SetSize(iconMask, targetSize, EAspectRatioNotPreserved)); + QPixmap result = fromFbsBitmap(icon, iconMask, flags, qt_TDisplayMode2Format(icon->DisplayMode())); + CleanupStack::PopAndDestroy(2); //icon, iconMask + 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()); +} + +QPixmap QS60StyleModeSpecifics::fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask, QS60StylePrivate::SkinElementFlags flags, QImage::Format format) +{ + Q_ASSERT(icon); + const TSize iconSize = icon->SizeInPixels(); + const int iconBytesPerLine = CFbsBitmap::ScanLineLength(iconSize.iWidth, icon->DisplayMode()); + const int iconBytesCount = iconBytesPerLine * iconSize.iHeight; + + QImage iconImage(qt_TSize2QSize(iconSize), format); + if (iconImage.isNull()) + return QPixmap(); + + checkAndUnCompressBitmap(icon); + if (!icon) //checkAndUnCompressBitmap might set icon to NULL + return QPixmap(); + + icon->LockHeap(); + const uchar *const iconBytes = (uchar*)icon->DataAddress(); + // The icon data needs to be copied, since the color format will be + // automatically converted to Format_ARGB32 when setAlphaChannel is called. + memcpy(iconImage.bits(), iconBytes, iconBytesCount); + icon->UnlockHeap(); + if (mask) { + checkAndUnCompressBitmap(mask); + if (mask) { //checkAndUnCompressBitmap might set mask to NULL + const TSize maskSize = icon->SizeInPixels(); + const int maskBytesPerLine = CFbsBitmap::ScanLineLength(maskSize.iWidth, mask->DisplayMode()); + mask->LockHeap(); + const uchar *const maskBytes = (uchar *)mask->DataAddress(); + // Since no other bitmap should be locked, we can just "borrow" the mask data for setAlphaChannel + const QImage maskImage(maskBytes, maskSize.iWidth, maskSize.iHeight, maskBytesPerLine, QImage::Format_Indexed8); + if (!maskImage.isNull()) + iconImage.setAlphaChannel(maskImage); + mask->UnlockHeap(); + } + } + + 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); + + return QPixmap::fromImage(iconImage); +} + +QPixmap QS60StylePrivate::backgroundTexture() +{ + static QPixmap result; + // Poor mans caching. + Making sure that there is always only one background image in memory at a time + +/* + TODO: 1) Hold the background QPixmap as pointer in a static class member. + Also add a deleteBackground() function and call that in ~QS60StylePrivate() + 2) Don't cache the background at all as soon as we have native pixmap support +*/ + + if (!m_backgroundValid) { + result = QPixmap(); + result = part(QS60StyleEnums::SP_QsnBgScreen, + QSize(S60->screenWidthInPixels, S60->screenHeightInPixels), SkinElementFlags()); + m_backgroundValid = true; + } + return result; +} + +bool QS60StylePrivate::isTouchSupported() +{ + return bool(AknLayoutUtils::PenEnabled()); +} + +void qt_s60_fill_background(QPainter *painter, const QRegion &rgn, const QPoint &offset) +{ + const QPixmap backgroundTexture(QS60StylePrivate::backgroundTexture()); + const QPaintDevice *target = painter->device(); + if (target->devType() == QInternal::Widget) { + const QWidget *widget = static_cast<const QWidget *>(target); + const CCoeControl *control = widget->effectiveWinId(); + const TPoint globalPos = control ? control->PositionRelativeToScreen() : TPoint(0,0); + const QRegion translated = rgn.translated(offset); + const QVector<QRect> &rects = translated.rects(); + for (int i = 0; i < rects.size(); ++i) { + const QRect rect(rects.at(i)); + painter->drawPixmap(rect.topLeft(), backgroundTexture, + rect.translated(globalPos.iX, globalPos.iY)); + } + } +} + +QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsL( + QS60StyleEnums::SkinParts part, + const QSize &size, QS60StylePrivate::SkinElementFlags flags) +{ + if (!size.isValid()) + return QPixmap(); + + // Check release support and change part, if necessary. + const TAknsItemID skinId = checkAndUpdateReleaseSpecificGraphics((int)part); + const int stylepartIndex = (int)part; + const TDrawType drawType = m_partMap[stylepartIndex].drawType; + Q_ASSERT(drawType != ENoDraw); + const TInt fallbackGraphicID = m_partMap[stylepartIndex].fallbackGraphicID; + const bool rotatedBy90or270 = + (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest)); + TSize targetSize = + rotatedBy90or270 ? TSize(size.height(), size.width()) : qt_QSize2TSize(size); + + MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + + QPixmap result; + + switch (drawType) { + case EDrawIcon: + { + CFbsBitmap *icon = 0; + CFbsBitmap *iconMask = 0; + const TInt fallbackGraphicsMaskID = + fallbackGraphicID == KErrNotFound?KErrNotFound:fallbackGraphicID+1; //masks are auto-generated as next in mif files +// QS60WindowSurface::unlockBitmapHeap(); + AknsUtils::CreateIconLC(skinInstance, skinId, icon, iconMask, KAvkonBitmapFile, fallbackGraphicID , fallbackGraphicsMaskID); + User::LeaveIfError(AknIconUtils::SetSize(icon, targetSize, EAspectRatioNotPreserved)); + User::LeaveIfError(AknIconUtils::SetSize(iconMask, targetSize, EAspectRatioNotPreserved)); + result = fromFbsBitmap(icon, iconMask, flags, qt_TDisplayMode2Format(icon->DisplayMode())); + CleanupStack::PopAndDestroy(2); // iconMask, icon +// QS60WindowSurface::lockBitmapHeap(); + break; + } + case EDrawBackground: + { +// QS60WindowSurface::unlockBitmapHeap(); + CFbsBitmap *background = new (ELeave) CFbsBitmap(); //offscreen + CleanupStack::PushL(background); + User::LeaveIfError(background->Create(targetSize, EColor16MA)); + + // todo: push background into CleanupStack + 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, + KAknsDrawParamDefault | KAknsDrawParamRGBOnly); + + if (drawn) + result = fromFbsBitmap(background, NULL, flags, QImage::Format_RGB32); + + CleanupStack::PopAndDestroy(4, background); //background, dev, gc, bgContext +// QS60WindowSurface::lockBitmapHeap(); + break; + } + } + + return result; // TODO: Let fromFbsBitmap return a QPixmap +} + +QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsL(QS60StylePrivate::SkinFrameElements frameElement, + const QSize &size, QS60StylePrivate::SkinElementFlags flags) +{ + if (!size.isValid()) + return QPixmap(); + + const bool rotatedBy90or270 = + (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest)); + TSize targetSize = + rotatedBy90or270 ? TSize(size.height(), size.width()) : qt_QSize2TSize(size); + + MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + + QPixmap result; + +// QS60WindowSurface::unlockBitmapHeap(); + static const bool canDoEColor16MAP = !(QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2); + static const TDisplayMode displayMode = canDoEColor16MAP ? TDisplayMode(13) : EColor16MA; // 13 = EColor16MAP + static const TInt drawParam = canDoEColor16MAP ? 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); + TRect innerRect = outerRect; + innerRect.Shrink( + QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth), + QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerHeight) + ); + + TAknsItemID frameSkinID, centerSkinID; + frameSkinID = centerSkinID = checkAndUpdateReleaseSpecificGraphics(QS60StylePrivate::m_frameElementsData[frameElement].center); + frameIdAndCenterId(frameElement, frameSkinID, centerSkinID); + const TBool drawn = AknsDrawUtils::DrawFrame( skinInstance, + *bitmapGc, outerRect, innerRect, + frameSkinID, centerSkinID, + drawParam ); + + if (canDoEColor16MAP) { + if (drawn) + result = fromFbsBitmap(frame, NULL, flags, QImage::Format_ARGB32_Premultiplied); + } else { + TDisplayMode maskDepth = EGray2; + // Query the skin item for possible frame graphics mask details. + if (skinInstance) { + CAknsMaskedBitmapItemData* skinMaskedBmp = static_cast<CAknsMaskedBitmapItemData*>( + 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); + + AknsDrawUtils::DrawFrame(skinInstance, + *maskBitGc, outerRect, innerRect, + frameSkinID, centerSkinID, + KAknsSDMAlphaOnly |KAknsDrawParamNoClearUnderImage); + result = fromFbsBitmap(frame, frameMask, flags, QImage::Format_ARGB32); + } + CleanupStack::PopAndDestroy(3, frameMask); + } + } + CleanupStack::PopAndDestroy(3, frame); //frame, bitmapDev, bitmapGc + + return result; // TODO: Let fromFbsBitmap return a QPixmap +} + +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_5_0 || QSysInfo::s60Version()==QSysInfo::SV_S60_3_2) { + centerId.Set(EAknsMajorSkin, 0x5300); + frameId.Set(EAknsMajorGeneric, 0x19c2); + } else { + centerId.Set(KAknsIIDQsnFrPopupCenter); + frameId.iMinor = centerId.iMinor - 9; + } + break; + default: + // center should be correct here + frameId.iMinor = centerId.iMinor - 9; + break; + } +} + +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)); +} + +TAknsItemID QS60StyleModeSpecifics::checkAndUpdateReleaseSpecificGraphics(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; +} + +void QS60StyleModeSpecifics::checkAndUnCompressBitmap(CFbsBitmap*& aOriginalBitmap) +{ + TRAPD(error, checkAndUnCompressBitmapL(aOriginalBitmap)); + if (error) + aOriginalBitmap = NULL; +} + +void QS60StyleModeSpecifics::checkAndUnCompressBitmapL(CFbsBitmap*& aOriginalBitmap) +{ + if (aOriginalBitmap->IsCompressedInRAM()) { + const TSize iconSize(aOriginalBitmap->SizeInPixels().iWidth, + aOriginalBitmap->SizeInPixels().iHeight); + CFbsBitmap* uncompressedBitmap = new (ELeave) CFbsBitmap(); + CleanupStack::PushL(uncompressedBitmap); + User::LeaveIfError(uncompressedBitmap->Create(iconSize, + aOriginalBitmap->DisplayMode())); + unCompressBitmapL(iconSize, uncompressedBitmap, aOriginalBitmap); + CleanupStack::Pop(uncompressedBitmap); + User::LeaveIfError(aOriginalBitmap->Duplicate( + uncompressedBitmap->Handle())); + delete uncompressedBitmap; + } +} + +QFont QS60StylePrivate::s60Font_specific( + QS60StyleEnums::FontCategories fontCategory, int pointSize) +{ + enum 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, { + 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; +} + +#ifdef QT_S60STYLE_LAYOUTDATA_SIMULATED +void QS60StylePrivate::setActiveLayout() +{ + //todo: how to find layouts that are of same size (QVGA1 vs. QVGA2) + const QSize activeScreenSize(screenSize()); + int activeLayoutIndex = 0; + const bool mirrored = !QApplication::isLeftToRight(); + const short screenHeight = (short)activeScreenSize.height(); + const short screenWidth = (short)activeScreenSize.width(); + for (int i=0; i<m_numberOfLayouts; i++) { + if (screenHeight==m_layoutHeaders[i].height && + screenWidth==m_layoutHeaders[i].width && + mirrored==m_layoutHeaders[i].mirroring) { + activeLayoutIndex = i; + break; + } + } + m_pmPointer = data[activeLayoutIndex]; +} +#endif // QT_S60STYLE_LAYOUTDATA_SIMULATED + +QS60StylePrivate::QS60StylePrivate() +{ +#ifdef QT_S60STYLE_LAYOUTDATA_SIMULATED + // No need to set active layout, if dynamic metrics API is available + setActiveLayout(); +#endif // QT_S60STYLE_LAYOUTDATA_SIMULATED +} + +QS60StylePrivate::~QS60StylePrivate() +{ + m_backgroundValid = false; +} + +short QS60StylePrivate::pixelMetric(int metric) +{ +#ifdef QT_S60STYLE_LAYOUTDATA_SIMULATED + Q_ASSERT(metric < MAX_PIXELMETRICS); + const short returnValue = m_pmPointer[metric]; + if (returnValue==-909) + return -1; + return returnValue; +#else + //todo - call the pixelmetrics API directly + return 0; +#endif // QT_S60STYLE_LAYOUTDATA_SIMULATED +} + +QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part, + const QSize &size, SkinElementFlags flags) +{ + QS60WindowSurface::unlockBitmapHeap(); + QPixmap result = (flags & SF_ColorSkinned)? + QS60StyleModeSpecifics::colorSkinnedGraphics(part, size, flags) + : QS60StyleModeSpecifics::skinnedGraphics(part, size, flags); + QS60WindowSurface::lockBitmapHeap(); + + if (flags & SF_StateDisabled) { + // TODO: fix this + QStyleOption opt; +// opt.palette = q->standardPalette(); + result = QApplication::style()->generatedIconPixmap(QIcon::Disabled, result, &opt); + } + return result; +} + +QPixmap QS60StylePrivate::frame(SkinFrameElements frame, const QSize &size, SkinElementFlags flags) +{ + QS60WindowSurface::unlockBitmapHeap(); + QPixmap result = QS60StyleModeSpecifics::skinnedGraphics(frame, size, flags); + QS60WindowSurface::lockBitmapHeap(); + + if (flags & SF_StateDisabled) { + // TODO: fix this + QStyleOption opt; +// opt.palette = q->standardPalette(); + result = QApplication::style()->generatedIconPixmap(QIcon::Disabled, result, &opt); + } + return result; +} + +void QS60StylePrivate::setStyleProperty_specific(const char *name, const QVariant &value) +{ + if (name == QLatin1String("foo")) { + // BaR + } else { + setStyleProperty(name, value); + } +} + +QVariant QS60StylePrivate::styleProperty_specific(const char *name) const +{ + if (name == QLatin1String("foo")) + return QLatin1String("Bar"); + else + return styleProperty(name); +} + +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; +} + +// If the public SDK returns compressed images, please let us also uncompress those! +void QS60StyleModeSpecifics::unCompressBitmapL(const TRect& aTrgRect, CFbsBitmap* aTrgBitmap, CFbsBitmap* aSrcBitmap) +{ + if (!aSrcBitmap) + User::Leave(KErrArgument); + if (!aTrgBitmap) + User::Leave(KErrArgument); + + // Note! aSrcBitmap->IsCompressedInRAM() is always ETrue, since this method is called only if that applies! + ASSERT(aSrcBitmap->IsCompressedInRAM()); + + TDisplayMode displayMode = aSrcBitmap->DisplayMode(); + + if (displayMode != aTrgBitmap->DisplayMode()) + User::Leave(KErrArgument); + + TSize trgSize = aTrgBitmap->SizeInPixels(); + TSize srcSize = aSrcBitmap->SizeInPixels(); + + // calculate the valid drawing area + TRect drawRect = aTrgRect; + drawRect.Intersection(TRect(TPoint(0, 0), trgSize)); + + if (drawRect.IsEmpty()) + return; + + CFbsBitmap* realSource = new (ELeave) CFbsBitmap(); + CleanupStack::PushL(realSource); + User::LeaveIfError(realSource->Create(srcSize, displayMode)); + CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(realSource); + CleanupStack::PushL(dev); + CFbsBitGc* gc = NULL; + User::LeaveIfError(dev->CreateContext(gc)); + CleanupStack::PushL(gc); + gc->BitBlt(TPoint(0, 0), aSrcBitmap); + CleanupStack::PopAndDestroy(2); // dev, gc + + // Heap lock for FBServ large chunk is only needed with large bitmaps. + if (realSource->IsLargeBitmap() || aTrgBitmap->IsLargeBitmap()) { + aTrgBitmap->LockHeapLC(ETrue); // fbsheaplock + } else { + CleanupStack::PushL((TAny*) NULL); + } + + TUint32* srcAddress = realSource->DataAddress(); + TUint32* trgAddress = aTrgBitmap->DataAddress(); + + const TInt xSkip = (srcSize.iWidth << 8) / aTrgRect.Width(); + const TInt ySkip = (srcSize.iHeight << 8) / aTrgRect.Height(); + + const TInt drawWidth = drawRect.Width(); + const TInt drawHeight = drawRect.Height(); + + TRect offsetRect(aTrgRect.iTl, drawRect.iTl); + const TInt yPosOffset = ySkip * offsetRect.Height(); + const TInt xPosOffset = xSkip * offsetRect.Width(); + + if ((displayMode == EGray256) || (displayMode == EColor256)) { + TInt srcScanLen8 = CFbsBitmap::ScanLineLength(srcSize.iWidth, + displayMode); + TInt trgScanLen8 = CFbsBitmap::ScanLineLength(trgSize.iWidth, + displayMode); + + TUint8* trgAddress8 = reinterpret_cast<TUint8*> (trgAddress); + + TInt yPos = yPosOffset; + // skip left and top margins in the beginning + trgAddress8 += trgScanLen8 * drawRect.iTl.iY + drawRect.iTl.iX; + + for (TInt y = 0; y < drawHeight; y++) { + TUint8* srcAddress8 = reinterpret_cast<TUint8*> (srcAddress) + + (srcScanLen8 * (yPos >> 8)); + + TInt xPos = xPosOffset; + for (TInt x = 0; x < drawWidth; x++) { + *(trgAddress8++) = srcAddress8[xPos >> 8]; + xPos += xSkip; + } + + yPos += ySkip; + + trgAddress8 += trgScanLen8 - drawWidth; + } + } else if (displayMode == EColor4K || displayMode == EColor64K) { + TInt srcScanLen16 = CFbsBitmap::ScanLineLength(srcSize.iWidth, + displayMode) >>1; + TInt trgScanLen16 = CFbsBitmap::ScanLineLength(trgSize.iWidth, + displayMode) >>1; + + TUint16* trgAddress16 = reinterpret_cast<TUint16*> (trgAddress); + + TInt yPos = yPosOffset; + // skip left and top margins in the beginning + trgAddress16 += trgScanLen16 * drawRect.iTl.iY + drawRect.iTl.iX; + + for (TInt y = 0; y < drawHeight; y++) { + TUint16* srcAddress16 = reinterpret_cast<TUint16*> (srcAddress) + + (srcScanLen16 * (yPos >> 8)); + + TInt xPos = xPosOffset; + for (TInt x = 0; x < drawWidth; x++) { + *(trgAddress16++) = srcAddress16[xPos >> 8]; + xPos += xSkip; + } + + yPos += ySkip; + + trgAddress16 += trgScanLen16 - drawWidth; + } + } else if (displayMode == EColor16MU || displayMode == EColor16MA) { + TInt srcScanLen32 = CFbsBitmap::ScanLineLength(srcSize.iWidth, + displayMode) >>2; + TInt trgScanLen32 = CFbsBitmap::ScanLineLength(trgSize.iWidth, + displayMode) >>2; + + TUint32* trgAddress32 = reinterpret_cast<TUint32*> (trgAddress); + + TInt yPos = yPosOffset; + // skip left and top margins in the beginning + trgAddress32 += trgScanLen32 * drawRect.iTl.iY + drawRect.iTl.iX; + + for (TInt y = 0; y < drawHeight; y++) { + TUint32* srcAddress32 = reinterpret_cast<TUint32*> (srcAddress) + + (srcScanLen32 * (yPos >> 8)); + + TInt xPos = xPosOffset; + for (TInt x = 0; x < drawWidth; x++) { + *(trgAddress32++) = srcAddress32[xPos >> 8]; + xPos += xSkip; + } + + yPos += ySkip; + + trgAddress32 += trgScanLen32 - drawWidth; + } + } else { User::Leave(KErrUnknown);} + + CleanupStack::PopAndDestroy(2); // fbsheaplock, realSource +} + +QSize QS60StylePrivate::screenSize() +{ + TSize mySize = QS60Data::screenDevice()->SizeInPixels(); + return QSize(mySize.iWidth, mySize.iHeight); +} + +void QS60StyleModeSpecifics::colorGroupAndIndex( + QS60StyleEnums::SkinParts skinID, TAknsItemID &colorGroup, int colorIndex) +{ + switch(skinID) { + case QS60StyleEnums::SP_QgnIndiRadiobuttOff: + case QS60StyleEnums::SP_QgnIndiRadiobuttOn: + case QS60StyleEnums::SP_QgnIndiCheckboxOff: + case QS60StyleEnums::SP_QgnIndiCheckboxOn: + colorGroup = KAknsIIDQsnIconColors; + colorIndex = EAknsCIQsnIconColorsCG1; + break; + default: + break; + } +} + +void QS60Style::handleDynamicLayoutVariantSwitch() +{ + Q_D(QS60Style); + d->clearCaches(); +#ifdef QT_S60STYLE_LAYOUTDATA_SIMULATED + d->setActiveLayout(); +#endif // QT_S60STYLE_LAYOUTDATA_SIMULATED + d->refreshUI(); + foreach (QWidget *widget, QApplication::allWidgets()) + d->setThemePalette(widget); +} + +void QS60Style::handleSkinChange() +{ + Q_D(QS60Style); + d->clearCaches(); + foreach (QWidget *topLevelWidget, QApplication::allWidgets()){ + d->setThemePalette(topLevelWidget); + topLevelWidget->update(); + } +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_S60 || QT_PLUGIN diff --git a/src/gui/styles/qstyle.cpp b/src/gui/styles/qstyle.cpp new file mode 100644 index 0000000000..982f48f942 --- /dev/null +++ b/src/gui/styles/qstyle.cpp @@ -0,0 +1,2445 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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" +#ifndef QT_NO_DEBUG +#include "qdebug.h" +#endif + +#ifdef Q_WS_X11 +#include <qx11info_x11.h> +#endif + +#include <limits.h> + +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 + + If you want to design a custom look and feel for your application, + the first step is to pick one of the styles provided with Qt to + build your custom style from. The choice will depend on which + existing style resembles your style the most. The most general + class that you can use as base is QCommonStyle (and 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 call 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 style available for use in other + applications, some of which may not be yours and are 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}, + {Implementing Styles and Style Aware Widgets}, QStyledItemDelegate +*/ + +/*! + Constructs a style object. +*/ +QStyle::QStyle() + : QObject(*new QStylePrivate) +{ +} + + +/*! + \internal + + Constructs a style object. +*/ +QStyle::QStyle(QStylePrivate &dd) + : QObject(dd) +{ +} + +/*! + 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 do provide a back-door through which the appearance + of a widget can be changed, but with Qt 4.0's style engine there + is rarely necessary to implement this function; reimplement the + 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 && 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 (styleHint(SH_DitherDisabledText)) { + painter->drawText(rect, alignment, text); + painter->fillRect(painter->boundingRect(rect, alignment, text), QBrush(painter->background().color(), Qt::Dense5Pattern)); + return; + } else if (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 that 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. + + \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 QWorkspace. + \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 + + \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 slider 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::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. + + \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. + + Note that currently, the \a returnData and \a widget parameters + are not used; they are provided for future enhancement. In + addition, the \a option parameter is used only in case of the + SH_ComboBox_Popup, SH_ComboBox_LayoutDirection, and + SH_GroupBox_TextLabelColor style hints. +*/ + +/*! + \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 QWorkspace). + \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 standardPixmap() standardIcon() +*/ + +/*### + \enum QStyle::IconMode + + This enum represents the effects performed on a pixmap to achieve a + GUI style's perferred way of representing the image in different + states. + + \value IM_Disabled A disabled pixmap (drawn on disabled widgets) + \value IM_Active An active pixmap (drawn on active tool buttons and menu items) + \value IM_CustomBase Base value for custom PixmapTypes; custom + values must be greater than this value + + \sa generatedIconPixmap() +*/ + +/*! + \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) +{ + if (!(alignment & Qt::AlignHorizontal_Mask)) + alignment |= Qt::AlignLeft; + if ((alignment & Qt::AlignAbsolute) == 0 && (alignment & (Qt::AlignLeft | Qt::AlignRight))) { + if (direction == Qt::RightToLeft) + alignment ^= (Qt::AlignLeft | Qt::AlignRight); + alignment |= Qt::AlignAbsolute; + } + return 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) +} + +/*### \fn void QStyle::drawItem(QPainter *p, const QRect &r, + int flags, const QColorGroup &colorgroup, bool enabled, + const QString &text, int len = -1, + const QColor *penColor = 0) const + + Use one of the drawItem() overloads that takes a QPalette instead + of a QColorGroup. +*/ + +/*### \fn void QStyle::drawItem(QPainter *p, const QRect &r, + int flags, const QColorGroup colorgroup, bool enabled, + const QPixmap &pixmap, + const QColor *penColor = 0) const + + Use one of the drawItem() overloads that takes a QPalette instead + of a QColorGroup. +*/ + +/*### \fn void QStyle::drawItem(QPainter *p, const QRect &r, + int flags, const QColorGroup colorgroup, bool enabled, + const QPixmap *pixmap, + const QString &text, int len = -1, + const QColor *penColor = 0) const + + Use one of the drawItem() overloads that takes a QPalette instead + of a QColorGroup. +*/ + +/*! + 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(), standardPixmap() +*/ +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<QStyle*>(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 default implementation simply calls the + standardPixmap() function with the given parameters. + + 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<QStyle *>(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; +} + +#if !defined(QT_NO_DEBUG) && !defined(QT_NO_DEBUG_STREAM) +QT_BEGIN_INCLUDE_NAMESPACE +#include <QDebug> +QT_END_INCLUDE_NAMESPACE + +QDebug operator<<(QDebug debug, QStyle::State state) +{ + 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 << ")"; + return debug; +} +#endif + +QT_END_NAMESPACE diff --git a/src/gui/styles/qstyle.h b/src/gui/styles/qstyle.h new file mode 100644 index 0000000000..6191d5105f --- /dev/null +++ b/src/gui/styles/qstyle.h @@ -0,0 +1,875 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLE_H +#define QSTYLE_H + +#include <QtCore/qobject.h> +#include <QtCore/qrect.h> +#include <QtCore/qsize.h> +#include <QtGui/qicon.h> +#include <QtGui/qpixmap.h> +#include <QtGui/qpalette.h> +#include <QtGui/qsizepolicy.h> + +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, + + // 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_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 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, + + // 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; + +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; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QStyle::State) +Q_DECLARE_OPERATORS_FOR_FLAGS(QStyle::SubControls) + +#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DEBUG) +Q_GUI_EXPORT QDebug operator<<(QDebug debug, QStyle::State state); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSTYLE_H diff --git a/src/gui/styles/qstyle.qrc b/src/gui/styles/qstyle.qrc new file mode 100644 index 0000000000..8654e66a37 --- /dev/null +++ b/src/gui/styles/qstyle.qrc @@ -0,0 +1,135 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/trolltech/styles/commonstyle"> +<file>images/filelink-16.png</file> +<file>images/filelink-32.png</file> +<file>images/filelink-128.png</file> +<file>images/file-16.png</file> +<file>images/file-32.png</file> +<file>images/file-128.png</file> +<file>images/newdirectory-16.png</file> +<file>images/newdirectory-32.png</file> +<file>images/newdirectory-128.png</file> +<file>images/parentdir-16.png</file> +<file>images/parentdir-32.png</file> +<file>images/parentdir-128.png</file> +<file>images/dvd-16.png</file> +<file>images/dvd-32.png</file> +<file>images/dvd-128.png</file> +<file>images/cdr-16.png</file> +<file>images/cdr-32.png</file> +<file>images/cdr-128.png</file> +<file>images/floppy-16.png</file> +<file>images/floppy-32.png</file> +<file>images/floppy-128.png</file> +<file>images/harddrive-16.png</file> +<file>images/harddrive-32.png</file> +<file>images/harddrive-128.png</file> +<file>images/trash-16.png</file> +<file>images/trash-32.png</file> +<file>images/trash-128.png</file> +<file>images/networkdrive-16.png</file> +<file>images/networkdrive-32.png</file> +<file>images/networkdrive-128.png</file> +<file>images/computer-16.png</file> +<file>images/computer-32.png</file> +<file>images/desktop-16.png</file> +<file>images/desktop-32.png</file> +<file>images/dirclosed-16.png</file> +<file>images/dirclosed-32.png</file> +<file>images/dirclosed-128.png</file> +<file>images/dirlink-16.png</file> +<file>images/dirlink-32.png</file> +<file>images/dirlink-128.png</file> +<file>images/diropen-16.png</file> +<file>images/diropen-32.png</file> +<file>images/diropen-128.png</file> +<file>images/left-16.png</file> +<file>images/left-32.png</file> +<file>images/left-128.png</file> +<file>images/right-16.png</file> +<file>images/right-32.png</file> +<file>images/right-128.png</file> +<file>images/up-16.png</file> +<file>images/up-32.png</file> +<file>images/up-128.png</file> +<file>images/down-16.png</file> +<file>images/down-32.png</file> +<file>images/down-128.png</file> +<file>images/filecontents-16.png</file> +<file>images/filecontents-32.png</file> +<file>images/filecontents-128.png</file> +<file>images/fileinfo-16.png</file> +<file>images/fileinfo-32.png</file> +<file>images/fileinfo-128.png</file> +<file>images/viewdetailed-16.png</file> +<file>images/viewdetailed-32.png</file> +<file>images/viewdetailed-128.png</file> +<file>images/viewlist-16.png</file> +<file>images/viewlist-32.png</file> +<file>images/viewlist-128.png</file> +<file>images/fontbitmap-16.png</file> +<file>images/fonttruetype-16.png</file> +<file>images/standardbutton-apply-128.png</file> +<file>images/standardbutton-apply-16.png</file> +<file>images/standardbutton-apply-32.png</file> +<file>images/standardbutton-cancel-128.png</file> +<file>images/standardbutton-cancel-16.png</file> +<file>images/standardbutton-cancel-32.png</file> +<file>images/standardbutton-clear-128.png</file> +<file>images/standardbutton-clear-16.png</file> +<file>images/standardbutton-clear-32.png</file> +<file>images/standardbutton-close-128.png</file> +<file>images/standardbutton-close-16.png</file> +<file>images/standardbutton-close-32.png</file> +<file>images/standardbutton-delete-128.png</file> +<file>images/standardbutton-delete-16.png</file> +<file>images/standardbutton-delete-32.png</file> +<file>images/standardbutton-help-128.png</file> +<file>images/standardbutton-help-16.png</file> +<file>images/standardbutton-help-32.png</file> +<file>images/standardbutton-no-128.png</file> +<file>images/standardbutton-no-16.png</file> +<file>images/standardbutton-no-32.png</file> +<file>images/standardbutton-ok-128.png</file> +<file>images/standardbutton-ok-16.png</file> +<file>images/standardbutton-ok-32.png</file> +<file>images/standardbutton-open-128.png</file> +<file>images/standardbutton-open-16.png</file> +<file>images/standardbutton-open-32.png</file> +<file>images/standardbutton-save-128.png</file> +<file>images/standardbutton-save-16.png</file> +<file>images/standardbutton-save-32.png</file> +<file>images/standardbutton-yes-128.png</file> +<file>images/standardbutton-yes-16.png</file> +<file>images/standardbutton-yes-32.png</file> +<file>images/standardbutton-closetab-16.png</file> +<file>images/standardbutton-closetab-down-16.png</file> +<file>images/standardbutton-closetab-hover-16.png</file> +<file>images/refresh-24.png</file> +<file>images/refresh-32.png</file> +<file>images/stop-24.png</file> +<file>images/stop-32.png</file> +<file>images/media-stop-16.png</file> +<file>images/media-stop-32.png</file> +<file>images/media-play-16.png</file> +<file>images/media-play-32.png</file> +<file>images/media-pause-16.png</file> +<file>images/media-pause-32.png</file> +<file>images/media-seek-forward-16.png</file> +<file>images/media-seek-forward-32.png</file> +<file>images/media-seek-backward-16.png</file> +<file>images/media-seek-backward-32.png</file> +<file>images/media-skip-forward-16.png</file> +<file>images/media-skip-forward-32.png</file> +<file>images/media-skip-backward-16.png</file> +<file>images/media-skip-backward-32.png</file> +<file>images/media-volume-16.png</file> +<file>images/media-volume-muted-16.png</file> +</qresource> +<qresource prefix="/trolltech/styles/macstyle"> +<file>images/closedock-16.png</file> +<file>images/closedock-down-16.png</file> +<file>images/dockdock-16.png</file> +<file>images/dockdock-down-16.png</file> +</qresource> +</RCC> diff --git a/src/gui/styles/qstyle_p.h b/src/gui/styles/qstyle_p.h new file mode 100644 index 0000000000..848bad6e66 --- /dev/null +++ b/src/gui/styles/qstyle_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLE_P_H +#define QSTYLE_P_H + +#include "private/qobject_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 QStylePrivate: public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QStyle) +public: + inline QStylePrivate() + : layoutSpacingIndex(-1) + { } + mutable int layoutSpacingIndex; +}; + + +#define BEGIN_STYLE_PIXMAPCACHE(a) \ + QRect rect = option->rect; \ + QPixmap internalPixmapCache; \ + QImage imageCache; \ + QPainter *p = painter; \ + QString unique = uniqueName((a), option, option->rect.size()); \ + int txType = painter->deviceTransform().type() | painter->worldTransform().type(); \ + bool doPixmapCache = UsePixmapCache && 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/gui/styles/qstyle_s60_simulated.qrc b/src/gui/styles/qstyle_s60_simulated.qrc new file mode 100644 index 0000000000..72aab9e624 --- /dev/null +++ b/src/gui/styles/qstyle_s60_simulated.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC> +<RCC version="1.0"> + <qresource prefix="/trolltech/styles/s60style"> + <file>images/s60themes.dat</file> + </qresource> +</RCC> diff --git a/src/gui/styles/qstyle_wince.qrc b/src/gui/styles/qstyle_wince.qrc new file mode 100644 index 0000000000..bdcf604625 --- /dev/null +++ b/src/gui/styles/qstyle_wince.qrc @@ -0,0 +1,97 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/trolltech/styles/commonstyle"> +<file>images/filelink-16.png</file> +<file>images/filelink-32.png</file> +<file>images/file-16.png</file> +<file>images/file-32.png</file> +<file>images/newdirectory-16.png</file> +<file>images/newdirectory-32.png</file> +<file>images/parentdir-16.png</file> +<file>images/parentdir-32.png</file> +<file>images/dvd-16.png</file> +<file>images/dvd-32.png</file> +<file>images/cdr-16.png</file> +<file>images/cdr-32.png</file> +<file>images/floppy-16.png</file> +<file>images/floppy-32.png</file> +<file>images/harddrive-16.png</file> +<file>images/harddrive-32.png</file> +<file>images/trash-16.png</file> +<file>images/trash-32.png</file> +<file>images/networkdrive-16.png</file> +<file>images/networkdrive-32.png</file> +<file>images/computer-16.png</file> +<file>images/computer-32.png</file> +<file>images/desktop-16.png</file> +<file>images/desktop-32.png</file> +<file>images/dirclosed-16.png</file> +<file>images/dirclosed-32.png</file> +<file>images/dirlink-16.png</file> +<file>images/dirlink-32.png</file> +<file>images/diropen-16.png</file> +<file>images/diropen-32.png</file> +<file>images/left-16.png</file> +<file>images/left-32.png</file> +<file>images/right-16.png</file> +<file>images/right-32.png</file> +<file>images/up-16.png</file> +<file>images/up-32.png</file> +<file>images/down-16.png</file> +<file>images/down-32.png</file> +<file>images/filecontents-16.png</file> +<file>images/filecontents-32.png</file> +<file>images/fileinfo-16.png</file> +<file>images/fileinfo-32.png</file> +<file>images/viewdetailed-16.png</file> +<file>images/viewdetailed-32.png</file> +<file>images/viewlist-16.png</file> +<file>images/viewlist-32.png</file> +<file>images/fontbitmap-16.png</file> +<file>images/fonttruetype-16.png</file> +<file>images/standardbutton-apply-16.png</file> +<file>images/standardbutton-apply-32.png</file> +<file>images/standardbutton-cancel-16.png</file> +<file>images/standardbutton-cancel-32.png</file> +<file>images/standardbutton-clear-16.png</file> +<file>images/standardbutton-clear-32.png</file> +<file>images/standardbutton-close-16.png</file> +<file>images/standardbutton-close-32.png</file> +<file>images/standardbutton-delete-16.png</file> +<file>images/standardbutton-delete-32.png</file> +<file>images/standardbutton-help-16.png</file> +<file>images/standardbutton-help-32.png</file> +<file>images/standardbutton-no-16.png</file> +<file>images/standardbutton-no-32.png</file> +<file>images/standardbutton-ok-16.png</file> +<file>images/standardbutton-ok-32.png</file> +<file>images/standardbutton-open-16.png</file> +<file>images/standardbutton-open-32.png</file> +<file>images/standardbutton-save-16.png</file> +<file>images/standardbutton-save-32.png</file> +<file>images/standardbutton-yes-16.png</file> +<file>images/standardbutton-yes-32.png</file> +<file>images/standardbutton-closetab-16.png</file> +<file>images/standardbutton-closetab-down-16.png</file> +<file>images/standardbutton-closetab-hover-16.png</file> +<file>images/refresh-24.png</file> +<file>images/refresh-32.png</file> +<file>images/stop-24.png</file> +<file>images/stop-32.png</file> +<file>images/media-stop-16.png</file> +<file>images/media-stop-32.png</file> +<file>images/media-play-16.png</file> +<file>images/media-play-32.png</file> +<file>images/media-pause-16.png</file> +<file>images/media-pause-32.png</file> +<file>images/media-seek-forward-16.png</file> +<file>images/media-seek-forward-32.png</file> +<file>images/media-seek-backward-16.png</file> +<file>images/media-seek-backward-32.png</file> +<file>images/media-skip-forward-16.png</file> +<file>images/media-skip-forward-32.png</file> +<file>images/media-skip-backward-16.png</file> +<file>images/media-skip-backward-32.png</file> +<file>images/media-volume-16.png</file> +<file>images/media-volume-muted-16.png</file> +</qresource> +</RCC> diff --git a/src/gui/styles/qstylefactory.cpp b/src/gui/styles/qstylefactory.cpp new file mode 100644 index 0000000000..42cd6dcc1a --- /dev/null +++ b/src/gui/styles/qstylefactory.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 + +#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) +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.left(9) == 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<QStyleFactoryInterface*>(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/gui/styles/qstylefactory.h b/src/gui/styles/qstylefactory.h new file mode 100644 index 0000000000..c082cbadc2 --- /dev/null +++ b/src/gui/styles/qstylefactory.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLEFACTORY_H +#define QSTYLEFACTORY_H + +#include <QtCore/qstringlist.h> + +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/gui/styles/qstyleoption.cpp b/src/gui/styles/qstyleoption.cpp new file mode 100644 index 0000000000..ce053aef31 --- /dev/null +++ b/src/gui/styles/qstyleoption.cpp @@ -0,0 +1,5353 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 +#ifndef QT_NO_DEBUG +#include <qdebug.h> +#endif + +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<const QStyleOptionFrameV2 *>(&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<const QStyleOptionFrameV2 *>(&other); + features = f2 ? f2->features : FrameFeatures(QStyleOptionFrameV2::None); + version = Version; + return *this; +} + +/*! + \enum QStyleOptionFrameV2::FrameFeature + + This enum describles 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) +{ +} + +/*! + \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) +{ +} + +/*! + 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<const QStyleOptionFrameV3 *>(&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<const QStyleOptionViewItemV2 *>(&other); + features = v2 ? v2->features : ViewItemFeatures(QStyleOptionViewItemV2::None); + return *this; +} + +/*! + \enum QStyleOptionViewItemV2::ViewItemFeature + + This enum describles 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) +{ +} + +/*! + Constructs a copy of \a other. +*/ +QStyleOptionViewItemV3::QStyleOptionViewItemV3(const QStyleOptionViewItem &other) + : QStyleOptionViewItemV2(Version) +{ + (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<const QStyleOptionViewItemV3*>(&other); + locale = v3 ? v3->locale : QLocale(); + widget = v3 ? v3->widget : 0; + return *this; +} + +/*! + \internal +*/ +QStyleOptionViewItemV3::QStyleOptionViewItemV3(int version) + : QStyleOptionViewItemV2(version) +{ +} + +#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<const QStyleOptionViewItemV4*>(&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<const QStyleOptionTabV2 *>(&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<const QStyleOptionTabV2 *>(&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<const QStyleOptionTabV3 *>(&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<const QStyleOptionTabV3 *>(&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<const QStyleOptionProgressBarV2 *>(&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<const QStyleOptionProgressBarV2 *>(&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 + \brief a bitwise OR of the various sub-controls that need to be + drawn for the complex control + + The default value is QStyle::SC_All. + + \sa QStyle::SubControl +*/ + +/*! + \variable QStyleOptionComplex::activeSubControls + \brief a bitwise OR of the various sub-controls that are active + (pressed) 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), movable(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<const QStyleOptionDockWidgetV2*>(&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<const QStyleOptionToolBoxV2 *>(&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<const QStyleOptionToolBoxV2 *>(&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 bars of QWorkspace's MDI + children. + + 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, QWorkspace +*/ + +/*! + 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<T>(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<T>(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. +*/ +#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<const QStyleOptionTabBarBaseV2*>(&other); + documentMode = v2 ? v2->documentMode : false; + return *this; +} + +/*! \internal */ +QStyleOptionTabBarBaseV2::QStyleOptionTabBarBaseV2(int version) + : QStyleOptionTabBarBase(version) +{ +} + +#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 multimedia + + 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. The levelOfDetail parameter is + initialized to 1. +*/ +QStyleOptionGraphicsItem::QStyleOptionGraphicsItem() + : QStyleOption(Version, Type), levelOfDetail(1) +{ +} + +/*! + \internal +*/ +QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(int version) + : QStyleOption(version, Type), levelOfDetail(1) +{ +} + +/*! + \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(). +*/ + +/*! + \variable QStyleOptionGraphicsItem::matrix + \brief the complete transformation matrix for the item + + This matrix is the sum 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 dimentions of an item in screen coordinates (i.e., pixels), + you can use the mapping functions of QMatrix, such as QMatrix::map(). + + \sa QStyleOptionGraphicsItem::levelOfDetail +*/ + +/*! + \variable QStyleOptionGraphicsItem::levelOfDetail + \brief a simple metric for determining an item's level of detail + + This simple metric provides an easy way to determine the level of detail + for an item. Its value represents the maximum value of the height and + width of a unity rectangle, mapped using the complete transformation + matrix 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. + + For more advanced level-of-detail metrics, use + QStyleOptionGraphicsItem::matrix directly. + + \sa QStyleOptionGraphicsItem::matrix +*/ + +/*! + \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<T>(), 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<T>(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<T>(QStyleHintReturn *hint) + \overload + \relates QStyleHintReturn + + Returns a T or 0 depending on the type of \a hint. +*/ + +#if !defined(QT_NO_DEBUG) && !defined(QT_NO_DEBUG_STREAM) +QDebug operator<<(QDebug debug, const QStyleOption::OptionType &optionType) +{ + 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; + } + return debug; +} + +QDebug operator<<(QDebug debug, const QStyleOption &option) +{ + debug << "QStyleOption("; + debug << QStyleOption::OptionType(option.type); + debug << "," << (option.direction == Qt::RightToLeft ? "RightToLeft" : "LeftToRight"); + debug << "," << option.state; + debug << "," << option.rect; + debug << ")"; + return debug; +} +#endif + +QT_END_NAMESPACE diff --git a/src/gui/styles/qstyleoption.h b/src/gui/styles/qstyleoption.h new file mode 100644 index 0000000000..5759a054a2 --- /dev/null +++ b/src/gui/styles/qstyleoption.h @@ -0,0 +1,949 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLEOPTION_H +#define QSTYLEOPTION_H + +#include <QtCore/qvariant.h> +#include <QtGui/qabstractspinbox.h> +#include <QtGui/qicon.h> +#include <QtGui/qmatrix.h> +#include <QtGui/qslider.h> +#include <QtGui/qstyle.h> +#include <QtGui/qtabbar.h> +#include <QtGui/qtabwidget.h> +#include <QtGui/qrubberband.h> +#include <QtGui/qframe.h> +#ifndef QT_NO_ITEMVIEWS +# include <QtCore/qabstractitemmodel.h> +#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); +}; +#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<QStyleOptionQ3ListViewItem> 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; } +protected: + QStyleOptionGraphicsItem(int version); +}; + +template <typename T> +T qstyleoption_cast(const QStyleOption *opt) +{ + if (opt && opt->version >= static_cast<T>(0)->Version && (opt->type == static_cast<T>(0)->Type + || int(static_cast<T>(0)->Type) == QStyleOption::SO_Default + || (int(static_cast<T>(0)->Type) == QStyleOption::SO_Complex + && opt->type > QStyleOption::SO_Complex))) + return static_cast<T>(opt); + return 0; +} + +template <typename T> +T qstyleoption_cast(QStyleOption *opt) +{ + if (opt && opt->version >= static_cast<T>(0)->Version && (opt->type == static_cast<T>(0)->Type + || int(static_cast<T>(0)->Type) == QStyleOption::SO_Default + || (int(static_cast<T>(0)->Type) == QStyleOption::SO_Complex + && opt->type > QStyleOption::SO_Complex))) + return static_cast<T>(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 <typename T> +T qstyleoption_cast(const QStyleHintReturn *hint) +{ + if (hint && hint->version <= static_cast<T>(0)->Version && + (hint->type == static_cast<T>(0)->Type || int(static_cast<T>(0)->Type) == QStyleHintReturn::SH_Default)) + return static_cast<T>(hint); + return 0; +} + +template <typename T> +T qstyleoption_cast(QStyleHintReturn *hint) +{ + if (hint && hint->version <= static_cast<T>(0)->Version && + (hint->type == static_cast<T>(0)->Type || int(static_cast<T>(0)->Type) == QStyleHintReturn::SH_Default)) + return static_cast<T>(hint); + return 0; +} + +#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DEBUG) +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/gui/styles/qstyleplugin.cpp b/src/gui/styles/qstyleplugin.cpp new file mode 100644 index 0000000000..19c08be0a9 --- /dev/null +++ b/src/gui/styles/qstyleplugin.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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/gui/styles/qstyleplugin.h b/src/gui/styles/qstyleplugin.h new file mode 100644 index 0000000000..c7d9202c59 --- /dev/null +++ b/src/gui/styles/qstyleplugin.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLEPLUGIN_H +#define QSTYLEPLUGIN_H + +#include <QtCore/qplugin.h> +#include <QtCore/qfactoryinterface.h> + +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/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp new file mode 100644 index 0000000000..2558409501 --- /dev/null +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -0,0 +1,5946 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qglobal.h> + +#ifndef QT_NO_STYLE_STYLESHEET + +#include "qstylesheetstyle_p.h" +#include "private/qcssutil_p.h" +#include <qdebug.h> +#include <qapplication.h> +#include <qmenu.h> +#include <qmenubar.h> +#include <qpainter.h> +#include <qstyleoption.h> +#include <qlineedit.h> +#include <qwindowsstyle.h> +#include <qcombobox.h> +#include <qwindowsstyle.h> +#include <qplastiquestyle.h> +#include "private/qcssparser_p.h" +#include "private/qmath_p.h" +#include <qabstractscrollarea.h> +#include "private/qabstractscrollarea_p.h" +#include <qtooltip.h> +#include <qshareddata.h> +#include <qradiobutton.h> +#include <qtoolbutton.h> +#include <qscrollbar.h> +#include <qstring.h> +#include <qfile.h> +#include <qcheckbox.h> +#include <qstatusbar.h> +#include <qheaderview.h> +#include <qprogressbar.h> +#include <private/qwindowsstyle_p.h> +#include <qtabbar.h> +#include <QMetaProperty> +#include <qmainwindow.h> +#include <qdockwidget.h> +#include <qmdisubwindow.h> +#include <qdialog.h> +#include <private/qwidget_p.h> +#include <QAbstractSpinBox> +#include <QLabel> + +#include <limits.h> + +QT_BEGIN_NAMESPACE + +using namespace QCss; + + +class QStyleSheetStylePrivate : public QWindowsStylePrivate +{ + Q_DECLARE_PUBLIC(QStyleSheetStyle) +public: + QStyleSheetStylePrivate() { } +}; + + +static QHash<const QWidget *, QVector<StyleRule> > *styleRulesCache = 0; +static QHash<const QWidget *, QHash<int, bool> > *hasStyleRuleCache = 0; +typedef QHash<int, QHash<quint64, QRenderRule> > QRenderRules; +static QHash<const QWidget *, QRenderRules> *renderRulesCache = 0; +static QHash<const QWidget *, QPalette> *customPaletteWidgets = 0; // widgets whose palette we tampered +static QHash<const void *, StyleSheet> *styleSheetCache = 0; // parsed style sheets +static QSet<const QWidget *> *autoFillDisabledWidgets = 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, + 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" } +}; + + +struct QStyleSheetBorderImageData : public QSharedData +{ + QStyleSheetBorderImageData() + : horizStretch(QCss::TileMode_Unknown), vertStretch(QCss::TileMode_Unknown) + { + for (int i = 0; i < 4; i++) + cuts[i] = -1; + } + QPixmap topEdge, bottomEdge, leftEdge, rightEdge, middle; + QRect topEdgeRect, bottomEdgeRect, leftEdgeRect, rightEdgeRect, middleRect; + QRect topLeftCorner, topRightCorner, bottomRightCorner, bottomLeftCorner; + int cuts[4]; + QPixmap pixmap; + QImage image; + QCss::TileMode horizStretch, vertStretch; + + void cutBorderImage(); +}; + +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<QStyleSheetBorderImageData> 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<QCss::Declaration> &, 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<QString, QVariant> 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<QStyleSheetPaletteData> pal; + QSharedDataPointer<QStyleSheetBoxData> b; + QSharedDataPointer<QStyleSheetBackgroundData> bg; + QSharedDataPointer<QStyleSheetBorderData> bd; + QSharedDataPointer<QStyleSheetOutlineData> ou; + QSharedDataPointer<QStyleSheetGeometryData> geo; + QSharedDataPointer<QStyleSheetPositionData> p; + QSharedDataPointer<QStyleSheetImageData> 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<QVariant> subControlLayout(const QString& layout) +{ + QList<QVariant> 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<QStyle::SubControl, QRect> QStyleSheetStyle::titleBarLayout(const QWidget *w, const QStyleOptionTitleBar *tb) const +{ + QHash<QStyle::SubControl, QRect> 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<QVariant> 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<ButtonInfo> 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<Declaration> &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 = qApp->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<QStyleSheetStyle *>(globalStyleSheetStyle); + if (!style) + style = qobject_cast<QStyleSheetStyle *>(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 (!hasNativeBorder() && (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]); + } + bi->cutBorderImage(); +} + +void QStyleSheetBorderImageData::cutBorderImage() +{ + const int w = pixmap.width(); + const int h = pixmap.height(); + const int &l = cuts[LeftEdge], &r = cuts[RightEdge], + &t = cuts[TopEdge], &b = cuts[BottomEdge]; + + topEdgeRect = QRect(l, 0, w - r - l, t); + bottomEdgeRect = QRect(l, h - b, w - l - r, b); + if (horizStretch != TileMode_Stretch) { + if (topEdgeRect.isValid()) + topEdge = pixmap.copy(topEdgeRect).scaledToHeight(t); + if (bottomEdgeRect.isValid()) + bottomEdge = pixmap.copy(bottomEdgeRect).scaledToHeight(b); + } + + leftEdgeRect = QRect(0, t, l, h - b - t); + rightEdgeRect = QRect(w - r, t, r, h - t- b); + if (vertStretch != TileMode_Stretch) { + if (leftEdgeRect.isValid()) + leftEdge = pixmap.copy(leftEdgeRect).scaledToWidth(l); + if (rightEdgeRect.isValid()) + rightEdge = pixmap.copy(rightEdgeRect).scaledToWidth(r); + } + + middleRect = QRect(l, t, w - r -l, h - t - b); + if (middleRect.isValid() + && !(horizStretch == TileMode_Stretch && vertStretch == TileMode_Stretch)) { + middle = pixmap.copy(middleRect); + } +} + +static void qDrawCenterTiledPixmap(QPainter *p, const QRectF& r, const QPixmap& pix) +{ + p->drawTiledPixmap(r, pix, QPoint(pix.width() - int(r.width())%pix.width(), + pix.height() - int(r.height())%pix.height())); +} + +// Note: Round is not supported +void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect) +{ + setClip(p, rect); + const QRectF br(rect); + const int *borders = border()->borders; + const int &l = borders[LeftEdge], &r = borders[RightEdge], + &t = borders[TopEdge], &b = borders[BottomEdge]; + QRectF pr = br.adjusted(l, t, -r, -b); + + bool wasSmoothPixmapTransform = p->renderHints() & QPainter::SmoothPixmapTransform; + p->setRenderHint(QPainter::SmoothPixmapTransform); + + const QStyleSheetBorderImageData *bi = border()->borderImage(); + const QPixmap& pix = bi->pixmap; + const int *c = bi->cuts; + QRectF tlc(0, 0, c[LeftEdge], c[TopEdge]); + if (tlc.isValid()) + p->drawPixmap(QRectF(br.topLeft(), QSizeF(l, t)), pix, tlc); + QRectF trc(pix.width() - c[RightEdge], 0, c[RightEdge], c[TopEdge]); + if (trc.isValid()) + p->drawPixmap(QRectF(br.left() + br.width() - r, br.y(), r, t), pix, trc); + QRectF blc(0, pix.height() - c[BottomEdge], c[LeftEdge], c[BottomEdge]); + if (blc.isValid()) + p->drawPixmap(QRectF(br.x(), br.y() + br.height() - b, l, b), pix, blc); + QRectF brc(pix.width() - c[RightEdge], pix.height() - c[BottomEdge], + c[RightEdge], c[BottomEdge]); + if (brc.isValid()) + p->drawPixmap(QRectF(br.x() + br.width() - r, br.y() + br.height() - b, r, b), + pix, brc); + + QRectF topEdgeRect(br.x() + l, br.y(), pr.width(), t); + QRectF bottomEdgeRect(br.x() + l, br.y() + br.height() - b, pr.width(), b); + + switch (bi->horizStretch) { + case TileMode_Stretch: + if (bi->topEdgeRect.isValid()) + p->drawPixmap(topEdgeRect, pix, bi->topEdgeRect); + if (bi->bottomEdgeRect.isValid()) + p->drawPixmap(bottomEdgeRect, pix, bi->bottomEdgeRect); + if (bi->middleRect.isValid()) { + if (bi->vertStretch == TileMode_Stretch) + p->drawPixmap(pr, pix, bi->middleRect); + else if (bi->vertStretch == TileMode_Repeat) { + QPixmap scaled = bi->middle.scaled(int(pr.width()), bi->middle.height()); + qDrawCenterTiledPixmap(p, pr, scaled); + } + } + break; + case TileMode_Repeat: + if (!bi->topEdge.isNull() && !topEdgeRect.isEmpty()) { + QPixmap scaled = bi->topEdge.scaled(bi->topEdge.width(), t); + qDrawCenterTiledPixmap(p, topEdgeRect, scaled); + } + if (!bi->bottomEdge.isNull() && !bottomEdgeRect.isEmpty()) { + QPixmap scaled = bi->bottomEdge.scaled(bi->bottomEdge.width(), b); + qDrawCenterTiledPixmap(p, bottomEdgeRect, scaled); + } + if (bi->middleRect.isValid()) { + if (bi->vertStretch == TileMode_Repeat) { + qDrawCenterTiledPixmap(p, pr, bi->middle); + } else if (bi->vertStretch == TileMode_Stretch) { + QPixmap scaled = bi->middle.scaled(bi->middle.width(), int(pr.height())); + qDrawCenterTiledPixmap(p, pr, scaled); + } + } + break; + case TileMode_Round: + if (!bi->topEdge.isNull()) { + int rwh = (int)pr.width()/ceil(pr.width()/bi->topEdge.width()); + QPixmap scaled = bi->topEdge.scaled(rwh, bi->topEdge.height()); + int blank = int(pr.width()) % rwh; + p->drawTiledPixmap(QRectF(br.x() + l + blank/2, br.y(), pr.width() - blank, t), + scaled); + } + if (!bi->bottomEdge.isNull()) { + int rwh = (int) pr.width()/ceil(pr.width()/bi->bottomEdge.width()); + QPixmap scaled = bi->bottomEdge.scaled(rwh, bi->bottomEdge.height()); + int blank = int(pr.width()) % rwh; + p->drawTiledPixmap(QRectF(br.x() + l+ blank/2, br.y()+br.height()-b, + pr.width() - blank, b), scaled); + } + break; + default: + break; + } + + QRectF leftEdgeRect(br.x(), br.y() + t, l, pr.height()); + QRectF rightEdgeRect(br.x() + br.width()- r, br.y() + t, r, pr.height()); + + switch (bi->vertStretch) { + case TileMode_Stretch: + if (bi->leftEdgeRect.isValid()) + p->drawPixmap(leftEdgeRect, pix, bi->leftEdgeRect); + if (bi->rightEdgeRect.isValid()) + p->drawPixmap(rightEdgeRect, pix, bi->rightEdgeRect); + break; + case TileMode_Repeat: + if (!bi->leftEdge.isNull() && !leftEdgeRect.isEmpty()) { + QPixmap scaled = bi->leftEdge.scaled(l, bi->leftEdge.height()); + qDrawCenterTiledPixmap(p, leftEdgeRect, scaled); + } + if (!bi->rightEdge.isNull() && !rightEdgeRect.isEmpty()) { + QPixmap scaled = bi->rightEdge.scaled(r, bi->rightEdge.height()); + qDrawCenterTiledPixmap(p, rightEdgeRect, scaled); + } + break; + case TileMode_Round: + if (!bi->leftEdge.isNull()) { + int rwh = (int) pr.height()/ceil(pr.height()/bi->leftEdge.height()); + QPixmap scaled = bi->leftEdge.scaled(bi->leftEdge.width(), rwh); + int blank = int(pr.height()) % rwh; + p->drawTiledPixmap(QRectF(br.x(), br.y() + t + blank/2, l, pr.height() - blank), + scaled); + } + if (!bi->rightEdge.isNull()) { + int rwh = (int) pr.height()/ceil(pr.height()/bi->rightEdge.height()); + QPixmap scaled = bi->rightEdge.scaled(bi->rightEdge.width(), rwh); + int blank = int(pr.height()) % rwh; + p->drawTiledPixmap(QRectF(br.x() + br.width() - r, br.y()+t+blank/2, r, + pr.height() - blank), scaled); + } + break; + default: + break; + } + + 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.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) +{ + setClip(p, borderRect(rect)); + 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 + p->fillRect(originRect(rect, origin), brush); + } + + drawBackgroundImage(p, rect, off); + unsetClip(p); +} + +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 (!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) +{ +#ifdef QT_NO_COMBOBOX + const bool isReadOnlyCombo = false; +#else + const bool isReadOnlyCombo = qobject_cast<const QComboBox *>(w) != 0; +#endif + + if (bg && bg->brush.style() != Qt::NoBrush) { + if (isReadOnlyCombo) { + p->setBrush(cg, QPalette::Base, bg->brush); // for windows, windowxp + p->setBrush(cg, QPalette::Button, bg->brush); // for plastique + } else { + 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()->middleRect.isValid())) + p->setBrush(cg, w->backgroundRole(), Qt::NoBrush); + } + + if (!hasPalette()) + return; + + if (pal->foreground.style() != Qt::NoBrush) { + if (isReadOnlyCombo) { + p->setBrush(cg, QPalette::ButtonText, pal->foreground); + } else { + 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<QWidget *>(x.ptr)) + +static inline QWidget *parentWidget(const QWidget *w) +{ + if(qobject_cast<const QLabel *>(w) && qstrcmp(w->metaObject()->className(), "QTipLabel") == 0) { + QWidget *p = qvariant_cast<QWidget *>(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<QString, QString> &cache = m_attributeCache[WIDGET(node)]; + QHash<QString, QString>::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<QStyleSheetStyle *>(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<const QWidget *, QHash<QString, QString> > m_attributeCache; +}; + +QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const +{ + QHash<const QWidget *, QVector<StyleRule> >::const_iterator cacheIt = styleRulesCache->constFind(w); + if (cacheIt != styleRulesCache->constEnd()) + return cacheIt.value(); + + if (!initWidget(w)) { + return QVector<StyleRule>(); + } + + QStyleSheetStyleSelector styleSelector; + + StyleSheet defaultSs; + QHash<const void *, StyleSheet>::const_iterator defaultCacheIt = styleSheetCache->constFind(baseStyle()); + if (defaultCacheIt == styleSheetCache->constEnd()) { + defaultSs = getDefaultStyleSheet(); + styleSheetCache->insert(baseStyle(), defaultSs); + } else { + defaultSs = defaultCacheIt.value(); + } + styleSelector.styleSheets += defaultSs; + + if (!qApp->styleSheet().isEmpty()) { + StyleSheet appSs; + QHash<const void *, StyleSheet>::const_iterator appCacheIt = styleSheetCache->constFind(qApp); + if (appCacheIt == 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; + styleSheetCache->insert(qApp, appSs); + } else { + appSs = appCacheIt.value(); + } + styleSelector.styleSheets += appSs; + } + + QVector<QCss::StyleSheet> widgetSs; + for (const QWidget *wid = w; wid; wid = parentWidget(wid)) { + if (wid->styleSheet().isEmpty()) + continue; + StyleSheet ss; + QHash<const void *, StyleSheet>::const_iterator widCacheIt = styleSheetCache->constFind(wid); + if (widCacheIt == styleSheetCache->constEnd()) { + parser.init(wid->styleSheet()); + if (!parser.parse(&ss)) { + parser.init(QLatin1String("* {") + wid->styleSheet() + QLatin1String("}")); + if (!parser.parse(&ss)) + qWarning("Could not parse stylesheet of widget %p", wid); + } + ss.origin = StyleSheetOrigin_Inline; + 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<QCss::StyleRule> rules = styleSelector.styleRulesForNode(n); + styleRulesCache->insert(w, rules); + return rules; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Rendering rules +static QVector<Declaration> declarations(const QVector<StyleRule> &styleRules, const QString &part, quint64 pseudoClass = PseudoClass_Unspecified) +{ + QVector<Declaration> 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<const QAbstractSpinBox *>(w)) + return base->pixelMetric(QStyle::PM_SpinBoxFrameWidth, 0, w); +#endif + +#ifndef QT_NO_COMBOBOX + if (qobject_cast<const QComboBox *>(w)) + return base->pixelMetric(QStyle::PM_ComboBoxFrameWidth, 0, w); +#endif + +#ifndef QT_NO_MENU + if (qobject_cast<const QMenu *>(w)) + return base->pixelMetric(QStyle::PM_MenuPanelWidth, 0, w); +#endif + +#ifndef QT_NO_MENUBAR + if (qobject_cast<const QMenuBar *>(w)) + return base->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, w); +#endif +#ifndef QT_NO_FRAME + if (const QFrame *frame = qobject_cast<const QFrame *>(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<quint64, QRenderRule> &cache = (*renderRulesCache)[w][element]; + QHash<quint64, QRenderRule>::const_iterator cacheIt = cache.constFind(state); + if (cacheIt != cache.constEnd()) + return cacheIt.value(); + + if (!initWidget(w)) + return QRenderRule(); + + quint64 stateMask = 0; + const QVector<StyleRule> 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<Declaration> 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<const QStyleOptionComplex *>(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(state & (QStyle::State_Enabled | QStyle::State_Horizontal)); + } + + 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<const QStyleOptionSpinBox *>(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<const QStyleOptionComboBox *>(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<const QStyleOptionSpinBox *>(opt)) { + if (!spin->frame) + extraClass |= PseudoClass_Frameless; +#endif // QT_NO_SPINBOX + } else if (const QStyleOptionGroupBox *gb = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) { + if (gb->features & QStyleOptionFrameV2::Flat) + extraClass |= PseudoClass_Flat; + if (gb->lineWidth == 0) + extraClass |= PseudoClass_Frameless; + } else if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(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<const QStyleOptionMenuItem *>(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<const QStyleOptionHeader *>(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<const QStyleOptionTabWidgetFrame *>(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<const QStyleOptionTab *>(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<const QStyleOptionButton *>(opt)) { + if (btn->features & QStyleOptionButton::Flat) + extraClass |= PseudoClass_Flat; + if (btn->features & QStyleOptionButton::DefaultButton) + extraClass |= PseudoClass_Default; + } else if (const QStyleOptionFrame *frm = qstyleoption_cast<const QStyleOptionFrame *>(opt)) { + if (frm->lineWidth == 0) + extraClass |= PseudoClass_Frameless; + if (const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt)) { + if (frame2->features & QStyleOptionFrameV2::Flat) + extraClass |= PseudoClass_Flat; + } + } +#ifndef QT_NO_TOOLBAR + else if (const QStyleOptionToolBar *tb = qstyleoption_cast<const QStyleOptionToolBar *>(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<const QStyleOptionToolBoxV2 *>(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<const QStyleOptionDockWidgetV2 *>(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<const QStyleOptionViewItemV2 *>(opt)) { + if (v2->features & QStyleOptionViewItemV2::Alternate) + extraClass |= PseudoClass_Alternate; + if (const QStyleOptionViewItemV4 *v4 = qstyleoption_cast<const QStyleOptionViewItemV4 *>(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<const QLineEdit *>(w)) { + state &= ~QStyle::State_Sunken; + if (lineEdit->hasFrame()) { + extraClass &= ~PseudoClass_Frameless; + } else { + extraClass |= PseudoClass_Frameless; + } + } else +#endif + { } // required for the above ifdef'ery + } + + return renderRule(w, pseudoElement, pseudoClass(state) | extraClass); +} + +bool QStyleSheetStyle::hasStyleRule(const QWidget *w, int part) const +{ + QHash<int, bool> &cache = (*hasStyleRuleCache)[w]; + QHash<int, bool>::const_iterator cacheIt = cache.constFind(part); + if (cacheIt != cache.constEnd()) + return cacheIt.value(); + + if (!initWidget(w)) + return false; + + + const QVector<StyleRule> &rules = styleRules(w); + if (part == PseudoElement_None) { + bool result = w && !rules.isEmpty(); + cache[part] = result; + return result; + } + + QString pseudoElement = QLatin1String(knownPseudoElements[part].name); + QVector<Declaration> 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<QComboBox *>(w)) { + if (cmb->isEditable()) + return cmb->lineEdit(); + else + return cmb; + } +#endif + +#ifndef QT_NO_SPINBOX + if (QAbstractSpinBox *sb = qobject_cast<QAbstractSpinBox *>(w)) + return qFindChild<QLineEdit *>(sb); +#endif + +#ifndef QT_NO_SCROLLAREA + if (QAbstractScrollArea *sa = qobject_cast<QAbstractScrollArea *>(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<const QLineEdit *>(w)) { + //if the QLineEdit is an embeddedWidget, we need the rule of the real widget +#ifndef QT_NO_COMBOBOX + if (qobject_cast<const QComboBox *>(w->parentWidget())) + return w->parentWidget(); +#endif +#ifndef QT_NO_SPINBOX + if (qobject_cast<const QAbstractSpinBox *>(w->parentWidget())) + return w->parentWidget(); +#endif + } +#endif // QT_NO_LINEEDIT + +#ifndef QT_NO_SCROLLAREA + if (const QAbstractScrollArea *sa = qobject_cast<const QAbstractScrollArea *>(w->parentWidget())) { + if (sa->viewport() == w) + return w->parentWidget(); + } +#endif + + return const_cast<QWidget *>(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<const QFrame *>(w)) { + if (0 +#ifndef QT_NO_COMBOBOX + || qobject_cast<const QComboBox *>(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<const QAbstractSlider *>(w)) { + pc |= ((slider->orientation() == Qt::Vertical) ? PseudoClass_Vertical : PseudoClass_Horizontal); + } else +#ifndef QT_NO_COMBOBOX + if (const QComboBox *combo = qobject_cast<const QComboBox *>(w)) { + if (combo->isEditable()) + pc |= (combo->isEditable() ? PseudoClass_Editable : PseudoClass_ReadOnly); + } else +#endif +#ifndef QT_NO_LINEEDIT + if (const QLineEdit *edit = qobject_cast<const QLineEdit *>(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<QString, QVariant> propertyHash; + QVector<Declaration> 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<QString> 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] = { + { 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); + } + + customPaletteWidgets->insert(w, w->palette()); + w->setPalette(p); + if (ew != w) + ew->setPalette(p); +} + +void QStyleSheetStyle::unsetPalette(QWidget *w) +{ + if (customPaletteWidgets->contains(w)) { + QPalette p = customPaletteWidgets->value(w); + w->setPalette(p); + QWidget *ew = embeddedWidget(w); + if (ew != w) + ew->setPalette(p); + customPaletteWidgets->remove(w); + } + QVariant oldFont = w->property("_q_styleSheetWidgetFont"); + if (oldFont.isValid()) { + w->setFont(qVariantValue<QFont>(oldFont)); + } + if (autoFillDisabledWidgets->contains(w)) { + embeddedWidget(w)->setAutoFillBackground(true); + autoFillDisabledWidgets->remove(w); + } +} + +static void updateWidgets(const QList<const QWidget *>& widgets) +{ + if (!styleRulesCache->isEmpty() || !hasStyleRuleCache->isEmpty() || !renderRulesCache->isEmpty()) { + for (int i = 0; i < widgets.size(); ++i) { + const QWidget *widget = widgets.at(i); + styleRulesCache->remove(widget); + hasStyleRuleCache->remove(widget); + renderRulesCache->remove(widget); + } + } + for (int i = 0; i < widgets.size(); ++i) { + QWidget *widget = const_cast<QWidget *>(widgets.at(i)); + if (widget == 0) + continue; + widget->style()->polish(widget); + QEvent event(QEvent::StyleChange); + qApp->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) { + styleRulesCache = new QHash<const QWidget *, QVector<StyleRule> >; + hasStyleRuleCache = new QHash<const QWidget *, QHash<int, bool> >; + renderRulesCache = new QHash<const QWidget *, QRenderRules>; + customPaletteWidgets = new QHash<const QWidget *, QPalette>; + styleSheetCache = new QHash<const void *, StyleSheet>; + autoFillDisabledWidgets = new QSet<const QWidget *>; + } +} + +QStyleSheetStyle::~QStyleSheetStyle() +{ + --numinstances; + if (numinstances == 0) { + delete styleRulesCache; + styleRulesCache = 0; + delete hasStyleRuleCache; + hasStyleRuleCache = 0; + delete renderRulesCache; + renderRulesCache = 0; + delete customPaletteWidgets; + customPaletteWidgets = 0; + delete styleSheetCache; + styleSheetCache = 0; + delete autoFillDisabledWidgets; + autoFillDisabledWidgets = 0; + } +} +QStyle *QStyleSheetStyle::baseStyle() const +{ + if (base) + return base; + if (QStyleSheetStyle *me = qobject_cast<QStyleSheetStyle *>(qApp->style())) + return me->base; + return qApp->style(); +} + +void QStyleSheetStyle::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); +} + +/*! + * 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<QWidget *>(w)->setAttribute(Qt::WA_StyleSheet, true); + QObject::connect(w, SIGNAL(destroyed(QObject*)), this, SLOT(widgetDestroyed(QObject*))); + return true; +} + +void QStyleSheetStyle::polish(QWidget *w) +{ + baseStyle()->polish(w); + RECURSION_GUARD(return) + + if (!initWidget(w)) + return; + + if (styleRulesCache->contains(w)) { + // the widget accessed its style pointer before polish (or repolish) + // (exemple: the QAbstractSpinBox constructor ask for the stylehint) + styleRulesCache->remove(w); + hasStyleRuleCache->remove(w); + 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<StyleRule> 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<QAbstractScrollArea *>(w)) { + QRenderRule rule = renderRule(sa, PseudoElement_None, PseudoClass_Enabled); + if ((rule.hasBorder() && rule.border()->hasBorderImage()) + || (rule.hasBackground() && !rule.background()->pixmap.isNull())) { + QObject::disconnect(sa->horizontalScrollBar(), SIGNAL(valueChanged(int)), + sa, SLOT(update())); + QObject::disconnect(sa->verticalScrollBar(), SIGNAL(valueChanged(int)), + sa, SLOT(update())); + QObject::connect(sa->horizontalScrollBar(), SIGNAL(valueChanged(int)), + sa, SLOT(update())); + QObject::connect(sa->verticalScrollBar(), SIGNAL(valueChanged(int)), + sa, SLOT(update())); + } + } +#endif + +#ifndef QT_NO_PROGRESSBAR + if (QProgressBar *pb = qobject_cast<QProgressBar *>(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_MENUBAR + || qobject_cast<QMenuBar *>(w) +#endif +#ifndef QT_NO_MENU + || qobject_cast<QMenu *>(w) +#endif +#ifndef QT_NO_ITEMVIEWS + || qobject_cast<QHeaderView *>(w) +#endif +#ifndef QT_NO_TABBAR + || qobject_cast<QTabBar *>(w) +#endif +#ifndef QT_NO_FRAME + || qobject_cast<QFrame *>(w) +#endif +#ifndef QT_NO_MAINWINDOW + || qobject_cast<QMainWindow *>(w) +#endif +#ifndef QT_NO_MDIAREA + || qobject_cast<QMdiSubWindow *>(w) +#endif + || qobject_cast<QDialog *>(w)) { + w->setAttribute(Qt::WA_StyledBackground, true); + } + QWidget *ew = embeddedWidget(w); + if (ew->autoFillBackground()) { + ew->setAutoFillBackground(false); + autoFillDisabledWidgets->insert(w); + } + 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<const QWidget *> children = qFindChildren<const QWidget *>(w, QString()); + children.append(w); + styleSheetCache->remove(w); + updateWidgets(children); +} + +void QStyleSheetStyle::repolish(QApplication *app) +{ + Q_UNUSED(app); + const QList<const QWidget*> allWidgets = styleRulesCache->keys(); + styleSheetCache->remove(qApp); + styleRulesCache->clear(); + hasStyleRuleCache->clear(); + renderRulesCache->clear(); + updateWidgets(allWidgets); +} + +void QStyleSheetStyle::unpolish(QWidget *w) +{ + if (!w || !w->testAttribute(Qt::WA_StyleSheet)) { + baseStyle()->unpolish(w); + return; + } + + styleRulesCache->remove(w); + hasStyleRuleCache->remove(w); + renderRulesCache->remove(w); + 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<QAbstractScrollArea *>(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<QProgressBar *>(w)) + QWindowsStyle::unpolish(pb); +#endif + baseStyle()->unpolish(w); +} + +void QStyleSheetStyle::unpolish(QApplication *app) +{ + baseStyle()->unpolish(app); + RECURSION_GUARD(return) + styleRulesCache->clear(); + hasStyleRuleCache->clear(); + renderRulesCache->clear(); + 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<const QStyleOptionComboBox *>(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); + 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<const QStyleOptionSpinBox *>(opt)) { + QStyleOptionSpinBox spinOpt(*spin); + rule.configurePalette(&spinOpt.palette, QPalette::ButtonText, QPalette::Button); + 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(); + bool downRuleMatch = downRule.hasGeometry(); + if (rule.hasNativeBorder() && !upRuleMatch && !downRuleMatch) { + rule.drawBackgroundImage(p, spinOpt.rect); + customUp = (opt->subControls & QStyle::SC_SpinBoxUp) + && hasStyleRule(w, PseudoElement_SpinBoxUpButton); + if (customUp) + spinOpt.subControls &= ~QStyle::SC_SpinBoxUp; + customDown = (opt->subControls & QStyle::SC_SpinBoxDown) + && hasStyleRule(w, PseudoElement_SpinBoxDownButton); + 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<const QStyleOptionGroupBox *>(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); + } + + return; + } + break; + + case CC_ToolButton: + if (const QStyleOptionToolButton *tool = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) { + QStyleOptionToolButton toolOpt(*tool); + rule.configurePalette(&toolOpt.palette, QPalette::ButtonText, QPalette::Button); + 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<const QStyleOptionSlider *>(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<const QStyleOptionSlider *>(opt)) { + rule.drawRule(p, opt->rect); + + QRenderRule subRule = renderRule(w, opt, PseudoElement_SliderGroove); + if (!subRule.hasDrawable()) { + baseStyle()->drawComplexControl(cc, slider, p, w); + return; + } + + QRect gr = subControlRect(cc, opt, SC_SliderGroove, w); + if (slider->subControls & SC_SliderGroove) { + subRule.drawRule(p, gr); + } + + if (slider->subControls & SC_SliderHandle) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_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()) + : QPoint(gr.x()+gr.width(), 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); + } + + subRule.drawRule(p, subRule.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<QVariant> 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)); + 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<const QStyleOptionTitleBar *>(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_TitleBar); + if (!subRule.hasDrawable() && !subRule.hasBox() && !subRule.hasBorder()) + break; + subRule.drawRule(p, opt->rect); + QHash<QStyle::SubControl, QRect> 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<const QStyleOptionToolButton *>(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_PushButton: + ParentStyle::drawControl(ce, opt, p, w); + return; + + case CE_PushButtonBevel: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(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<const QStyleOptionButton *>(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::AlignVCenter | Qt::TextShowMnemonic; + 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: + rule.drawRule(p, opt->rect); + ParentStyle::drawControl(ce, opt, p, w); + return; + + case CE_RadioButtonLabel: + case CE_CheckBoxLabel: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(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<const QStyleOptionToolBar *>(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()) { + return; + } + break; + + case CE_MenuTearoff: + case CE_MenuScroller: + if (const QStyleOptionMenuItem *m = qstyleoption_cast<const QStyleOptionMenuItem *>(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<const QStyleOptionMenuItem *>(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)) { + QWindowsStyle::drawControl(ce, &mi, 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<const QStyleOptionMenuItem *>(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 { + baseStyle()->drawControl(ce, &mi, p, w); + } + } + return; + +#ifndef QT_NO_COMBOBOX + case CE_ComboBoxLabel: + if (!rule.hasBox()) + break; + if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(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(QApplication::layoutDirection(), + 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) { + drawItemText(p, editRect.adjusted(0, 0, 0, 0), Qt::AlignLeft | Qt::AlignVCenter, cb->palette, + cb->state & State_Enabled, cb->currentText); + } + 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<const QStyleOptionHeader *>(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<const QStyleOptionHeader *>(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<const QStyleOptionProgressBarV2 *>(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<const QStyleOptionProgressBarV2 *>(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<const QStyleOptionSizeGrip *>(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<const QStyleOptionToolBox *>(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<const QStyleOptionViewItemV4 *>(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<const QStyleOptionTab *>(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()) { + 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<const QStyleOptionDockWidgetV2 *>(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<const QStyleOptionFrame *>(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 { + rule.drawBorder(p, rule.borderRect(opt->rect)); + } + } + return; + + + default: + break; + } + + if (pe1 != PseudoElement_None) { + QRenderRule subRule = renderRule(w, opt, pe1); + if (subRule.bg != 0 || subRule.hasDrawable()) { + //We test subRule.bg dirrectly 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_PanelStatusBar: + if (rule.hasDrawable()) { + rule.drawRule(p, opt->rect); + return; + } + break; + + 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_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<const QStyleOptionHeader *>(opt)) { + pseudoElement = hdr->sortIndicator == QStyleOptionHeader::SortUp + ? PseudoElement_HeaderViewUpArrow + : PseudoElement_HeaderViewDownArrow; + } + break; + + case PE_PanelButtonTool: + case PE_PanelButtonCommand: + if (qobject_cast<const QAbstractButton *>(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<const QStyleOptionFrame *>(opt)) { + if (rule.hasNativeBorder()) { + QStyleOptionFrameV2 frmOpt(*frm); + rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base); + if (!qstyleoption_cast<const QStyleOptionFrameV3 *>(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<const QStyleOptionFrame *>(opt)) { +#ifndef QT_NO_SPINBOX + if (w && qobject_cast<const QAbstractSpinBox *>(w->parentWidget())) { + QRenderRule spinboxRule = renderRule(w->parentWidget(), opt); + if (!spinboxRule.hasNativeBorder() || !spinboxRule.baseStyleCanDraw()) + return; + } +#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 (!rule.hasBackground()) + break; + +#ifndef QT_NO_SCROLLAREA + if (const QAbstractScrollArea *sa = qobject_cast<const QAbstractScrollArea *>(w)) { + const QAbstractScrollAreaPrivate *sap = sa->d_func(); + rule.drawBackground(p, opt->rect, sap->contentsOffset()); + } else +#endif + { + rule.drawBackground(p, opt->rect); + } + + return; + + case PE_FrameMenu: + case PE_PanelMenuBar: + if (!rule.hasNativeBorder()) { + rule.drawBorder(p, rule.borderRect(opt->rect)); + 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<const QStyleOptionViewItem *>(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<const QStyleOptionViewItemV2 *>(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 { + QStyleOptionViewItemV2 v2Copy(*v2); + if (v2->showDecorationSelected) { + QRenderRule subRule2 = renderRule(w, opt, PseudoElement_ViewItem); + if (v2->state & QStyle::State_Selected) { + subRule2.configurePalette(&v2Copy.palette, QPalette::NoRole, QPalette::Highlight); + } else if (v2->features & QStyleOptionViewItemV2::Alternate) { + subRule2.configurePalette(&v2Copy.palette, QPalette::NoRole, QPalette::AlternateBase); + } else if (subRule2.hasBackground()) { + p->fillRect(v2->rect, subRule2.background()->brush); + } + } else if (v2->features & QStyleOptionViewItemV2::Alternate) { + quint64 pc = v2->state & QStyle::State_Enabled ? PseudoClass_Enabled : PseudoClass_Disabled; + pc |= PseudoClass_Alternate; + QRenderRule subRule2 = renderRule(w, PseudoElement_ViewItem, pc); + subRule2.configurePalette(&v2Copy.palette, QPalette::NoRole, QPalette::AlternateBase); + } + baseStyle()->drawPrimitive(pe, &v2Copy, p, w); + } + } + return; + + case PE_PanelTipLabel: + if (!rule.hasDrawable()) + break; + + if (const QStyleOptionFrame *frmOpt = qstyleoption_cast<const QStyleOptionFrame *>(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<const QStyleOptionTabWidgetFrame *>(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_TabWidgetPane); + if (subRule.hasNativeBorder()) { + subRule.drawBackground(p, opt->rect); + QStyleOptionTabWidgetFrame 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: + if (!styleHint(SH_ItemView_ShowDecorationSelected, opt, w)) { + rect = subElementRect(QStyle::SE_ItemViewItemText, opt, w) + | subElementRect(QStyle::SE_ItemViewItemDecoration, opt, w) + | subElementRect(QStyle::SE_ItemViewItemCheckIndicator, opt, w); + } + pseudoElement = PseudoElement_ViewItem; + break; + + case PE_PanelItemViewRow: + ParentStyle::drawPrimitive(pe, opt, p, w); + if (!styleHint(SH_ItemView_ShowDecorationSelected, opt, w)) + return; + pseudoElement = PseudoElement_ViewItem; + break; + + case PE_PanelScrollAreaCorner: + pseudoElement = PseudoElement_ScrollAreaCorner; + break; + + 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<const QStyleOptionTitleBar *>(opt)) { + QRenderRule rule = renderRule(w, opt, PseudoElement_TitleBar); + if (rule.hasDrawable() || rule.hasBox() || rule.hasBorder()) { + QHash<QStyle::SubControl, QRect> 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<const QToolButton *>(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<const QCheckBox *>(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<const QStyleOptionSlider *>(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<const QStyleOptionSlider *>(opt)) + return sb->orientation == Qt::Horizontal ? msz.width() : msz.height(); + return msz.width() == -1 ? msz.height() : msz.width(); + } + 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; + + 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: + if (hasStyleRule(w->parentWidget(), PseudoElement_TabWidgetPane)) { + return 0; + } + break; + + 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()) { + return subRule.size(QSize(0, opt->fontMetrics.lineSpacing())).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<const QStyleOptionHeader *>(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<QAbstractSpinBox *>(w->parentWidget())) { + 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<const QStyleOptionButton *>(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<const QStyleOptionMenuItem *>(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(), height = qMax(csz.height(), mi->fontMetrics.height()); + if (!mi->icon.isNull()) { + int iconExtent = pixelMetric(PM_SmallIconSize); + height = qMax(height, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height()); + } + width += mi->tabWidth; + return subRule.boxSize(csz.expandedTo(subRule.minimumContentsSize())); + } + } + 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<const QStyleOptionTab *>(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<const QStyleOptionComplex *>(opt)) { + if (!hasStyleRule(w, PseudoElement_MdiCloseButton) + && !hasStyleRule(w, PseudoElement_MdiNormalButton) + && !hasStyleRule(w, PseudoElement_MdiMinButton)) + break; + + QList<QVariant> 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 qVariantValue<QIcon>(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 = qVariantValue<QIcon>(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<const QTabWidget *>(w)) { + rule = renderRule(w, opt, PseudoElement_TabWidgetTabBar); + if (rule.hasPosition()) + return rule.position()->position; + } +#endif // QT_NO_TABWIDGET + s = QLatin1String("alignment"); + break; + 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<const QComboBox *>(w)) { + QAbstractItemView *view = qFindChild<QAbstractItemView *>(w); + 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<const QStyleOptionComboBox *>(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<const QStyleOptionSpinBox *>(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(); + bool downRuleMatch = downRule.hasGeometry(); + 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<const QStyleOptionGroupBox *>(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<const QStyleOptionToolButton *>(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<const QStyleOptionSlider *>(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<const QStyleOptionSlider *>(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<QVariant> 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<const QStyleOptionTitleBar *>(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_TitleBar); + if (!subRule.hasDrawable() && !subRule.hasBox() && !subRule.hasBorder()) + break; + QHash<QStyle::SubControl, QRect> 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<const QStyleOptionButton *>(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<const QStyleOptionViewItemV4 *>(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<const QStyleOptionViewItemV4 *>(opt)) { + QRenderRule subRule = renderRule(w, opt, PseudoElement_ViewItem); + QStyleOptionViewItemV4 optCopy(*vopt); + optCopy.rect = subRule.contentsRect(vopt->rect); + QRect rect = ParentStyle::subElementRect(se, &optCopy, w); + 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; + QRenderRule subRule2 = renderRule(w, opt, pe); + 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<const QStyleOptionProgressBarV2 *>(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<const QStyleOptionTab *>(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; + } +#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); + } + + default: + break; + } + + return baseStyle()->subElementRect(se, opt, w); +} + +bool QStyleSheetStyle::event(QEvent *e) +{ + return baseStyle()->event(e) || 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<QWidget *>(w->parent())) { + + font = font.resolve(static_cast<QWidget *>(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)); +} + +// Returns the palette that should be used when the particular widget is focused. +// This needs to be called by some widgets that do drawing themselves instead +// of through the style. +// ### This should be removed ideally by Qt 4.5, and at least by Qt 5, and fixed +// for good by letting the style draw everything. +// Returns true if there is a new palette in pal. +bool QStyleSheetStyle::focusPalette(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/gui/styles/qstylesheetstyle_default.cpp b/src/gui/styles/qstylesheetstyle_default.cpp new file mode 100644 index 0000000000..74e23b8d6e --- /dev/null +++ b/src/gui/styles/qstylesheetstyle_default.cpp @@ -0,0 +1,555 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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; + 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; + } + + /*QLineEdit[style="QCleanlooksStyle"] { + padding-top: 2px; + padding-bottom: 2px; + }*/ + if (baseStyle()->inherits("QCleanlooksStyle")) + { + SET_ELEMENT_NAME(QLatin1String("QLineEdit")); + ADD_BASIC_SELECTOR; + ADD_SELECTOR; + + + SET_PROPERTY(QLatin1String("padding-top"), PaddingTop); + ADD_VALUE(Value::Identifier, QString::fromLatin1("2px")); + ADD_DECLARATION; + + SET_PROPERTY(QLatin1String("padding-bottom"), PaddingBottom); + ADD_VALUE(Value::Identifier, QString::fromLatin1("2px")); + ADD_DECLARATION; + + ADD_STYLE_RULE; + } + + /*QLineEdit[style="QWindowsXPStyle"], + QLineEdit[style="QWindowsVistaStyle"], + QLineEdit[style="QGtkStyle"] { + padding-top: 1px; + padding-bottom: 1px; + }*/ + if (baseStyle()->inherits("QWindowsXPStyle") || baseStyle()->inherits("QGtkStyle")) + { + SET_ELEMENT_NAME(QLatin1String("QLineEdit")); + + SET_PROPERTY(QLatin1String("padding-top"), PaddingTop); + ADD_VALUE(Value::Identifier, QString::fromLatin1("1px")); + ADD_DECLARATION; + + SET_PROPERTY(QLatin1String("padding-bottom"), PaddingBottom); + ADD_VALUE(Value::Identifier, QString::fromLatin1("1px")); + 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/gui/styles/qstylesheetstyle_p.h b/src/gui/styles/qstylesheetstyle_p.h new file mode 100644 index 0000000000..1f61445fd9 --- /dev/null +++ b/src/gui/styles/qstylesheetstyle_p.h @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 focusPalette(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 Q_SLOTS: + void widgetDestroyed(QObject *); + +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<QCss::StyleRule> styleRules(const QWidget *w) const; + bool hasStyleRule(const QWidget *w, int part) const; + + QHash<QStyle::SubControl, QRect> 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) +}; + + +QT_END_NAMESPACE +#endif // QT_NO_STYLE_STYLESHEET +#endif // QSTYLESHEETSTYLE_P_H diff --git a/src/gui/styles/qwindowscestyle.cpp b/src/gui/styles/qwindowscestyle.cpp new file mode 100644 index 0000000000..5cb72f9712 --- /dev/null +++ b/src/gui/styles/qwindowscestyle.cpp @@ -0,0 +1,2422 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 windowsSepHeight = 9; // 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 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<QToolBar*>(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<const QStyleOptionTab *>(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<const QDockWidget *>(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<const QStyleOptionFrame *>(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<const QStyleOptionButton *>(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<const QStyleOptionFrame *>(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<const QStyleOptionMenuItem *>(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<const QStyleOptionMenuItem *>(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<const QStyleOptionTab *>(option)) { + drawControl(CE_TabBarTabShape, tab, painter, widget); + drawControl(CE_TabBarTabLabel, tab, painter, widget); + } + break; + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(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<const QStyleOptionButton *>(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<const QStyleOptionSlider *>(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<const QStyleOptionToolButton *>(option)) { + QRect button, menuarea; + +#ifndef QT_NO_TOOLBAR + bool flat = !(widget ? qobject_cast<QToolBar*>(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<const QStyleOptionGroupBox *>(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<const QStyleOptionComboBox *>(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<const QStyleOptionSpinBox *>(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<const QStyleOptionButton *>(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<const QStyleOptionButton *>(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<const QStyleOptionComboBox *>(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<const QStyleOptionSpinBox *>(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<const QStyleOptionToolButton *>(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<const QStyleOptionComboBox *>(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<const QStyleOptionSlider *>(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<const QStyleOptionComboBox *>(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<const QStyleOptionSpinBox *>(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: + 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<const QStyleOptionGroupBox *>(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<const QStyleOptionSlider *>(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; + 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/gui/styles/qwindowscestyle.h b/src/gui/styles/qwindowscestyle.h new file mode 100644 index 0000000000..fbb6d691fd --- /dev/null +++ b/src/gui/styles/qwindowscestyle.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSCESTYLE_H +#define QWINDOWSCESTYLE_H + +#include <QtGui/qwindowsstyle.h> + +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/gui/styles/qwindowscestyle_p.h b/src/gui/styles/qwindowscestyle_p.h new file mode 100644 index 0000000000..177d93058d --- /dev/null +++ b/src/gui/styles/qwindowscestyle_p.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSCE_P_H +#define QWINDOWSCE_P_H + +#include "qwindowscestyle.h" +#include <private/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. +// + +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/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp new file mode 100644 index 0000000000..c52c700367 --- /dev/null +++ b/src/gui/styles/qwindowsmobilestyle.cpp @@ -0,0 +1,3503 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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_OS_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 +#endif // Q_OS_WINCE + +QT_BEGIN_NAMESPACE + +static const int windowsItemFrame = 1; // menu item frame width +static const int windowsItemHMargin = 2; // 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 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", +" ", +" ++++++++++++ ", +" +..........+ ", +" +..........+ ", +" +..........+ ", +" +..........+ ", +" +..........+ ", +" +..........+ ", +" +..........+ ", +" +.@@@@@@@@.+ ", +" +..........+ ", +" +..........+ ", +" ++++++++++++ ", +" "}; + + + +enum QSliderDirection { SliderUp, SliderDown, SliderLeft, SliderRight }; + +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_OS_WINCE + doubleControls = qt_wince_is_high_dpi(); + smartphone = qt_wince_is_smartphone(); +#else + doubleControls = false; + smartphone = false; +#endif //Q_OS_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); + } + + 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<QWindowsMobileStylePrivate*>(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<QTabWidget *>(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<const QStyleOptionTab *>(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<const QStyleOptionProgressBarV2 *>(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<const QDockWidget *>(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<const QStyleOptionFocusRect *>(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<const QComboBox*>(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<const QStyleOptionFrame *>(option)) { + + const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(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<const QStyleOptionButton *>(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 = 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_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; + 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 = 2; + break; + case PE_IndicatorArrowRight: + image = d->imageArrowRight; + xoffset = 8; + yoffset = 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<const QStyleOptionTabWidgetFrame *>(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: + 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: + if (d->doubleControls) + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + else + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + break; + case QTabBar::RoundedEast: + painter->drawLine(rect.topRight(), rect.bottomRight()); + break; + case QTabBar::RoundedWest: + 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 + + 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<QLineF> 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_Frame: + if (d->doubleControls) + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(),2,&option->palette.light()); + else + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(),1,&option->palette.light()); + 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<QWindowsMobileStylePrivate*>(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<const QStyleOptionButton *>(option)) { + QRect br = button->rect; + int dbi = 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; + drawPrimitive(PE_PanelButtonCommand, &tmpBtn, painter, widget); + if (button->features & QStyleOptionButton::HasMenu) { + int mbi = 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); + drawPrimitive(PE_IndicatorArrowDown, &newButton, painter, widget); + } + if (button->features & QStyleOptionButton::DefaultButton) + drawPrimitive(PE_FrameDefaultButton, option, painter, widget); + } + break; + case CE_RadioButton: + case CE_CheckBox: + if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) { + bool isRadio = (element == CE_RadioButton); + QStyleOptionButton subopt = *button; + subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator + : SE_CheckBoxIndicator, button, widget); + drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox, + &subopt, painter, widget); + subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents + : SE_CheckBoxContents, button, widget); + drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget); + if (button->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*button); + fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect + : SE_CheckBoxFocusRect, button, widget); + drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + } + break; + case CE_RadioButtonLabel: + case CE_CheckBoxLabel: + if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(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); + 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) + drawItemText(painter, textRect, alignment | Qt::TextShowMnemonic, + button->palette, false, button->text, QPalette::WindowText); + else + 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<const QStyleOptionTab *>(option)) { + drawControl(CE_TabBarTabShape, tab, painter, widget); + drawControl(CE_TabBarTabLabel, tab, painter, widget); + } + break; + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) { + if (tab->shape == QTabBar::RoundedNorth || tab->shape == QTabBar::RoundedEast || + tab->shape == QTabBar::RoundedSouth || tab->shape == QTabBar::RoundedWest) { + + painter->save(); + painter->setPen(tab->palette.shadow().color()); + if (d->doubleControls) { + QPen pen = painter->pen(); + pen.setWidth(2); + pen.setCapStyle(Qt::FlatCap); + painter->setPen(pen); + } + if(tab->shape == QTabBar::RoundedNorth) { + if (tab->state & 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 & 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 (d->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 & 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 & 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(); + } 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<const QStyleOptionToolBar *>(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<const QStyleOptionHeader *>(option)) { + QRegion clipRegion = painter->clipRegion(); + painter->setClipRect(option->rect); + drawControl(CE_HeaderSection, header, painter, widget); + QStyleOptionHeader subopt = *header; + subopt.rect = 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()) + drawControl(CE_HeaderLabel, &subopt, painter, widget); + if (header->sortIndicator != QStyleOptionHeader::None) { + subopt.rect = subElementRect(SE_HeaderArrow, option, widget); + drawPrimitive(PE_IndicatorHeaderArrow, &subopt, painter, widget); + } + painter->setClipRegion(clipRegion); + } + break; + + case CE_HeaderSection: + if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(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<const QAbstractScrollArea *> (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_DOCKWIDGET + case CE_DockWidgetTitle: + if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) { + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(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 = 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()); + } + 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<const QStyleOptionButton *>(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() -= 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) + drawItemText(painter, ir, tf, button->palette, true, button->text, colorRole); + else + 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<QWindowsMobileStylePrivate*>(d_func()); + + switch (control) { +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(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) { + 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 = 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); + 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<const QStyleOptionSlider *>(option)) { + // Make a copy here and reset it for each primitive. + QBrush fill; + if (d->smartphone) { + fill = option->palette.light(); + painter->fillRect(option->rect,fill); + fill = option->palette.button(); + QImage image; +#ifndef QT_NO_IMAGEFORMAT_XPM + if (scrollbar->orientation == Qt::Horizontal) + image = QImage(vertlines_xpm); + else + image = QImage(horlines_xpm); +#endif + image.setColor(1, option->palette.button().color().rgb()); + fill.setTextureImage(image); + } + else { + fill = option->palette.light(); + } + painter->fillRect(option->rect,fill); + 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<QAbstractScrollArea *>(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<QListView *>(parent->parentWidget())) + drawCompleteFrame = false; +#endif + } + if (scrollbar->minimum == scrollbar->maximum) + saveFlags |= State_Enabled; + if (scrollbar->subControls & SC_ScrollBarSubLine) { + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarSubLine, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarSubLine)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + QStyleOption arrowOpt = newScrollbar; + if (d->doubleControls) + arrowOpt.rect = newScrollbar.rect.adjusted(4, 6, -5, -3); + else + arrowOpt.rect = newScrollbar.rect.adjusted(5, 6, -4, -3); + QBrush fill = option->palette.button(); + if (newScrollbar.state & State_Sunken) + fill = option->palette.shadow(); + if (scrollbar->orientation == Qt::Horizontal) { + painter->fillRect(newScrollbar.rect,fill); + QRect r = newScrollbar.rect.adjusted(0,0,1,0); + painter->drawLine(r.topRight(), r.bottomRight()); + if (d->doubleControls) + arrowOpt.rect.adjust(0, -2 ,0, -2); + drawPrimitive(PE_IndicatorArrowLeft, &arrowOpt, painter, widget); + } + else { + painter->fillRect(newScrollbar.rect,fill); + QRect r = newScrollbar.rect.adjusted(0, 0, 0, 1); + painter->drawLine(r.bottomLeft(), r.bottomRight()); + if (drawCompleteFrame) + arrowOpt.rect.adjust(-2, 0, -2, 0); + if (d->doubleControls) + arrowOpt.rect.adjust(0, -4 , 0, -4); + if (drawCompleteFrame && d->doubleControls) + arrowOpt.rect.adjust(2, 0, 2, 0); + drawPrimitive(PE_IndicatorArrowUp, &arrowOpt, painter, widget); + } + } + } + if (scrollbar->subControls & SC_ScrollBarAddLine) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarAddLine, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarAddLine)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + QStyleOption arrowOpt = newScrollbar; + if (d->doubleControls) + arrowOpt.rect = newScrollbar.rect.adjusted(4, 0, -5, 3); + else + arrowOpt.rect = newScrollbar.rect.adjusted(5, 6, -4, -3); + QBrush fill = option->palette.button(); + if (newScrollbar.state & State_Sunken) + fill = option->palette.shadow(); + if (scrollbar->orientation == Qt::Horizontal) { + painter->fillRect(newScrollbar.rect,fill); + QRect r = newScrollbar.rect.adjusted(0, 0, 0, 0); + painter->drawLine(r.topLeft(), r.bottomLeft()); + if (secondScrollBar) + painter->drawLine(r.topRight(), r.bottomRight()); + if (d->doubleControls) + arrowOpt.rect.adjust(0, 4, 0, 4 ); + drawPrimitive(PE_IndicatorArrowRight, &arrowOpt, painter, widget); + } + else { + painter->fillRect(newScrollbar.rect,fill); + QRect r = newScrollbar.rect.adjusted(0, -1, 0, -1); + painter->drawLine(r.topLeft(), r.topRight()); + if (secondScrollBar) + painter->drawLine(r.bottomLeft() + QPoint(0,1), r.bottomRight() + QPoint(0, 1)); + if (drawCompleteFrame) + arrowOpt.rect.adjust(-2, 0, -2, 0); + if (d->doubleControls) + arrowOpt.rect.adjust(1, 0, 1, 0 ); + if (drawCompleteFrame && d->doubleControls) + arrowOpt.rect.adjust(1, 0, 1, 0); + drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget); + } + } + } + if (scrollbar->subControls & SC_ScrollBarSubPage) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarSubPage, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarSubPage)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + if (scrollbar->orientation == Qt::Horizontal) { + QRect r = newScrollbar.rect.adjusted(0, 0, 0, 0); + } + else{ + QRect r = newScrollbar.rect.adjusted(0, 0, 0, 0); + } + } + } + if (scrollbar->subControls & SC_ScrollBarAddPage) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarAddPage, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarAddPage)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + if (scrollbar->orientation == Qt::Horizontal) { + QRect r = newScrollbar.rect.adjusted(0, 0, 0, -1); + } + else { + QRect r = newScrollbar.rect.adjusted(0, 0,- 1, 0); + } + } + } + if (scrollbar->subControls & SC_ScrollBarFirst) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarFirst, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarFirst)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + QRect r = newScrollbar.rect; + } + } + if (scrollbar->subControls & SC_ScrollBarLast) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarLast, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarLast)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + QRect r = newScrollbar.rect; + } + } + if (scrollbar->subControls & SC_ScrollBarSlider) { + newScrollbar.rect = scrollbar->rect; + newScrollbar.state = saveFlags; + newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarSlider, widget); + if (newScrollbar.rect.isValid()) { + if (!(scrollbar->activeSubControls & SC_ScrollBarSlider)) + newScrollbar.state &= ~(State_Sunken | State_MouseOver); + if (scrollbar->orientation == Qt::Horizontal) { + painter->fillRect(newScrollbar.rect,option->palette.button()); + QRect r = newScrollbar.rect; + painter->drawLine(r.topLeft(), r.bottomLeft()); + painter->drawLine(r.topRight(), r.bottomRight()); + if (d->smartphone) { + painter->drawLine(r.topLeft(), r.topRight()); + painter->drawLine(r.bottomLeft(), r.bottomRight()); + } + } + else { + painter->fillRect(newScrollbar.rect,option->palette.button()); + QRect r = newScrollbar.rect; + painter->drawLine(r.topLeft(), r.topRight()); + painter->drawLine(r.bottomLeft(), r.bottomRight()); + if (d->smartphone) { + painter->drawLine(r.topLeft(), r.bottomLeft()); + painter->drawLine(r.topRight(), r.bottomRight()); + } + } + 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); + } + } + } + int gripMargin = d->doubleControls ? 4 : 2; + int doubleLines = d->doubleControls ? 2 : 1; + //If there is a frame around the scrollbar (abstractScrollArea), + //then the margin is different, because of the missing frame + int gripMarginFrame = d->doubleControls ? 3 : 1; + if (drawCompleteFrame) + gripMarginFrame = 0; + //draw grips + if (!d->smartphone) + if (scrollbar->orientation == Qt::Horizontal) { + for (int i = -3; i < 3; i += 2) { + painter->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) { + painter->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 (!d->smartphone) { + QRect r; + if (d->doubleControls) + r = option->rect.adjusted(1, 1, -1, 0); + else + r = option->rect.adjusted(0, 0, -1, 0); + if (drawCompleteFrame && d->doubleControls) + r.adjust(0, 0, 0, -1); + //Check if the scrollbar is part of an abstractItemView and draw the frame according + if (drawCompleteFrame) + painter->drawRect(r); + else + if (scrollbar->orientation == Qt::Horizontal) + painter->drawLine(r.topLeft(), r.topRight()); + else + painter->drawLine(r.topLeft(), r.bottomLeft()); + } + } + painter->restore(); + break; +#endif // QT_NO_SLIDER + case CC_ToolButton: + if (const QStyleOptionToolButton *toolbutton + = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { + QRect button, menuarea; + bool isTabWidget = false; +#ifndef QT_NO_TABWIDGET + if (widget) + if (QWidget *parent = widget->parentWidget()) + isTabWidget = (qobject_cast<QTabWidget *>(parent->parentWidget())); +#endif //QT_NO_TABWIDGET + + button = subControlRect(control, toolbutton, SC_ToolButton, widget); + menuarea = 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; + 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) + 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; + 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, -pixelMetric(QStyle::PM_MenuButtonIndicator, + toolbutton, widget), 0); + drawPrimitive(PE_FrameFocusRect, &focusRect, painter, widget); + } + QStyleOptionToolButton label = *toolbutton; + if (isTabWidget) + label.state = toolbutton->state; + else + label.state = toolbutton->state & State_Enabled; + 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<const QStyleOptionGroupBox *>(option)) { + // Draw frame + painter->save(); + QFont font = painter->font(); + font.setBold(true); + painter->setFont(font); + QStyleOptionGroupBox groupBoxFont = *groupBox; + groupBoxFont.fontMetrics = QFontMetrics(font); + QRect textRect = subControlRect(CC_GroupBox, &groupBoxFont, SC_GroupBoxLabel, widget); + QRect checkBoxRect = 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 = 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; + } + drawPrimitive(PE_FrameGroupBox, &frame, painter, widget); + painter->restore(); + } + // Draw checkbox + if (groupBox->subControls & SC_GroupBoxCheckBox) { + QStyleOptionButton box; + box.QStyleOption::operator=(*groupBox); + box.rect = checkBoxRect; + 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) + drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment, + groupBox->palette, true, groupBox->text, + textColor.isValid() ? QPalette::NoRole : QPalette::Link); + else + 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; + 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<const QStyleOptionComboBox *>(option)) { + QBrush editBrush = cmb->palette.brush(QPalette::Base); + if ((cmb->subControls & SC_ComboBoxFrame) && cmb->frame) + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(), pixelMetric(PM_ComboBoxFrameWidth, option, widget), &editBrush); + else + painter->fillRect(option->rect, editBrush); + State flags = State_None; + QRect ar = 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; + drawPrimitive(PrimitiveElement(PE_IndicatorArrowDownBig), &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(); + if ((option->state & State_On)) + drawPrimitive(PE_FrameFocusRect, &focus, painter, widget); + } + } + } + break; +#endif // QT_NO_COMBOBOX + + +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { + QStyleOptionSpinBox copy = *spinBox; + //PrimitiveElement primitiveElement; + int primitiveElement; + + if (spinBox->frame && (spinBox->subControls & SC_SpinBoxFrame)) { + QRect r = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxFrame, widget); + qDrawPlainRect(painter, r, option->palette.shadow().color(),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 = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxUp, widget); + if (copy.state & (State_Sunken | State_On)) + qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(),pixelMetric(PM_SpinBoxFrameWidth, option, widget), ©.palette.brush(QPalette::Shadow)); + else + qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(),pixelMetric(PM_SpinBoxFrameWidth, option, widget), ©.palette.brush(QPalette::Base)); + copy.rect.adjust(pixelMetric(PM_SpinBoxFrameWidth, option, widget), 0, -pixelMetric(PM_SpinBoxFrameWidth, option, widget), 0); + 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 = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxDown, widget); + qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(),pixelMetric(PM_SpinBoxFrameWidth, option, widget), ©.palette.brush(QPalette::Base)); + if (copy.state & (State_Sunken | State_On)) + qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(),pixelMetric(PM_SpinBoxFrameWidth, option, widget), ©.palette.brush(QPalette::Shadow)); + else + qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(),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 = pixelMetric(PM_SpinBoxFrameWidth, option, widget); + copy.rect = copy.rect.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth); + drawPrimitive(PrimitiveElement(primitiveElement), ©, painter, widget); + } + else { + drawPrimitive(PrimitiveElement(primitiveElement), ©, painter, widget); + } + if (spinBox->frame && (spinBox->subControls & SC_SpinBoxFrame)) { + QRect r = 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<const QStyleOptionButton *>(option)) { + newSize = QWindowsStyle::sizeFromContents(type, option, size, widget); + int w = newSize.width(), + h = newSize.height(); + int defwidth = 0; + if (button->features & QStyleOptionButton::AutoDefaultButton) + defwidth = 2 * pixelMetric(PM_ButtonDefaultIndicator, button, widget); + if (w < 75 + defwidth && button->icon.isNull()) + w = 75 + defwidth; + if (h < 23 + defwidth) + h = 23 + defwidth; + newSize = QSize(w + 4, h + 4); + } + break; + +#ifndef QT_NO_GROUPBOX + case CT_GroupBox: + if (const QGroupBox *grb = static_cast<const QGroupBox *>(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<const QStyleOptionButton *>(option)) { + bool isRadio = (type == CT_RadioButton); + QRect irect = visualRect(button->direction, button->rect, + subElementRect(isRadio ? SE_RadioButtonIndicator + : SE_CheckBoxIndicator, button, widget)); + int h = 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<const QStyleOptionComboBox *>(option)) { + int fw = comboBox->frame ? pixelMetric(PM_ComboBoxFrameWidth, option, widget) * 2 : 0; + newSize = QSize(newSize.width() + fw + 9, newSize.height() + fw-4); //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<const QStyleOptionSpinBox *>(option)) { + int fw = spinBox->frame ? 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: + newSize += QSize(0,0); + break; + case CT_HeaderSection: + newSize += QSize(4, 2); + break; + default: + break; + } + return newSize; +} + +QRect QWindowsMobileStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const { + + QWindowsMobileStylePrivate *d = const_cast<QWindowsMobileStylePrivate*>(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<const QStyleOptionSlider *>(option)) { + rect = slider->rect; + } + break; + case SE_PushButtonFocusRect: + if (d->doubleControls) + rect.adjust(-1, -1, 0, 0); + break; +#endif // QT_NO_SLIDER + } + return rect; +} + +QRect QWindowsMobileStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, + SubControl subControl, const QWidget *widget) const { + + QWindowsMobileStylePrivate *d = const_cast<QWindowsMobileStylePrivate*>(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<const QStyleOptionSlider *>(option)) { + int sliderButtonExtent = pixelMetric(PM_ScrollBarExtent, scrollbar, widget); + int sliderlen; + float stretchFactor = 1.4f; + int sliderButtonExtentDir = int (sliderButtonExtent * stretchFactor); + 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 = 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<const QStyleOptionToolButton *>(option)) { + int mbi = 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<const QStyleOptionSlider *>(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 *comboBox = qstyleoption_cast<const QStyleOptionComboBox *>(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); + rect.setRect(xpos, y + bmarg, int((he - 2*bmarg)), he - 2*bmarg); + break; + case SC_ComboBoxEditField: + rect.setRect(x + margin+4, y + margin+2, wi - 4 * margin - int((he - 2*bmarg) * 0.84f) -2, he - 2 * margin-4); + 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<const QStyleOptionSpinBox *>(option)) { + QSize bs; + int fw = spinBox->frame ? 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+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: + 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<const QStyleOptionGroupBox *>(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 = 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 = 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(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 = 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<QToolBar*>(widget)) { + QPalette pal = toolBar->palette(); + pal.setColor(QPalette::Background, pal.button().color()); + toolBar->setPalette(pal); + } + else +#endif //QT_NO_TOOLBAR + +#ifndef QT_NO_PROPERTIES + if (QAbstractButton *pushButton = qobject_cast<QAbstractButton*>(widget)) { + QVariant oldFont = widget->property("_q_styleWindowsMobileFont"); + if (!oldFont.isValid()) { + QFont f = pushButton->font(); + widget->setProperty("_q_styleWindowsMobileFont", f); + f.setBold(true); + int p = f.pointSize(); + if (p > 2) + f.setPointSize(p-1); + pushButton->setFont(f); + } + } +#endif + QWindowsStyle::polish(widget); +} + +void QWindowsMobileStyle::unpolish(QWidget *widget) +{ +#ifndef QT_NO_PROPERTIES + if (QAbstractButton *pushButton = qobject_cast<QAbstractButton*>(widget)) { + QVariant oldFont = widget->property("_q_styleWindowsMobileFont"); + if (oldFont.isValid()) { + widget->setFont(qVariantValue<QFont>(oldFont)); + widget->setProperty("_q_styleWindowsMobileFont", QVariant()); + } + } +#endif + 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<QWindowsMobileStylePrivate*>(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; + case PM_CheckBoxLabelSpacing: + case PM_RadioButtonLabelSpacing: + ret = d->doubleControls ? 6 * 2 : 6; + break; + 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<const QStyleOptionSlider *>(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 += 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 = 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: + d->doubleControls ? ret = 36 : ret = 18; + break; + case PM_ScrollBarExtent: { + //Check if the scrollbar is part of an abstractItemView and set size according + if (d->smartphone) + ret = 9; + else + d->doubleControls ? ret = 25 : ret = 13; +#ifndef QT_NO_SCROLLAREA + if (widget) + if (QWidget *parent = widget->parentWidget()) + if (qobject_cast<QAbstractScrollArea *>(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; + 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<QWindowsMobileStylePrivate*>(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: { + 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<QWindowsMobileStylePrivate*>(d_func()); + + return d->doubleControls; +} + +void QWindowsMobileStyle::setDoubleControls(bool doubleControls) { + + QWindowsMobileStylePrivate *d = const_cast<QWindowsMobileStylePrivate*>(d_func()); + + d->doubleControls = doubleControls; +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_WINDOWSMOBILE + diff --git a/src/gui/styles/qwindowsmobilestyle.h b/src/gui/styles/qwindowsmobilestyle.h new file mode 100644 index 0000000000..f23ecc9928 --- /dev/null +++ b/src/gui/styles/qwindowsmobilestyle.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSMOBILESTYLE_H +#define QWINDOWSMOBILESTYLE_H + +#include <QtGui/qwindowsstyle.h> + +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/gui/styles/qwindowsmobilestyle_p.h b/src/gui/styles/qwindowsmobilestyle_p.h new file mode 100644 index 0000000000..83129cf58b --- /dev/null +++ b/src/gui/styles/qwindowsmobilestyle_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 QWindowsMobileStylePrivate : public QWindowsStylePrivate +{ + Q_DECLARE_PUBLIC(QWindowsMobileStyle) +public: + QWindowsMobileStylePrivate(); + bool doubleControls; + bool smartphone; + + 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; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_WINDOWSMOBILE +#endif //QWINDOWSMOBILESTYLE_P_H diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp new file mode 100644 index 0000000000..00c3f99cc2 --- /dev/null +++ b/src/gui/styles/qwindowsstyle.cpp @@ -0,0 +1,3408 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsstyle.h" +#include "qwindowsstyle_p.h" +#include <private/qpixmapdata_p.h> + +#if !defined(QT_NO_STYLE_WINDOWS) || defined(QT_PLUGIN) + +#include "qlibrary.h" +#include "qapplication.h" +#include "qbitmap.h" +#include "qdrawutil.h" // for now +#include "qevent.h" +#include "qmenu.h" +#include "qmenubar.h" +#include <private/qmenubar_p.h> +#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" + +#ifdef Q_WS_X11 +#include "qfileinfo.h" +#include "qdir.h" +#include <private/qt_x11_p.h> +#endif + +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 <limits.h> +QT_END_INCLUDE_NAMESPACE + +static const int windowsItemFrame = 2; // menu item frame width +static const int windowsSepHeight = 9; // 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 windowsCheckMarkHMargin = 2; // horiz. margins of check mark +static const int windowsRightBorder = 15; // right border on windows +static const int windowsCheckMarkWidth = 12; // checkmarks width on windows + +static bool use2000style = true; + +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)) { + QLibrary shellLib(QLatin1String("shell32")); + pSHGetStockIconInfo = (PtrSHGetStockIconInfo)shellLib.resolve("SHGetStockIconInfo"); + } +#endif +} + +// 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<QWidget*>(o); + Q_D(QWindowsStyle); + switch(e->type()) { + case QEvent::KeyPress: + if (static_cast<QKeyEvent *>(e)->key() == Qt::Key_Alt) { + widget = widget->window(); + + // Alt has been pressed - find all widgets that care + QList<QWidget *> l = qFindChildren<QWidget *>(widget); + 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<QKeyEvent*>(e)->key() == Qt::Key_Alt) { + widget = widget->window(); + + // Update state and repaint the menu bars. + d->alt_down = false; +#ifndef QT_NO_MENUBAR + QList<QMenuBar *> l = qFindChildren<QMenuBar *>(widget); + 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<QProgressBar *>(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<QProgressBar *>(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) +{ +#if defined(Q_OS_WIN32) + use2000style = QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95; +#endif +} + +/*! + \internal + + Constructs a QWindowsStyle object. +*/ +QWindowsStyle::QWindowsStyle(QWindowsStylePrivate &dd) : QCommonStyle(dd) +{ +#if defined(Q_OS_WIN32) + use2000style = QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95; +#endif +} + + +/*! 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<QWindowsStylePrivate*>(d_func()); + // We only need the overhead when shortcuts are sometimes hidden + if (!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<QProgressBar *>(widget)) + widget->installEventFilter(this); +#endif +} + +/*! \reimp */ +void QWindowsStyle::unpolish(QWidget *widget) +{ + QCommonStyle::unpolish(widget); +#ifndef QT_NO_PROGRESSBAR + if (QProgressBar *bar=qobject_cast<QProgressBar *>(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 = 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<const QStyleOptionSlider *>(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 += 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 = 16; + break; + + case PM_LargeIconSize: + ret = 32; + break; + + case PM_IconViewIconSize: + ret = pixelMetric(PM_LargeIconSize, opt, widget); + break; + + case PM_ToolBarIconSize: + ret = 24; + break; + case PM_DockWidgetTitleMargin: + ret = 2; + break; + case PM_DockWidgetTitleBarButtonMargin: + ret = 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 = sizeof(NONCLIENTMETRICS); + 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 = 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 + +/*! + \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 = convertHIconToPixmap( iconHandle ); + DestroyIcon(iconHandle); + break; + } + case SP_MessageBoxWarning: + { + HICON iconHandle = LoadIcon(NULL, IDI_WARNING); + desktopIcon = convertHIconToPixmap( iconHandle ); + DestroyIcon(iconHandle); + break; + } + case SP_MessageBoxCritical: + { + HICON iconHandle = LoadIcon(NULL, IDI_ERROR); + desktopIcon = convertHIconToPixmap( iconHandle ); + DestroyIcon(iconHandle); + break; + } + case SP_MessageBoxQuestion: + { + HICON iconHandle = LoadIcon(NULL, IDI_QUESTION); + desktopIcon = convertHIconToPixmap( 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 = convertHIconToPixmap(iconInfo.hIcon); + DestroyIcon(iconInfo.hIcon); + return pixmap; + } + } + } + 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<const QListView*>(widget)) + ret = 1; +#endif + break; + case SH_ItemView_ChangeHighlightOnFocus: +#if defined(Q_WS_WIN) + if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) + ret = 1; + else +#endif + ret = 0; + break; + case SH_ToolBox_SelectedPageTitleBold: + ret = 0; + break; + +#if defined(Q_WS_WIN) + case SH_UnderlineShortcut: + ret = 1; + if (QSysInfo::WindowsVersion != QSysInfo::WV_95 + && QSysInfo::WindowsVersion != QSysInfo::WV_98 + && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { + BOOL cues; + 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<const QMenuBar *>(widget); + if (!menuBar && qobject_cast<const QMenu *>(widget)) { + QWidget *w = QApplication::activeWindow(); + if (w && w != widget) + menuBar = qFindChild<QMenuBar *>(w); + } + // 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<const QStyleOptionRubberBand *>(opt)) { + ret = 0; + if (rbOpt->shape == QRubberBand::Rectangle) { + ret = true; + if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(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; + 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 (QApplication::layoutDirection() == 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) && use2000style) { + 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<const QStyleOptionButton *>(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; + pixmapName.sprintf("%s-%s-%d-%d-%d-%lld", + "$qt_ia", metaObject()->className(), + uint(opt->state), pe, + size, opt->palette.cacheKey()); + if (!QPixmapCache::find(pixmapName, pixmap)) { + int border = size/5; + int sqsize = 2*(size/2); + QImage image(sqsize, sqsize, QImage::Format_ARGB32); + image.fill(Qt::transparent); + 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 = pixelMetric(PM_ButtonShiftHorizontal, opt, w); + bsy = 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<const QStyleOptionViewItem *>(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<const QStyleOptionFocusRect *>(opt)) { + //### check for d->alt_down + if (!(fropt->state & State_KeyboardFocusChange) && !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 = pixelMetric(PM_ExclusiveIndicatorWidth); + int indicatorHeight = 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<const QStyleOptionFrame *>(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 (use2000style && pe == PE_Frame && (frame->state & State_Raised)) + qDrawWinButton(p, frame->rect, popupPal, frame->state & State_Sunken); + else if (use2000style && 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<const QStyleOptionFrame *>(opt)) { + 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<const QStyleOptionProgressBarV2 *>(opt)) { + vertical = (pb2->orientation == Qt::Vertical); + inverted = pb2->invertedAppearance; + } + + int space = 2; + int chunksize = 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: + if (use2000style) { + QRect rect = opt->rect; + QPalette pal = opt->palette; + 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<const QStyleOptionRubberBand *>(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 (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<const QMainWindow *>(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<const QStyleOptionMenuItem *>(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, 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(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(); + 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() + windowsItemFrame, menuitem->rect.y() + windowsItemFrame, + checkcol - 2 * windowsItemFrame, menuitem->rect.height() - 2*windowsItemFrame)); + 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 = 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, 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 && 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 * windowsItemFrame) / 2; + PrimitiveElement arrow; + arrow = (opt->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; + xpos = x + w - windowsArrowHMargin - 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()); + drawPrimitive(arrow, &newMI, p, widget); + } + + } + break; +#endif // QT_NO_MENU +#ifndef QT_NO_MENUBAR + case CE_MenuBarItem: + if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(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(pixelMetric(PM_ButtonShiftHorizontal, mbi, widget), + 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<const QStyleOptionTab *>(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 = 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(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); + if (!use2000style) { + p->setPen(midlight); + p->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); + p->setPen(light); + p->drawLine(beg, y1, end, y1); + if (!use2000style) { + p->setPen(midlight); + p->drawLine(beg, y1 + 1, end, y1 + 1); + } + } + // 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); + if (!use2000style) { + p->setPen(midlight); + p->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); + 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); + if (!use2000style) { + p->setPen(midlight); + p->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); + p->setPen(light); + p->drawLine(x1, beg, x1, end); + if (!use2000style) { + p->setPen(midlight); + p->drawLine(x1 + 1, beg, x1 + 1, 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); + if (!use2000style) { + p->setPen(midlight); + p->drawLine(x2 - 3, y1 + 1, x1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1 + 1); + p->drawPoint(x2 - 1, y1); + } + } + // 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 (use2000style && (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); + 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<const QStyleOptionToolBar *>(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(QApplication::layoutDirection() == 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<const QStyleOptionProgressBar *>(opt)) { + + QRect rect = pb->rect; + bool vertical = false; + bool inverted = false; + + // Get extra style options if version 2 + const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(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 = 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(); + 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(); + 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<const QStyleOptionDockWidget *>(opt)) { + Q_D(const QWindowsStyle); + + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(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; + int menuOffset = 0; //used to center text when floated + 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; + } + 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; + } + 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()); + } + 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<const QStyleOptionDockWidgetV2*>(opt); + bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + int m = pixelMetric(PM_DockWidgetTitleMargin, opt, w); + if (verticalTitleBar) { + r.adjust(0, 0, 0, -m); + } else { + if (QApplication::layoutDirection() == 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<const QStyleOptionSlider *>(opt)) { + 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; + + 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); + 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<const QStyleOptionSlider *>(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<const QStyleOptionQ3ListView *>(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<const QStyleOptionComboBox *>(opt)) { + QBrush editBrush = cmb->palette.brush(QPalette::Base); + if ((cmb->subControls & SC_ComboBoxFrame)) { + if (cmb->frame) { + QPalette shadePal = opt->palette; + if (use2000style) + 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 = 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 (sunkenArrow) + flags |= State_Sunken; + QStyleOption arrowOpt(0); + arrowOpt.rect = ar.adjusted(1, 1, -1, -1); + arrowOpt.palette = cmb->palette; + arrowOpt.state = flags; + drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); + } + + if (cmb->subControls & SC_ComboBoxEditField) { + QRect re = 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(); + drawPrimitive(PE_FrameFocusRect, &focus, p, widget); + } + } + } + break; +#endif // QT_NO_COMBOBOX +#ifndef QT_NO_SPINBOX + case CC_SpinBox: + if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(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 = subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget); + QPalette shadePal = sb->palette; + if (use2000style) + 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 = 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) ) { + QStyleOptionSpinBox lightCopy = copy; + lightCopy.rect.adjust(1, 1, 1, 1); + lightCopy.palette.setBrush(QPalette::ButtonText, copy.palette.light()); + drawPrimitive(pe, &lightCopy, p, widget); + } + 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 = 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) ) { + QStyleOptionSpinBox lightCopy = copy; + lightCopy.rect.adjust(1, 1, 1, 1); + lightCopy.palette.setBrush(QPalette::ButtonText, copy.palette.light()); + drawPrimitive(pe, &lightCopy, p, widget); + } + 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<const QStyleOptionButton *>(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 * pixelMetric(PM_ButtonDefaultIndicator, btn, widget); +#ifndef QT_QWS_SMALL_PUSHBUTTON + if (w < 75 + defwidth && !btn->text.isEmpty()) + w = 75 + defwidth; + if (h < 23 + defwidth) + h = 23 + defwidth; +#endif + sz = QSize(w, h); + } + break; +#ifndef QT_NO_MENU + case CT_MenuItem: + if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) { + int w = sz.width(); + sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); + + if (mi->menuItemType == QStyleOptionMenuItem::Separator) { + sz = QSize(10, windowsSepHeight); + } + else if (mi->icon.isNull()) { + sz.setHeight(sz.height() - 2); + w -= 6; + } + + if (mi->menuItemType != QStyleOptionMenuItem::Separator && !mi->icon.isNull()) { + int iconExtent = pixelMetric(PM_SmallIconSize, opt, widget); + sz.setHeight(qMax(sz.height(), + mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + + 2 * windowsItemFrame)); + } + int maxpmw = mi->maxIconWidth; + int tabSpacing = use2000style ? 20 :windowsTabSpacing; + if (mi->text.contains(QLatin1Char('\t'))) + w += tabSpacing; + else if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) + w += 2 * 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, windowsCheckMarkWidth); // Windows always shows a check column + w += checkcol; + w += windowsRightBorder + 10; + sz.setWidth(w); + } + break; +#endif // QT_NO_MENU +#ifndef QT_NO_MENUBAR + case CT_MenuBarItem: + if (!sz.isEmpty()) + sz += QSize(windowsItemHMargin * 4, windowsItemVMargin * 2); + break; +#endif + // Otherwise, fall through + case CT_ToolButton: + if (qstyleoption_cast<const QStyleOptionToolButton *>(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(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(convertHIconToPixmap(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/gui/styles/qwindowsstyle.h b/src/gui/styles/qwindowsstyle.h new file mode 100644 index 0000000000..7f45f206ca --- /dev/null +++ b/src/gui/styles/qwindowsstyle.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSSTYLE_H +#define QWINDOWSSTYLE_H + +#include <QtGui/qcommonstyle.h> + +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/gui/styles/qwindowsstyle_p.h b/src/gui/styles/qwindowsstyle_p.h new file mode 100644 index 0000000000..1d1bdf5ee6 --- /dev/null +++ b/src/gui/styles/qwindowsstyle_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 <qlist.h> +#include <qdatetime.h> +#include <qhash.h> + +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<const QWidget *> seenAlt; + int menuBarTimer; + + QList<QProgressBar *> bars; + int animationFps; + int animateTimer; + QTime startTime; + int animateStep; + QColor inactiveCaptionText; + QColor activeCaptionColor; + QColor activeGradientCaptionColor; + QColor inactiveCaptionColor; + QColor inactiveGradientCaptionColor; + }; + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_WINDOWS + +#endif //QWINDOWSSTYLE_P_H diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp new file mode 100644 index 0000000000..4c3060d063 --- /dev/null +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -0,0 +1,2650 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsvistastyle.h" +#include "qwindowsvistastyle_p.h" + +#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 +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 Animation::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 Animation::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 Transition::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 Pulse::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); +} + + +/*! + \reimp + * + * 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<QWindowsVistaStylePrivate*>(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<const QLineEdit*>(widget) && element == PE_FrameLineEdit) || +#endif // QT_NO_LINEEDIT + (qobject_cast<const QRadioButton*>(widget)&& element == PE_IndicatorRadioButton) || + (qobject_cast<const QCheckBox*>(widget) && element == PE_IndicatorCheckBox) || + (qobject_cast<const QGroupBox *>(widget)&& element == PE_IndicatorCheckBox) || + (qobject_cast<const QToolButton*>(widget) && element == PE_PanelButtonBevel) + ) + { + // Retrieve and update the dynamic properties tracking + // the previous state of the widget: + QWidget *w = const_cast<QWidget *> (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 = ((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<const QLineEdit *>(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); + + Animation *anim = d->widgetAnimation(widget); + Transition *t = new Transition; + 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) + 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; + 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<const QStyleOptionHeader *>(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 const int decoration_size = 16; + 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 (Animation *a = d->widgetAnimation(widget)) { + a->paint(painter, option); + } else { + QWindowsXPStyle::drawPrimitive(element, option, painter, widget); + } + } + break; + + case PE_IndicatorToolBarHandle: + { + XPThemeData theme; + if (option->state & State_Horizontal) + theme = XPThemeData(widget, painter, QLatin1String("REBAR"), RP_GRIPPER, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2)); + else + theme = XPThemeData(widget, painter, QLatin1String("REBAR"), RP_GRIPPERVERT, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2)); + d->drawBackground(theme); + } + 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<const QTextEdit*>(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<const QStyleOptionFrame *>(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<QAbstractSpinBox*>(widget->parentWidget())) + resolve_mask = spinbox->palette().resolve(); +#endif // QT_NO_SPINBOX +#ifndef QT_NO_COMBOBOX + if (QComboBox *combobox = qobject_cast<QComboBox*>(widget->parentWidget())) + resolve_mask = combobox->palette().resolve(); +#endif // QT_NO_COMBOBOX + } + 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) + drawPrimitive(PE_FrameLineEdit, panel, painter, widget); + return; + } + break; + + case PE_FrameLineEdit: + if (Animation *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_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<const QAbstractItemView *>(widget); + bool newStyle = false; + + if (const QListView *listview = qobject_cast<const QListView *>(widget)) { + if (listview->viewMode() == QListView::IconMode) + newStyle = true; + } else if (const QTreeView* treeview = qobject_cast<const QTreeView *>(widget)) { + newStyle = true; + } + if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(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(pixmapRect, pixmap, srcRect.adjusted(0, 0, -frame, 0)); + else if (reverse ? leftSection : rightSection) + painter->drawPixmap(pixmapRect, pixmap, + srcRect.adjusted(frame, 0, 0, 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<const QMessageBox *> (widget)) + buttonBox = qFindChild<const QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); +#ifndef QT_NO_INPUTDIALOG + else if (qobject_cast<const QInputDialog *> (widget)) + buttonBox = qFindChild<const QDialogButtonBox *>(widget,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; + } +} + + +/*! + + \reimp + + 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<QWindowsVistaStylePrivate*>(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<const QStyleOptionButton *>(option)) { + if ((qobject_cast<const QPushButton*>(widget) && element == CE_PushButtonBevel)) + { + QWidget *w = const_cast<QWidget *> (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); + Animation *anim = d->widgetAnimation(widget); + + QStyleOptionButton opt = *button; + opt.state = (QStyle::State)oldState; + + startImage.fill(0); + Transition *t = new Transition; + t->setWidget(w); + QPainter startPainter(&startImage); + + if (!anim) { + 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); + 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<const QStyleOptionButton *>(option)) + { + + if (Animation *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)) + { + Animation *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); + + Pulse *pulse = new Pulse; + pulse->setWidget(const_cast<QWidget*>(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.height()/2) - (mbih/2), + mbiw + 1, mbih + 1)); + drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget); + } + return; + } + break; +#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBarContents: + if (const QStyleOptionProgressBar *bar + = qstyleoption_cast<const QStyleOptionProgressBar *>(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<const QStyleOptionProgressBarV2 *>(option)) { + vertical = (pb2->orientation == Qt::Vertical); + inverted = pb2->invertedAppearance; + } + + if (const QProgressBar *progressbar = qobject_cast<const QProgressBar *>(widget)) { + if (((progressbar->value() > 0 && d->transitionsEnabled()) || isIndeterminate)) { + if (!d->widgetAnimation(progressbar) && progressbar->value() < progressbar->maximum()) { + Animation *a = new Animation; + a->setWidget(const_cast<QWidget*>(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 (Animation *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<qint64>(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 (Animation *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<const QStyleOptionMenuItem *>(option)) + { + if (mbi->menuItemType == QStyleOptionMenuItem::DefaultItem) + break; + + QPalette::ColorRole textRole = disabled ? QPalette::Text : QPalette::ButtonText; + QPixmap pix = mbi->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal); + + uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!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, 1 , 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<const QStyleOptionMenuItem *>(option)) { + // windows always has a check column, regardless whether we have an icon or not + int checkcol = qMax(menuitem->maxIconWidth, 28); + 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); + int stateId = 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) { + int stateId = 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); + d->drawBackground(theme); + if (menuitem->icon.isNull()) { + 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(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(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 (!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; + drawPrimitive(arrow, &newMI, painter, widget); + } + } + break; +#endif // QT_NO_MENU + case CE_HeaderSection: + if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(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: + { + int 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<const QStyleOptionToolBar *>(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<const QDockWidget *>(widget)) { + QRect rect = option->rect; + if (dockWidget->isFloating()) { + QWindowsXPStyle::drawControl(element, option, painter, widget); + break; //otherwise fall through + } + + if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) { + + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(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 = pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget); + int fw = pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget); + const QDockWidget *dw = qobject_cast<const QDockWidget *>(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() != qApp->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<const QAbstractItemView *>(widget); + bool newStyle = false; + + if (const QListView *listview = qobject_cast<const QListView *>(widget)) { + if (listview->viewMode() == QListView::IconMode) + newStyle = true; + } else if (const QTreeView* treeview = qobject_cast<const QTreeView *>(widget)) { + newStyle = true; + } + if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(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; + } +} + +/*! + \reimp + + 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<QWindowsVistaStylePrivate*>(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<const QScrollBar *>(widget) && control == CC_ScrollBar) +#ifndef QT_NO_SPINBOX + || (qobject_cast<const QAbstractSpinBox*>(widget) && control == CC_SpinBox) +#endif // QT_NO_SPINBOX +#ifndef QT_NO_COMBOBOX + || (qobject_cast<const QComboBox*>(widget) && control == CC_ComboBox) +#endif // QT_NO_COMBOBOX + ) + { + QWidget *w = const_cast<QWidget *> (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<const QStyleOptionSlider *>(option)) { + QRect oldSliderPos = w->property("_q_stylesliderpos").toRect(); + QRect currentPos = 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); + Animation *anim = d->widgetAnimation(widget); + Transition *t = new Transition; + t->setWidget(w); + if (!anim) { + if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(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; + drawComplexControl(control, &startCombo, &startPainter, 0 /* Intentional */); + t->setStartImage(startImage); + } else if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(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; + 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); + 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 (Animation *anim = d->widgetAnimation(widget)) { + anim->paint(painter, option); + return; + } + + } + } + + switch (control) { + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(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 = subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget); + XPThemeData theme(widget, painter, QLatin1String("COMBOBOX")); + theme.rect = subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget); + 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; + drawControl(QStyle::CE_PushButton, &btn, painter, widget); + } + } + } + break; + case CC_ScrollBar: + if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(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 = 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 = 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 = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); + theme.rect = theme.rect.united(subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget)); + theme.rect = theme.rect.united(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 = 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 = 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 = 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 = 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<const QStyleOptionSpinBox *>(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 = 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 = 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; + } +} + +/*! + \reimp + */ +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); + + QSize newSize = QWindowsXPStyle::sizeFromContents(type, option, size, widget); + switch (type) { + case CT_LineEdit: + case CT_ComboBox: + { + HTHEME theme = pOpenThemeData(0, L"Button"); + 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); + } + sz += QSize(23, 0); //arrow button + } + } + return sz; + case CT_MenuItem: + sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget); + sz.rwidth() += 28; + if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { + int minimumHeight = qMax<qint32>(22, sz.height()); + 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 = pixelMetric(PM_SpinBoxFrameWidth, option, widget); + sz -= QSize(2*border, 2*border); + } + return sz; + default: + break; + } + return newSize; +} + +/*! + \reimp + */ +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<const QStyleOptionButton *>(option)) { + MARGINS borderSize; + HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"Button"); + 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 = 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 = 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 = 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<const QStyleOptionHeader *>(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 (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) + rect.adjust(-2, 0, 2, 0); + break; + case SE_ItemViewItemFocusRect: + if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(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; +} + + +/*! \reimp */ +int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, + QStyleHintReturn *returnData) const +{ + QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(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<QStyleHintReturnMask*>(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; +} + + +/*! + \reimp + */ +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<const QStyleOptionComboBox *>(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 - bmarg - 16; + + switch (subControl) { + case SC_ComboBoxFrame: + rect = cb->rect; + break; + case SC_ComboBoxArrow: + rect.setRect(cb->editable ? xpos : 0, y , wi - xpos, 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<const QStyleOptionTitleBar *>(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 = 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 = 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; + } + } + break; + default: + break; + } + return rect; +} + +/*! + \reimp + */ +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); +} + +/*! + \reimp + */ +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); +} + +/*! + \reimp + */ +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 5; + case PM_ScrollBarSliderMin: + return 18; + case PM_MenuHMargin: + case PM_MenuVMargin: + return 0; + case PM_MenuPanelWidth: + return 3; + default: + break; + } + return QWindowsXPStyle::pixelMetric(metric, option, widget); +} + +/*! + \reimp + */ +QPalette QWindowsVistaStyle::standardPalette() const +{ + return QWindowsXPStyle::standardPalette(); +} + +/*! + \reimp + */ +void QWindowsVistaStyle::polish(QApplication *app) +{ + QWindowsXPStyle::polish(app); +} + +/*! + \reimp + */ +void QWindowsVistaStyle::polish(QWidget *widget) +{ + QWindowsXPStyle::polish(widget); +#ifndef QT_NO_LINEEDIT + if (qobject_cast<QLineEdit*>(widget)) + widget->setAttribute(Qt::WA_Hover); + else +#endif // QT_NO_LINEEDIT + if (qobject_cast<QGroupBox*>(widget)) + widget->setAttribute(Qt::WA_Hover); + else if (qobject_cast<QCommandLinkButton*>(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<QMessageBox *> (widget)) { + widget->setAttribute(Qt::WA_StyledBackground); + QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); + if (buttonBox) + buttonBox->setContentsMargins(0, 9, 0, 0); + } +#ifndef QT_NO_INPUTDIALOG + else if (qobject_cast<QInputDialog *> (widget)) { + widget->setAttribute(Qt::WA_StyledBackground); + QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); + if (buttonBox) + buttonBox->setContentsMargins(0, 9, 0, 0); + } +#endif // QT_NO_INPUTDIALOG + else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) { + tree->viewport()->setAttribute(Qt::WA_Hover); + } +} + +/*! + \reimp + */ +void QWindowsVistaStyle::unpolish(QWidget *widget) +{ + QWindowsXPStyle::unpolish(widget); + + QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func()); + d->stopAnimation(widget); + +#ifndef QT_NO_LINEEDIT + if (qobject_cast<QLineEdit*>(widget)) + widget->setAttribute(Qt::WA_Hover, false); + else +#endif // QT_NO_LINEEDIT + if (qobject_cast<QGroupBox*>(widget)) + widget->setAttribute(Qt::WA_Hover, false); + else if (qobject_cast<QMessageBox *> (widget)) { + widget->setAttribute(Qt::WA_StyledBackground, false); + QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); + if (buttonBox) + buttonBox->setContentsMargins(0, 0, 0, 0); + } +#ifndef QT_NO_INPUTDIALOG + else if (qobject_cast<QInputDialog *> (widget)) { + widget->setAttribute(Qt::WA_StyledBackground, false); + QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); + if (buttonBox) + buttonBox->setContentsMargins(0, 0, 0, 0); + } +#endif // QT_NO_INPUTDIALOG + else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) { + tree->viewport()->setAttribute(Qt::WA_Hover, false); + } else if (qobject_cast<QCommandLinkButton*>(widget)) { + QFont font = qApp->font("QCommandLinkButton"); + QFont widgetFont = widget->font(); + widgetFont.setFamily(font.family()); //Only family set by polish + widget->setFont(widgetFont); + } +} + + +/*! + \reimp + */ +void QWindowsVistaStyle::unpolish(QApplication *app) +{ + QWindowsXPStyle::unpolish(app); +} + +/*! + \reimp + */ +void QWindowsVistaStyle::polish(QPalette &pal) +{ + QWindowsStyle::polish(pal); + pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(104)); +} + +/*! + \reimp + */ +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()) + { + Animation *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) { + Animation *a = animations.takeAt(i); + delete a; + break; + } + } +} + +void QWindowsVistaStylePrivate::startAnimation(Animation *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 (QT_WA_INLINE(SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0), + SystemParametersInfoA(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0) + )) + { + if (animEnabled) + return true; + } + return false; +} + + +Animation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const +{ + if (!widget) + return 0; + foreach (Animation *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; + QLibrary 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<QWindowsVistaStylePrivate *>(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/gui/styles/qwindowsvistastyle.h b/src/gui/styles/qwindowsvistastyle.h new file mode 100644 index 0000000000..0d1f20201f --- /dev/null +++ b/src/gui/styles/qwindowsvistastyle.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSVISTASTYLE_H +#define QWINDOWSVISTASTYLE_H + +#include <QtGui/qwindowsxpstyle.h> + +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/gui/styles/qwindowsvistastyle_p.h b/src/gui/styles/qwindowsvistastyle_p.h new file mode 100644 index 0000000000..877bc50469 --- /dev/null +++ b/src/gui/styles/qwindowsvistastyle_p.h @@ -0,0 +1,217 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 <private/qwindowsxpstyle_p.h> +#include <private/qpaintengine_raster_p.h> +#include <qlibrary.h> +#include <qpaintengine.h> +#include <qwidget.h> +#include <qapplication.h> +#include <qpixmapcache.h> +#include <qstyleoption.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qlineedit.h> +#include <qgroupbox.h> +#include <qtoolbutton.h> +#include <qspinbox.h> +#include <qtoolbar.h> +#include <qcombobox.h> +#include <qscrollbar.h> +#include <qprogressbar.h> +#include <qdockwidget.h> +#include <qtreeview.h> +#include <qtextedit.h> +#include <qmessagebox.h> +#include <qdialogbuttonbox.h> +#include <qinputdialog.h> +#include <qtreeview.h> +#include <qlistview.h> +#include <qbasictimer.h> +#include <qcommandlinkbutton.h> + +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 Animation +{ +public : + Animation() : _running(true) { } + virtual ~Animation() { } + 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<QWidget> _widget; + QImage _primaryImage; + QImage _secondaryImage; + QImage _tempImage; + bool _running; +}; + + +// Handles state transition animations +class Transition : public Animation +{ +public : + Transition() : Animation() {} + virtual ~Transition() { } + 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 Pulse: public Animation +{ +public : + Pulse() : Animation() {} + virtual ~Pulse() { } + 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(Animation *); + void stopAnimation(const QWidget *); + Animation* widgetAnimation(const QWidget *) const; + void timerEvent(); + bool transitionsEnabled() const; + QWidget *treeViewHelper(); + +private: + QList <Animation*> animations; + QBasicTimer animationTimer; + QWidget *m_treeViewHelper; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_WINDOWSVISTA + +#endif // QWINDOWSVISTASTYLE_P_H diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp new file mode 100644 index 0000000000..9d735a7078 --- /dev/null +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -0,0 +1,4205 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qwindowsxpstyle.h" +#include "qwindowsxpstyle_p.h" + +#if !defined(QT_NO_STYLE_WINDOWSXP) || defined(QT_PLUGIN) + +#include <private/qobject_p.h> +#include <private/qpaintengine_raster_p.h> +#include <private/qapplication_p.h> +#include <qlibrary.h> +#include <qpainter.h> +#include <qpaintengine.h> +#include <qwidget.h> +#include <qapplication.h> +#include <qpixmapcache.h> + +#include <qdesktopwidget.h> +#include <qtoolbutton.h> +#include <qtabbar.h> +#include <qcombobox.h> +#include <qscrollbar.h> +#include <qheaderview.h> +#include <qspinbox.h> +#include <qlistview.h> +#include <qstackedwidget.h> +#include <qpushbutton.h> +#include <qtoolbar.h> +#include <qlabel.h> +#include <qvarlengtharray.h> +#include <qdebug.h> + +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 windowsSepHeight = 9; // separator item height +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 windowsCheckMarkHMargin = 0; // horiz. margins of check mark +static const int windowsRightBorder = 12; // right border on windows + +// External function calls +extern Q_GUI_EXPORT HDC qt_win_display_dc(); + + + +// 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), + (TCHAR*)name.utf16()); + if (htheme) { + if (!QWindowsXPStylePrivate::handleMap) + QWindowsXPStylePrivate::handleMap = new QMap<QString, HTHEME>; + 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<QString,HTHEME> *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 (qApp->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<QString, HTHEME>::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->setObjectName(QLatin1String("xp_limbo_widget")); + } + + 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; + QLibrary 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(); + + QRegion rgn = QRegion(0,0,1,1); + const bool success = CombineRgn(rgn.handle(), hRgn, 0, RGN_COPY) != ERROR; + DeleteObject(hRgn); + if (success) + return rgn; + return QRegion(); +} + +/*! \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 &= 0x00FFFFFF; + 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) + return; + + painter->save(); + + QMatrix m = painter->matrix(); + bool complexXForm = m.m11() != 1.0 || m.m22() != 1.0 || m.m12() != 0.0 || m.m21() != 0.0; + + bool useFallback = painter->paintEngine()->getDC() == 0 + || painter->opacity() != 1.0 + || themeData.rotate + || complexXForm + || themeData.mirrorVertically + || (themeData.mirrorHorizontally && pDrawThemeBackgroundEx == 0); + 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<QRect> 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(), 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<QAbstractButton*>(widget) + || qobject_cast<QToolButton*>(widget) + || qobject_cast<QTabBar*>(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast<QComboBox*>(widget) +#endif // QT_NO_COMBOBOX + || qobject_cast<QScrollBar*>(widget) + || qobject_cast<QSlider*>(widget) + || qobject_cast<QHeaderView*>(widget) +#ifndef QT_NO_SPINBOX + || qobject_cast<QAbstractSpinBox*>(widget) + || qobject_cast<QSpinBox*>(widget) +#endif // QT_NO_SPINBOX + || widget->inherits("QWorkspaceChild") + || widget->inherits("Q3TitleBar")) + widget->setAttribute(Qt::WA_Hover); + +#ifndef QT_NO_RUBBERBAND + if (qobject_cast<QRubberBand*>(widget)) { + widget->setWindowOpacity(0.6); + } +#endif + if (qobject_cast<QStackedWidget*>(widget) && + qobject_cast<QTabWidget*>(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<QRubberBand*>(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<QAbstractButton*>(widget) + || qobject_cast<QToolButton*>(widget) + || qobject_cast<QTabBar*>(widget) +#ifndef QT_NO_COMBOBOX + || qobject_cast<QComboBox*>(widget) +#endif // QT_NO_COMBOBOX + || qobject_cast<QScrollBar*>(widget) + || qobject_cast<QSlider*>(widget) + || qobject_cast<QHeaderView*>(widget) +#ifndef QT_NO_SPINBOX + || qobject_cast<QAbstractSpinBox*>(widget) + || qobject_cast<QSpinBox*>(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<const QStyleOptionTabWidgetFrame *>(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<const QStyleOptionTabWidgetFrame *>(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 = pixelMetric(PM_TabBarBaseOverlap, &otherOption, widget); + int borderThickness = pixelMetric(PM_DefaultFrameWidth, option, widget); + rect.adjust(-overlap + borderThickness, 0, -overlap + borderThickness, 0); + } + break;} + + case SE_PushButtonContents: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { + MARGINS borderSize; + if (widget) { + HTHEME theme = pOpenThemeData(QWindowsXPStylePrivate::winId(widget), L"Button"); + 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 = 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<QWindowsXPStylePrivate*>(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<const QStyleOptionTabBarBase *>(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<const QStyleOptionFrame *>(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<const QStyleOptionFrame *>(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<QAbstractSpinBox*>(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) + drawPrimitive(PE_FrameLineEdit, panel, p, widget); + return; + } + break; + + case PE_FrameTabWidget: + if (const QStyleOptionTabWidgetFrame *tab = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) + { + name = QLatin1String("TAB"); + partId = TABP_PANE; + + if (widget) { + bool useGradient = true; + const int maxlength = 256; + WCHAR themeFileName[maxlength]; + WCHAR 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* offset; + 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) { + QStyleOptionTabWidgetFrame 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<const QStyleOptionFrame *>(option)) + { + name = QLatin1String("WINDOW"); + if (flags & State_Active) + stateId = FS_ACTIVE; + else + stateId = FS_INACTIVE; + + int fwidth = 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<const QStyleOptionHeader *>(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<const QStyleOptionFrame *>(option)) { + const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(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<const QStyleOptionProgressBarV2 *>(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<const QStyleOptionFrame *>(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: + + 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; + 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<QWindowsXPStylePrivate*>(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<const QStyleOptionSizeGrip *>(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<const QStyleOptionButton *>(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); + drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); + } + return; + } + break; + case CE_TabBarTab: + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) + { + stateId = tab->state & State_Enabled ? TIS_NORMAL : TIS_DISABLED; + } + break; + + case CE_TabBarTabShape: + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(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 = styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignLeft; + bool centerAligned = styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignCenter; + int borderThickness = pixelMetric(PM_DefaultFrameWidth, option, widget); + int tabOverlap = 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<const QStyleOptionProgressBarV2 *>(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<const QStyleOptionMenuItem *>(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(pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On) : + menuitem->icon.pixmap(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, -2, 1, 1)); + 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); + 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 (!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 && 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 && 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()); + drawPrimitive(arrow, &newMI, p, widget); + } + } + return; + + case CE_MenuBarItem: + if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(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(pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal); + + uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!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<const QStyleOptionDockWidget *>(option)) + { + int buttonMargin = 4; + int mw = pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget); + int fw = pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget); + bool isFloating = widget && widget->isWindow(); + bool isActive = dwOpt->state & State_Active; + + const QStyleOptionDockWidgetV2 *v2 + = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(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 = 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() != qApp->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() != qApp->windowIcon().cacheKey()); + if (hasIcon) { + QPixmap pxIco = ico.pixmap(titleHeight); + if (!verticalTitleBar && QApplication::layoutDirection() == 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<const QStyleOptionRubberBand *>(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<QWindowsXPStylePrivate*>(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<const QStyleOptionSpinBox *>(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 = 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 = 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<const QStyleOptionComboBox *>(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 = 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 = 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<const QStyleOptionSlider *>(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 = 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 = 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 = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); + theme.rect = theme.rect.united(subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget)); + theme.rect = theme.rect.united(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 = 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 = 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 = 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 = 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(); + XPThemeData grippBackground = theme; + grippBackground.partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; + theme.rect = gripperBounds; + p->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 + p->restore(); + } + } + } + } + break; + +#ifndef QT_NO_SLIDER + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) + { + XPThemeData theme(widget, p, QLatin1String("TRACKBAR")); + QRect slrect = slider->rect; + QRegion tickreg = slrect; + if (sub & SC_SliderGroove) { + theme.rect = 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 = pixelMetric(PM_SliderTickmarkOffset, slider, widget); + int ticks = slider->tickPosition; + int thickness = pixelMetric(PM_SliderControlThickness, slider, widget); + int len = pixelMetric(PM_SliderLength, slider, widget); + int available = 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<QLine, 32> 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 = 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); + drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + } + break; +#endif +#ifndef QT_NO_TOOLBUTTON + case CC_ToolButton: + if (const QStyleOptionToolButton *toolbutton + = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { + QRect button, menuarea; + button = subControlRect(cc, toolbutton, SC_ToolButton, widget); + menuarea = subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget); + + State bflags = toolbutton->state & ~State_Sunken; + State mflags = bflags; + + if (bflags & State_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) || !(flags & State_AutoRaise)) { + if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup) { + 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 = button; + tool.state = bflags; + if (widget && !qobject_cast<QToolBar*>(widget->parentWidget()) + && !(bflags & State_AutoRaise)) + drawPrimitive(PE_PanelButtonBevel, &tool, p, widget); + else + 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, -pixelMetric(QStyle::PM_MenuButtonIndicator, + toolbutton, widget), 0); + drawPrimitive(PE_FrameFocusRect, &fr, p, widget); + } + QStyleOptionToolButton label = *toolbutton; + label.state = bflags; + int fw = 2; + label.rect = button.adjusted(fw, fw, -fw, -fw); + drawControl(CE_ToolButtonLabel, &label, p, widget); + + if (toolbutton->subControls & SC_ToolButtonMenu) { + tool.rect = menuarea; + tool.state = mflags; + drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); + } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { + int mbi = 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); + drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); + } + } + break; +#endif // QT_NO_TOOLBUTTON + + case CC_TitleBar: + { + if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(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 = 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 = 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 = pixelMetric(PM_SmallIconSize, tb, widget); + QPixmap pm = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 + 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<const QListView*>(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<const QStyleOptionTab *>(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(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+2 : res = size.cy+2); + } + } + 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+2 : res = size.cy+2); + } + } + break; + + case PM_ProgressBarChunkWidth: + { + Qt::Orientation orient = Qt::Horizontal; + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(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_MenuButtonIndicator: + { + 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); + res = size.cx; + } + } + 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 = 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 = 4; + break; + case PM_DockWidgetTitleMargin: + res = 4; + break; + + case PM_ButtonShiftHorizontal: + case PM_ButtonShiftVertical: + if (qstyleoption_cast<const QStyleOptionToolButton *>(option)) + res = 1; + else + 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<const QStyleOptionTitleBar *>(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 = 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 = 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; + } + } + break; + + case CC_ComboBox: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(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; + } + } + 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: + { + HTHEME theme = pOpenThemeData(QWindowsXPStylePrivate::winId(widget), L"Button"); + 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); + } + sz += QSize(23, 0); //arrow button + } + } + break; + case CT_SpinBox: + { + //Spinbox adds frame twice + sz = QWindowsStyle::sizeFromContents(ct, option, contentsSize, widget); + int border = 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<const QStyleOptionMenuItem *>(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<const QStyleOptionComplex *>(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<QWindowsXPStylePrivate*>(d_func()); + if (!QWindowsXPStylePrivate::useXP()) + return QWindowsStyle::styleHint(hint, option, widget, returnData); + + int res = 0; + switch (hint) { + + case SH_EtchDisabledText: + res = (qobject_cast<const QLabel*>(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<QStyleHintReturnMask *>(returnData); + const QStyleOptionTitleBar *titlebar = qstyleoption_cast<const QStyleOptionTitleBar *>(option); + if (mask && titlebar) { + XPThemeData themeData; + if (titlebar->titleBarState & Qt::WindowMinimized) { + themeData = XPThemeData(widget, 0, QLatin1String("WINDOW"), WP_MINCAPTION, CS_ACTIVE, option->rect); + } else + themeData = XPThemeData(widget, 0, QLatin1String("WINDOW"), WP_CAPTION, CS_ACTIVE, option->rect); + mask->region = d->region(themeData); + } + } + break; +#ifndef QT_NO_RUBBERBAND + case SH_RubberBand_Mask: + if (qstyleoption_cast<const QStyleOptionRubberBand *>(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<const QStyleOptionDockWidget *>(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; + } + 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<QWindowsXPStylePrivate*>(d_func()); + switch(standardIcon) { + case SP_TitleBarMaxButton: + if (qstyleoption_cast<const QStyleOptionDockWidget *>(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<const QStyleOptionDockWidget *>(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<const QStyleOptionDockWidget *>(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; + } + + 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 <tmschema.h> +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<PropPair> 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/gui/styles/qwindowsxpstyle.h b/src/gui/styles/qwindowsxpstyle.h new file mode 100644 index 0000000000..8faae8224f --- /dev/null +++ b/src/gui/styles/qwindowsxpstyle.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSXPSTYLE_H +#define QWINDOWSXPSTYLE_H + +#include <QtGui/qwindowsstyle.h> + +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/gui/styles/qwindowsxpstyle_p.h b/src/gui/styles/qwindowsxpstyle_p.h new file mode 100644 index 0000000000..717162930e --- /dev/null +++ b/src/gui/styles/qwindowsxpstyle_p.h @@ -0,0 +1,356 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 <qmap.h> +#include <qt_windows.h> + +// Note, these tests are duplicated in qwizard_win.cpp. +#ifdef Q_CC_GNU +# include <w32api.h> +# 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 <commctrl.h> +# endif +#endif + +#include <uxtheme.h> + +#if WINVER >= 0x0600 +#include <vssym32.h> +#else +#include <tmschema.h> +#endif + +#include <limits.h> + +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<QString,HTHEME> *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<ThemeMapKey, ThemeMapData> 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/gui/styles/styles.pri b/src/gui/styles/styles.pri new file mode 100644 index 0000000000..9aa170e8be --- /dev/null +++ b/src/gui/styles/styles.pri @@ -0,0 +1,174 @@ +# Qt styles module + +HEADERS += \ + styles/qstyle.h \ + styles/qstylefactory.h \ + styles/qstyleoption.h \ + styles/qstyleplugin.h \ + styles/qcommonstylepixmaps_p.h \ + styles/qcommonstyle.h \ + styles/qstylesheetstyle_p.h +SOURCES += \ + styles/qstyle.cpp \ + styles/qstylefactory.cpp \ + styles/qstyleoption.cpp \ + styles/qstyleplugin.cpp \ + styles/qcommonstyle.cpp \ + styles/qstylesheetstyle.cpp \ + styles/qstylesheetstyle_default.cpp + +!wince* { + RESOURCES += styles/qstyle.qrc +} else { + RESOURCES += styles/qstyle_wince.qrc +} + +contains( styles, all ) { + styles = mac windows windowsxp windowsvista +} + +x11|embedded|!macx-*:styles -= mac + +x11{ + QMAKE_CXXFLAGS += $$QT_CFLAGS_QGTKSTYLE + LIBS += $$QT_LIBS_QGTKSTYLE + styles += gtk +} + +contains( styles, mac ) { + HEADERS += \ + styles/qmacstyle_mac.h \ + styles/qmacstylepixmaps_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/gtksymbols_p.h + SOURCES += styles/qgtkstyle.cpp + SOURCES += styles/qgtkpainter.cpp + SOURCES += styles/gtksymbols.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 ) { + HEADERS += \ + styles/qs60style.h \ + styles/qs60style_p.h + SOURCES += styles/qs60style.cpp + DEFINES += QT_S60STYLE_LAYOUTDATA_SIMULATED + symbian { + SOURCES += styles/qs60style_symbian.cpp + # TODO: fix the following LIBS hack. Line 1 is for armv5, 2 for winscw + LIBS += aknicon aknskins aknskinsrv fontutils + LIBS += -laknicon -laknskins -laknskinsrv -lfontutils + } else { + SOURCES += styles/qs60style_simulated.cpp + } +} else { + DEFINES += QT_NO_STYLE_S60 +} |