[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    Re: KColorScheme changes,
From:       Matthew Woehlke <mw_triad () users ! sourceforge ! net>
Date:       2007-09-05 17:36:02
Message-ID: fbmpe3$ceq$1 () sea ! gmane ! org
[Download RAW message or body]

(copy previous e-mail, but updated)

After taking a closer look at current KColorScheme users, it looks like 
correct use of state information needs one of two things (where "which 
one" depends on the user):

1: adjust{Fore,Back}ground, as in kdelibs/kate/utils/katesearchbar.cpp
2: KStatefulBrush, as in the change to Oxygen in the previous message

I would like to add both next Monday. Arto Hytönen has been porting a 
lot of KColorScheme users off of the old (deprecated) ctor, and I'm 
working with him to start getting some "proper use" patches prepared for 
some of these. Between us, I hope to also have some "sample ports" by 
Friday, which I will post as I get them, but I can give the following 
lists of known will-be-users now:

For 1: katepart
For 2: katepart, oxygen

...and I've seen at least one other example for each from lxr (I just 
don't have them handy right now).

I've also attached the patch against KColorScheme. KStatefulBrush is 
documented, adjust* isn't yet, but should be documented before Monday. 
Comments on the API appreciated; especially for adjust*, which I tried 
to make 'friendly' for restoring the colors later.

Also... should there be adjustPalette taking a KStatefulBrush? Should 
there be ONLY adjustPalette (which would require apps to always cache 
the brushes, or use lengthier calls to adjustPalette)? Should there be a 
KStatefulBrush ctor that takes a QPalette and QPalette::ColorRole (i.e. 
to make restoring from the original palette easier)?

(See also http://permalink.gmane.org/gmane.comp.kde.devel.core/45349)

-- 
Matthew
A pool hall put up a sign in their front window that read: "Profound 
language prohibited within." I could just imagine some people discussing 
the meaning of life and being told to take it outside. -- Scott Adams

["kcs-helpers.patch" (text/x-patch)]

Index: colors/kcolorscheme.cpp
===================================================================
--- colors/kcolorscheme.cpp     (revision 708763)
+++ colors/kcolorscheme.cpp     (working copy)
@@ -27,6 +27,7 @@

 #include <QtGui/QColor>
 #include <QtGui/QBrush>
+#include <QtGui/QWidget>

 typedef struct {
     int NormalBackground[3];
@@ -187,6 +203,7 @@
 }
 //END KColorSchemePrivate

+//BEGIN KColorScheme
 KColorScheme::KColorScheme(const KColorScheme &other) : d(other.d)
 {
 }
@@ -327,4 +344,92 @@
             return KColorUtils::darken(KColorUtils::shade(color, darkAmount, \
chromaAdjust), 0.5 + 0.3 * y);  }
 }
+
+void KColorScheme::adjustBackground(QPalette &palette, BackgroundRole newRole, \
QPalette::ColorRole color, ColorSet set) { +    palette.setBrush(QPalette::Active,   \
color, KColorScheme(QPalette::Active,   set).background(newRole)); +    \
palette.setBrush(QPalette::Inactive, color, KColorScheme(QPalette::Inactive, \
set).background(newRole)); +    palette.setBrush(QPalette::Disabled, color, \
KColorScheme(QPalette::Disabled, set).background(newRole)); +}
+
+void KColorScheme::adjustForeground(QPalette &palette, ForegroundRole newRole, \
QPalette::ColorRole color, ColorSet set) { +    palette.setBrush(QPalette::Active,   \
color, KColorScheme(QPalette::Active,   set).foreground(newRole)); +    \
palette.setBrush(QPalette::Inactive, color, KColorScheme(QPalette::Inactive, \
set).foreground(newRole)); +    palette.setBrush(QPalette::Disabled, color, \
KColorScheme(QPalette::Disabled, set).foreground(newRole)); +}
+//END KColorScheme
+
+//BEGIN KStatefulBrush
+class KStatefulBrushPrivate : public QBrush // for now, just be a QBrush
+{
+    public:
+        KStatefulBrushPrivate() : QBrush() {}
+        KStatefulBrushPrivate(const QBrush &brush) : QBrush(brush) {} // not \
explicit +};
+
+KStatefulBrush::KStatefulBrush(KColorScheme::ColorSet set, \
KColorScheme::ForegroundRole role, +                               KSharedConfigPtr \
config) +{
+    d = new KStatefulBrushPrivate[3];
+    d[0] = KColorScheme(QPalette::Active,   set, config).foreground(role);
+    d[1] = KColorScheme(QPalette::Disabled, set, config).foreground(role);
+    d[2] = KColorScheme(QPalette::Inactive, set, config).foreground(role);
+}
+
+KStatefulBrush::KStatefulBrush(KColorScheme::ColorSet set, \
KColorScheme::BackgroundRole role, +                               KSharedConfigPtr \
config) +{
+    d = new KStatefulBrushPrivate[3];
+    d[0] = KColorScheme(QPalette::Active,   set, config).background(role);
+    d[1] = KColorScheme(QPalette::Disabled, set, config).background(role);
+    d[2] = KColorScheme(QPalette::Inactive, set, config).background(role);
+}
+
+KStatefulBrush::KStatefulBrush(KColorScheme::ColorSet set, \
KColorScheme::DecorationRole role, +                               KSharedConfigPtr \
config) +{
+    d = new KStatefulBrushPrivate[3];
+    d[0] = KColorScheme(QPalette::Active,   set, config).decoration(role);
+    d[1] = KColorScheme(QPalette::Disabled, set, config).decoration(role);
+    d[2] = KColorScheme(QPalette::Inactive, set, config).decoration(role);
+}
+
+KStatefulBrush::KStatefulBrush(const KStatefulBrush &other)
+{
+    d = new KStatefulBrushPrivate[3];
+    d[0] = other.d[0];
+    d[1] = other.d[1];
+    d[2] = other.d[2];
+}
+
+KStatefulBrush::~KStatefulBrush()
+{
+    delete[] d;
+}
+
+QBrush KStatefulBrush::brush(QPalette::ColorGroup state) const
+{
+    switch (state) {
+        case QPalette::Inactive:
+            return d[2];
+        case QPalette::Disabled:
+            return d[1];
+        default:
+            return d[0];
+    }
+}
+
+QBrush KStatefulBrush::brush(const QPalette &pal) const
+{
+    return brush(pal.currentColorGroup());
+}
+
+QBrush KStatefulBrush::brush(const QWidget *widget) const
+{
+    if (widget)
+        return brush(widget->palette());
+    else
+        return QBrush();
+}
+//END KStatefulBrush
+
 // kate: space-indent on; indent-width 4; replace-tabs on; auto-insert-doxygen on;
Index: colors/kcolorscheme.h
===================================================================
--- colors/kcolorscheme.h       (revision 708763)
+++ colors/kcolorscheme.h       (working copy)
@@ -52,6 +52,19 @@
  * foreground for any other set. Individual colors may be quickly referenced by
  * creating an anonymous instance and invoking a lookup member.
  *
+ * @note
+ * Historically, it was not needed for applications to give much concern to the
+ * state of a widget (active, inactive, disabled) since only the disabled state
+ * was different, and only slightly. As a result, the old KGlobalSettings color
+ * getters did not care about the widget state. However, starting with KDE4,
+ * the color palettes for the various states may be wildly different.
+ * Therefore, it is important to take the state into account. This is why the
+ * KColorScheme constructor requires a QPalette::ColorGroup as an argument.
+ *
+ * To facilitate working with potentially-varying states, two convenience API's
+ * are provided. These are KColorScheme::adjustBackground and its sister
+ * KColorScheme::adjustForeground, and the helper class ::KStatefulBrush.
+ *
  * @see KColorScheme::ColorSet, KColorScheme::ForegroundRole,
  * KColorScheme::BackgroundRole, KColorScheme::DecorationRole,
  * KColorScheme::ShadeRole
@@ -271,6 +284,10 @@
     /**
      * Construct a palette from given color set and state, using the colors
      * from the given KConfig (if null, the system colors are used).
+     *
+     * @note Don't construct a KColorScheme unless you understand why you are
+     * doing so, and how you will deal with widget states (or why you don't
+     * need to). You probably want a ::KStatefulBrush instead.
      */
     explicit KColorScheme(QPalette::ColorGroup, ColorSet = View, KSharedConfigPtr = \
KSharedConfigPtr());

@@ -337,9 +354,97 @@
     static QColor shade(const QColor&, ShadeRole,
                         qreal contrast, qreal chromaAdjust = 0.0);

+    static void adjustBackground(QPalette &,
+                                 BackgroundRole newRole = NormalBackground,
+                                 QPalette::ColorRole color = QPalette::Base,
+                                 ColorSet set = View);
+
+    static void adjustForeground(QPalette &,
+                                 ForegroundRole newRole = NormalText,
+                                 QPalette::ColorRole color = QPalette::Text,
+                                 ColorSet set = View);
+
 private:
     QExplicitlySharedDataPointer<KColorSchemePrivate> d;
 };

+/**
+ * A container for a "state-aware" brush.
+ *
+ * KStatefulBrush provides an easy and safe way to store a color for use in a
+ * user interface. It is "safe" both in that it will make it easy to deal with
+ * widget states in a correct manner, and that it insulates you against changes
+ * in QPalette::ColorGroup.
+ *
+ * Basically, a stateful brush is used to cache a particular "color" from the
+ * KDE system palette (usually, one which does not live in QPalette) in the way
+ * you would have used a QColor in KDE3. When you are ready to draw using the
+ * brush, you use the current state to retrieve the appropriate brush.
+ *
+ * @note As of Qt 4.3, QPalette::ColorGroup is missing a state for disabled
+ * widgets in an inactive window. Hopefully Trolltech will fix this bug, at
+ * which point KColorScheme and KStatefulBrush will be updated to recognize the
+ * new state. Using KStatefulBrush will allow your application to inherit these
+ * changes "for free", without even recompiling.
+ */
+class KStatefulBrush
+{
+public:
+
+    /**
+     * Construct a stateful brush from given color set and foreground role,
+     * using the colors from the given KConfig (if null, the system colors are
+     * used).
+     */
+    explicit KStatefulBrush(KColorScheme::ColorSet,
+                            KColorScheme::ForegroundRole,
+                            KSharedConfigPtr = KSharedConfigPtr());
+
+    /**
+     * Construct a stateful brush from given color set and background role,
+     * using the colors from the given KConfig (if null, the system colors are
+     * used).
+     */
+    explicit KStatefulBrush(KColorScheme::ColorSet,
+                            KColorScheme::BackgroundRole,
+                            KSharedConfigPtr = KSharedConfigPtr());
+
+    /**
+     * Construct a stateful brush from given color set and decoration role,
+     * using the colors from the given KConfig (if null, the system colors are
+     * used).
+     */
+    explicit KStatefulBrush(KColorScheme::ColorSet,
+                            KColorScheme::DecorationRole,
+                            KSharedConfigPtr = KSharedConfigPtr());
+
+    KStatefulBrush(const KStatefulBrush&);
+    ~KStatefulBrush();
+
+    /**
+     * Retrieve the brush for the specified widget state.
+     */
+    QBrush brush(QPalette::ColorGroup) const;
+
+    /**
+     * Retrieve the brush, using a QPalette reference to determine the correct
+     * state. Use when your painting code has easy access to the QPalette that
+     * it is supposed to be using.
+     */
+    QBrush brush(const QPalette&) const;
+
+    /**
+     * Retrieve the brush, using a QPalette reference to determine the correct
+     * state. Use when you have a pointer to the widget that you are painting.
+     *
+     * @note If you pass an invalid widget, you will get a default brush (i.e.
+     * <tt>QBrush()</tt>).
+     */
+    QBrush brush(const QWidget*) const;
+
+private:
+    class KStatefulBrushPrivate *d;
+};
+
 #endif // KCOLORSCHEME_H
 // kate: space-indent on; indent-width 4; replace-tabs on; auto-insert-doxygen on;



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic