src/gui/styles/qgtkstyle_p.cpp
changeset 30 5dc02b23752f
parent 19 fcece45ef507
child 33 3e2da88830cd
--- a/src/gui/styles/qgtkstyle_p.cpp	Wed Jun 23 19:07:03 2010 +0300
+++ b/src/gui/styles/qgtkstyle_p.cpp	Tue Jul 06 15:10:48 2010 +0300
@@ -60,6 +60,7 @@
 #include <QtCore/QHash>
 #include <QtCore/QUrl>
 #include <QtCore/QLibrary>
+#include <QtCore/QDebug>
 
 #include <private/qapplication_p.h>
 #include <private/qiconloader_p.h>
@@ -233,17 +234,22 @@
     }
 }
 
-static QString classPath(GtkWidget *widget)
+static QHashableLatin1Literal classPath(GtkWidget *widget)
 {
-    char* class_path;
+    char *class_path;
     QGtkStylePrivate::gtk_widget_path (widget, NULL, &class_path, NULL);
-    QString path = QLS(class_path);
+
+    char *copy = class_path;
+    if (strncmp(copy, "GtkWindow.", 10) == 0)
+        copy += 10;
+    if (strncmp(copy, "GtkFixed.", 9) == 0)
+        copy += 9;
+
+    copy = strdup(copy);
+
     g_free(class_path);
 
-    // Remove the prefixes
-    path.remove(QLS("GtkWindow."));
-    path.remove(QLS("GtkFixed."));
-    return path;
+    return QHashableLatin1Literal::fromData(copy);
 }
 
 
@@ -261,6 +267,7 @@
 }
 
 QList<QGtkStylePrivate *> QGtkStylePrivate::instances;
+QGtkStylePrivate::WidgetMap *QGtkStylePrivate::widgetMap = 0;
 
 QGtkStylePrivate::QGtkStylePrivate()
   : QCleanlooksStylePrivate()
@@ -282,7 +289,7 @@
         qApp->installEventFilter(&filter);
 }
 
-GtkWidget* QGtkStylePrivate::gtkWidget(const QString &path)
+GtkWidget* QGtkStylePrivate::gtkWidget(const QHashableLatin1Literal &path)
 {
     GtkWidget *widget = gtkWidgetMap()->value(path);
     if (!widget) {
@@ -292,10 +299,10 @@
     return widget;
 }
 
-GtkStyle* QGtkStylePrivate::gtkStyle(const QString &path)
+GtkStyle* QGtkStylePrivate::gtkStyle(const QHashableLatin1Literal &path)
 {
-    if (gtkWidgetMap()->contains(path))
-        return gtkWidgetMap()->value(path)->style;
+    if (GtkWidget *w = gtkWidgetMap()->value(path))
+        return w->style;
     return 0;
 }
 
@@ -494,7 +501,7 @@
     }
 
     static QString themeName;
-    if (!gtkWidgetMap()->contains(QLS("GtkWindow")) && themeName.isEmpty()) {
+    if (!gtkWidgetMap()->contains("GtkWindow") && themeName.isEmpty()) {
         themeName = getThemeName();
 
         if (themeName.isEmpty()) {
@@ -519,14 +526,14 @@
         QGtkStylePrivate::gtk_widget_realize(gtkWindow);
         if (displayDepth == -1)
             displayDepth = QGtkStylePrivate::gdk_drawable_get_depth(gtkWindow->window);
-        gtkWidgetMap()->insert(QLS("GtkWindow"), gtkWindow);
+        gtkWidgetMap()->insert(QHashableLatin1Literal::fromData(strdup("GtkWindow")), gtkWindow);
 
 
         // Make all other widgets. respect the text direction
         if (qApp->layoutDirection() == Qt::RightToLeft)
             QGtkStylePrivate::gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL);
 
-        if (!gtkWidgetMap()->contains(QLS("GtkButton"))) {
+        if (!gtkWidgetMap()->contains("GtkButton")) {
             GtkWidget *gtkButton = QGtkStylePrivate::gtk_button_new();
             addWidget(gtkButton);
             g_signal_connect(gtkButton, "style-set", G_CALLBACK(gtkStyleSetCallback), 0);
@@ -563,12 +570,12 @@
             // When styles change subwidgets can get rearranged
             // as with the combo box. We need to update the widget map
             // to reflect this;
-            QHash<QString, GtkWidget*> oldMap = *gtkWidgetMap();
+            QHash<QHashableLatin1Literal, GtkWidget*> oldMap = *gtkWidgetMap();
             gtkWidgetMap()->clear();
-            QHashIterator<QString, GtkWidget*> it(oldMap);
+            QHashIterator<QHashableLatin1Literal, GtkWidget*> it(oldMap);
             while (it.hasNext()) {
                 it.next();
-                if (!it.key().contains(QLatin1Char('.'))) {
+                if (!strchr(it.key().data(), '.')) {
                     addAllSubWidgets(it.value());
                 }
             }
@@ -583,8 +590,13 @@
  */
 void QGtkStylePrivate::cleanupGtkWidgets()
 {
-    if (gtkWidgetMap()->contains(QLS("GtkWindow"))) // Gtk will destroy all children
-        gtk_widget_destroy(gtkWidgetMap()->value(QLS("GtkWindow")));
+    if (!widgetMap)
+        return;
+    if (widgetMap->contains("GtkWindow")) // Gtk will destroy all children
+        gtk_widget_destroy(widgetMap->value("GtkWindow"));
+    for (QHash<QHashableLatin1Literal, GtkWidget *>::const_iterator it = widgetMap->constBegin();
+         it != widgetMap->constEnd(); ++it)
+        free(const_cast<char *>(it.key().data()));
 }
 
 static bool resolveGConf()
@@ -675,7 +687,7 @@
 int QGtkStylePrivate::getSpinboxArrowSize() const
 {
     const int MIN_ARROW_WIDTH = 6;
-    GtkWidget *spinButton = gtkWidget(QLS("GtkSpinButton"));
+    GtkWidget *spinButton = gtkWidget("GtkSpinButton");
     GtkStyle *style = spinButton->style;
     gint size = pango_font_description_get_size (style->font_desc);
     gint arrow_size;
@@ -695,17 +707,17 @@
 
 void QGtkStylePrivate::applyCustomPaletteHash()
 {
-    QPalette menuPal = gtkWidgetPalette(QLS("GtkMenu"));
-    GdkColor gdkBg = gtkWidget(QLS("GtkMenu"))->style->bg[GTK_STATE_NORMAL];
+    QPalette menuPal = gtkWidgetPalette("GtkMenu");
+    GdkColor gdkBg = gtkWidget("GtkMenu")->style->bg[GTK_STATE_NORMAL];
     QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8);
     menuPal.setBrush(QPalette::Base, bgColor);
     menuPal.setBrush(QPalette::Window, bgColor);
     qApp->setPalette(menuPal, "QMenu");
 
-    QPalette toolbarPal = gtkWidgetPalette(QLS("GtkToolbar"));
+    QPalette toolbarPal = gtkWidgetPalette("GtkToolbar");
     qApp->setPalette(toolbarPal, "QToolBar");
 
-    QPalette menuBarPal = gtkWidgetPalette(QLS("GtkMenuBar"));
+    QPalette menuBarPal = gtkWidgetPalette("GtkMenuBar");
     qApp->setPalette(menuBarPal, "QMenuBar");
 }
 
@@ -714,7 +726,7 @@
 */
 GtkWidget* QGtkStylePrivate::getTextColorWidget() const
 {
-    return  gtkWidget(QLS("GtkEntry"));
+    return  gtkWidget("GtkEntry");
 }
 
 void QGtkStylePrivate::setupGtkWidget(GtkWidget* widget)
@@ -723,7 +735,7 @@
         static GtkWidget* protoLayout = 0;
         if (!protoLayout) {
             protoLayout = QGtkStylePrivate::gtk_fixed_new();
-            QGtkStylePrivate::gtk_container_add((GtkContainer*)(gtkWidgetMap()->value(QLS("GtkWindow"))), protoLayout);
+            QGtkStylePrivate::gtk_container_add((GtkContainer*)(gtkWidgetMap()->value("GtkWindow")), protoLayout);
         }
         Q_ASSERT(protoLayout);
 
@@ -736,8 +748,19 @@
 void QGtkStylePrivate::addWidgetToMap(GtkWidget *widget)
 {
     if (Q_GTK_IS_WIDGET(widget)) {
-       gtk_widget_realize(widget);
-       gtkWidgetMap()->insert(classPath(widget), widget);
+        gtk_widget_realize(widget);
+        QHashableLatin1Literal widgetPath = classPath(widget);
+
+        WidgetMap *map = gtkWidgetMap();
+        WidgetMap::iterator it = map->find(widgetPath);
+        if (it != map->end()) {
+            free(const_cast<char *>(it.key().data()));
+            map->erase(it);
+        }
+        map->insert(widgetPath, widget);
+#ifdef DUMP_GTK_WIDGET_TREE
+        qWarning("Inserted Gtk Widget: %s", widgetPath.data());
+#endif
     }
  }
 
@@ -750,7 +773,7 @@
 }
 
 // Updates window/windowtext palette based on the indicated gtk widget
-QPalette QGtkStylePrivate::gtkWidgetPalette(const QString &gtkWidgetName) const
+QPalette QGtkStylePrivate::gtkWidgetPalette(const QHashableLatin1Literal &gtkWidgetName) const
 {
     GtkWidget *gtkWidget = QGtkStylePrivate::gtkWidget(gtkWidgetName);
     Q_ASSERT(gtkWidget);
@@ -1086,6 +1109,28 @@
     return icon;
 }
 
+bool operator==(const QHashableLatin1Literal &l1, const QHashableLatin1Literal &l2)
+{
+    return l1.size() == l2.size() || qstrcmp(l1.data(), l2.data()) == 0;
+}
+
+// copied from qHash.cpp
+uint qHash(const QHashableLatin1Literal &key)
+{
+    int n = key.size();
+    const uchar *p = reinterpret_cast<const uchar *>(key.data());
+    uint h = 0;
+    uint g;
+
+    while (n--) {
+        h = (h << 4) + *p++;
+        if ((g = (h & 0xf0000000)) != 0)
+            h ^= g >> 23;
+        h &= ~g;
+    }
+    return h;
+}
+
 QT_END_NAMESPACE
 
 #endif // !defined(QT_NO_STYLE_GTK)