| 1 |
/**************************************************************************** |
| 2 |
** |
| 3 |
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
| 4 |
** All rights reserved. |
| 5 |
** Contact: Nokia Corporation (qt-info@nokia.com) |
| 6 |
** |
| 7 |
** This file is part of the QtGui module of the Qt Toolkit. |
| 8 |
** |
| 9 |
** $QT_BEGIN_LICENSE:LGPL$ |
| 10 |
** No Commercial Usage |
| 11 |
** This file contains pre-release code and may not be distributed. |
| 12 |
** You may use this file in accordance with the terms and conditions |
| 13 |
** contained in the Technology Preview License Agreement accompanying |
| 14 |
** this package. |
| 15 |
** |
| 16 |
** GNU Lesser General Public License Usage |
| 17 |
** Alternatively, this file may be used under the terms of the GNU Lesser |
| 18 |
** General Public License version 2.1 as published by the Free Software |
| 19 |
** Foundation and appearing in the file LICENSE.LGPL included in the |
| 20 |
** packaging of this file. Please review the following information to |
| 21 |
** ensure the GNU Lesser General Public License version 2.1 requirements |
| 22 |
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| 23 |
** |
| 24 |
** In addition, as a special exception, Nokia gives you certain additional |
| 25 |
** rights. These rights are described in the Nokia Qt LGPL Exception |
| 26 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| 27 |
** |
| 28 |
** If you have questions regarding the use of this file, please contact |
| 29 |
** Nokia at qt-info@nokia.com. |
| 30 |
** |
| 31 |
** |
| 32 |
** |
| 33 |
** |
| 34 |
** |
| 35 |
** |
| 36 |
** |
| 37 |
** |
| 38 |
** $QT_END_LICENSE$ |
| 39 |
** |
| 40 |
****************************************************************************/ |
| 41 |
|
| 42 |
#include <qgtkstyle.h> |
| 43 |
#include <qmaemo5style.h> |
| 44 |
#include <private/qmaemo5style_p.h> |
| 45 |
|
| 46 |
#include <private/qapplication_p.h> |
| 47 |
|
| 48 |
#include <QtCore/QLibrary> |
| 49 |
#include <QtGui/QStyleOption> |
| 50 |
#include <QtGui/QLineEdit> |
| 51 |
#include <QtGui/QDialogButtonBox> |
| 52 |
#include <QtGui/QCommandLinkButton> |
| 53 |
#include <QtGui/QAbstractScrollArea> |
| 54 |
#include <QtGui/QAbstractItemView> |
| 55 |
#include <QtGui/QScrollBar> |
| 56 |
#include <QtGui/QPlainTextEdit> |
| 57 |
#include <QtGui/QTextEdit> |
| 58 |
#include <QtGui/QTextBrowser> |
| 59 |
#include <QtGui/QButtonGroup> |
| 60 |
#include <QtGui/QPushButton> |
| 61 |
#include <QtGui/QRadioButton> |
| 62 |
#include <QtGui/QAbstractSpinBox> |
| 63 |
#include <QtGui/QX11Info> |
| 64 |
#include <QtGui/QHBoxLayout> |
| 65 |
#include <QtCore/QTimer> |
| 66 |
#include <QtCore/QTimeLine> |
| 67 |
|
| 68 |
#include <QtDebug> |
| 69 |
|
| 70 |
#include "qpixmapcache.h" |
| 71 |
#undef signals // Collides with GTK stymbols |
| 72 |
#include "qgtkpainter_p.h" |
| 73 |
|
| 74 |
#include <private/qt_x11_p.h> |
| 75 |
|
| 76 |
#if defined(Q_WS_MAEMO_5) |
| 77 |
|
| 78 |
QT_BEGIN_NAMESPACE |
| 79 |
|
| 80 |
Ptr_gtk_widget_show QMaemo5StylePrivate::gtk_widget_show = 0; |
| 81 |
Ptr_gtk_widget_set_name QMaemo5StylePrivate::gtk_widget_set_name = 0; |
| 82 |
Ptr_gtk_text_view_new QMaemo5StylePrivate::gtk_text_view_new = 0; |
| 83 |
Ptr_gtk_widget_get_size_request QMaemo5StylePrivate::gtk_widget_get_size_request = 0; |
| 84 |
Ptr_gtk_button_set_label QMaemo5StylePrivate::gtk_button_set_label = 0; |
| 85 |
Ptr_gtk_style_lookup_color QMaemo5StylePrivate::gtk_style_lookup_color = 0; |
| 86 |
Ptr_gtk_hbox_new QMaemo5StylePrivate::gtk_hbox_new = 0; |
| 87 |
Ptr_gtk_box_pack_start QMaemo5StylePrivate::gtk_box_pack_start = 0; |
| 88 |
Ptr_gtk_box_pack_end QMaemo5StylePrivate::gtk_box_pack_end = 0; |
| 89 |
Ptr_gtk_widget_set_size_request QMaemo5StylePrivate::gtk_widget_set_size_request = 0; |
| 90 |
|
| 91 |
Ptr_hildon_init QMaemo5StylePrivate::hildon_init = 0; |
| 92 |
Ptr_hildon_entry_new QMaemo5StylePrivate::hildon_entry_new = 0; |
| 93 |
Ptr_hildon_number_editor_new QMaemo5StylePrivate::hildon_number_editor_new = 0; |
| 94 |
Ptr_hildon_app_menu_new QMaemo5StylePrivate::hildon_app_menu_new = 0; |
| 95 |
Ptr_hildon_app_menu_add_filter QMaemo5StylePrivate::hildon_app_menu_add_filter = 0; |
| 96 |
Ptr_hildon_edit_toolbar_new_with_text QMaemo5StylePrivate::hildon_edit_toolbar_new_with_text = 0; |
| 97 |
Ptr_hildon_button_new QMaemo5StylePrivate::hildon_button_new = 0; |
| 98 |
Ptr_hildon_check_button_new QMaemo5StylePrivate::hildon_check_button_new = 0; |
| 99 |
Ptr_hildon_pannable_area_new QMaemo5StylePrivate::hildon_pannable_area_new = 0; |
| 100 |
Ptr_hildon_gtk_widget_set_theme_size QMaemo5StylePrivate::hildon_gtk_widget_set_theme_size = 0; |
| 101 |
Ptr_hildon_dialog_new_with_buttons QMaemo5StylePrivate::hildon_dialog_new_with_buttons = 0; |
| 102 |
Ptr_hildon_note_new_information QMaemo5StylePrivate::hildon_note_new_information = 0; |
| 103 |
|
| 104 |
Ptr_hildon_file_chooser_dialog_new QMaemo5StylePrivate::hildon_file_chooser_dialog_new = 0; |
| 105 |
Ptr_hildon_file_chooser_dialog_set_extension QMaemo5StylePrivate::hildon_file_chooser_dialog_set_extension = 0; |
| 106 |
Ptr_hildon_file_chooser_dialog_add_extensions_combo QMaemo5StylePrivate::hildon_file_chooser_dialog_add_extensions_combo = 0; |
| 107 |
|
| 108 |
QMap<QAbstractScrollArea *, ScrollBarFader *> QMaemo5StylePrivate::scrollBarFaders; |
| 109 |
int QMaemo5StylePrivate::scrollBarFadeDelay = 3000; // [ms] hardcoded in hildon pannable area |
| 110 |
int QMaemo5StylePrivate::scrollBarFadeDuration = 400; // [ms] hardcoded in hildon pannable area |
| 111 |
int QMaemo5StylePrivate::scrollBarFadeUpdateInterval = 100; // [ms] hardcoded in hildon pannable area |
| 112 |
GtkWidget *QMaemo5StylePrivate::radioButtonLeft = 0; |
| 113 |
GtkWidget *QMaemo5StylePrivate::radioButtonMiddle = 0; |
| 114 |
GtkWidget *QMaemo5StylePrivate::radioButtonRight = 0; |
| 115 |
|
| 116 |
|
| 117 |
/*! |
| 118 |
\internal |
| 119 |
*/ |
| 120 |
void QMaemo5StylePrivate::resolveGtk() const |
| 121 |
{ |
| 122 |
QGtkStylePrivate::resolveGtk(); |
| 123 |
|
| 124 |
QLibrary libgtk(QLS("gtk-x11-2.0"), 0, 0); |
| 125 |
QLibrary libhildon(QLS("hildon-1"), 0, 0); |
| 126 |
QLibrary libhildonfm(QLS("hildonfm"), 2, 0); |
| 127 |
|
| 128 |
gtk_widget_show = (Ptr_gtk_widget_show)libgtk.resolve("gtk_widget_show"); |
| 129 |
gtk_widget_set_name = (Ptr_gtk_widget_set_name)libgtk.resolve("gtk_widget_set_name"); |
| 130 |
gtk_text_view_new = (Ptr_gtk_text_view_new)libgtk.resolve("gtk_text_view_new"); |
| 131 |
gtk_widget_get_size_request = (Ptr_gtk_widget_get_size_request)libgtk.resolve("gtk_widget_get_size_request"); |
| 132 |
gtk_button_set_label = (Ptr_gtk_button_set_label)libgtk.resolve("gtk_button_set_label"); |
| 133 |
gtk_style_lookup_color = (Ptr_gtk_style_lookup_color)libgtk.resolve("gtk_style_lookup_color"); |
| 134 |
gtk_hbox_new = (Ptr_gtk_hbox_new)libgtk.resolve("gtk_hbox_new"); |
| 135 |
gtk_box_pack_start = (Ptr_gtk_box_pack_start)libgtk.resolve("gtk_box_pack_start"); |
| 136 |
gtk_box_pack_end = (Ptr_gtk_box_pack_end)libgtk.resolve("gtk_box_pack_end"); |
| 137 |
gtk_widget_set_size_request = (Ptr_gtk_widget_set_size_request)libgtk.resolve("gtk_widget_set_size_request"); |
| 138 |
|
| 139 |
hildon_init = (Ptr_hildon_init)libhildon.resolve("hildon_init"); |
| 140 |
hildon_entry_new = (Ptr_hildon_entry_new)libhildon.resolve("hildon_entry_new"); |
| 141 |
hildon_number_editor_new = (Ptr_hildon_number_editor_new)libhildon.resolve("hildon_number_editor_new"); |
| 142 |
hildon_app_menu_new = (Ptr_hildon_app_menu_new)libhildon.resolve("hildon_app_menu_new"); |
| 143 |
hildon_app_menu_add_filter = (Ptr_hildon_app_menu_add_filter)libhildon.resolve("hildon_app_menu_add_filter"); |
| 144 |
hildon_edit_toolbar_new_with_text = (Ptr_hildon_edit_toolbar_new_with_text)libhildon.resolve("hildon_edit_toolbar_new_with_text"); |
| 145 |
hildon_button_new = (Ptr_hildon_button_new)libhildon.resolve("hildon_button_new"); |
| 146 |
hildon_check_button_new = (Ptr_hildon_check_button_new)libhildon.resolve("hildon_check_button_new"); |
| 147 |
hildon_pannable_area_new = (Ptr_hildon_pannable_area_new)libhildon.resolve("hildon_pannable_area_new"); |
| 148 |
hildon_gtk_widget_set_theme_size = (Ptr_hildon_gtk_widget_set_theme_size)libhildon.resolve("hildon_gtk_widget_set_theme_size"); |
| 149 |
hildon_dialog_new_with_buttons = (Ptr_hildon_dialog_new_with_buttons)libhildon.resolve("hildon_dialog_new_with_buttons"); |
| 150 |
hildon_note_new_information = (Ptr_hildon_note_new_information)libhildon.resolve("hildon_note_new_information"); |
| 151 |
|
| 152 |
hildon_file_chooser_dialog_new = (Ptr_hildon_file_chooser_dialog_new)libhildonfm.resolve("hildon_file_chooser_dialog_new"); |
| 153 |
hildon_file_chooser_dialog_set_extension = (Ptr_hildon_file_chooser_dialog_set_extension)libhildonfm.resolve("hildon_file_chooser_dialog_set_extension"); |
| 154 |
hildon_file_chooser_dialog_add_extensions_combo = (Ptr_hildon_file_chooser_dialog_add_extensions_combo)libhildonfm.resolve("hildon_file_chooser_dialog_add_extensions_combo"); |
| 155 |
|
| 156 |
} |
| 157 |
|
| 158 |
/*! |
| 159 |
\internal |
| 160 |
NOTE: Reverse color in fremantle themes are set only for |
| 161 |
GtkTextView widgets. GtkEntry returns a dark base color. |
| 162 |
*/ |
| 163 |
GtkWidget* QMaemo5StylePrivate::getTextColorWidget() const |
| 164 |
{ |
| 165 |
return gtkWidget("GtkTextView"); |
| 166 |
} |
| 167 |
|
| 168 |
/*! |
| 169 |
\internal |
| 170 |
\reimp |
| 171 |
*/ |
| 172 |
void QMaemo5StylePrivate::initGtkMenu() const |
| 173 |
{ |
| 174 |
QGtkStylePrivate::initGtkMenu(); |
| 175 |
|
| 176 |
// --- create widgets for the context sensitive menu |
| 177 |
GtkWidget *gtkMenu = gtk_menu_new(); |
| 178 |
gtk_widget_set_name(gtkMenu, "hildon-context-sensitive-menu"); |
| 179 |
gtk_widget_realize(gtkMenu); |
| 180 |
|
| 181 |
GtkWidget *gtkMenuItem = QGtkStylePrivate::gtk_menu_item_new_with_label("X"); |
| 182 |
gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkMenuItem); |
| 183 |
gtk_widget_realize(gtkMenuItem); |
| 184 |
|
| 185 |
GtkWidget *gtkCheckMenuItem = QGtkStylePrivate::gtk_check_menu_item_new_with_label("X"); |
| 186 |
gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkCheckMenuItem); |
| 187 |
gtk_widget_realize(gtkCheckMenuItem); |
| 188 |
|
| 189 |
GtkWidget *gtkMenuSeparator = QGtkStylePrivate::gtk_separator_menu_item_new(); |
| 190 |
gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkMenuSeparator); |
| 191 |
|
| 192 |
addAllSubWidgets(gtkMenu); |
| 193 |
|
| 194 |
// --- and now for the "normal" app menu |
| 195 |
GtkWidget *gtkMenu2 = hildon_app_menu_new(); |
| 196 |
|
| 197 |
// -- three menu buttons. Sapwood will use different background images depending on their position. |
| 198 |
radioButtonLeft = gtk_radio_button_new(NULL); |
| 199 |
gtk_widget_show(radioButtonLeft); // only a visible button is really added. |
| 200 |
hildon_app_menu_add_filter( (HildonAppMenu*)gtkMenu2, (GtkButton*)radioButtonLeft); |
| 201 |
|
| 202 |
radioButtonMiddle = gtk_radio_button_new(NULL); |
| 203 |
gtk_widget_show(radioButtonMiddle); // only a visible button is really added. |
| 204 |
hildon_app_menu_add_filter( (HildonAppMenu*)gtkMenu2, (GtkButton*)radioButtonMiddle); |
| 205 |
|
| 206 |
radioButtonRight = gtk_radio_button_new(NULL); |
| 207 |
gtk_widget_show(radioButtonRight); // only a visible button is really added. |
| 208 |
hildon_app_menu_add_filter( (HildonAppMenu*)gtkMenu2, (GtkButton*)radioButtonRight); |
| 209 |
|
| 210 |
addAllSubWidgets(gtkMenu2); |
| 211 |
|
| 212 |
// and now a hack for the sapwood engine |
| 213 |
radioButtonLeft->allocation.x = 0; |
| 214 |
radioButtonLeft->allocation.y = 0; |
| 215 |
GTK_WIDGET_FLAGS(radioButtonLeft) |= GTK_MAPPED; |
| 216 |
radioButtonMiddle->allocation.x = 1; |
| 217 |
radioButtonMiddle->allocation.y = 0; |
| 218 |
GTK_WIDGET_FLAGS(radioButtonMiddle) |= GTK_MAPPED; |
| 219 |
radioButtonRight->allocation.x = 2; |
| 220 |
radioButtonRight->allocation.y = 0; |
| 221 |
GTK_WIDGET_FLAGS(radioButtonRight) |= GTK_MAPPED; |
| 222 |
} |
| 223 |
|
| 224 |
void QMaemo5StylePrivate::initGtkWidgets() const |
| 225 |
{ |
| 226 |
QGtkStylePrivate::initGtkWidgets(); |
| 227 |
|
| 228 |
if (gtk_init && hildon_init) { |
| 229 |
hildon_init(); |
| 230 |
|
| 231 |
if (!gtkWidgetMap()->contains("GtkWindow")) |
| 232 |
return; // without window all other widgets won't be created cleanly |
| 233 |
|
| 234 |
// ComboBoxes buttons |
| 235 |
addWidget(hildon_number_editor_new(0,1)); |
| 236 |
addWidget(hildon_entry_new(HILDON_SIZE_FINGER_HEIGHT)); |
| 237 |
addWidget(gtk_text_view_new()); |
| 238 |
addWidget(hildon_dialog_new_with_buttons("", NULL, GTK_DIALOG_MODAL, "", 0, NULL)); |
| 239 |
addWidget(hildon_pannable_area_new()); |
| 240 |
GtkWidget *note = hildon_note_new_information(NULL, ""); |
| 241 |
gtk_widget_set_name(note, "HildonNote-InformationTheme"); |
| 242 |
addWidget(note); |
| 243 |
|
| 244 |
// I need a tree view inside a pannable area |
| 245 |
GtkWidget *hildonPan = gtkWidget("HildonPannableArea"); |
| 246 |
GtkWidget *gtkTreeView = gtk_tree_view_new(); |
| 247 |
QGtkStylePrivate::gtk_container_add((GtkContainer*)hildonPan, gtkTreeView); |
| 248 |
addWidget(gtkTreeView); |
| 249 |
|
| 250 |
// Gtk bug - a GtkButton without a label won't even create it's child widgets |
| 251 |
GtkWidget *button = hildon_button_new(HILDON_SIZE_FINGER_HEIGHT, HILDON_BUTTON_ARRANGEMENT_VERTICAL); |
| 252 |
gtk_button_set_label(reinterpret_cast<GtkButton *>(button), ""); |
| 253 |
addWidget(button); |
| 254 |
button = hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT); |
| 255 |
gtk_button_set_label(reinterpret_cast<GtkButton*>(button), ""); |
| 256 |
addWidget(button); |
| 257 |
|
| 258 |
addWidget(hildon_edit_toolbar_new_with_text("", "")); |
| 259 |
|
| 260 |
// now for a special combobox trick... |
| 261 |
for (int i = 0; i < 3; i++) { |
| 262 |
const char *names[] = { "hildon-combobox-disabled-button", "hildon-combobox-active-button", "hildon-combobox-button" }; |
| 263 |
|
| 264 |
GtkWidget *popup_button = hildon_button_new(HILDON_SIZE_FINGER_HEIGHT, HILDON_BUTTON_ARRANGEMENT_VERTICAL); |
| 265 |
gtk_widget_set_name(popup_button, names[i]); |
| 266 |
gtk_widget_set_size_request (popup_button, 60, -1); |
| 267 |
|
| 268 |
GtkWidget *address_entry = hildon_entry_new(HILDON_SIZE_FINGER_HEIGHT); |
| 269 |
GtkWidget *address_container_box = gtk_hbox_new(FALSE, 0); |
| 270 |
gtk_widget_set_name(address_container_box, "hildon-combobox"); |
| 271 |
|
| 272 |
gtk_box_pack_start((GtkBox *)address_container_box, address_entry, TRUE, TRUE, 0); |
| 273 |
gtk_box_pack_end((GtkBox *)address_container_box, popup_button, FALSE, FALSE, 0); |
| 274 |
gtk_widget_show (address_entry); |
| 275 |
gtk_widget_show (popup_button); |
| 276 |
// gtk_widget_set_sensitive(popup_button, FALSE); |
| 277 |
|
| 278 |
addWidget(address_container_box); |
| 279 |
} |
| 280 |
} |
| 281 |
} |
| 282 |
|
| 283 |
extern QStringList qt_make_filter_list(const QString &filter); |
| 284 |
|
| 285 |
void QMaemo5StylePrivate::setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, |
| 286 |
const QString &dir, const QString &filter, QString *, |
| 287 |
QFileDialog::Options options, bool isSaveDialog, |
| 288 |
QMap<GtkFileFilter *, QString> *) |
| 289 |
{ |
| 290 |
g_object_set(gtkFileChooser, "do-overwrite-confirmation", gboolean(!(options & QFileDialog::DontConfirmOverwrite)), NULL); |
| 291 |
g_object_set(gtkFileChooser, "local_only", gboolean(true), NULL); |
| 292 |
if (!filter.isEmpty()) { |
| 293 |
QStringList filters = qt_make_filter_list(filter); |
| 294 |
|
| 295 |
if (isSaveDialog) { |
| 296 |
const int Nfilters = filters.count(); |
| 297 |
char *ext_names[Nfilters]; |
| 298 |
char *extensions[Nfilters]; |
| 299 |
|
| 300 |
for (int i = 0; i < Nfilters; i++) { |
| 301 |
const QString &rawfilter = filters[i]; |
| 302 |
QString name = rawfilter.left(rawfilter.indexOf(QLatin1Char('('))); |
| 303 |
QString extension = extract_filter(rawfilter)[0].remove(QLatin1String("*.")); |
| 304 |
//Doesn't make sense adding '*' extension in a save dialog; |
| 305 |
if (extension.compare(QLatin1String("*")) == 0) |
| 306 |
qWarning("'*' is not a valid extension for a save dialog"); |
| 307 |
ext_names[i]= (char*) malloc(name.count()+1); |
| 308 |
memcpy(ext_names[i], qPrintable(name), name.count()); |
| 309 |
extensions[i]= (char*) malloc(extension.count()+1); |
| 310 |
memcpy(extensions[i], qPrintable(extension), extension.count()); |
| 311 |
} |
| 312 |
ext_names[Nfilters] = NULL; |
| 313 |
extensions[Nfilters] = NULL; |
| 314 |
|
| 315 |
GtkWidget* gtkExtensionCombo; |
| 316 |
gtkExtensionCombo = hildon_file_chooser_dialog_add_extensions_combo((HildonFileChooserDialog*)(gtkFileChooser), |
| 317 |
extensions,ext_names); |
| 318 |
//gtk_signal_connect (GTK_OBJECT(gtkExtensionCombo), "changed", |
| 319 |
// GTK_SIGNAL_FUNC (qt_update_file_filter), NULL); |
| 320 |
} else { |
| 321 |
//Set "*.ext" filters in the open file dialogs. There we don't have a combobox to select a filter. :( |
| 322 |
//TODO the combobox in the HildonFileChooserDialog doesn't change the filter automatically. We have to set it |
| 323 |
//in Qt.. |
| 324 |
GtkFileFilter *gtkFilter = gtk_file_filter_new (); |
| 325 |
foreach (const QString &rawfilter, filters) { |
| 326 |
QStringList extensions = extract_filter(rawfilter); |
| 327 |
foreach (const QString &fileExtension, extensions) { |
| 328 |
gtk_file_filter_add_pattern (gtkFilter, qPrintable(fileExtension)); |
| 329 |
} |
| 330 |
} |
| 331 |
g_object_set(gtkFileChooser, "filter", gtkFilter, NULL); |
| 332 |
} |
| 333 |
} |
| 334 |
|
| 335 |
// Using the currently active window is not entirely correct, however |
| 336 |
// it gives more sensible behavior for applications that do not provide a |
| 337 |
// parent |
| 338 |
QWidget *modalFor = parent ? parent->window() : qApp->activeWindow(); |
| 339 |
if (modalFor) { |
| 340 |
gtk_widget_realize(gtkFileChooser); // Creates X window |
| 341 |
XSetTransientForHint(gdk_x11_drawable_get_xdisplay(gtkFileChooser->window), |
| 342 |
gdk_x11_drawable_get_xid(gtkFileChooser->window), |
| 343 |
modalFor->winId()); |
| 344 |
gdk_x11_window_set_user_time (gtkFileChooser->window, QX11Info::appUserTime()); |
| 345 |
} |
| 346 |
|
| 347 |
QFileInfo fileinfo(dir); |
| 348 |
if (dir.isEmpty()) |
| 349 |
fileinfo.setFile(QDir::currentPath()); |
| 350 |
fileinfo.makeAbsolute(); |
| 351 |
if (fileinfo.isDir()) { |
| 352 |
gtk_file_chooser_set_current_folder((GtkFileChooser*)gtkFileChooser, qPrintable(dir)); |
| 353 |
} else if (isSaveDialog) { |
| 354 |
gtk_file_chooser_set_current_folder((GtkFileChooser*)gtkFileChooser, qPrintable(fileinfo.absolutePath())); |
| 355 |
gtk_file_chooser_set_current_name((GtkFileChooser*)gtkFileChooser, qPrintable(fileinfo.fileName())); |
| 356 |
} else { |
| 357 |
gtk_file_chooser_set_filename((GtkFileChooser*)gtkFileChooser, qPrintable(dir)); |
| 358 |
} |
| 359 |
} |
| 360 |
|
| 361 |
QString QMaemo5StylePrivate::openFilename(QWidget *parent, const QString &, const QString &dir, const QString &filter, |
| 362 |
QString *selectedFilter, QFileDialog::Options options) |
| 363 |
{ |
| 364 |
QMap<GtkFileFilter *, QString> filterMap; |
| 365 |
GtkWidget *gtkFileChooser = hildon_file_chooser_dialog_new (NULL, GTK_FILE_CHOOSER_ACTION_OPEN); |
| 366 |
|
| 367 |
setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, false, &filterMap); |
| 368 |
|
| 369 |
QWidget modal_widget; |
| 370 |
modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); |
| 371 |
modal_widget.setParent(parent, Qt::Window); |
| 372 |
QApplicationPrivate::enterModal(&modal_widget); |
| 373 |
|
| 374 |
QString filename; |
| 375 |
if (gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_OK) { |
| 376 |
char *gtk_filename = gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); |
| 377 |
filename = QString::fromUtf8(gtk_filename); |
| 378 |
g_free (gtk_filename); |
| 379 |
if (selectedFilter) { |
| 380 |
GtkFileFilter *gtkFilter = gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); |
| 381 |
*selectedFilter = filterMap.value(gtkFilter); |
| 382 |
} |
| 383 |
} |
| 384 |
|
| 385 |
QApplicationPrivate::leaveModal(&modal_widget); |
| 386 |
gtk_widget_destroy (gtkFileChooser); |
| 387 |
return filename; |
| 388 |
} |
| 389 |
|
| 390 |
|
| 391 |
QString QMaemo5StylePrivate::openDirectory(QWidget *parent, const QString &, const QString &dir, QFileDialog::Options options) |
| 392 |
{ |
| 393 |
QMap<GtkFileFilter *, QString> filterMap; |
| 394 |
GtkWidget *gtkFileChooser = hildon_file_chooser_dialog_new (NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); |
| 395 |
|
| 396 |
setupGtkFileChooser(gtkFileChooser, parent, dir, QString(), 0, options); |
| 397 |
QWidget modal_widget; |
| 398 |
modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); |
| 399 |
modal_widget.setParent(parent, Qt::Window); |
| 400 |
QApplicationPrivate::enterModal(&modal_widget); |
| 401 |
|
| 402 |
QString filename; |
| 403 |
if (gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_OK) { |
| 404 |
char *gtk_filename = gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); |
| 405 |
filename = QString::fromUtf8(gtk_filename); |
| 406 |
g_free (gtk_filename); |
| 407 |
} |
| 408 |
|
| 409 |
QApplicationPrivate::leaveModal(&modal_widget); |
| 410 |
gtk_widget_destroy (gtkFileChooser); |
| 411 |
return filename; |
| 412 |
} |
| 413 |
|
| 414 |
QStringList QMaemo5StylePrivate::openFilenames(QWidget *parent, const QString &, const QString &dir, const QString &filter, |
| 415 |
QString *selectedFilter, QFileDialog::Options options) |
| 416 |
{ |
| 417 |
QStringList filenames; |
| 418 |
QMap<GtkFileFilter *, QString> filterMap; |
| 419 |
GtkWidget *gtkFileChooser = hildon_file_chooser_dialog_new (NULL, GTK_FILE_CHOOSER_ACTION_OPEN); |
| 420 |
|
| 421 |
setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, false, &filterMap); |
| 422 |
g_object_set(gtkFileChooser, "select-multiple", gboolean(true), NULL); |
| 423 |
|
| 424 |
QWidget modal_widget; |
| 425 |
modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); |
| 426 |
modal_widget.setParent(parent, Qt::Window); |
| 427 |
QApplicationPrivate::enterModal(&modal_widget); |
| 428 |
|
| 429 |
if (gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_OK) { |
| 430 |
GSList *gtk_file_names = gtk_file_chooser_get_filenames((GtkFileChooser*)gtkFileChooser); |
| 431 |
for (GSList *iterator = gtk_file_names ; iterator; iterator = iterator->next) |
| 432 |
filenames << QString::fromUtf8((const char*)iterator->data); |
| 433 |
g_slist_free(gtk_file_names); |
| 434 |
if (selectedFilter) { |
| 435 |
GtkFileFilter *gtkFilter = gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); |
| 436 |
*selectedFilter = filterMap.value(gtkFilter); |
| 437 |
} |
| 438 |
} |
| 439 |
|
| 440 |
QApplicationPrivate::leaveModal(&modal_widget); |
| 441 |
gtk_widget_destroy (gtkFileChooser); |
| 442 |
return filenames; |
| 443 |
} |
| 444 |
|
| 445 |
QString QMaemo5StylePrivate::saveFilename(QWidget *parent, const QString &, const QString &dir, const QString &filter, |
| 446 |
QString *selectedFilter, QFileDialog::Options options) |
| 447 |
{ |
| 448 |
QMap<GtkFileFilter *, QString> filterMap; |
| 449 |
GtkWidget *gtkFileChooser = hildon_file_chooser_dialog_new (NULL, GTK_FILE_CHOOSER_ACTION_SAVE); |
| 450 |
setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, true, &filterMap); |
| 451 |
|
| 452 |
QWidget modal_widget; |
| 453 |
modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); |
| 454 |
modal_widget.setParent(parent, Qt::Window); |
| 455 |
QApplicationPrivate::enterModal(&modal_widget); |
| 456 |
|
| 457 |
QString filename; |
| 458 |
if (gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_OK) { |
| 459 |
char *gtk_filename = gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); |
| 460 |
filename = QString::fromUtf8(gtk_filename); |
| 461 |
g_free (gtk_filename); |
| 462 |
if (selectedFilter) { |
| 463 |
GtkFileFilter *gtkFilter = gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); |
| 464 |
*selectedFilter = filterMap.value(gtkFilter); |
| 465 |
} |
| 466 |
} |
| 467 |
|
| 468 |
QApplicationPrivate::leaveModal(&modal_widget); |
| 469 |
gtk_widget_destroy (gtkFileChooser); |
| 470 |
return filename; |
| 471 |
} |
| 472 |
|
| 473 |
|
| 474 |
/*! \internal |
| 475 |
* Returns one int value from the HildonAppMenu widget style. |
| 476 |
*/ |
| 477 |
int QMaemo5StylePrivate::getAppMenuMetric( const char *metricName, int defaultValue ) const |
| 478 |
{ |
| 479 |
guint value = defaultValue; |
| 480 |
if (GtkWidget *hildonAppMenu = gtkWidget("HildonAppMenu")) |
| 481 |
gtk_widget_style_get(hildonAppMenu, metricName, &value, NULL); |
| 482 |
return value; |
| 483 |
} |
| 484 |
|
| 485 |
|
| 486 |
/*! |
| 487 |
\class QMaemo5Style |
| 488 |
\brief The QMaemo5Style class provides a widget style rendered by GTK+ |
| 489 |
\since 4.6 |
| 490 |
\ingroup qtmaemo5 |
| 491 |
|
| 492 |
The QMaemo5Style style provides a look and feel that integrates Qt widgets |
| 493 |
into Hildon-based desktop environments. |
| 494 |
|
| 495 |
It is largely based on QGtkStyle, but does some special magic to "Hildonize" the look and feel. |
| 496 |
|
| 497 |
\note The style requires GTK+ version 2.10 or later and the special patched GTK+ Hildon include files. |
| 498 |
*/ |
| 499 |
|
| 500 |
/*! |
| 501 |
Constructs a QMaemo5Style object. |
| 502 |
*/ |
| 503 |
QMaemo5Style::QMaemo5Style() |
| 504 |
: QGtkStyle(*new QMaemo5StylePrivate) |
| 505 |
{ |
| 506 |
} |
| 507 |
|
| 508 |
/*! |
| 509 |
Destroys the QMaemo5Style object. |
| 510 |
*/ |
| 511 |
QMaemo5Style::~QMaemo5Style() |
| 512 |
{ |
| 513 |
} |
| 514 |
|
| 515 |
/*! |
| 516 |
\reimp |
| 517 |
Sets the Maemo style file dialog hooks. |
| 518 |
*/ |
| 519 |
void QMaemo5Style::polish(QApplication *app) |
| 520 |
{ |
| 521 |
Q_D(QMaemo5Style); |
| 522 |
|
| 523 |
QGtkStyle::polish(app); |
| 524 |
|
| 525 |
if (d->hildon_init |
| 526 |
&& app->desktopSettingsAware() && d->isThemeAvailable()) { |
| 527 |
// I want to use the maemo style dialogs |
| 528 |
qt_filedialog_open_filename_hook = &QMaemo5StylePrivate::openFilename; |
| 529 |
qt_filedialog_save_filename_hook = &QMaemo5StylePrivate::saveFilename; |
| 530 |
qt_filedialog_open_filenames_hook = &QMaemo5StylePrivate::openFilenames; |
| 531 |
qt_filedialog_existing_directory_hook = &QMaemo5StylePrivate::openDirectory; |
| 532 |
} |
| 533 |
} |
| 534 |
|
| 535 |
|
| 536 |
ScrollBarFader::ScrollBarFader(QAbstractScrollArea *area, int delay, int duration, int update_interval) |
| 537 |
: QObject(area), m_area(area), m_current_alpha(0.0) |
| 538 |
{ |
| 539 |
m_fade_timeline = new QTimeLine(duration, this); |
| 540 |
m_fade_timeline->setUpdateInterval(update_interval); |
| 541 |
connect(m_fade_timeline, SIGNAL(valueChanged(qreal)), this, SLOT(fade(qreal))); |
| 542 |
m_delay_timer = new QTimer(this); |
| 543 |
m_delay_timer->setInterval(delay); |
| 544 |
connect(m_delay_timer, SIGNAL(timeout()), this, SLOT(delayTimeout())); |
| 545 |
|
| 546 |
area->viewport()->installEventFilter(this); |
| 547 |
} |
| 548 |
|
| 549 |
ScrollBarFader::~ScrollBarFader() |
| 550 |
{ |
| 551 |
} |
| 552 |
|
| 553 |
bool ScrollBarFader::eventFilter(QObject *o, QEvent *e) |
| 554 |
{ |
| 555 |
if (o == m_area->viewport()) { |
| 556 |
switch (e->type()) { |
| 557 |
case QEvent::Show: |
| 558 |
case QEvent::MouseButtonPress: |
| 559 |
case QEvent::MouseMove: |
| 560 |
case QEvent::MouseButtonRelease: |
| 561 |
case QEvent::Wheel: |
| 562 |
case QEvent::KeyPress: |
| 563 |
case QEvent::KeyRelease: |
| 564 |
if (!m_delay_timer->isActive()) { |
| 565 |
m_fade_timeline->setDirection(QTimeLine::Forward); |
| 566 |
if (m_fade_timeline->state() != QTimeLine::Running) |
| 567 |
m_fade_timeline->start(); |
| 568 |
} |
| 569 |
m_delay_timer->start(); |
| 570 |
break; |
| 571 |
|
| 572 |
default: |
| 573 |
break; |
| 574 |
} |
| 575 |
} |
| 576 |
return QObject::eventFilter(o, e); |
| 577 |
} |
| 578 |
|
| 579 |
void ScrollBarFader::delayTimeout() |
| 580 |
{ |
| 581 |
m_fade_timeline->setDirection(QTimeLine::Backward); |
| 582 |
m_fade_timeline->resume(); |
| 583 |
m_delay_timer->stop(); |
| 584 |
} |
| 585 |
|
| 586 |
void ScrollBarFader::fade(qreal value) |
| 587 |
{ |
| 588 |
m_current_alpha = value; |
| 589 |
|
| 590 |
if (QScrollBar *hsb = m_area->horizontalScrollBar()) { |
| 591 |
if (hsb->isVisible()) { |
| 592 |
QStyleOptionSlider option; |
| 593 |
option.initFrom(hsb); |
| 594 |
option.subControls = QStyle::SC_All; |
| 595 |
hsb->update(); // ### hsb->style()->subControlRect(QStyle::CC_ScrollBar, &option, QStyle::SC_ScrollBarSlider, hsb)); |
| 596 |
} |
| 597 |
} |
| 598 |
if (QScrollBar *vsb = m_area->verticalScrollBar()) { |
| 599 |
if (vsb->isVisible()) { |
| 600 |
QStyleOptionSlider option; |
| 601 |
option.initFrom(vsb); |
| 602 |
option.subControls = QStyle::SC_All; |
| 603 |
vsb->update(); // ### vsb->style()->subControlRect(QStyle::CC_ScrollBar, &option, QStyle::SC_ScrollBarSlider, vsb)); |
| 604 |
} |
| 605 |
} |
| 606 |
} |
| 607 |
|
| 608 |
|
| 609 |
/*! |
| 610 |
\reimp |
| 611 |
*/ |
| 612 |
void QMaemo5Style::polish(QWidget *widget) |
| 613 |
{ |
| 614 |
Q_D(QMaemo5Style); |
| 615 |
|
| 616 |
QGtkStyle::polish(widget); |
| 617 |
if (QAbstractScrollArea *area = qobject_cast<QAbstractScrollArea *>(widget)) { |
| 618 |
if ((qobject_cast<QTextEdit *>(widget) && !qobject_cast<QTextBrowser *>(widget)) || qobject_cast<QPlainTextEdit *>(widget)) { |
| 619 |
area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| 620 |
area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| 621 |
} else { |
| 622 |
area->setFrameStyle(QFrame::NoFrame); |
| 623 |
|
| 624 |
d->scrollBarFaders.insert(area, new ScrollBarFader(area, d->scrollBarFadeDelay, |
| 625 |
d->scrollBarFadeDuration, |
| 626 |
d->scrollBarFadeUpdateInterval)); |
| 627 |
|
| 628 |
// make sure that the scrollbars have a white text color, because the scroll indicators are |
| 629 |
// drawn using the QPalette::Text color |
| 630 |
if (GtkWidget *gtkWidget = d->gtkWidget("HildonPannableArea.GtkTreeView")) { |
| 631 |
GdkColor gdkText = gtkWidget->style->text[GTK_STATE_NORMAL]; |
| 632 |
QPalette scrollPalette = area->horizontalScrollBar()->palette(); |
| 633 |
scrollPalette.setColor(QPalette::Text, QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8)); |
| 634 |
area->horizontalScrollBar()->setPalette(scrollPalette); |
| 635 |
area->verticalScrollBar()->setPalette(scrollPalette); |
| 636 |
} |
| 637 |
|
| 638 |
if (QAbstractItemView *itemview = qobject_cast<QAbstractItemView *>(area)) { |
| 639 |
itemview->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); |
| 640 |
itemview->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); |
| 641 |
|
| 642 |
if (GtkWidget *gtkWidget = d->gtkWidget("HildonPannableArea.GtkTreeView")) { |
| 643 |
QPalette palette = widget->palette(); |
| 644 |
|
| 645 |
GdkColor gdkBg, gdkBase, gdkText, gdkForeground; |
| 646 |
GdkColor gdkSbg, gdkSfg, gdkIbg, gdkIfg; |
| 647 |
QColor bg, base, text, fg, highlight, highlightText, disabled, disabledText; |
| 648 |
|
| 649 |
gdkBg = gtkWidget->style->bg[GTK_STATE_NORMAL]; |
| 650 |
gdkForeground = gtkWidget->style->fg[GTK_STATE_NORMAL]; |
| 651 |
|
| 652 |
// Our base and selected color is primarily used for text |
| 653 |
// so we assume a gtkWidget will have the most correct value |
| 654 |
gdkBase = gtkWidget->style->base[GTK_STATE_NORMAL]; |
| 655 |
gdkText = gtkWidget->style->text[GTK_STATE_NORMAL]; |
| 656 |
gdkSbg = gtkWidget->style->base[GTK_STATE_SELECTED]; |
| 657 |
gdkSfg = gtkWidget->style->text[GTK_STATE_SELECTED]; |
| 658 |
gdkIbg = gtkWidget->style->base[GTK_STATE_INSENSITIVE]; |
| 659 |
gdkIfg = gtkWidget->style->text[GTK_STATE_INSENSITIVE]; |
| 660 |
|
| 661 |
bg = QColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); |
| 662 |
text = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); |
| 663 |
fg = QColor(gdkForeground.red>>8, gdkForeground.green>>8, gdkForeground.blue>>8); |
| 664 |
base = QColor(gdkBase.red>>8, gdkBase.green>>8, gdkBase.blue>>8); |
| 665 |
highlight = QColor(gdkSbg.red>>8, gdkSbg.green>>8, gdkSbg.blue>>8); |
| 666 |
highlightText = QColor(gdkSfg.red>>8, gdkSfg.green>>8, gdkSfg.blue>>8); |
| 667 |
disabled = QColor(gdkIbg.red>>8, gdkIbg.green>>8, gdkIbg.blue>>8); |
| 668 |
disabledText = QColor(gdkIfg.red>>8, gdkIfg.green>>8, gdkIfg.blue>>8); |
| 669 |
|
| 670 |
palette.setColor(QPalette::HighlightedText, highlightText); |
| 671 |
palette.setColor(QPalette::Light, bg.lighter(125)); |
| 672 |
palette.setColor(QPalette::Shadow, bg.darker(130)); |
| 673 |
palette.setColor(QPalette::Dark, bg.darker(120)); |
| 674 |
palette.setColor(QPalette::Text, text); |
| 675 |
palette.setColor(QPalette::WindowText, fg); |
| 676 |
palette.setColor(QPalette::ButtonText, fg); |
| 677 |
palette.setColor(QPalette::Base, base); |
| 678 |
|
| 679 |
palette.setColor(QPalette::Disabled, QPalette::Text, disabledText); |
| 680 |
palette.setColor(QPalette::Disabled, QPalette::WindowText, disabledText); |
| 681 |
palette.setColor(QPalette::Disabled, QPalette::Foreground, disabledText); |
| 682 |
palette.setColor(QPalette::Disabled, QPalette::ButtonText, disabledText); |
| 683 |
|
| 684 |
widget->setPalette(palette); |
| 685 |
} |
| 686 |
} |
| 687 |
} |
| 688 |
} else if (qobject_cast<QCommandLinkButton*>(widget)) { |
| 689 |
widget->setFont(standardFont(QLS("SystemFont"))); |
| 690 |
widget->setAttribute(Qt::WA_Hover, false); |
| 691 |
} |
| 692 |
|
| 693 |
if (widget && widget->parentWidget() && widget->parentWidget()->inherits("QMaemo5InformationBox")) { |
| 694 |
const char name[] = "HildonNote-information-theme.GtkAlignment.GtkHBox.GtkVBox.GtkEventBox.GtkAlignment.GtkVBox.HildonNoteLabel-information-theme"; |
| 695 |
if (d->gtkWidget(name)) |
| 696 |
widget->setPalette(d->gtkWidgetPalette(name)); |
| 697 |
} |
| 698 |
} |
| 699 |
|
| 700 |
/*! |
| 701 |
\reimp |
| 702 |
*/ |
| 703 |
void QMaemo5Style::unpolish(QWidget *widget) |
| 704 |
{ |
| 705 |
Q_D(QMaemo5Style); |
| 706 |
|
| 707 |
QGtkStyle::unpolish(widget); |
| 708 |
|
| 709 |
if (QAbstractScrollArea *area = qobject_cast<QAbstractScrollArea*>(widget)) { |
| 710 |
delete d->scrollBarFaders.take(area); |
| 711 |
|
| 712 |
if (QAbstractItemView *itemview = qobject_cast<QAbstractItemView *>(area)) |
| 713 |
itemview->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); |
| 714 |
} |
| 715 |
} |
| 716 |
|
| 717 |
/*! |
| 718 |
\reimp |
| 719 |
*/ |
| 720 |
int QMaemo5Style::pixelMetric(QStyle::PixelMetric metric, |
| 721 |
const QStyleOption *option, |
| 722 |
const QWidget *widget) const |
| 723 |
{ |
| 724 |
Q_D(const QMaemo5Style); |
| 725 |
|
| 726 |
if (!d->isThemeAvailable()) |
| 727 |
return QCleanlooksStyle::pixelMetric(metric, option, widget); |
| 728 |
|
| 729 |
switch (metric) { |
| 730 |
case PM_DefaultLayoutSpacing: |
| 731 |
return 8; |
| 732 |
case PM_DefaultTopLevelMargin: |
| 733 |
return 8; |
| 734 |
case PM_LayoutLeftMargin: |
| 735 |
case PM_LayoutRightMargin: |
| 736 |
return 16; |
| 737 |
case PM_LayoutTopMargin: |
| 738 |
return 0; |
| 739 |
case PM_LayoutBottomMargin: |
| 740 |
return 8; |
| 741 |
case PM_DialogButtonsButtonHeight: |
| 742 |
return 70; |
| 743 |
case PM_DialogButtonsButtonWidth: |
| 744 |
return 180; |
| 745 |
case PM_MessageBoxIconSize: |
| 746 |
return 0; |
| 747 |
case PM_ToolBarIconSize: |
| 748 |
return 48; // thumb icon size |
| 749 |
case PM_TabBarIconSize: |
| 750 |
case PM_ListViewIconSize: |
| 751 |
return 48; // thumb icon size |
| 752 |
case PM_TextCursorWidth: |
| 753 |
return 2; |
| 754 |
case PM_SplitterWidth: |
| 755 |
return 14; |
| 756 |
case PM_HeaderGripMargin: |
| 757 |
return 30; |
| 758 |
case PM_SmallIconSize: |
| 759 |
return 24; |
| 760 |
case PM_LargeIconSize: |
| 761 |
return 48; |
| 762 |
case PM_ButtonShiftHorizontal: { |
| 763 |
guint horizontal_shift = 1; |
| 764 |
if (GtkWidget *gtkButton = d->gtkWidget("HildonButton-finger")) |
| 765 |
d->gtk_widget_style_get(gtkButton, "child-displacement-x", &horizontal_shift, NULL); |
| 766 |
return horizontal_shift; |
| 767 |
} |
| 768 |
case PM_ButtonShiftVertical: { |
| 769 |
guint vertical_shift = 1; |
| 770 |
if (GtkWidget *gtkButton = d->gtkWidget("HildonButton-finger")) |
| 771 |
d->gtk_widget_style_get(gtkButton, "child-displacement-y", &vertical_shift, NULL); |
| 772 |
return vertical_shift; |
| 773 |
} |
| 774 |
case PM_ScrollBarSliderMin: // fall through |
| 775 |
case PM_ScrollBarExtent: { |
| 776 |
guint indicator_width = 6; |
| 777 |
if (GtkWidget *hildonPan = d->gtkWidget("HildonPannableArea")) |
| 778 |
d->gtk_widget_style_get(hildonPan, "indicator-width", &indicator_width, NULL); |
| 779 |
return indicator_width; |
| 780 |
} |
| 781 |
case PM_ScrollView_ScrollBarSpacing: |
| 782 |
return 0; |
| 783 |
|
| 784 |
case PM_TabBarTabHSpace: |
| 785 |
return 38; |
| 786 |
case PM_TabBarTabVSpace: |
| 787 |
return 38; |
| 788 |
|
| 789 |
case PM_ExclusiveIndicatorWidth: |
| 790 |
case PM_ExclusiveIndicatorHeight: |
| 791 |
case PM_IndicatorWidth: |
| 792 |
case PM_IndicatorHeight: { |
| 793 |
gint size = 38, spacing = 8; |
| 794 |
if (GtkWidget *hildonCheckButton = d->gtkWidget("HildonCheckButton-finger")) |
| 795 |
d->gtk_widget_style_get(hildonCheckButton, "image-spacing", &spacing, "checkbox-size", &size, NULL); |
| 796 |
return size + 2 * spacing; |
| 797 |
} |
| 798 |
case PM_CheckBoxLabelSpacing: |
| 799 |
return 3; // image-spacing is already calculated into PM_IndicatorWidth, but we're still 3pix to narrow... |
| 800 |
|
| 801 |
case PM_Maemo5AppMenuHorizontalSpacing: |
| 802 |
return d->getAppMenuMetric("horizontal-spacing", 16); |
| 803 |
case PM_Maemo5AppMenuVerticalSpacing: |
| 804 |
return d->getAppMenuMetric("vertical-spacing", 16); |
| 805 |
case PM_Maemo5AppMenuContentMargin: |
| 806 |
return d->getAppMenuMetric("inner-border", 16); |
| 807 |
case PM_Maemo5AppMenuLandscapeXOffset: |
| 808 |
return d->getAppMenuMetric("external-border", 50); |
| 809 |
case PM_Maemo5AppMenuFilterGroupWidth: |
| 810 |
return d->getAppMenuMetric("filter-group-width", 444); |
| 811 |
case PM_Maemo5AppMenuFilterGroupVerticalSpacing: |
| 812 |
return d->getAppMenuMetric("filter-vertical-spacing", 16); |
| 813 |
|
| 814 |
case PM_Maemo5EditBarBackButtonWidth: { |
| 815 |
gint width = 112; |
| 816 |
if (GtkWidget *hildonEditBar = d->gtkWidget("toolbar-edit-mode")) |
| 817 |
d->gtk_widget_style_get(hildonEditBar, "arrow-width", &width, NULL); |
| 818 |
return width; |
| 819 |
} |
| 820 |
case PM_Maemo5EditBarBackButtonHeight: { |
| 821 |
gint height = 56; |
| 822 |
if (GtkWidget *hildonEditBar = d->gtkWidget("toolbar-edit-mode")) |
| 823 |
d->gtk_widget_style_get(hildonEditBar, "arrow-height", &height, NULL); |
| 824 |
return height; |
| 825 |
} |
| 826 |
|
| 827 |
default: |
| 828 |
return QGtkStyle::pixelMetric(metric, option, widget); |
| 829 |
} |
| 830 |
} |
| 831 |
|
| 832 |
/*! |
| 833 |
\reimp |
| 834 |
*/ |
| 835 |
int QMaemo5Style::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, |
| 836 |
QStyleHintReturn *returnData = 0) const |
| 837 |
{ |
| 838 |
Q_D(const QMaemo5Style); |
| 839 |
|
| 840 |
if (!d->isThemeAvailable()) |
| 841 |
return QCleanlooksStyle::styleHint(hint, option, widget, returnData); |
| 842 |
|
| 843 |
switch (hint) { |
| 844 |
case SH_Menu_Scrollable: |
| 845 |
return int(true); |
| 846 |
case SH_DialogButtonBox_ButtonsHaveIcons: |
| 847 |
case SH_ScrollBar_ContextMenu: |
| 848 |
return int(false); |
| 849 |
case SH_UnderlineShortcut: |
| 850 |
return int(false); |
| 851 |
case SH_RequestSoftwareInputPanel: |
| 852 |
return int(RSIP_OnMouseClick); |
| 853 |
case SH_Slider_AbsoluteSetButtons: |
| 854 |
return int(Qt::LeftButton); |
| 855 |
case SH_Slider_PageSetButtons: |
| 856 |
return int(Qt::NoButton); |
| 857 |
case SH_ItemView_ActivateItemOnSingleClick: |
| 858 |
return int(true); |
| 859 |
case SH_ComboBox_ListMouseTracking: |
| 860 |
return int(false); |
| 861 |
case SH_ComboBox_Popup: |
| 862 |
return int(false); |
| 863 |
case SH_ComboBox_PopupFrameStyle: |
| 864 |
return int(QFrame::Plain | QFrame::Box); |
| 865 |
case SH_ProgressDialog_TextLabelAlignment: |
| 866 |
return int(Qt::AlignLeft | Qt::AlignVCenter); |
| 867 |
default: |
| 868 |
return QGtkStyle::styleHint(hint, option, widget, returnData); |
| 869 |
} |
| 870 |
} |
| 871 |
|
| 872 |
/*! |
| 873 |
\reimp |
| 874 |
*/ |
| 875 |
void QMaemo5Style::drawPrimitive(QStyle::PrimitiveElement element, |
| 876 |
const QStyleOption *option, |
| 877 |
QPainter *painter, |
| 878 |
const QWidget *widget) const |
| 879 |
{ |
| 880 |
Q_D(const QMaemo5Style); |
| 881 |
|
| 882 |
if (!d->isThemeAvailable()) { |
| 883 |
QCleanlooksStyle::drawPrimitive(element, option, painter, widget); |
| 884 |
return; |
| 885 |
} |
| 886 |
|
| 887 |
QGtkPainter gtkPainter(painter); |
| 888 |
|
| 889 |
switch (element) { |
| 890 |
case PE_PanelButtonTool: // fall through |
| 891 |
case PE_PanelButtonCommand: { |
| 892 |
bool isTool = (element == PE_PanelButtonTool); |
| 893 |
|
| 894 |
GtkStateType state = gtkPainter.gtkState(option); |
| 895 |
GtkShadowType shadow = GTK_SHADOW_OUT; |
| 896 |
if (option->state & State_On || option->state & State_Sunken) { |
| 897 |
state = GTK_STATE_ACTIVE; |
| 898 |
shadow = GTK_SHADOW_IN; |
| 899 |
} |
| 900 |
GtkWidget *gtkButton = 0; |
| 901 |
if (isTool) |
| 902 |
gtkButton = d->gtkWidget("GtkToolButton.GtkButton"); |
| 903 |
else if (widget && qobject_cast<QDialogButtonBox *>(widget->parentWidget())) |
| 904 |
gtkButton = d->gtkWidget("HildonDialog.GtkAlignment.GtkHBox.hildon-dialog-action-area.GtkButton-finger"); |
| 905 |
else if (widget && widget->parentWidget() && !qstrcmp(widget->parentWidget()->metaObject()->className(), "QMaemo5EditBar")) |
| 906 |
gtkButton = d->gtkWidget("toolbar-edit-mode.GtkAlignment.GtkHBox.GtkButton"); |
| 907 |
else |
| 908 |
gtkButton = d->gtkWidget("HildonButton-finger"); |
| 909 |
|
| 910 |
if (gtkButton) { |
| 911 |
gtkPainter.paintBox(gtkButton, "button", option->rect, state, shadow, |
| 912 |
gtkButton->style, QString()); |
| 913 |
} |
| 914 |
break; |
| 915 |
} |
| 916 |
case PE_IndicatorBranch: |
| 917 |
// Due to style guidelines, maemo5 does not draw |
| 918 |
// expanders. But for compatibilitys sake we have to |
| 919 |
if (option->state & State_Children) { |
| 920 |
if (option->state & State_Open) |
| 921 |
QCleanlooksStyle::drawPrimitive(PE_IndicatorArrowDown, option, painter, widget); |
| 922 |
else |
| 923 |
QCleanlooksStyle::drawPrimitive(PE_IndicatorArrowRight, option, painter, widget); |
| 924 |
} |
| 925 |
break; |
| 926 |
|
| 927 |
case PE_FrameFocusRect: |
| 928 |
// never required with Hildon |
| 929 |
break; |
| 930 |
|
| 931 |
case PE_Frame: |
| 932 |
if ((qobject_cast<const QTextEdit *>(widget) && !qobject_cast<const QTextBrowser *>(widget)) || qobject_cast<const QPlainTextEdit *>(widget)) |
| 933 |
proxy()->drawPrimitive(PE_FrameLineEdit, option, painter, widget); |
| 934 |
else |
| 935 |
QGtkStyle::drawPrimitive(element, option, painter, widget); |
| 936 |
break; |
| 937 |
|
| 938 |
case PE_PanelLineEdit: |
| 939 |
{ |
| 940 |
int lineWidth = 1; |
| 941 |
if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) |
| 942 |
lineWidth = panel->lineWidth; |
| 943 |
// For embedded line edits we rely on the parent widget to fill the |
| 944 |
// background. The entry_bg is not a uniform color in Hildon |
| 945 |
if (lineWidth > 0) { |
| 946 |
GtkWidget *gtkEntry = d->gtkWidget("HildonEntry-finger"); |
| 947 |
uint resolve_mask = option->palette.resolve(); |
| 948 |
QRect textRect = option->rect.adjusted(gtkEntry->style->xthickness, gtkEntry->style->ythickness, |
| 949 |
-gtkEntry->style->xthickness, -gtkEntry->style->ythickness); |
| 950 |
if (widget && widget->testAttribute(Qt::WA_SetPalette) && |
| 951 |
resolve_mask & (1 << QPalette::Base)) // Palette overridden by user |
| 952 |
painter->fillRect(textRect, option->palette.base()); |
| 953 |
else { |
| 954 |
gtkPainter.paintFlatBox(gtkEntry, "entry_bg", textRect, |
| 955 |
option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, GTK_SHADOW_NONE, gtkEntry->style); |
| 956 |
} |
| 957 |
proxy()->drawPrimitive(PE_FrameLineEdit, option, painter, widget); |
| 958 |
} else if (option->state & State_Enabled) { |
| 959 |
// Note this is a bit of a workaround. Open item editors require us to fill the line |
| 960 |
// edit background but doing this will make it impossible to get the correct |
| 961 |
// background color for disabled spin box, line edit and combo box. |
| 962 |
// |
| 963 |
// This would be more elegant if we could either get the correct fill color for |
| 964 |
// disabled line edits or if itemview did not draw the item when an editor is open |
| 965 |
painter->fillRect(option->rect.adjusted(lineWidth, lineWidth, -lineWidth, -lineWidth), |
| 966 |
option->palette.brush(QPalette::Base)); |
| 967 |
} |
| 968 |
} |
| 969 |
break; |
| 970 |
|
| 971 |
case PE_FrameLineEdit: { |
| 972 |
GtkWidget *gtkEntry = d->gtkWidget("HildonEntry-finger"); |
| 973 |
|
| 974 |
gboolean interior_focus; |
| 975 |
gint focus_line_width; |
| 976 |
gboolean state_hint = false; |
| 977 |
QRect rect = option->rect; |
| 978 |
d->gtk_widget_style_get(gtkEntry, |
| 979 |
"interior-focus", &interior_focus, |
| 980 |
"focus-line-width", &focus_line_width, |
| 981 |
"state-hint", &state_hint, NULL); |
| 982 |
|
| 983 |
// See https://bugzilla.mozilla.org/show_bug.cgi?id=405421 for info about this hack |
| 984 |
g_object_set_data(G_OBJECT(gtkEntry), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); |
| 985 |
|
| 986 |
if (!interior_focus && option->state & State_HasFocus) |
| 987 |
rect.adjust(focus_line_width, focus_line_width, -focus_line_width, -focus_line_width); |
| 988 |
|
| 989 |
if (option->state & State_HasFocus) |
| 990 |
GTK_WIDGET_SET_FLAGS(gtkEntry, GTK_HAS_FOCUS); |
| 991 |
gtkPainter.paintShadow(gtkEntry, "entry", rect, option->state & State_Enabled ? |
| 992 |
(state_hint && option->state & State_HasFocus ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL) : GTK_STATE_INSENSITIVE, |
| 993 |
GTK_SHADOW_IN, gtkEntry->style, |
| 994 |
option->state & State_HasFocus ? QLS("focus") : QString()); |
| 995 |
if (!interior_focus && option->state & State_HasFocus) |
| 996 |
gtkPainter.paintShadow(gtkEntry, "entry", option->rect, option->state & State_Enabled ? |
| 997 |
GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE, |
| 998 |
GTK_SHADOW_IN, gtkEntry->style, QLS("GtkEntryShadowIn")); |
| 999 |
|
| 1000 |
if (option->state & State_HasFocus) |
| 1001 |
GTK_WIDGET_UNSET_FLAGS(gtkEntry, GTK_HAS_FOCUS); |
| 1002 |
break; |
| 1003 |
} |
| 1004 |
|
| 1005 |
case PE_IndicatorCheckBox: { |
| 1006 |
GtkShadowType shadow = GTK_SHADOW_OUT; |
| 1007 |
GtkStateType state = gtkPainter.gtkState(option); |
| 1008 |
|
| 1009 |
if (option->state & State_Sunken) |
| 1010 |
state = GTK_STATE_ACTIVE; |
| 1011 |
|
| 1012 |
if (option->state & State_NoChange) |
| 1013 |
shadow = GTK_SHADOW_ETCHED_IN; |
| 1014 |
else if (option->state & State_On) |
| 1015 |
shadow = GTK_SHADOW_IN; |
| 1016 |
else |
| 1017 |
shadow = GTK_SHADOW_OUT; |
| 1018 |
|
| 1019 |
int spacing; |
| 1020 |
|
| 1021 |
if (GtkWidget *gtkCheckButton = d->gtkWidget("HildonCheckButton-finger")) { |
| 1022 |
GtkWidget *gtkCellView = d->gtkWidget("HildonCheckButton-finger.GtkAlignment.GtkHBox.GtkCellView"); |
| 1023 |
// Some styles such as aero-clone assume they can paint in the spacing area |
| 1024 |
gtkPainter.setClipRect(option->rect); |
| 1025 |
|
| 1026 |
d->gtk_widget_style_get(gtkCheckButton, "image-spacing", &spacing, NULL); |
| 1027 |
|
| 1028 |
QRect checkRect = option->rect.adjusted(spacing, spacing, -spacing, -spacing); |
| 1029 |
|
| 1030 |
gtkPainter.paintCheckbox(gtkCellView, checkRect, state, shadow, gtkCellView->style, |
| 1031 |
QLS("checkbutton")); |
| 1032 |
} |
| 1033 |
break; |
| 1034 |
} |
| 1035 |
case PE_PanelItemViewItem: { |
| 1036 |
|
| 1037 |
//To improve the performance we won't cache unusable states |
| 1038 |
QStyle::State old_state = option->state; |
| 1039 |
const_cast<QStyleOption*>(option)->state |= QStyle::State_Active; |
| 1040 |
const_cast<QStyleOption*>(option)->state &= ~(QStyle::State_HasFocus | QStyle::State_MouseOver); |
| 1041 |
|
| 1042 |
BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("panelitem")); |
| 1043 |
QGtkPainter gtkCachedPainter(p); |
| 1044 |
QRect cacheRect(0, 0, option->rect.width(), option->rect.height()); |
| 1045 |
if (GtkWidget *gtkTreeView = d->gtkWidget("HildonPannableArea.GtkTreeView")) { |
| 1046 |
const char *detail = "cell_odd_ruled"; |
| 1047 |
const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option); |
| 1048 |
if (vopt && vopt->features & QStyleOptionViewItemV2::Alternate) |
| 1049 |
detail = "cell_even_ruled"; |
| 1050 |
|
| 1051 |
int rowHeight = 70; |
| 1052 |
if (GtkWidget *gtkTreeView = d->gtkWidget("HildonPannableArea.GtkTreeView")) |
| 1053 |
d->gtk_widget_style_get(gtkTreeView, "row-height", &rowHeight, NULL); |
| 1054 |
|
| 1055 |
if (option->rect.height() != rowHeight) { |
| 1056 |
QPixmap scalePix(option->rect.width(), rowHeight); |
| 1057 |
scalePix.fill(Qt::transparent); |
| 1058 |
QPainter scalePainter(&scalePix); |
| 1059 |
QGtkPainter gtkScalePainter(&scalePainter); |
| 1060 |
gtkScalePainter.setUsePixmapCache(false); // cached externally |
| 1061 |
|
| 1062 |
// the sapwood engine won't scale the image, but instead tile it, which looks ridiculous |
| 1063 |
gtkScalePainter.paintFlatBox(gtkTreeView, detail, QRect(0, 0, option->rect.width(), rowHeight), |
| 1064 |
option->state & State_Selected ? GTK_STATE_SELECTED : |
| 1065 |
option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, |
| 1066 |
GTK_SHADOW_NONE, gtkTreeView->style); |
| 1067 |
|
| 1068 |
// don't just scale the whole pixmap - the bottom border line would look extremly ugly for big items |
| 1069 |
int dh = 8; // just an arbitrary value which looks good with the default Maemo styles |
| 1070 |
p->drawPixmap(cacheRect.topLeft(), scalePix, QRect(0, 0, scalePix.width(), dh)); |
| 1071 |
p->drawPixmap(cacheRect.adjusted(0, dh, 0, -dh), scalePix, QRect(0, dh, scalePix.width(), scalePix.height() - 2 * dh)); |
| 1072 |
p->drawPixmap(cacheRect.bottomLeft() - QPoint(0, dh), scalePix, QRect(0, scalePix.height() - dh, scalePix.width(), dh)); |
| 1073 |
} else { |
| 1074 |
gtkCachedPainter.paintFlatBox(gtkTreeView, detail, cacheRect, |
| 1075 |
option->state & State_Selected ? GTK_STATE_SELECTED : |
| 1076 |
option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, |
| 1077 |
GTK_SHADOW_NONE, gtkTreeView->style); |
| 1078 |
} |
| 1079 |
} |
| 1080 |
END_STYLE_PIXMAPCACHE |
| 1081 |
const_cast<QStyleOption*>(option)->state = old_state; |
| 1082 |
break; |
| 1083 |
} |
| 1084 |
case PE_Maemo5InformationBox: { |
| 1085 |
if (GtkWidget *hildonInformation = d->gtkWidget("HildonNote-information-theme")) |
| 1086 |
gtkPainter.paintFlatBox(hildonInformation, NULL, option->rect, GTK_STATE_NORMAL, GTK_SHADOW_NONE, hildonInformation->style, QString()); |
| 1087 |
break; |
| 1088 |
} |
| 1089 |
case PE_Maemo5AppMenu: { |
| 1090 |
if (GtkWidget *hildonAppMenu = d->gtkWidget("HildonAppMenu")) |
| 1091 |
gtkPainter.paintFlatBox(hildonAppMenu, NULL, option->rect, GTK_STATE_NORMAL, GTK_SHADOW_NONE, hildonAppMenu->style, QString()); |
| 1092 |
break; |
| 1093 |
} |
| 1094 |
case PE_Maemo5EditBar: { |
| 1095 |
if (GtkWidget *hildonEditBar = d->gtkWidget("toolbar-edit-mode")) |
| 1096 |
gtkPainter.paintFlatBox(hildonEditBar, NULL, option->rect, GTK_STATE_NORMAL, GTK_SHADOW_NONE, hildonEditBar->style, QString()); |
| 1097 |
break; |
| 1098 |
} |
| 1099 |
case PE_Maemo5EditBarBackButton: { |
| 1100 |
if (GtkWidget *hildonEditBarBackButton = d->gtkWidget("toolbar-edit-mode.hildon-edit-toolbar-arrow")) { |
| 1101 |
GtkStateType state = gtkPainter.gtkState(option); |
| 1102 |
GtkShadowType shadow = GTK_SHADOW_OUT; |
| 1103 |
if (option->state & State_On || option->state & State_Sunken) { |
| 1104 |
state = GTK_STATE_ACTIVE; |
| 1105 |
shadow = GTK_SHADOW_IN; |
| 1106 |
} |
| 1107 |
gtkPainter.paintBox(hildonEditBarBackButton, "button", option->rect, state, shadow, hildonEditBarBackButton->style, QString()); |
| 1108 |
} |
| 1109 |
break; |
| 1110 |
} |
| 1111 |
default: |
| 1112 |
QGtkStyle::drawPrimitive(element, option, painter, widget); |
| 1113 |
} |
| 1114 |
} |
| 1115 |
|
| 1116 |
/*! |
| 1117 |
\reimp |
| 1118 |
*/ |
| 1119 |
void QMaemo5Style::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, |
| 1120 |
QPainter *painter, const QWidget *widget) const |
| 1121 |
{ |
| 1122 |
Q_D(const QMaemo5Style); |
| 1123 |
|
| 1124 |
if (!d->isThemeAvailable()) { |
| 1125 |
|
| 1126 |
QCleanlooksStyle::drawComplexControl(control, option, painter, widget); |
| 1127 |
return; |
| 1128 |
} |
| 1129 |
|
| 1130 |
QGtkPainter gtkPainter(painter); |
| 1131 |
|
| 1132 |
switch (control) { |
| 1133 |
case CC_Dial: |
| 1134 |
if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) { |
| 1135 |
QPalette pal = option->palette; |
| 1136 |
QColor buttonColor(0x404040); //= pal.button().color(); |
| 1137 |
const int width = option->rect.width(); |
| 1138 |
const int height = option->rect.height(); |
| 1139 |
const bool enabled = option->state & QStyle::State_Enabled; |
| 1140 |
qreal r = qMin(width, height) / 2; |
| 1141 |
r -= r/50; |
| 1142 |
const qreal penSize = r/20.0; |
| 1143 |
|
| 1144 |
painter->save(); |
| 1145 |
painter->setRenderHint(QPainter::Antialiasing); |
| 1146 |
|
| 1147 |
// Draw notches |
| 1148 |
if (option->subControls & QStyle::SC_DialTickmarks) { |
| 1149 |
painter->setPen(option->palette.dark().color().darker(120)); |
| 1150 |
painter->drawLines(QStyleHelper::calcLines(scrollBar)); |
| 1151 |
} |
| 1152 |
|
| 1153 |
// Cache dial background |
| 1154 |
BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("qdial")); |
| 1155 |
p->setRenderHint(QPainter::Antialiasing); |
| 1156 |
|
| 1157 |
const qreal d_ = r / 6; |
| 1158 |
const qreal dx = option->rect.x() + d_ + (width - 2 * r) / 2 + 1; |
| 1159 |
const qreal dy = option->rect.y() + d_ + (height - 2 * r) / 2 + 1; |
| 1160 |
|
| 1161 |
QRectF br = QRectF(dx + 0.5, dy + 0.5, |
| 1162 |
int(r * 2 - 2 * d_ - 2), |
| 1163 |
int(r * 2 - 2 * d_ - 2)); |
| 1164 |
QColor shadowColor(0, 0, 0, 20); |
| 1165 |
|
| 1166 |
if (enabled) { |
| 1167 |
// Drop shadow |
| 1168 |
qreal shadowSize = qMax(1.0, penSize/2.0); |
| 1169 |
QRectF shadowRect= br.adjusted(-2*shadowSize, -2*shadowSize, |
| 1170 |
2*shadowSize, 2*shadowSize); |
| 1171 |
QRadialGradient shadowGradient(shadowRect.center().x(), |
| 1172 |
shadowRect.center().y(), shadowRect.width()/2.0, |
| 1173 |
shadowRect.center().x(), shadowRect.center().y()); |
| 1174 |
shadowGradient.setColorAt(qreal(0.91), QColor(0, 0, 0, 40)); |
| 1175 |
shadowGradient.setColorAt(qreal(1.0), Qt::transparent); |
| 1176 |
p->setBrush(shadowGradient); |
| 1177 |
p->setPen(Qt::NoPen); |
| 1178 |
p->translate(shadowSize, shadowSize); |
| 1179 |
p->drawEllipse(shadowRect); |
| 1180 |
p->translate(-shadowSize, -shadowSize); |
| 1181 |
|
| 1182 |
// Main gradient |
| 1183 |
QRadialGradient gradient(br.center().x() - br.width()/3, dy, |
| 1184 |
br.width()*1.3, br.center().x(), |
| 1185 |
br.center().y() - br.height()/2); |
| 1186 |
gradient.setColorAt(0, buttonColor); |
| 1187 |
gradient.setColorAt(qreal(0.6), buttonColor); |
| 1188 |
gradient.setColorAt(qreal(0.601), buttonColor.darker(107)); |
| 1189 |
gradient.setColorAt(1, buttonColor.darker(107)); |
| 1190 |
p->setBrush(gradient); |
| 1191 |
} else { |
| 1192 |
p->setBrush(Qt::NoBrush); |
| 1193 |
} |
| 1194 |
|
| 1195 |
p->setPen(QPen(buttonColor.lighter(160), 2)); |
| 1196 |
p->drawEllipse(br); |
| 1197 |
p->setBrush(Qt::NoBrush); |
| 1198 |
p->setPen(buttonColor.lighter(110)); |
| 1199 |
p->drawEllipse(br.adjusted(1, 1, -1, -1)); |
| 1200 |
|
| 1201 |
if (option->state & QStyle::State_HasFocus) { |
| 1202 |
QColor highlight = pal.highlight().color(); |
| 1203 |
highlight.setHsv(highlight.hue(), |
| 1204 |
qMin(190, highlight.saturation()), |
| 1205 |
qMax(210, highlight.value())); |
| 1206 |
highlight.setAlpha(200); |
| 1207 |
p->setPen(QPen(highlight, 2.0)); |
| 1208 |
p->setBrush(Qt::NoBrush); |
| 1209 |
p->drawEllipse(br.adjusted(-1, -1, 1, 1)); |
| 1210 |
} |
| 1211 |
|
| 1212 |
END_STYLE_PIXMAPCACHE |
| 1213 |
|
| 1214 |
QPointF dp = QStyleHelper::calcRadialPos(scrollBar, qreal(0.70)); |
| 1215 |
buttonColor = buttonColor.darker(104); |
| 1216 |
buttonColor.setAlphaF(qreal(0.8)); |
| 1217 |
const qreal ds = r/qreal(7.0); |
| 1218 |
QRectF dialRect(dp.x() - ds, dp.y() - ds, 2*ds, 2*ds); |
| 1219 |
QRadialGradient dialGradient(dialRect.center().x() + dialRect.width()/2, |
| 1220 |
dialRect.center().y() + dialRect.width(), |
| 1221 |
dialRect.width()*2, |
| 1222 |
dialRect.center().x(), dialRect.center().y()); |
| 1223 |
dialGradient.setColorAt(1, buttonColor.darker(130)); |
| 1224 |
dialGradient.setColorAt(qreal(0.4), buttonColor.darker(160)); |
| 1225 |
dialGradient.setColorAt(0, buttonColor.darker(130)); |
| 1226 |
if (penSize > 3.0) { |
| 1227 |
painter->setPen(QPen(QColor(255,255,255,150), penSize)); |
| 1228 |
painter->drawLine(QStyleHelper::calcRadialPos(scrollBar, qreal(0.90)), QStyleHelper::calcRadialPos(scrollBar, qreal(0.96))); |
| 1229 |
} |
| 1230 |
painter->setBrush(dialGradient); |
| 1231 |
painter->setPen(QPen(Qt::white, 3)); |
| 1232 |
painter->drawEllipse(dialRect.adjusted(-1, -1, 1, 1)); |
| 1233 |
painter->setPen(QPen(Qt::black, 2)); |
| 1234 |
painter->drawEllipse(dialRect); |
| 1235 |
painter->restore(); |
| 1236 |
} |
| 1237 |
break; |
| 1238 |
case CC_ScrollBar: |
| 1239 |
if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) { |
| 1240 |
painter->fillRect(option->rect, option->palette.background()); |
| 1241 |
QRect scrollBarSlider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget); |
| 1242 |
QColor color = option->palette.color(QPalette::Text); |
| 1243 |
|
| 1244 |
if (widget && widget->parentWidget()) { |
| 1245 |
if (QAbstractScrollArea *area = qobject_cast<QAbstractScrollArea*>(widget->parentWidget()->parentWidget())) { |
| 1246 |
if (ScrollBarFader *fader = d->scrollBarFaders.value(area)) { |
| 1247 |
color.setAlphaF(fader->currentAlpha()); |
| 1248 |
} |
| 1249 |
} |
| 1250 |
} |
| 1251 |
|
| 1252 |
painter->fillRect(scrollBarSlider, color); |
| 1253 |
} |
| 1254 |
break; |
| 1255 |
case CC_SpinBox: |
| 1256 |
if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { |
| 1257 |
bool sunken = (spinBox->state & State_Sunken); |
| 1258 |
bool upIsActive = (spinBox->activeSubControls == SC_SpinBoxUp); |
| 1259 |
bool downIsActive = (spinBox->activeSubControls == SC_SpinBoxDown); |
| 1260 |
bool reverse = (spinBox->direction == Qt::RightToLeft); |
| 1261 |
|
| 1262 |
QStyleOption editOpt = *spinBox; |
| 1263 |
QRect editRect = subControlRect(CC_SpinBox, option, SC_SpinBoxFrame, widget); |
| 1264 |
editOpt.rect = editRect; |
| 1265 |
drawPrimitive(PE_PanelLineEdit, &editOpt, painter, widget); |
| 1266 |
|
| 1267 |
if (spinBox->buttonSymbols != QAbstractSpinBox::NoButtons) { |
| 1268 |
QRect plusRect = subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget); |
| 1269 |
QRect minusRect = subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget); |
| 1270 |
QColor textColor = option->palette.color(QPalette::Text); |
| 1271 |
QColor highlightedTextColor = option->palette.color(QPalette::Highlight); |
| 1272 |
QColor disabledColor = option->palette.color(QPalette::Disabled, QPalette::Text); |
| 1273 |
disabledColor.setAlpha(100); |
| 1274 |
int size = 10; |
| 1275 |
int gripMargin = 1; |
| 1276 |
int centerX = minusRect.center().x(); |
| 1277 |
int centerY = minusRect.center().y(); |
| 1278 |
|
| 1279 |
// minus |
| 1280 |
centerX = minusRect.center().x(); |
| 1281 |
QColor penColor = (downIsActive && sunken) ? highlightedTextColor : textColor; |
| 1282 |
painter->setPen(QPen(penColor, 5)); |
| 1283 |
painter->drawLine(centerX - size, centerY, centerX + size, centerY); |
| 1284 |
|
| 1285 |
// plus |
| 1286 |
centerX = plusRect.center().x(); |
| 1287 |
penColor = (upIsActive && sunken) ? highlightedTextColor : textColor; |
| 1288 |
painter->setPen(QPen(penColor, 5)); |
| 1289 |
painter->drawLine(centerX - size, centerY, centerX + size, centerY); |
| 1290 |
painter->drawLine(centerX, centerY - size, centerX, centerY + size); |
| 1291 |
|
| 1292 |
// dots |
| 1293 |
size = 15; |
| 1294 |
textColor.setAlpha(50); |
| 1295 |
QRect scrollBarSlider = option->rect; |
| 1296 |
QRect rightRect = reverse ? minusRect : plusRect; |
| 1297 |
QRect leftRect = reverse ? plusRect: minusRect; |
| 1298 |
for (int i = -size; i < size ; i += 4) { |
| 1299 |
QPoint left(leftRect.right() + gripMargin, leftRect.center().y()+ i); |
| 1300 |
painter->fillRect(QRect(left, QSize(2,2)), textColor); |
| 1301 |
QPoint right(rightRect.left() + gripMargin - 1, rightRect.center().y() + i); |
| 1302 |
painter->fillRect(QRect(right, QSize(2,2)), textColor); |
| 1303 |
} |
| 1304 |
} |
| 1305 |
} |
| 1306 |
|
| 1307 |
break; |
| 1308 |
|
| 1309 |
case CC_ComboBox: |
| 1310 |
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { |
| 1311 |
if (!combo->editable) { |
| 1312 |
QStyleOptionButton button; |
| 1313 |
button.QStyleOption::operator=(*option); // copy QStyleOption members |
| 1314 |
button.features = QStyleOptionButton::None; |
| 1315 |
button.icon = combo->currentIcon; |
| 1316 |
button.iconSize = combo->iconSize; |
| 1317 |
button.text = QString(); |
| 1318 |
|
| 1319 |
proxy()->drawControl(QStyle::CE_PushButtonBevel, &button, painter, widget); |
| 1320 |
} else { |
| 1321 |
if (const QStyleOptionComboBox *comboBox = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { |
| 1322 |
bool sunken = comboBox->state & State_On; // play dead, if combobox has no items |
| 1323 |
BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("cb-%0-%1").arg(sunken).arg(comboBox->editable)); |
| 1324 |
QGtkPainter gtkCachedPainter(p); |
| 1325 |
gtkCachedPainter.setUsePixmapCache(false); // cached externally |
| 1326 |
|
| 1327 |
bool isEnabled = (comboBox->state & State_Enabled); |
| 1328 |
bool focus = isEnabled && (comboBox->state & State_HasFocus); |
| 1329 |
QColor buttonShadow = option->palette.dark().color(); |
| 1330 |
GtkStateType state = gtkPainter.gtkState(option); |
| 1331 |
int appears_as_list = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, comboBox, widget); |
| 1332 |
QPixmap cache; |
| 1333 |
QString pixmapName; |
| 1334 |
QStyleOptionComboBox comboBoxCopy = *comboBox; |
| 1335 |
comboBoxCopy.rect = option->rect; |
| 1336 |
|
| 1337 |
bool reverse = (option->direction == Qt::RightToLeft); |
| 1338 |
QRect rect = option->rect; |
| 1339 |
QRect arrowButtonRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy, |
| 1340 |
SC_ComboBoxArrow, widget); |
| 1341 |
QRect editRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy, |
| 1342 |
SC_ComboBoxEditField, widget); |
| 1343 |
|
| 1344 |
GtkShadowType shadow = (option->state & State_Sunken || option->state & State_On ) ? |
| 1345 |
GTK_SHADOW_IN : GTK_SHADOW_OUT; |
| 1346 |
|
| 1347 |
// We use the gtk widget to position arrows and separators for us |
| 1348 |
GtkWidget *gtkCombo = d->gtkWidget("hildon-combobox"); |
| 1349 |
GtkAllocation geometry = {0, 0, option->rect.width(), option->rect.height()}; |
| 1350 |
d->gtk_widget_set_direction(gtkCombo, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); |
| 1351 |
d->gtk_widget_size_allocate(gtkCombo, &geometry); |
| 1352 |
|
| 1353 |
QHashableLatin1Literal buttonPath("hildon-combobox.hildon-combobox-disabled-button"); |
| 1354 |
if (focus) |
| 1355 |
buttonPath = "hildon-combobox.hildon-combobox-active-button"; |
| 1356 |
else if (isEnabled) |
| 1357 |
buttonPath = "hildon-combobox.hildon-combobox-button"; |
| 1358 |
GtkWidget *gtkToggleButton = d->gtkWidget(buttonPath); |
| 1359 |
d->gtk_widget_set_direction(gtkToggleButton, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); |
| 1360 |
if (gtkToggleButton && (appears_as_list || comboBox->editable)) { |
| 1361 |
if (focus) |
| 1362 |
GTK_WIDGET_SET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS); |
| 1363 |
// Draw the combo box as a line edit with a button next to it |
| 1364 |
if (comboBox->editable || appears_as_list) { |
| 1365 |
GtkStateType frameState = (state == GTK_STATE_PRELIGHT) ? GTK_STATE_NORMAL : state; |
| 1366 |
if (focus) |
| 1367 |
frameState = GTK_STATE_ACTIVE; |
| 1368 |
QHashableLatin1Literal entryPath("hildon-combobox.HildonEntry-finger"); |
| 1369 |
GtkWidget *gtkEntry = d->gtkWidget(entryPath); |
| 1370 |
d->gtk_widget_set_direction(gtkEntry, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); |
| 1371 |
QRect frameRect = option->rect; |
| 1372 |
|
| 1373 |
if (reverse) |
| 1374 |
frameRect.setLeft(arrowButtonRect.right()); |
| 1375 |
else |
| 1376 |
frameRect.setRight(arrowButtonRect.left()); |
| 1377 |
|
| 1378 |
// Fill the line edit background |
| 1379 |
// We could have used flat_box with "entry_bg" but that is probably not worth the overhead |
| 1380 |
uint resolve_mask = option->palette.resolve(); |
| 1381 |
int xt = gtkEntry->style->xthickness; |
| 1382 |
int yt = gtkEntry->style->ythickness; |
| 1383 |
QRect contentRect = frameRect.adjusted(xt, yt, -xt, -yt); |
| 1384 |
// Required for inner blue highlight with clearlooks |
| 1385 |
if (focus) |
| 1386 |
GTK_WIDGET_SET_FLAGS(gtkEntry, GTK_HAS_FOCUS); |
| 1387 |
|
| 1388 |
if (widget && widget->testAttribute(Qt::WA_SetPalette) && |
| 1389 |
resolve_mask & (1 << QPalette::Base)) // Palette overridden by user |
| 1390 |
painter->fillRect(contentRect, option->palette.base().color()); |
| 1391 |
else { |
| 1392 |
gtkCachedPainter.paintFlatBox(gtkEntry, "entry_bg", contentRect, |
| 1393 |
option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, |
| 1394 |
GTK_SHADOW_NONE, gtkEntry->style, entryPath.toString() + QString::number(focus)); |
| 1395 |
} |
| 1396 |
gtkCachedPainter.paintShadow(gtkEntry, comboBox->editable ? "entry" : "frame", frameRect, frameState, |
| 1397 |
GTK_SHADOW_IN, gtkEntry->style, entryPath.toString() + |
| 1398 |
QString::number(focus) + QString::number(comboBox->editable) + |
| 1399 |
QString::number(option->direction)/* + QString::number(frameState)*/); |
| 1400 |
if (focus) |
| 1401 |
GTK_WIDGET_UNSET_FLAGS(gtkEntry, GTK_HAS_FOCUS); |
| 1402 |
} |
| 1403 |
|
| 1404 |
GtkStateType buttonState = GTK_STATE_NORMAL; |
| 1405 |
|
| 1406 |
if (!(option->state & State_Enabled)) |
| 1407 |
buttonState = GTK_STATE_INSENSITIVE; |
| 1408 |
else if (option->state & State_Sunken || option->state & State_On) |
| 1409 |
buttonState = GTK_STATE_ACTIVE; |
| 1410 |
else if (option->state & State_MouseOver && comboBox->activeSubControls & SC_ComboBoxArrow) |
| 1411 |
buttonState = GTK_STATE_PRELIGHT; |
| 1412 |
|
| 1413 |
Q_ASSERT(gtkToggleButton); |
| 1414 |
gtkCachedPainter.paintBox( gtkToggleButton, "button", arrowButtonRect, buttonState, |
| 1415 |
shadow, gtkToggleButton->style, buttonPath.toString() + |
| 1416 |
QString::number(focus) + QString::number(option->direction)); |
| 1417 |
if (focus) |
| 1418 |
GTK_WIDGET_UNSET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS); |
| 1419 |
} |
| 1420 |
|
| 1421 |
END_STYLE_PIXMAPCACHE; |
| 1422 |
} |
| 1423 |
} |
| 1424 |
} |
| 1425 |
break; |
| 1426 |
|
| 1427 |
default: |
| 1428 |
QGtkStyle::drawComplexControl(control, option, painter, widget); |
| 1429 |
} |
| 1430 |
} |
| 1431 |
|
| 1432 |
static QHBoxLayout *findHBoxLayoutContaining(const QWidget *widget, QLayout *lay) |
| 1433 |
{ |
| 1434 |
for (int i = 0; i < lay->count(); ++i) { |
| 1435 |
if (QLayout *sublay = lay->itemAt(i)->layout()) { |
| 1436 |
if (QHBoxLayout *box = findHBoxLayoutContaining(widget, sublay)) |
| 1437 |
return box; |
| 1438 |
} else if (lay->itemAt(i)->widget() == widget) { |
| 1439 |
return qobject_cast<QHBoxLayout *>(lay); |
| 1440 |
} |
| 1441 |
} |
| 1442 |
return 0; |
| 1443 |
} |
| 1444 |
|
| 1445 |
/*! |
| 1446 |
\reimp |
| 1447 |
*/ |
| 1448 |
void QMaemo5Style::drawControl(ControlElement element, |
| 1449 |
const QStyleOption *option, |
| 1450 |
QPainter *painter, |
| 1451 |
const QWidget *widget) const |
| 1452 |
{ |
| 1453 |
Q_D(const QMaemo5Style); |
| 1454 |
|
| 1455 |
if (!d->isThemeAvailable()) { |
| 1456 |
QCleanlooksStyle::drawControl(element, option, painter, widget); |
| 1457 |
return; |
| 1458 |
} |
| 1459 |
|
| 1460 |
QGtkPainter gtkPainter(painter); |
| 1461 |
|
| 1462 |
switch (element) { |
| 1463 |
case CE_PushButtonBevel: |
| 1464 |
// This code is copied from commonstyle sans the CommandLink part |
| 1465 |
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { |
| 1466 |
QRect br = btn->rect; |
| 1467 |
int dbi = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget); |
| 1468 |
if (btn->features & QStyleOptionButton::DefaultButton) |
| 1469 |
proxy()->drawPrimitive(PE_FrameDefaultButton, option, painter, widget); |
| 1470 |
if (btn->features & QStyleOptionButton::AutoDefaultButton) |
| 1471 |
br.setCoords(br.left() + dbi, br.top() + dbi, br.right() - dbi, br.bottom() - dbi); |
| 1472 |
if (!(btn->features & (QStyleOptionButton::Flat)) |
| 1473 |
|| btn->state & (State_Sunken | State_On) |
| 1474 |
|| (btn->features & QStyleOptionButton::CommandLinkButton && btn->state & State_MouseOver)) { |
| 1475 |
QStyleOptionButton tmpBtn = *btn; |
| 1476 |
tmpBtn.rect = br; |
| 1477 |
proxy()->drawPrimitive(PE_PanelButtonCommand, &tmpBtn, painter, widget); |
| 1478 |
} |
| 1479 |
if (btn->features & QStyleOptionButton::HasMenu) { |
| 1480 |
int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget); |
| 1481 |
QRect ir = btn->rect; |
| 1482 |
QStyleOptionButton newBtn = *btn; |
| 1483 |
newBtn.rect = QRect(ir.right() - mbi + 2, ir.height()/2 - mbi/2 + 3, mbi - 6, mbi - 6); |
| 1484 |
proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget); |
| 1485 |
} |
| 1486 |
} |
| 1487 |
break; |
| 1488 |
case CE_RadioButton: |
| 1489 |
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { |
| 1490 |
bool handled = false; |
| 1491 |
|
| 1492 |
if (qobject_cast<const QRadioButton *>(widget) && widget->parentWidget() && widget->parentWidget()->layout()) { |
| 1493 |
if (QHBoxLayout *box = findHBoxLayoutContaining(widget, widget->parentWidget()->layout())) { |
| 1494 |
QList<const QRadioButton *> buttonList; |
| 1495 |
for (int i = 0; i < box->count(); ++i) { |
| 1496 |
if (QRadioButton *radio = qobject_cast<QRadioButton *>(box->itemAt(i)->widget())) |
| 1497 |
buttonList << radio; |
| 1498 |
} |
| 1499 |
|
| 1500 |
GtkWidget *gtkButton = 0; |
| 1501 |
int pos = buttonList.indexOf(qobject_cast<const QRadioButton *>(widget)); |
| 1502 |
if (pos == 0) |
| 1503 |
gtkButton = d->radioButtonLeft; |
| 1504 |
else if (pos == buttonList.count() - 1) |
| 1505 |
gtkButton = d->radioButtonRight; |
| 1506 |
else |
| 1507 |
gtkButton = d->radioButtonMiddle; |
| 1508 |
|
| 1509 |
GtkStateType state = gtkPainter.gtkState(option); |
| 1510 |
GtkShadowType shadow = GTK_SHADOW_OUT; |
| 1511 |
if (option->state & State_On || option->state & State_Sunken) { |
| 1512 |
state = GTK_STATE_ACTIVE; |
| 1513 |
shadow = GTK_SHADOW_IN; |
| 1514 |
} |
| 1515 |
if (gtkButton) { |
| 1516 |
gtkPainter.paintBox(gtkButton, "button", option->rect, state, shadow, |
| 1517 |
gtkButton->style, QString()); |
| 1518 |
} |
| 1519 |
handled = true; |
| 1520 |
} |
| 1521 |
} |
| 1522 |
if (!handled) |
| 1523 |
proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget); |
| 1524 |
|
| 1525 |
QStyleOptionButton subopt = *btn; |
| 1526 |
subopt.rect = proxy()->subElementRect(SE_RadioButtonContents, btn, widget); |
| 1527 |
proxy()->drawControl(CE_RadioButtonLabel, &subopt, painter, widget); |
| 1528 |
} |
| 1529 |
break; |
| 1530 |
|
| 1531 |
case CE_CheckBox: |
| 1532 |
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { |
| 1533 |
QStyleOptionButton bevelopt = *btn; |
| 1534 |
bevelopt.state &= ~State_On; |
| 1535 |
proxy()->drawControl(CE_PushButtonBevel, &bevelopt, painter, widget); |
| 1536 |
QStyleOptionButton subopt = *btn; |
| 1537 |
subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); |
| 1538 |
QStyleOptionButton checkopt = subopt; |
| 1539 |
checkopt.rect = proxy()->subElementRect(SE_CheckBoxIndicator, &subopt, widget); |
| 1540 |
proxy()->drawPrimitive(PE_IndicatorCheckBox, &checkopt, painter, widget); |
| 1541 |
checkopt.rect = subElementRect(SE_CheckBoxContents, &subopt, widget); |
| 1542 |
proxy()->drawControl(CE_CheckBoxLabel, &checkopt, painter, widget); |
| 1543 |
} |
| 1544 |
break; |
| 1545 |
|
| 1546 |
case CE_PushButton: |
| 1547 |
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { |
| 1548 |
proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget); |
| 1549 |
QStyleOptionButton subopt = *btn; |
| 1550 |
subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); |
| 1551 |
proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget); |
| 1552 |
} |
| 1553 |
break; |
| 1554 |
|
| 1555 |
case CE_RadioButtonLabel: // fall through |
| 1556 |
case CE_PushButtonLabel: |
| 1557 |
if (const QStyleOptionMaemo5ValueButton *button = qstyleoption_cast<const QStyleOptionMaemo5ValueButton *>(option)) { |
| 1558 |
QRect ir = button->rect; |
| 1559 |
uint tf = Qt::AlignVCenter | Qt::TextHideMnemonic | Qt::AlignLeft; |
| 1560 |
int spacing = 8; |
| 1561 |
QRect textRect, valueRect, iconRect; |
| 1562 |
|
| 1563 |
if (!button->text.isEmpty()) |
| 1564 |
textRect = ir; |
| 1565 |
if (!button->value.isEmpty()) |
| 1566 |
valueRect = ir; |
| 1567 |
if (!button->icon.isNull()) { |
| 1568 |
iconRect = ir; |
| 1569 |
iconRect.setTop(ir.top() + (ir.height() - button->iconSize.height()) / 2); |
| 1570 |
iconRect.setWidth(button->iconSize.width()); |
| 1571 |
iconRect.setHeight(button->iconSize.height()); |
| 1572 |
textRect.setLeft(iconRect.right() + spacing); |
| 1573 |
valueRect.setLeft(textRect.left()); |
| 1574 |
} |
| 1575 |
|
| 1576 |
QFont valuefont = painter->font(); |
| 1577 |
QFontMetrics valuefm = button->fontMetrics; |
| 1578 |
|
| 1579 |
if (button->styles & QStyleOptionMaemo5ValueButton::ValueUnderText) { |
| 1580 |
valuefont = standardFont(QLS("SmallSystemFont")); |
| 1581 |
valuefm = QFontMetrics(valuefont); |
| 1582 |
} |
| 1583 |
|
| 1584 |
QSize textSize = button->fontMetrics.size(Qt::TextSingleLine, button->text); |
| 1585 |
QSize valueSize = valuefm.size(Qt::TextSingleLine, button->value); |
| 1586 |
|
| 1587 |
if (textRect.isValid()) |
| 1588 |
textRect.setWidth(textSize.width()); |
| 1589 |
if (valueRect.isValid()) |
| 1590 |
valueRect.setWidth(valueSize.width()); |
| 1591 |
|
| 1592 |
if (button->styles & QStyleOptionMaemo5ValueButton::ValueUnderText) { |
| 1593 |
if (valueRect.isValid() && textRect.isValid()) { |
| 1594 |
int delta = (ir.height() - (textSize.height() + valueSize.height())) / 2; |
| 1595 |
textRect.setTop(textRect.top() + delta); |
| 1596 |
textRect.setHeight(textSize.height()); |
| 1597 |
valueRect.setTop(textRect.bottom() + 1); |
| 1598 |
valueRect.setHeight(valueSize.height()); |
| 1599 |
} |
| 1600 |
if (button->styles & QStyleOptionMaemo5ValueButton::Centered) { |
| 1601 |
int deltaText = (textRect.width() - valueRect.width()) / 2; |
| 1602 |
int offsetX = ir.left() + (ir.width() - ((iconRect.isValid() ? iconRect.width() + spacing : 0) + qMax(textRect.width(), valueRect.width()))) / 2; |
| 1603 |
if (iconRect.isValid()) { |
| 1604 |
iconRect.moveLeft(offsetX); |
| 1605 |
offsetX += (iconRect.width() + spacing); |
| 1606 |
} |
| 1607 |
if (textRect.isValid()) |
| 1608 |
textRect.moveLeft(offsetX + (deltaText > 0 ? 0 : -deltaText)); |
| 1609 |
if (valueRect.isValid()) |
| 1610 |
valueRect.moveLeft(offsetX + (deltaText < 0 ? 0 : deltaText)); |
| 1611 |
} |
| 1612 |
} else { |
| 1613 |
int middle = ir.center().x(); |
| 1614 |
if (textRect.isValid() && valueRect.isValid()) { |
| 1615 |
if ((textRect.right() + spacing) < middle) |
| 1616 |
valueRect.moveLeft(middle); |
| 1617 |
else |
| 1618 |
valueRect.moveLeft(textRect.right() + spacing); |
| 1619 |
} |
| 1620 |
} |
| 1621 |
valueRect = visualRect(button->direction, ir, valueRect & ir); |
| 1622 |
textRect = visualRect(button->direction, ir, textRect & ir); |
| 1623 |
iconRect = visualRect(button->direction, ir, iconRect & ir); |
| 1624 |
|
| 1625 |
//qDebug() << "Icon, Text, Value: " << iconRect << textRect << valueRect; |
| 1626 |
|
| 1627 |
if (iconRect.isValid()) { |
| 1628 |
QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal |
| 1629 |
: QIcon::Disabled; |
| 1630 |
QIcon::State state = QIcon::Off; |
| 1631 |
if (button->state & State_On) |
| 1632 |
state = QIcon::On; |
| 1633 |
|
| 1634 |
QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state); |
| 1635 |
painter->drawPixmap(iconRect, pixmap); |
| 1636 |
} |
| 1637 |
if (textRect.isValid()) { |
| 1638 |
proxy()->drawItemText(painter, textRect, tf, button->palette, (button->state & State_Enabled), |
| 1639 |
button->text, QPalette::ButtonText); |
| 1640 |
} |
| 1641 |
if (valueRect.isValid()) { |
| 1642 |
QPalette pal = button->palette; |
| 1643 |
if (!(button->state & (State_On | State_Sunken)) && (button->state & State_Enabled)) { |
| 1644 |
QColor color = standardColor(button->styles & QStyleOptionMaemo5ValueButton::PickButton ? QLS("ActiveTextColor") : QLS("SecondaryTextColor")); |
| 1645 |
pal.setBrush(QPalette::ButtonText, color); |
| 1646 |
} |
| 1647 |
QFont oldfont = painter->font(); |
| 1648 |
painter->setFont(valuefont); |
| 1649 |
|
| 1650 |
proxy()->drawItemText(painter, valueRect, tf, pal, (button->state & State_Enabled), |
| 1651 |
button->value, QPalette::ButtonText); |
| 1652 |
painter->setFont(oldfont); |
| 1653 |
} |
| 1654 |
} else if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) { |
| 1655 |
QRect ir = button->rect; |
| 1656 |
uint tf = Qt::AlignVCenter | Qt::TextHideMnemonic; |
| 1657 |
|
| 1658 |
if (!button->icon.isNull()) { |
| 1659 |
//Center both icon and text |
| 1660 |
QPoint point; |
| 1661 |
|
| 1662 |
QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal |
| 1663 |
: QIcon::Disabled; |
| 1664 |
QIcon::State state = QIcon::Off; |
| 1665 |
if (button->state & State_On) |
| 1666 |
state = QIcon::On; |
| 1667 |
|
| 1668 |
QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state); |
| 1669 |
int w = pixmap.width(); |
| 1670 |
int h = pixmap.height(); |
| 1671 |
|
| 1672 |
if (!button->text.isEmpty()) |
| 1673 |
w += button->fontMetrics.boundingRect(option->rect, tf, button->text).width() + 2; |
| 1674 |
|
| 1675 |
point = QPoint(ir.x() + ir.width() / 2 - w / 2, |
| 1676 |
ir.y() + ir.height() / 2 - h / 2); |
| 1677 |
|
| 1678 |
if (button->direction == Qt::RightToLeft) |
| 1679 |
point.rx() += pixmap.width(); |
| 1680 |
|
| 1681 |
painter->drawPixmap(visualPos(button->direction, button->rect, point), pixmap); |
| 1682 |
|
| 1683 |
if (button->direction == Qt::RightToLeft) |
| 1684 |
ir.translate(-point.x() - 2, 0); |
| 1685 |
else |
| 1686 |
ir.translate(point.x() + pixmap.width(), 0); |
| 1687 |
|
| 1688 |
// left-align text if there is |
| 1689 |
if (!button->text.isEmpty()) |
| 1690 |
tf |= Qt::AlignLeft; |
| 1691 |
|
| 1692 |
} else { |
| 1693 |
tf |= Qt::AlignHCenter; |
| 1694 |
} |
| 1695 |
|
| 1696 |
if (button->features & QStyleOptionButton::HasMenu) |
| 1697 |
ir = ir.adjusted(0, 0, -pixelMetric(PM_MenuButtonIndicator, button, widget), 0); |
| 1698 |
proxy()->drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled), |
| 1699 |
button->text, QPalette::ButtonText); |
| 1700 |
} |
| 1701 |
break; |
| 1702 |
|
| 1703 |
case CE_ComboBoxLabel: |
| 1704 |
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { |
| 1705 |
if (!combo->editable) { |
| 1706 |
QStyleOptionMaemo5ValueButton button; |
| 1707 |
button.QStyleOption::operator=(*option); // copy QStyleOption members |
| 1708 |
button.features = QStyleOptionButton::None; |
| 1709 |
button.icon = combo->currentIcon; |
| 1710 |
button.iconSize = combo->iconSize; |
| 1711 |
button.text = QString(); |
| 1712 |
button.styles = QStyleOptionMaemo5ValueButton::ValueBesideText | QStyleOptionMaemo5ValueButton::PickButton; |
| 1713 |
button.value = combo->currentText; |
| 1714 |
button.rect = proxy()->subElementRect(QStyle::SE_PushButtonContents, &button, widget); |
| 1715 |
|
| 1716 |
proxy()->drawControl(CE_PushButtonLabel, &button, painter, widget); |
| 1717 |
} else { |
| 1718 |
QRect editRect = proxy()->subControlRect(CC_ComboBox, combo, SC_ComboBoxEditField, widget); |
| 1719 |
painter->save(); |
| 1720 |
painter->setClipRect(editRect); |
| 1721 |
|
| 1722 |
if (!combo->currentIcon.isNull()) { |
| 1723 |
QIcon::Mode mode = combo->state & State_Enabled ? QIcon::Normal |
| 1724 |
: QIcon::Disabled; |
| 1725 |
QPixmap pixmap = combo->currentIcon.pixmap(combo->iconSize, mode); |
| 1726 |
QRect iconRect(editRect); |
| 1727 |
iconRect.setWidth(combo->iconSize.width() + 4); |
| 1728 |
|
| 1729 |
iconRect = alignedRect(combo->direction, |
| 1730 |
Qt::AlignLeft | Qt::AlignVCenter, |
| 1731 |
iconRect.size(), editRect); |
| 1732 |
|
| 1733 |
proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); |
| 1734 |
|
| 1735 |
if (combo->direction == Qt::RightToLeft) |
| 1736 |
editRect.translate(-4 - combo->iconSize.width(), 0); |
| 1737 |
else |
| 1738 |
editRect.translate(combo->iconSize.width() + 4, 0); |
| 1739 |
} |
| 1740 |
painter->restore(); |
| 1741 |
} |
| 1742 |
} |
| 1743 |
break; |
| 1744 |
|
| 1745 |
case CE_Splitter: |
| 1746 |
painter->save(); |
| 1747 |
{ |
| 1748 |
QColor gripShadow(0xffffff); |
| 1749 |
gripShadow.setAlpha(190); |
| 1750 |
bool vertical = !(option->state & State_Horizontal); |
| 1751 |
QRect scrollBarSlider = option->rect; |
| 1752 |
int gripMargin = 5; |
| 1753 |
int size = 15; |
| 1754 |
//draw grips |
| 1755 |
if (vertical) { |
| 1756 |
for( int i = -size; i< size ; i += 4) { |
| 1757 |
painter->setPen(QPen(gripShadow, 2)); |
| 1758 |
painter->drawLine( |
| 1759 |
QPoint(scrollBarSlider.center().x() + i , |
| 1760 |
scrollBarSlider.top() + gripMargin), |
| 1761 |
QPoint(scrollBarSlider.center().x() + i, |
| 1762 |
scrollBarSlider.bottom() - gripMargin)); |
| 1763 |
} |
| 1764 |
} else { |
| 1765 |
for (int i = -size; i < size ; i += 4) { |
| 1766 |
painter->setPen(QPen(gripShadow, 2)); |
| 1767 |
painter->drawLine( |
| 1768 |
QPoint(scrollBarSlider.left() + gripMargin , |
| 1769 |
scrollBarSlider.center().y()+ i), |
| 1770 |
QPoint(scrollBarSlider.right() - gripMargin, |
| 1771 |
scrollBarSlider.center().y()+ i)); |
| 1772 |
} |
| 1773 |
} |
| 1774 |
} |
| 1775 |
painter->restore(); |
| 1776 |
break; |
| 1777 |
|
| 1778 |
default: |
| 1779 |
QGtkStyle::drawControl(element, option, painter, widget); |
| 1780 |
break; |
| 1781 |
} |
| 1782 |
} |
| 1783 |
|
| 1784 |
/*! |
| 1785 |
\reimp |
| 1786 |
*/ |
| 1787 |
QRect QMaemo5Style::subControlRect(ComplexControl control, const QStyleOptionComplex *option, |
| 1788 |
SubControl subControl, const QWidget *widget) const |
| 1789 |
{ |
| 1790 |
Q_D(const QMaemo5Style); |
| 1791 |
QRect rect; |
| 1792 |
switch (control) { |
| 1793 |
|
| 1794 |
case CC_SpinBox: |
| 1795 |
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { |
| 1796 |
int x = spinbox->rect.x(); |
| 1797 |
int y = spinbox->rect.y(); |
| 1798 |
int h = spinbox->rect.height(); |
| 1799 |
int w = spinbox->rect.width(); |
| 1800 |
int buttonSize = 0, spacing = 0; |
| 1801 |
if (spinbox->buttonSymbols != QAbstractSpinBox::NoButtons) |
| 1802 |
buttonSize = 54; |
| 1803 |
|
| 1804 |
int frameOffset = buttonSize + spacing; |
| 1805 |
|
| 1806 |
GtkBorder *border = 0; |
| 1807 |
GtkWidget *gtkEntry = d->gtkWidget("HildonNumberEditor.GtkEntry"); |
| 1808 |
d->gtk_widget_style_get(gtkEntry, "inner-border", &border, NULL); |
| 1809 |
int xframe = border->left + gtkEntry->style->xthickness + 10; |
| 1810 |
int yframe = border->top + gtkEntry->style->ythickness + 12; |
| 1811 |
d->gtk_border_free(border); |
| 1812 |
|
| 1813 |
switch (subControl) { |
| 1814 |
case SC_SpinBoxFrame: |
| 1815 |
rect = spinbox->rect; |
| 1816 |
break; |
| 1817 |
|
| 1818 |
case SC_SpinBoxEditField: |
| 1819 |
rect = QRect(x + frameOffset + xframe, y + yframe, |
| 1820 |
w - 2 * (frameOffset + xframe), |
| 1821 |
h - 2 * yframe); |
| 1822 |
break; |
| 1823 |
|
| 1824 |
case SC_SpinBoxUp: |
| 1825 |
rect = QRect(x + w - buttonSize, y, buttonSize, h); |
| 1826 |
break; |
| 1827 |
|
| 1828 |
case SC_SpinBoxDown: |
| 1829 |
rect = QRect(x, y, buttonSize, h); |
| 1830 |
break; |
| 1831 |
|
| 1832 |
default: |
| 1833 |
break; |
| 1834 |
|
| 1835 |
} |
| 1836 |
rect = visualRect(spinbox->direction, spinbox->rect, rect); |
| 1837 |
} |
| 1838 |
break; |
| 1839 |
case CC_ScrollBar: |
| 1840 |
if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option)) { |
| 1841 |
const QRect scrollBarRect = scrollbar->rect; |
| 1842 |
int maxlen = ((scrollbar->orientation == Qt::Horizontal) ? |
| 1843 |
scrollBarRect.width() : scrollBarRect.height()); |
| 1844 |
int sliderlen; |
| 1845 |
|
| 1846 |
// calculate slider length |
| 1847 |
if (scrollbar->maximum != scrollbar->minimum) { |
| 1848 |
uint range = scrollbar->maximum - scrollbar->minimum; |
| 1849 |
sliderlen = (qint64(scrollbar->pageStep) * maxlen) / (range + scrollbar->pageStep); |
| 1850 |
|
| 1851 |
int slidermin = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollbar, widget); |
| 1852 |
if (sliderlen < slidermin || range > INT_MAX / 2) |
| 1853 |
sliderlen = slidermin; |
| 1854 |
if (sliderlen > maxlen) |
| 1855 |
sliderlen = maxlen; |
| 1856 |
} else { |
| 1857 |
sliderlen = maxlen; |
| 1858 |
} |
| 1859 |
|
| 1860 |
int sliderstart = sliderPositionFromValue(scrollbar->minimum, |
| 1861 |
scrollbar->maximum, |
| 1862 |
scrollbar->sliderPosition, |
| 1863 |
maxlen - sliderlen, |
| 1864 |
scrollbar->upsideDown); |
| 1865 |
|
| 1866 |
switch (subControl) { |
| 1867 |
case SC_ScrollBarSubLine: // top/left button |
| 1868 |
case SC_ScrollBarAddLine: // bottom/right button |
| 1869 |
rect = QRect(); |
| 1870 |
break; |
| 1871 |
case SC_ScrollBarSubPage: // between top/left button and slider |
| 1872 |
if (scrollbar->orientation == Qt::Horizontal) |
| 1873 |
rect.setRect(0, 0, sliderstart, scrollBarRect.height()); |
| 1874 |
else |
| 1875 |
rect.setRect(0, 0, scrollBarRect.width(), sliderstart); |
| 1876 |
break; |
| 1877 |
case SC_ScrollBarAddPage: // between bottom/right button and slider |
| 1878 |
if (scrollbar->orientation == Qt::Horizontal) |
| 1879 |
rect.setRect(sliderstart + sliderlen, 0, |
| 1880 |
maxlen - sliderstart - sliderlen, scrollBarRect.height()); |
| 1881 |
else |
| 1882 |
rect.setRect(0, sliderstart + sliderlen, scrollBarRect.width(), |
| 1883 |
maxlen - sliderstart - sliderlen); |
| 1884 |
break; |
| 1885 |
case SC_ScrollBarGroove: |
| 1886 |
rect = scrollBarRect; |
| 1887 |
break; |
| 1888 |
case SC_ScrollBarSlider: |
| 1889 |
if (scrollbar->orientation == Qt::Horizontal) |
| 1890 |
rect.setRect(sliderstart, 0, sliderlen, scrollBarRect.height()); |
| 1891 |
else |
| 1892 |
rect.setRect(0, sliderstart, scrollBarRect.width(), sliderlen); |
| 1893 |
break; |
| 1894 |
default: |
| 1895 |
break; |
| 1896 |
} |
| 1897 |
rect = visualRect(scrollbar->direction, scrollBarRect, rect); |
| 1898 |
} |
| 1899 |
break; |
| 1900 |
|
| 1901 |
case CC_ComboBox: |
| 1902 |
if (const QStyleOptionComboBox *box = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { |
| 1903 |
if (!box->editable) { |
| 1904 |
switch (subControl) { |
| 1905 |
case SC_ComboBoxArrow: |
| 1906 |
rect = QRect(option->rect.topLeft(), QSize(0, 0)); |
| 1907 |
break; |
| 1908 |
default: |
| 1909 |
rect = option->rect; |
| 1910 |
break; |
| 1911 |
} |
| 1912 |
break; |
| 1913 |
} |
| 1914 |
|
| 1915 |
// We employ the gtk widget to position arrows and separators for us |
| 1916 |
GtkWidget *gtkCombo = d->gtkWidget("hildon-combobox"); |
| 1917 |
d->gtk_widget_set_direction(gtkCombo, (option->direction == Qt::RightToLeft) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); |
| 1918 |
GtkAllocation geometry = {0, 0, qMax(0, option->rect.width()), qMax(0, option->rect.height())}; |
| 1919 |
d->gtk_widget_size_allocate(gtkCombo, &geometry); |
| 1920 |
|
| 1921 |
GtkWidget *arrowWidget = d->gtkWidget("hildon-combobox.hildon-combobox-button"); |
| 1922 |
GtkWidget *entryWidget = d->gtkWidget("hildon-combobox.HildonEntry-finger"); |
| 1923 |
if (!arrowWidget || !entryWidget) |
| 1924 |
return QCleanlooksStyle::subControlRect(control, option, subControl, widget); |
| 1925 |
|
| 1926 |
QRect buttonRect(option->rect.left() + arrowWidget->allocation.x, |
| 1927 |
option->rect.top() + arrowWidget->allocation.y, |
| 1928 |
arrowWidget->allocation.width, arrowWidget->allocation.height); |
| 1929 |
|
| 1930 |
switch (subControl) { |
| 1931 |
|
| 1932 |
case SC_ComboBoxArrow: // Note: this indicates the arrowbutton for editable combos |
| 1933 |
rect = buttonRect; |
| 1934 |
break; |
| 1935 |
|
| 1936 |
case SC_ComboBoxEditField: { |
| 1937 |
rect = visualRect(option->direction, option->rect, rect); |
| 1938 |
int xMargin = 8, yMargin = 12; |
| 1939 |
rect.setRect(option->rect.left() + entryWidget->style->xthickness + xMargin, |
| 1940 |
option->rect.top() + entryWidget->style->ythickness + yMargin, |
| 1941 |
option->rect.width() - buttonRect.width() - 2*(entryWidget->style->xthickness + xMargin), |
| 1942 |
option->rect.height() - 2*(entryWidget->style->ythickness + yMargin)); |
| 1943 |
rect = visualRect(option->direction, option->rect, rect); |
| 1944 |
break; |
| 1945 |
} |
| 1946 |
|
| 1947 |
default: |
| 1948 |
rect = QWindowsStyle::subControlRect(control, option, subControl, widget); |
| 1949 |
break; |
| 1950 |
} |
| 1951 |
} |
| 1952 |
|
| 1953 |
break; |
| 1954 |
|
| 1955 |
default: |
| 1956 |
rect = QGtkStyle::subControlRect(control, option, subControl, widget); |
| 1957 |
break; |
| 1958 |
} |
| 1959 |
return rect; |
| 1960 |
} |
| 1961 |
|
| 1962 |
/*! |
| 1963 |
\reimp |
| 1964 |
*/ |
| 1965 |
QSize QMaemo5Style::sizeFromContents(ContentsType type, const QStyleOption *option, |
| 1966 |
const QSize &size, const QWidget *widget) const |
| 1967 |
{ |
| 1968 |
Q_D(const QMaemo5Style); |
| 1969 |
|
| 1970 |
QSize newSize = QGtkStyle::sizeFromContents(type, option, size, widget); |
| 1971 |
if (!d->isThemeAvailable()) |
| 1972 |
return newSize; |
| 1973 |
|
| 1974 |
GtkWidget *gtkWidget = 0; |
| 1975 |
|
| 1976 |
switch (type) { |
| 1977 |
case CT_ToolButton: |
| 1978 |
if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { |
| 1979 |
// tool buttons are always at least as high as the icon (even if it only has a text) |
| 1980 |
// the 78/70 is a hack, since these values are also hardcoded in Hildon |
| 1981 |
newSize = newSize.expandedTo(toolbutton->iconSize + QSize(12, 12)).expandedTo(QSize(78, 70)); |
| 1982 |
} |
| 1983 |
break; |
| 1984 |
|
| 1985 |
case CT_LineEdit: { |
| 1986 |
if (const QStyleOptionFrameV2 *frame = qstyleoption_cast<const QStyleOptionFrameV2 *>(option)) { |
| 1987 |
if (!frame->lineWidth) |
| 1988 |
return QCleanlooksStyle::sizeFromContents(type, option, size, widget); |
| 1989 |
|
| 1990 |
gtkWidget = d->gtkWidget("HildonEntry-finger"); |
| 1991 |
if (gtkWidget) { |
| 1992 |
newSize = size + 2 * QSize(gtkWidget->style->xthickness, 1 + gtkWidget->style->ythickness); |
| 1993 |
GtkBorder *border = 0; |
| 1994 |
d->gtk_widget_style_get(gtkWidget, "inner-border", &border, NULL); |
| 1995 |
if (border) { |
| 1996 |
newSize += QSize(border->left + border->right, border->top + border->bottom + 3); |
| 1997 |
d->gtk_border_free(border); |
| 1998 |
} else { |
| 1999 |
newSize += QSize(4, 7); // default inner-border |
| 2000 |
} |
| 2001 |
//The widget size should not be adjusted automaticly if it is too small |
| 2002 |
//otherwise the tst_QLineEdit::textMargin() fails |
| 2003 |
gtkWidget = 0; |
| 2004 |
} |
| 2005 |
} |
| 2006 |
break; |
| 2007 |
} |
| 2008 |
|
| 2009 |
case CT_ComboBox: { |
| 2010 |
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { |
| 2011 |
if (!combo->editable) { |
| 2012 |
QStyleOptionButton button; |
| 2013 |
button.QStyleOption::operator=(*option); // copy QStyleOption members |
| 2014 |
button.features = QStyleOptionButton::None; |
| 2015 |
button.icon = combo->currentIcon; |
| 2016 |
button.iconSize = combo->iconSize; |
| 2017 |
button.text = combo->currentText; |
| 2018 |
|
| 2019 |
newSize = proxy()->sizeFromContents(CT_PushButton, &button, size, widget); |
| 2020 |
} else { |
| 2021 |
GtkWidget *gtkCombo = d->gtkWidget("hildon-combobox.HildonEntry-finger"); |
| 2022 |
QRect arrowButtonRect = proxy()->subControlRect(CC_ComboBox, combo, SC_ComboBoxArrow, widget); |
| 2023 |
newSize = size + QSize(12 + arrowButtonRect.width() + 2*gtkCombo->style->xthickness, 4 + 2*gtkCombo->style->ythickness); |
| 2024 |
newSize = newSize.expandedTo(QSize(0, 70)); |
| 2025 |
} |
| 2026 |
} |
| 2027 |
break; |
| 2028 |
} |
| 2029 |
|
| 2030 |
case CT_PushButton: { |
| 2031 |
if (widget && qobject_cast<QDialogButtonBox *>(widget->parentWidget())) |
| 2032 |
newSize.setWidth(qMax(newSize.width(), 174)); // hardcoded value in gtkdialog.c |
| 2033 |
gtkWidget = d->gtkWidget("HildonButton-finger"); |
| 2034 |
break; |
| 2035 |
} |
| 2036 |
|
| 2037 |
case CT_RadioButton: |
| 2038 |
case CT_CheckBox: { |
| 2039 |
gtkWidget = d->gtkWidget("HildonButton-finger"); |
| 2040 |
if (gtkWidget) |
| 2041 |
{ |
| 2042 |
gint w = -1, h = -1; |
| 2043 |
d->gtk_widget_get_size_request(gtkWidget, &w, &h); |
| 2044 |
newSize = newSize.expandedTo(QSize(w, h)); |
| 2045 |
|
| 2046 |
GtkBorder *border = 0; |
| 2047 |
d->gtk_widget_style_get(gtkWidget, "inner-border", &border, NULL); |
| 2048 |
if (border) |
| 2049 |
{ |
| 2050 |
newSize += QSize(border->left + border->right,0); |
| 2051 |
d->gtk_border_free(border); |
| 2052 |
} |
| 2053 |
gtkWidget = 0; |
| 2054 |
} |
| 2055 |
break; |
| 2056 |
} |
| 2057 |
|
| 2058 |
case CT_MenuItem: { |
| 2059 |
if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { |
| 2060 |
int textMargin = 8; |
| 2061 |
|
| 2062 |
if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { |
| 2063 |
GtkWidget *gtkMenuSeparator = d->gtkWidget("hildon-context-sensitive-menu.GtkSeparatorMenuItem"); |
| 2064 |
GtkRequisition sizeReq = {0, 0}; |
| 2065 |
d->gtk_widget_size_request(gtkMenuSeparator, &sizeReq); |
| 2066 |
newSize = QSize(size.width(), sizeReq.height); |
| 2067 |
break; |
| 2068 |
} |
| 2069 |
|
| 2070 |
GtkWidget *gtkMenuItem = d->gtkWidget("hildon-context-sensitive-menu.GtkCheckMenuItem"); |
| 2071 |
GtkStyle* style = gtkMenuItem->style; |
| 2072 |
|
| 2073 |
// Note we get the perfect height for the default font since we |
| 2074 |
// set a fake text label on the gtkMenuItem |
| 2075 |
// But if custom fonts are used on the widget we need a minimum size |
| 2076 |
GtkRequisition sizeReq = {0, 0}; |
| 2077 |
d->gtk_widget_size_request(gtkMenuItem, &sizeReq); |
| 2078 |
newSize.setHeight(qMax(newSize.height() - 4, sizeReq.height)); |
| 2079 |
newSize += QSize(textMargin + style->xthickness - 1, 0); |
| 2080 |
|
| 2081 |
// Cleanlooks assumes a check column of 20 pixels so we need to |
| 2082 |
// expand it a bit |
| 2083 |
gint checkSize; |
| 2084 |
d->gtk_widget_style_get(gtkMenuItem, "indicator-size", &checkSize, NULL); |
| 2085 |
newSize.setWidth(newSize.width() + qMax(0, checkSize - 20)); |
| 2086 |
} |
| 2087 |
break; |
| 2088 |
} |
| 2089 |
#ifndef QT_NO_ITEMVIEWS |
| 2090 |
case CT_ItemViewItem: { |
| 2091 |
uint rowHeight = 70; |
| 2092 |
if (GtkWidget *gtkTreeView = d->gtkWidget("HildonPannableArea.GtkTreeView")) |
| 2093 |
d->gtk_widget_style_get(gtkTreeView, "row-height", &rowHeight, NULL); |
| 2094 |
newSize = newSize.expandedTo(QSize(0, rowHeight)); |
| 2095 |
break; |
| 2096 |
} |
| 2097 |
#endif // QT_NO_ITEMVIEWS |
| 2098 |
case CT_ProgressBar: { |
| 2099 |
gint minw = 70, minh = 70; |
| 2100 |
if (GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar")) { |
| 2101 |
d->gtk_widget_style_get(gtkProgressBar, |
| 2102 |
"min-vertical-bar-width", &minw, |
| 2103 |
"min-horizontal-bar-height", &minh, |
| 2104 |
NULL); |
| 2105 |
} |
| 2106 |
newSize = newSize.expandedTo(QSize(minw, minh)); |
| 2107 |
break; |
| 2108 |
} |
| 2109 |
|
| 2110 |
case CT_Slider: { |
| 2111 |
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) { |
| 2112 |
// I have no idea why the Gtk widget ends up being 70px high given the Hildon gtkrc and the gtkscale source code... |
| 2113 |
QSize expandFix(0, 70); |
| 2114 |
if (slider->orientation == Qt::Horizontal) { |
| 2115 |
gtkWidget = d->gtkWidget("GtkHScale"); |
| 2116 |
} else { |
| 2117 |
gtkWidget = d->gtkWidget("GtkVScale"); |
| 2118 |
expandFix.transpose(); |
| 2119 |
} |
| 2120 |
newSize = newSize.expandedTo(expandFix); |
| 2121 |
} |
| 2122 |
break; |
| 2123 |
} |
| 2124 |
|
| 2125 |
default: |
| 2126 |
break; |
| 2127 |
} |
| 2128 |
|
| 2129 |
if (gtkWidget) { |
| 2130 |
gint w = -1, h = -1; |
| 2131 |
d->gtk_widget_get_size_request(gtkWidget, &w, &h); |
| 2132 |
newSize = newSize.expandedTo(QSize(w, h)); |
| 2133 |
} |
| 2134 |
return newSize; |
| 2135 |
} |
| 2136 |
|
| 2137 |
/*! |
| 2138 |
\reimp |
| 2139 |
*/ |
| 2140 |
QRect QMaemo5Style::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const |
| 2141 |
{ |
| 2142 |
Q_D(const QMaemo5Style); |
| 2143 |
|
| 2144 |
QRect r; |
| 2145 |
switch (element) { |
| 2146 |
case SE_TreeViewDisclosureItem: |
| 2147 |
// Increases the actual expander hitrect for more finger friendliness |
| 2148 |
r = option->rect.adjusted(0, 0, 20, 0); |
| 2149 |
break; |
| 2150 |
|
| 2151 |
case SE_LineEditContents: |
| 2152 |
if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(option)) { |
| 2153 |
if (!frame->lineWidth) |
| 2154 |
return QCleanlooksStyle::subElementRect(element, option, widget); |
| 2155 |
} |
| 2156 |
r = option->rect; |
| 2157 |
if (GtkWidget *gtkEntry = d->gtkWidget("HildonEntry-finger")) { |
| 2158 |
int xt = gtkEntry->style->xthickness; |
| 2159 |
int yt = gtkEntry->style->ythickness; |
| 2160 |
|
| 2161 |
r.adjust(xt, yt, -xt, -yt); |
| 2162 |
|
| 2163 |
GtkBorder *border = 0; |
| 2164 |
d->gtk_widget_style_get(gtkEntry, "inner-border", &border, NULL); |
| 2165 |
if (border) { |
| 2166 |
r.adjust(border->left, border->top, -border->right, -border->bottom); |
| 2167 |
d->gtk_border_free(border); |
| 2168 |
} else { |
| 2169 |
r.adjust(2, 2, -2, -2); // default inner-border |
| 2170 |
} |
| 2171 |
} |
| 2172 |
r = visualRect(option->direction, option->rect, r); |
| 2173 |
break; |
| 2174 |
|
| 2175 |
case SE_CheckBoxIndicator: { |
| 2176 |
int h = proxy()->pixelMetric(PM_IndicatorHeight, option, widget); |
| 2177 |
r.setRect(option->rect.x(), option->rect.y() + ((option->rect.height() - h) / 2), |
| 2178 |
proxy()->pixelMetric(PM_IndicatorWidth, option, widget), h); |
| 2179 |
r = visualRect(option->direction, option->rect, r); |
| 2180 |
break; |
| 2181 |
} |
| 2182 |
case SE_RadioButtonContents: |
| 2183 |
r = proxy()->subElementRect(SE_PushButtonContents, option, widget); |
| 2184 |
break; |
| 2185 |
|
| 2186 |
case SE_RadioButtonClickRect: // fall through |
| 2187 |
case SE_CheckBoxClickRect: |
| 2188 |
r = visualRect(option->direction, option->rect, option->rect); |
| 2189 |
break; |
| 2190 |
|
| 2191 |
case SE_FrameContents: |
| 2192 |
if ((qobject_cast<const QTextEdit *>(widget) && !qobject_cast<const QTextBrowser *>(widget)) || qobject_cast<const QPlainTextEdit *>(widget)) |
| 2193 |
r = proxy()->subElementRect(SE_LineEditContents, option, widget); |
| 2194 |
else |
| 2195 |
r = QGtkStyle::subElementRect(element, option, widget); |
| 2196 |
break; |
| 2197 |
|
| 2198 |
default: |
| 2199 |
r = QGtkStyle::subElementRect(element, option, widget); |
| 2200 |
} |
| 2201 |
return r; |
| 2202 |
} |
| 2203 |
|
| 2204 |
/*! |
| 2205 |
\reimp |
| 2206 |
*/ |
| 2207 |
QStyle::SubControl QMaemo5Style::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, |
| 2208 |
const QPoint &pt, const QWidget *w) const |
| 2209 |
{ |
| 2210 |
switch (cc) { |
| 2211 |
case CC_ScrollBar: |
| 2212 |
return SC_None; |
| 2213 |
default: |
| 2214 |
return QGtkStyle::hitTestComplexControl(cc, opt, pt, w); |
| 2215 |
} |
| 2216 |
} |
| 2217 |
|
| 2218 |
/*! |
| 2219 |
Returns a font for the given \a logicalFontName. |
| 2220 |
|
| 2221 |
Please see the Maemo 5 style guides for a list of valid logical font |
| 2222 |
names. If the named font cannot be found, the function returns the |
| 2223 |
application's default font. |
| 2224 |
|
| 2225 |
\sa standardColor() |
| 2226 |
*/ |
| 2227 |
QFont QMaemo5Style::standardFont(const QString &logicalFontName) |
| 2228 |
{ |
| 2229 |
return QGtkStylePrivate::getThemeFont(logicalFontName); |
| 2230 |
} |
| 2231 |
|
| 2232 |
/*! |
| 2233 |
Returns a color for the given \a logicalColorName. |
| 2234 |
|
| 2235 |
Please see the Maemo 5 style guides for a list of valid logical color |
| 2236 |
names. If the named color cannot be found, the function returns an |
| 2237 |
invalid color. |
| 2238 |
|
| 2239 |
\sa standardFont() |
| 2240 |
*/ |
| 2241 |
QColor QMaemo5Style::standardColor(const QString &logicalColorName) |
| 2242 |
{ |
| 2243 |
if (GtkStyle *style = QGtkStylePrivate::gtkStyle()) { |
| 2244 |
GdkColor color; |
| 2245 |
if (QMaemo5StylePrivate::gtk_style_lookup_color(style, logicalColorName.toUtf8().constData(), &color)) |
| 2246 |
return QColor(color.red>>8, color.green>>8, color.blue>>8); |
| 2247 |
} |
| 2248 |
return QColor(); |
| 2249 |
} |
| 2250 |
|
| 2251 |
|
| 2252 |
/*! |
| 2253 |
\enum QMaemo5Style::PrimitiveElement |
| 2254 |
\since 4.6 |
| 2255 |
|
| 2256 |
This enum contains additional Maemo 5 specific PrimitiveElement entries. |
| 2257 |
|
| 2258 |
\value PE_Maemo5InformationBox Represents a Maemo 5 information box overlay. |
| 2259 |
|
| 2260 |
\value PE_Maemo5AppMenu Represents a Maemo 5 application menu frame. |
| 2261 |
|
| 2262 |
\value PE_Maemo5EditBar Represents the special Maemo 5 edit bar pop-up background. |
| 2263 |
|
| 2264 |
\value PE_Maemo5EditBarBackButton Represents the back button for the edit bar. |
| 2265 |
|
| 2266 |
\sa QStyle::PrimitiveElement |
| 2267 |
*/ |
| 2268 |
|
| 2269 |
/*! |
| 2270 |
\enum QMaemo5Style::PixelMetric |
| 2271 |
\since 4.6 |
| 2272 |
|
| 2273 |
This enum contains additional Maemo 5 specific PixelMetric entries. |
| 2274 |
|
| 2275 |
\value PM_Maemo5AppMenuHorizontalSpacing The horizontal space between entries inside the Maemo 5 application menu. |
| 2276 |
|
| 2277 |
\value PM_Maemo5AppMenuVerticalSpacing The vertical space between entries inside the Maemo 5 application menu. |
| 2278 |
|
| 2279 |
\value PM_Maemo5AppMenuContentMargin The space around the Maemo 5 app menu content. |
| 2280 |
|
| 2281 |
\value PM_Maemo5AppMenuLandscapeXOffset The space from the edge of the screen to the menu border. |
| 2282 |
|
| 2283 |
\value PM_Maemo5AppMenuFilterGroupWidth The width of the Maemo5 menu filter group. |
| 2284 |
|
| 2285 |
\value PM_Maemo5AppMenuFilterGroupVerticalSpacing The space between the filter group and the rest of the Maemo5 menu. |
| 2286 |
|
| 2287 |
\value PM_Maemo5EditBarBackButtonWidth The width of the Maemo5 edit bar back button. |
| 2288 |
|
| 2289 |
\value PM_Maemo5EditBarBackButtonHeight The height of the Maemo5 edit bar back button. |
| 2290 |
|
| 2291 |
\sa QStyle::PixelMetric |
| 2292 |
*/ |
| 2293 |
|
| 2294 |
/*! \internal */ |
| 2295 |
QIcon QMaemo5Style::standardIconImplementation(StandardPixmap standardIcon, |
| 2296 |
const QStyleOption *option, const QWidget *widget) const |
| 2297 |
{ |
| 2298 |
return standardPixmap(standardIcon, option, widget); |
| 2299 |
} |
| 2300 |
|
| 2301 |
/*! \reimp */ |
| 2302 |
QPixmap QMaemo5Style::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, |
| 2303 |
const QWidget *widget) const |
| 2304 |
{ |
| 2305 |
switch (standardPixmap) { |
| 2306 |
case SP_MediaPlay: |
| 2307 |
return QPixmap(QLatin1String("/etc/hildon/theme/mediaplayer/Play.png")); |
| 2308 |
case SP_MediaStop: |
| 2309 |
return QPixmap(QLatin1String("/etc/hildon/theme/mediaplayer/Stop.png")); |
| 2310 |
case SP_MediaPause: |
| 2311 |
return QPixmap(QLatin1String("/etc/hildon/theme/mediaplayer/Pause.png")); |
| 2312 |
case SP_MediaSkipForward: |
| 2313 |
return QPixmap(QLatin1String("/etc/hildon/theme/mediaplayer/Forward.png")); |
| 2314 |
case SP_MediaSkipBackward: |
| 2315 |
return QPixmap(QLatin1String("/etc/hildon/theme/mediaplayer/Back.png")); |
| 2316 |
default: |
| 2317 |
return QGtkStyle::standardPixmap(standardPixmap, opt, widget); |
| 2318 |
} |
| 2319 |
} |
| 2320 |
|
| 2321 |
QT_END_NAMESPACE |
| 2322 |
|
| 2323 |
#endif |