summaryrefslogtreecommitdiffstats
path: root/tdm/kfrontend/themer
diff options
context:
space:
mode:
Diffstat (limited to 'tdm/kfrontend/themer')
-rw-r--r--tdm/kfrontend/themer/CMakeLists.txt41
-rw-r--r--tdm/kfrontend/themer/Makefile.am16
-rw-r--r--tdm/kfrontend/themer/tdmitem.cpp657
-rw-r--r--tdm/kfrontend/themer/tdmitem.h272
-rw-r--r--tdm/kfrontend/themer/tdmlabel.cpp276
-rw-r--r--tdm/kfrontend/themer/tdmlabel.h87
-rw-r--r--tdm/kfrontend/themer/tdmlayout.cpp168
-rw-r--r--tdm/kfrontend/themer/tdmlayout.h98
-rw-r--r--tdm/kfrontend/themer/tdmpixmap.cpp340
-rw-r--r--tdm/kfrontend/themer/tdmpixmap.h73
-rw-r--r--tdm/kfrontend/themer/tdmrect.cpp181
-rw-r--r--tdm/kfrontend/themer/tdmrect.h67
-rw-r--r--tdm/kfrontend/themer/tdmthemer.cpp404
-rw-r--r--tdm/kfrontend/themer/tdmthemer.h128
14 files changed, 2808 insertions, 0 deletions
diff --git a/tdm/kfrontend/themer/CMakeLists.txt b/tdm/kfrontend/themer/CMakeLists.txt
new file mode 100644
index 000000000..fc0b80fc3
--- /dev/null
+++ b/tdm/kfrontend/themer/CMakeLists.txt
@@ -0,0 +1,41 @@
+#################################################
+#
+# (C) 2010-2011 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/tdm/kfrontend
+ ${CMAKE_SOURCE_DIR}/tdmlib
+ ${TDE_INCLUDE_DIR}
+ ${TQT_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+)
+
+
+# FIXME this must be optimized
+##### config.ci (generated) #####################
+
+add_custom_command( OUTPUT config.ci
+ COMMAND perl -w ${CMAKE_SOURCE_DIR}/tdm/confproc.pl ${CMAKE_SOURCE_DIR}/tdm/config.def config.ci
+ DEPENDS ${CMAKE_SOURCE_DIR}/tdm/confproc.pl ${CMAKE_SOURCE_DIR}/tdm/config.def )
+set_property( SOURCE tdmthemer.cpp APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/config.ci )
+
+
+##### tdmthemer (static) ########################
+
+tde_add_library( tdmthemer STATIC_PIC AUTOMOC
+ SOURCES
+ tdmthemer.cpp tdmitem.cpp tdmpixmap.cpp
+ tdmrect.cpp tdmlabel.cpp tdmlayout.cpp
+)
diff --git a/tdm/kfrontend/themer/Makefile.am b/tdm/kfrontend/themer/Makefile.am
new file mode 100644
index 000000000..f736795d6
--- /dev/null
+++ b/tdm/kfrontend/themer/Makefile.am
@@ -0,0 +1,16 @@
+AM_CPPFLAGS = -I$(srcdir)/../../backend -I$(srcdir)/.. -I../.. \
+ -I$(top_srcdir)/tdmlib \
+ $(all_includes)
+
+noinst_LIBRARIES = libtdmthemer.a
+libtdmthemer_a_SOURCES = \
+ tdmthemer.cpp \
+ tdmitem.cpp \
+ tdmpixmap.cpp \
+ tdmrect.cpp \
+ tdmlabel.cpp \
+ tdmlayout.cpp
+
+METASOURCES = AUTO
+
+libtdmthemer_a_COMPILE_FIRST = ../../config.ci
diff --git a/tdm/kfrontend/themer/tdmitem.cpp b/tdm/kfrontend/themer/tdmitem.cpp
new file mode 100644
index 000000000..8cf126b66
--- /dev/null
+++ b/tdm/kfrontend/themer/tdmitem.cpp
@@ -0,0 +1,657 @@
+/*
+ * Copyright (C) 2003 by Unai Garro <[email protected]>
+ * Copyright (C) 2004 by Enrico Ros <[email protected]>
+ * Copyright (C) 2004 by Stephan Kulow <[email protected]>
+ * Copyright (C) 2004 by Oswald Buddenhagen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Generic Kdm Item
+ */
+
+// #define DRAW_OUTLINE 1 // for debugging only
+
+#include "tdmitem.h"
+#include "tdmlayout.h"
+#include "tdmconfig.h"
+
+#include <kglobal.h>
+#include <kdebug.h>
+
+#include <tqframe.h>
+#include <tqwidget.h>
+#include <tqlayout.h>
+#include <tqimage.h>
+#include <tqpainter.h>
+
+extern bool argb_visual_available;
+
+KdmItem::KdmItem( KdmItem *parent, const TQDomNode &node, const char *name )
+ : TQObject( parent, name )
+ , boxManager( 0 )
+ , fixedManager( 0 )
+ , image( 0 )
+ , myWidget( 0 )
+ , myLayoutItem( 0 )
+ , buttonParent( 0 )
+{
+ init(node, name);
+}
+
+
+KdmItem::KdmItem( TQWidget *parent, const TQDomNode &node, const char *name )
+ : TQObject( parent, name )
+ , boxManager( 0 )
+ , fixedManager( 0 )
+ , image( 0 )
+ , myWidget( 0 )
+ , myLayoutItem( 0 )
+ , buttonParent( 0 )
+{
+ init(node, name);
+}
+
+void
+KdmItem::init( const TQDomNode &node, const char * )
+{
+ // Set default layout for every item
+ currentManager = MNone;
+ pos.x = pos.y = 0;
+ pos.width = pos.height = 1;
+ pos.xType = pos.yType = pos.wType = pos.hType = DTnone;
+ pos.anchor = "nw";
+ m_backgroundModifier = 255;
+
+ isShown = InitialHidden;
+
+ // Set defaults for derived item's properties
+ properties.incrementalPaint = false;
+ state = Snormal;
+
+ // The "toplevel" node (the screen) is really just like a fixed node
+ if (!parent() || !parent()->inherits( "KdmItem" )) {
+ setFixedLayout();
+ return;
+ }
+ // Read the mandatory Pos tag. Other tags such as normal, prelighted,
+ // etc.. are read under specific implementations.
+ TQDomNodeList childList = node.childNodes();
+ for (uint nod = 0; nod < childList.count(); nod++) {
+ TQDomNode child = childList.item( nod );
+ TQDomElement el = child.toElement();
+ TQString tagName = el.tagName(), attr;
+
+ if (tagName == "pos") {
+ parseAttribute( el.attribute( "x", TQString::null ), pos.x, pos.xType );
+ parseAttribute( el.attribute( "y", TQString::null ), pos.y, pos.yType );
+ parseAttribute( el.attribute( "width", TQString::null ), pos.width, pos.wType );
+ parseAttribute( el.attribute( "height", TQString::null ), pos.height, pos.hType );
+ pos.anchor = el.attribute( "anchor", "nw" );
+ }
+
+ if (tagName == "bgmodifier") {
+ m_backgroundModifier = TQString(el.attribute( "value", "255" )).toInt();
+ }
+ }
+
+ TQDomNode tnode = node;
+ id = tnode.toElement().attribute( "id", TQString::number( (ulong)this, 16 ) );
+
+ // Tell 'parent' to add 'me' to its children
+ KdmItem *parentItem = static_cast<KdmItem *>( parent() );
+ parentItem->addChildItem( this );
+}
+
+KdmItem::~KdmItem()
+{
+ delete boxManager;
+ delete fixedManager;
+ delete image;
+}
+
+void
+KdmItem::update()
+{
+}
+
+void
+KdmItem::needUpdate()
+{
+ emit needUpdate( area.x(), area.y(), area.width(), area.height() );
+}
+
+void
+KdmItem::show( bool force )
+{
+ if (isShown != InitialHidden && !force)
+ return;
+
+ TQValueList<KdmItem *>::Iterator it;
+ for (it = m_children.begin(); it != m_children.end(); ++it)
+ (*it)->show();
+
+ isShown = Shown;
+
+ if (myWidget)
+ myWidget->show();
+ // XXX showing of layouts not implemented, prolly pointless anyway
+
+ needUpdate();
+}
+
+void
+KdmItem::hide( bool force )
+{
+ if (isShown == ExplicitlyHidden)
+ return;
+
+ if (isShown == InitialHidden && force) {
+ isShown = ExplicitlyHidden;
+ return; // no need for further action
+ }
+
+ TQValueList<KdmItem *>::Iterator it;
+ for (it = m_children.begin(); it != m_children.end(); ++it)
+ (*it)->hide();
+
+ isShown = force ? ExplicitlyHidden : InitialHidden;
+
+ if (myWidget)
+ myWidget->hide();
+ // XXX hiding of layouts not implemented, prolly pointless anyway
+
+ needUpdate();
+}
+
+void
+KdmItem::inheritFromButton( KdmItem *button )
+{
+ if (button)
+ buttonParent = button;
+
+ TQValueList<KdmItem *>::Iterator it;
+ for (it = m_children.begin(); it != m_children.end(); ++it)
+ (*it)->inheritFromButton( button );
+}
+
+KdmItem *
+KdmItem::findNode( const TQString &_id ) const
+{
+ if (id == _id)
+ return const_cast<KdmItem *>( this );
+
+ TQValueList<KdmItem *>::ConstIterator it;
+ for (it = m_children.begin(); it != m_children.end(); ++it) {
+ KdmItem *t = (*it)->findNode( _id );
+ if (t)
+ return t;
+ }
+
+ return 0;
+}
+
+void
+KdmItem::setWidget( TQWidget *widget )
+{
+// delete myWidget; -- themer->widget() owns the widgets
+
+ myWidget = widget;
+ if (isHidden())
+ myWidget->hide();
+ else
+ myWidget->show();
+
+ // Remove borders so that it blends nicely with the theme background
+ TQFrame* frame = ::tqqt_cast<TQFrame *>( widget );
+ if (frame)
+ frame->setFrameStyle( TQFrame::NoFrame );
+
+ setGeometry(area, true);
+
+ connect( myWidget, TQT_SIGNAL(destroyed()), TQT_SLOT(widgetGone()) );
+}
+
+void
+KdmItem::widgetGone()
+{
+ myWidget = 0;
+}
+
+void
+KdmItem::setLayoutItem( TQLayoutItem *item )
+{
+ myLayoutItem = item;
+ // XXX hiding not supported - it think it's pointless here
+ if (myLayoutItem->widget())
+ connect( myLayoutItem->widget(), TQT_SIGNAL(destroyed()),
+ TQT_SLOT(layoutItemGone()) );
+ else if (myLayoutItem->layout())
+ connect( myLayoutItem->layout(), TQT_SIGNAL(destroyed()),
+ TQT_SLOT(layoutItemGone()) );
+}
+
+void
+KdmItem::layoutItemGone()
+{
+ myLayoutItem = 0;
+}
+
+/* This is called as a result of KdmLayout::update, and directly on the root */
+void
+KdmItem::setGeometry( const TQRect &newGeometry, bool force )
+{
+ kdDebug() << " KdmItem::setGeometry " << id << newGeometry << endl;
+ // check if already 'in place'
+ if (!force && area == newGeometry)
+ return;
+
+ area = newGeometry;
+
+ if (myWidget) {
+ TQRect widGeo = newGeometry;
+ if ( widGeo.height() > myWidget->maximumHeight() ) {
+ widGeo.moveTop( widGeo.top() + ( widGeo.height() - myWidget->maximumHeight() ) / 2 );
+ widGeo.setHeight( myWidget->maximumHeight() );
+ }
+ myWidget->setGeometry( widGeo );
+ }
+ if (myLayoutItem)
+ myLayoutItem->setGeometry( newGeometry );
+
+ // recurr to all boxed children
+ if (boxManager && !boxManager->isEmpty())
+ boxManager->update( newGeometry, force );
+
+ // recurr to all fixed children
+ if (fixedManager && !fixedManager->isEmpty())
+ fixedManager->update( newGeometry, force );
+
+ // TODO send *selective* repaint signal
+}
+
+void
+KdmItem::paint( TQPainter *p, const TQRect &rect )
+{
+ if (isHidden())
+ return;
+
+ if (myWidget || (myLayoutItem && myLayoutItem->widget())) {
+ // KListView because it's missing a Q_OBJECT'
+ // FIXME: This is a nice idea in theory, but in practice it is
+ // very confusing for the user not to see the empty list box
+ // delineated from the rest of the greeter.
+ // Maybe set a darker version of the background instead of an exact copy?
+ if ( myWidget && myWidget->isA( "KListView" ) ) {
+ if ((_compositor.isEmpty()) || (!argb_visual_available)) {
+ // Software blend only (no compositing support)
+ TQPixmap copy( myWidget->size() );
+ kdDebug() << myWidget->geometry() << " " << area << " " << myWidget->size() << endl;
+ bitBlt( &copy, TQPoint( 0, 0), p->device(), myWidget->geometry(), TQt::CopyROP );
+ // Lighten it slightly
+ TQImage lightVersion;
+ lightVersion = copy.convertToImage();
+
+ register uchar * r = lightVersion.bits();
+ register uchar * g = lightVersion.bits() + 1;
+ register uchar * b = lightVersion.bits() + 2;
+ uchar * end = lightVersion.bits() + lightVersion.numBytes();
+
+ while ( r != end ) {
+ if ((*r) < (255-m_backgroundModifier))
+ *r = (uchar) (*r) + m_backgroundModifier;
+ else
+ *r = 255;
+ if ((*g) < (255-m_backgroundModifier))
+ *g = (uchar) (*g) + m_backgroundModifier;
+ else
+ *g = 255;
+ if ((*b) < (255-m_backgroundModifier))
+ *b = (uchar) (*b) + m_backgroundModifier;
+ else
+ *b = 255;
+ r += 4;
+ g += 4;
+ b += 4;
+ }
+
+ copy = lightVersion;
+ // Set it
+ myWidget->setPaletteBackgroundPixmap( copy );
+ }
+ else {
+ // We have compositing support!
+ TQRgb blend_color = tqRgba(m_backgroundModifier, m_backgroundModifier, m_backgroundModifier, 0); // RGBA overlay
+ float alpha = tqAlpha(blend_color) / 255.;
+ int pixel = tqAlpha(blend_color) << 24 |
+ int(tqRed(blend_color) * alpha) << 16 |
+ int(tqGreen(blend_color) * alpha) << 8 |
+ int(tqBlue(blend_color) * alpha);
+
+ TQImage img( myWidget->size(), 32 );
+ img = img.convertDepth(32);
+ img.setAlphaBuffer(true);
+ register uchar * rd = img.bits();
+ for( int y = 0; y < img.height(); ++y )
+ {
+ for( short int x = 0; x < img.width(); ++x )
+ {
+ *reinterpret_cast<TQRgb*>(rd) = blend_color;
+ rd += 4;
+ }
+ }
+ myWidget->setPaletteBackgroundPixmap( img );
+ }
+ }
+ return;
+ }
+
+ if (area.intersects( rect )) {
+ TQRect contentsRect = area.intersect( rect );
+ contentsRect.moveBy( QMIN( 0, -area.x() ), QMIN( 0, -area.y() ) );
+ drawContents( p, contentsRect );
+ }
+
+#ifdef DRAW_OUTLINE
+ // Draw bounding rect for this item
+ p->setPen( Qt::white );
+ p->drawRect( area );
+#endif
+
+ if (myLayoutItem)
+ return;
+
+ // Dispatch paint events to children
+ TQValueList<KdmItem *>::Iterator it;
+ for (it = m_children.begin(); it != m_children.end(); ++it)
+ (*it)->paint( p, rect );
+
+
+}
+
+KdmItem *KdmItem::currentActive = 0;
+
+void
+KdmItem::mouseEvent( int x, int y, bool pressed, bool released )
+{
+ if (isShown == ExplicitlyHidden)
+ return;
+
+ if (buttonParent && buttonParent != this) {
+ buttonParent->mouseEvent( x, y, pressed, released );
+ return;
+ }
+
+ ItemState oldState = state;
+ if (area.contains( x, y )) {
+ if (released && oldState == Sactive) {
+ if (buttonParent)
+ emit activated( id );
+ state = Sprelight;
+ currentActive = 0;
+ } else if (pressed || currentActive == this) {
+ state = Sactive;
+ currentActive = this;
+ } else if (!currentActive)
+ state = Sprelight;
+ else
+ state = Snormal;
+ } else {
+ if (released)
+ currentActive = 0;
+ if (currentActive == this)
+ state = Sprelight;
+ else
+ state = Snormal;
+ }
+
+ if (!buttonParent) {
+ TQValueList<KdmItem *>::Iterator it;
+ for (it = m_children.begin(); it != m_children.end(); ++it)
+ (*it)->mouseEvent( x, y, pressed, released );
+ }
+
+ if (oldState != state)
+ statusChanged();
+}
+
+void
+KdmItem::statusChanged()
+{
+ if (buttonParent == this) {
+ TQValueList<KdmItem *>::Iterator it;
+ for (it = m_children.begin(); it != m_children.end(); ++it) {
+ (*it)->state = state;
+ (*it)->statusChanged();
+ }
+ }
+}
+
+// BEGIN protected inheritable
+
+TQSize
+KdmItem::sizeHint()
+{
+ if (myWidget)
+ return myWidget->size();
+ if (myLayoutItem)
+ return myLayoutItem->sizeHint();
+ int w = pos.wType == DTpixel ? kAbs( pos.width ) : -1,
+ h = pos.hType == DTpixel ? kAbs( pos.height ) : -1;
+ return TQSize( w, h );
+}
+
+TQRect
+KdmItem::placementHint( const TQRect &parentRect )
+{
+ TQSize hintedSize = sizeHint();
+ TQSize boxHint;
+
+ int x = parentRect.left(),
+ y = parentRect.top(),
+ w = parentRect.width(),
+ h = parentRect.height();
+
+ kdDebug() << timestamp() << " KdmItem::placementHint parentRect=" << parentRect << " hintedSize=" << hintedSize << endl;
+
+ // check if width or height are set to "box"
+ if (pos.wType == DTbox || pos.hType == DTbox) {
+ if (myLayoutItem || myWidget)
+ boxHint = hintedSize;
+ else {
+ if (!boxManager)
+ return parentRect;
+ boxHint = boxManager->sizeHint();
+ }
+ kdDebug() << timestamp() << " boxHint " << boxHint << endl;
+ }
+
+ if (pos.xType == DTpixel)
+ x += pos.x;
+ else if (pos.xType == DTnpixel)
+ x = parentRect.right() - pos.x;
+ else if (pos.xType == DTpercent)
+ x += tqRound( parentRect.width() / 100.0 * pos.x );
+
+ if (pos.yType == DTpixel)
+ y += pos.y;
+ else if (pos.yType == DTnpixel)
+ y = parentRect.bottom() - pos.y;
+ else if (pos.yType == DTpercent)
+ y += tqRound( parentRect.height() / 100.0 * pos.y );
+
+ if (pos.wType == DTpixel)
+ w = pos.width;
+ else if (pos.wType == DTnpixel)
+ w -= pos.width;
+ else if (pos.wType == DTpercent)
+ w = tqRound( parentRect.width() / 100.0 * pos.width );
+ else if (pos.wType == DTbox)
+ w = boxHint.width();
+ else if (hintedSize.width() > 0)
+ w = hintedSize.width();
+ else
+ w = 0;
+
+ if (pos.hType == DTpixel)
+ h = pos.height;
+ else if (pos.hType == DTnpixel)
+ h -= pos.height;
+ else if (pos.hType == DTpercent)
+ h = tqRound( parentRect.height() / 100.0 * pos.height );
+ else if (pos.hType == DTbox)
+ h = boxHint.height();
+ else if (hintedSize.height() > 0) {
+ if (w && pos.wType != DTnone)
+ h = (hintedSize.height() * w) / hintedSize.width();
+ else
+ h = hintedSize.height();
+ } else
+ h = 0;
+
+ // we choose to take the hinted size, but it's better to listen to the aspect ratio
+ if (pos.wType == DTnone && pos.hType != DTnone && h && w) {
+ w = tqRound(float(hintedSize.width() * h) / hintedSize.height());
+ }
+
+ // defaults to center
+ int dx = -w / 2, dy = -h / 2;
+
+ // anchor the rect to an edge / corner
+ if (pos.anchor.length() > 0 && pos.anchor.length() < 3) {
+ if (pos.anchor.find( 'n' ) >= 0)
+ dy = 0;
+ if (pos.anchor.find( 's' ) >= 0)
+ dy = -h;
+ if (pos.anchor.find( 'w' ) >= 0)
+ dx = 0;
+ if (pos.anchor.find( 'e' ) >= 0)
+ dx = -w;
+ }
+ // KdmItem *p = static_cast<KdmItem*>( parent() );
+ kdDebug() << timestamp() << " placementHint " << this << " x=" << x << " dx=" << dx << " w=" << w << " y=" << y << " dy=" << dy << " h=" << h << " " << parentRect << endl;
+ y += dy;
+ x += dx;
+
+ // Note: no clipping to parent because this broke many themes!
+ return TQRect( x, y, w, h );
+}
+
+// END protected inheritable
+
+
+void
+KdmItem::addChildItem( KdmItem *item )
+{
+ m_children.append( item );
+ switch (currentManager) {
+ case MNone: // fallback to the 'fixed' case
+ setFixedLayout();
+ case MFixed:
+ fixedManager->addItem( item );
+ break;
+ case MBox:
+ boxManager->addItem( item );
+ break;
+ }
+
+ // signal bounce from child to parent
+ connect( item, TQT_SIGNAL(needUpdate( int, int, int, int )), TQT_SIGNAL(needUpdate( int, int, int, int )) );
+ connect( item, TQT_SIGNAL(activated( const TQString & )), TQT_SIGNAL(activated( const TQString & )) );
+}
+
+void
+KdmItem::parseAttribute( const TQString &s, int &val, enum DataType &dType )
+{
+ if (s.isEmpty())
+ return;
+
+ int p;
+ if (s == "box") { // box value
+ dType = DTbox;
+ val = 0;
+ } else if ((p = s.find( '%' )) >= 0) { // percent value
+ dType = DTpercent;
+ TQString sCopy = s;
+ sCopy.remove( p, 1 );
+ sCopy.replace( ',', '.' );
+ val = (int)sCopy.toDouble();
+ } else { // int value
+ dType = DTpixel;
+ TQString sCopy = s;
+ if (sCopy.at( 0 ) == '-') {
+ sCopy.remove( 0, 1 );
+ dType = DTnpixel;
+ }
+ sCopy.replace( ',', '.' );
+ val = (int)sCopy.toDouble();
+ }
+}
+
+void
+KdmItem::parseFont( const TQString &s, TQFont &font )
+{
+ int splitAt = s.findRev( ' ' );
+ if (splitAt < 1)
+ return;
+ font.setFamily( s.left( splitAt ) );
+ int fontSize = s.mid( splitAt + 1 ).toInt();
+ if (fontSize > 1)
+ font.setPointSize( fontSize );
+}
+
+void
+KdmItem::parseColor( const TQString &s, TQColor &color )
+{
+ if (s.at( 0 ) != '#')
+ return;
+ bool ok;
+ TQString sCopy = s;
+ int hexColor = sCopy.remove( 0, 1 ).toInt( &ok, 16 );
+ if (ok)
+ color.setRgb( hexColor );
+}
+
+void
+KdmItem::setBoxLayout( const TQDomNode &node )
+{
+ if (!boxManager)
+ boxManager = new KdmLayoutBox( node );
+ currentManager = MBox;
+}
+
+void
+KdmItem::setFixedLayout( const TQDomNode &node )
+{
+ if (!fixedManager)
+ fixedManager = new KdmLayoutFixed( node );
+ currentManager = MFixed;
+}
+
+TQWidget *
+KdmItem::parentWidget() const
+{
+ if (myWidget)
+ return myWidget;
+ if (!this->parent())
+ return 0;
+
+ if (parent()->qt_cast(TQWIDGET_OBJECT_NAME_STRING))
+ return (TQWidget*)parent();
+ return ((KdmItem*)parent())->parentWidget();
+}
+
+#include "tdmitem.moc"
diff --git a/tdm/kfrontend/themer/tdmitem.h b/tdm/kfrontend/themer/tdmitem.h
new file mode 100644
index 000000000..27158a7fd
--- /dev/null
+++ b/tdm/kfrontend/themer/tdmitem.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2003 by Unai Garro <[email protected]>
+ * Copyright (C) 2004 by Enrico Ros <[email protected]>
+ * Copyright (C) 2004 by Stephan Kulow <[email protected]>
+ * Copyright (C) 2004 by Oswald Buddenhagen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TDMITEM_H
+#define TDMITEM_H
+
+#include <tqobject.h>
+#include <tqvaluelist.h>
+#include <tqrect.h>
+#include <tqdom.h>
+
+class KdmItem;
+class KdmLayoutBox;
+class KdmLayoutFixed;
+
+class TQPainter;
+class TQLayoutItem;
+
+/** class KdmItem
+ * @short Base class for every tdmthemes' element.
+ *
+ * This class provides methods for arranging it and its children to the
+ * screen (see note below), painting the whole area or a sub-region using
+ * an opened painter, handling mouse events or events in general dispatching
+ * them to children and sending some signals to the root (for example on
+ * mouse click).
+ *
+ * KdmItem sits in a hierarchical top to bottom tree with signals that
+ * traverse the tree back from leafs (or inner nodes) to the root.
+ *
+ * To implement a KdmItem only a few virtual protected methods must be
+ * reimplemented, other virtual functions are there for convenience only -
+ * the default implementation should satisfy your needs.
+ */
+
+/**
+ * A note on layouting - how does it work?
+ * - setgeometry is called by parent (passing the new geometry)
+ * - item changes its geometry
+ * - if item embeds a widget, reposition it too
+ * - call children's box manager. box->update( my geom )
+ * - sum up the whole space taken by children (via *hint calls) if
+ * needed for box width / height computation. note that the computed
+ * geometry should be equal or similar to parent's geometry.
+ * - pad the rectangle bounding box' contents
+ * - for every child
+ * - if vertical
+ * ( use a top-to-bottom insertion, spacing insertion lines by
+ * children's individual height )
+ * - set up a zero height Parent (placed at the insertion line's
+ * position) and get Geom = child->placementHint( p )
+ * - set up child's Size using Parent's width and Geom's height.
+ * - call to child->setGeometry( Parent.topLeft, Size )
+ * - if horizontal
+ * - flows like the vertical one but uses a left-to-right insertion
+ * and insertion entry points are vertical lines
+ * - call to children's fix manager. fixed->update( my geom )
+ * - for every child
+ * - S = get child's geometry hint (and we'll give item the whole
+ * space it needs, without constraints)
+ * - call to child->setGeometry( S )
+ * - TODO: send a selective redraw signal also merging children's areas
+ */
+
+class KdmItem : public TQObject {
+ Q_OBJECT
+
+ friend class KdmThemer;
+
+public:
+ /**
+ * Item constructor and destructor
+ */
+ KdmItem( KdmItem *parent, const TQDomNode &node = TQDomNode(), const char *name = 0 );
+ KdmItem( TQWidget *parent, const TQDomNode &node = TQDomNode(), const char *name = 0 ); // for the root
+
+ virtual ~KdmItem();
+
+ /**
+ * Fixup the geometry of an item and its children (even if fixed
+ * or boxed ones). Note that this will generate repaint signals
+ * when needed. The default implementation should fit all needs.
+ */
+ virtual void setGeometry( const TQRect &newGeometry, bool force );
+
+ /**
+ * Paint the item and its children using the given painter.
+ * This is the compositing core function. It buffers paint operations
+ * to speed up rendering of dynamic objects.
+ */
+ void paint( TQPainter *painter, const TQRect &boundaries );
+
+ /**
+ * Update representation of contents and repaint.
+ */
+ virtual void update();
+
+ /**
+ * Handle mouse motion and dispatch events to children. This
+ * leads to items prelighting, activation() on click and more..
+ */
+ void mouseEvent( int x, int y, bool pressed = false, bool released = false );
+
+ /**
+ * Similar to sizeHint(..), this returns the area of the item
+ * given the @p parentGeometry. The default implementation
+ * takes into account geometric constraints and layoutings.
+ * @param parentGeometry the geometry of the caller item or a
+ * null rect if the geometry of the parent is not yet defined.
+ */
+ virtual TQRect placementHint( const TQRect &parentGeometry );
+
+ /**
+ * Create the box layout manager; next children will be
+ * managed by the box layouter
+ */
+ void setBoxLayout( const TQDomNode &node = TQDomNode() );
+
+ /**
+ * Create the fixed layout manager; next children will be
+ * in fixed position relative to this item
+ */
+ void setFixedLayout( const TQDomNode &node = TQDomNode() );
+
+ TQString type() const { return itemType; }
+ void setType( const TQString &t ) { itemType = t; }
+ void setBaseDir( const TQString &bd ) { basedir = bd; }
+
+ TQString baseDir() const
+ {
+ if (basedir.isEmpty() && parent())
+ return static_cast<KdmItem *>( parent()->qt_cast( "KdmItem" ) )->baseDir();
+ return basedir;
+ }
+
+ KdmItem *findNode( const TQString &id ) const;
+ virtual void setWidget( TQWidget *widget );
+ TQWidget *widget() const { return myWidget; }
+ virtual void setLayoutItem( TQLayoutItem *item );
+
+ virtual void hide( bool force = false );
+ virtual void show( bool force = false );
+
+ bool isHidden() const { return isShown != Shown; }
+ bool isExplicitlyHidden() const { return isShown == ExplicitlyHidden; }
+ TQRect rect() const { return area; }
+
+ TQWidget *parentWidget() const;
+ TQString getId() const { return id; }
+
+signals:
+ void needUpdate( int x, int y, int w, int h );
+ void activated( const TQString &id );
+
+protected slots:
+ void widgetGone();
+ void layoutItemGone();
+
+protected:
+ /**
+ * Returns the optimal/minimal size for this item.
+ * This should be reimplemented in items like label and pixmap.
+ * @return (-1,-1) if no size can be determined (so it should
+ * default to parent's size).
+ */
+ virtual TQSize sizeHint();
+
+ /**
+ * Low level graphical function to paint the item.
+ * All items must reimplement this function to draw themeselves
+ * (or a part of) into the @p image keeping inside the @p rect .
+ * Try to do this as fast as possible.
+ * @param painter the painter to draw the item with
+ * @param region the part of the the image to render
+ */
+ virtual void drawContents( TQPainter *painter, const TQRect &region ) = 0;
+
+ /**
+ * Called when item changes its 'state' variable. This must
+ * handle item's repaint.
+ */
+ virtual void statusChanged();
+
+ /**
+ * emits needUpdate( int, int, int, int ) with the full widget area.
+ */
+ void needUpdate();
+
+ // This enum identifies in which state the item is
+ enum ItemState { Snormal, Sactive, Sprelight } state;
+
+ static KdmItem *currentActive;
+
+ // This struct can be filled in by derived items
+ struct {
+ bool incrementalPaint;
+ } properties;
+
+ // This is the placement of the item
+ TQRect area;
+
+ // This struct is filled in by KdmItem base class
+ enum DataType { DTnone, DTpixel, DTnpixel, DTpercent, DTbox };
+ struct {
+ enum DataType xType, yType, wType, hType;
+ int x;
+ int y;
+ int width;
+ int height;
+ TQString anchor;
+ } pos;
+
+ /* For internal use ONLY
+ * Add a child item. This function is called automatically
+ * when constructing an @p item with this as the parent.
+ */
+ void addChildItem( KdmItem *item );
+
+ /* For internal use ONLY
+ * Parse type and value of an attribute (pos tag), a font or a
+ * color.
+ */
+ void parseAttribute( const TQString &, int &, enum DataType & );
+ void parseFont( const TQString &, TQFont & );
+ void parseColor( const TQString &, TQColor & );
+
+ void inheritFromButton( KdmItem *button );
+ void init( const TQDomNode &node = TQDomNode(), const char *name = 0 );
+
+ TQString itemType, id;
+ TQValueList<KdmItem *> m_children;
+
+ int m_backgroundModifier;
+
+ // Layouting related variables
+ enum { MNone = 0, MFixed = 1, MBox = 2 } currentManager;
+ KdmLayoutBox *boxManager;
+ KdmLayoutFixed *fixedManager;
+
+ // Compositing related variables
+ TQImage *image;
+
+ // defines the directory the theme is in (may be present in the parent)
+ TQString basedir;
+
+ TQWidget *myWidget;
+ TQLayoutItem *myLayoutItem;
+
+ enum { InitialHidden, ExplicitlyHidden, Shown } isShown;
+
+ KdmItem *buttonParent;
+};
+
+#endif
diff --git a/tdm/kfrontend/themer/tdmlabel.cpp b/tdm/kfrontend/themer/tdmlabel.cpp
new file mode 100644
index 000000000..5239d48dc
--- /dev/null
+++ b/tdm/kfrontend/themer/tdmlabel.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2003 by Unai Garro <[email protected]>
+ * Copyright (C) 2004 by Enrico Ros <[email protected]>
+ * Copyright (C) 2004 by Stephan Kulow <[email protected]>
+ * Copyright (C) 2004 by Oswald Buddenhagen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+#include "tdmlabel.h"
+#include "tdmconfig.h"
+#include "../kgreeter.h"
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kmacroexpander.h>
+#include <kdebug.h>
+
+#include <tqdatetime.h>
+#include <tqpainter.h>
+#include <tqfontmetrics.h>
+#include <tqtimer.h>
+#include <tqaccel.h>
+
+#include <unistd.h>
+#include <sys/utsname.h>
+#if !defined(HAVE_GETDOMAINNAME) && defined(HAVE_SYSINFO)
+# include <sys/systeminfo.h>
+#endif
+
+KdmLabel::KdmLabel( KdmItem *parent, const TQDomNode &node, const char *name )
+ : KdmItem( parent, node, name ), myAccel(0)
+{
+ itemType = "label";
+
+ // Set default values for label (note: strings are already Null)
+ label.active.color.setRgb( 0xFFFFFF );
+ label.active.present = false;
+ label.prelight.present = false;
+ label.maximumWidth = -1;
+
+ const TQString locale = KGlobal::locale()->language();
+
+ // Read LABEL ID
+ TQDomNode n = node;
+ TQDomElement elLab = n.toElement();
+ // ID types: clock, pam-error, pam-message, pam-prompt,
+ // pam-warning, timed-label
+ label.id = elLab.attribute( "id", "" );
+ label.hasId = !(label.id).isEmpty();
+
+ // Read LABEL TAGS
+ TQDomNodeList childList = node.childNodes();
+ bool stockUsed = false;
+ for (uint nod = 0; nod < childList.count(); nod++) {
+ TQDomNode child = childList.item( nod );
+ TQDomElement el = child.toElement();
+ TQString tagName = el.tagName();
+
+ if (tagName == "pos")
+ label.maximumWidth = el.attribute( "max-width", "-1" ).toInt();
+ else if (tagName == "normal") {
+ parseColor( el.attribute( "color", "#ffffff" ), label.normal.color );
+ parseFont( el.attribute( "font", "Sans 14" ), label.normal.font );
+ } else if (tagName == "active") {
+ label.active.present = true;
+ parseColor( el.attribute( "color", "#ffffff" ), label.active.color );
+ parseFont( el.attribute( "font", "Sans 14" ), label.active.font );
+ } else if (tagName == "prelight") {
+ label.prelight.present = true;
+ parseColor( el.attribute( "color", "#ffffff" ), label.prelight.color );
+ parseFont( el.attribute( "font", "Sans 14" ), label.prelight.font );
+ } else if (tagName == "text" && el.attributes().count() == 0 && !stockUsed) {
+ label.text = el.text();
+ } else if (tagName == "text" && !stockUsed) {
+ TQString lang = el.attribute( "xml:lang", "" );
+ if (lang == locale)
+ label.text = el.text();
+ } else if (tagName == "stock") {
+ label.text = lookupStock( el.attribute( "type", "" ) );
+ stockUsed = true;
+ }
+ }
+
+ // Check if this is a timer label)
+ label.isTimer = label.text.find( "%c" ) >= 0;
+ if (label.isTimer) {
+ timer = new TQTimer( this );
+ timer->start( 1000 );
+ connect( timer, TQT_SIGNAL(timeout()), TQT_SLOT(update()) );
+ }
+ setTextInt( lookupText( label.text ) );
+}
+
+void
+KdmLabel::setTextInt( const TQString &txt)
+{
+ // TODO: catch &&
+ cText = txt;
+ cAccel = txt.find('&');
+ delete myAccel;
+ myAccel = 0;
+ if (cAccel != -1) {
+ cText.remove('&');
+ myAccel = new TQAccel(parentWidget());
+ myAccel->insertItem(ALT + UNICODE_ACCEL + cText.at(cAccel).lower().unicode());
+ connect(myAccel, TQT_SIGNAL(activated(int)), TQT_SLOT(slotAccel()));
+ }
+}
+
+void
+KdmLabel::slotAccel()
+{
+ if (buttonParent)
+ emit activated(buttonParent->getId());
+ else
+ emit activated(id);
+}
+
+void
+KdmLabel::setText( const TQString &txt )
+{
+ label.text = txt;
+ setTextInt( lookupText( label.text ) );
+}
+
+TQSize
+KdmLabel::sizeHint()
+{
+ // choose the correct label class
+ struct LabelStruct::LabelClass *l = &label.normal;
+ if (state == Sactive && label.active.present)
+ l = &label.active;
+ else if (state == Sprelight && label.prelight.present)
+ l = &label.prelight;
+ // get the hint from font metrics
+ TQSize hint = TQFontMetrics( l->font ).size( AlignLeft | SingleLine, cText );
+ // clip the result using the max-width label(pos) parameter
+ if (label.maximumWidth > 0 && hint.width() > label.maximumWidth)
+ hint.setWidth( label.maximumWidth );
+ return hint;
+}
+
+void
+KdmLabel::drawContents( TQPainter *p, const TQRect &/*r*/ )
+{
+ // choose the correct label class
+ struct LabelStruct::LabelClass *l = &label.normal;
+ if (state == Sactive && label.active.present)
+ l = &label.active;
+ else if (state == Sprelight && label.prelight.present)
+ l = &label.prelight;
+ // draw the label
+ p->setFont( l->font );
+ p->setPen( l->color );
+ //TODO paint clipped (tested but not working..)
+ if (cAccel != -1 && (!id.isEmpty() || buttonParent) ) {
+ TQString left = cText.left(cAccel);
+ TQString right = cText.mid(cAccel + 1);
+ p->drawText( area, AlignLeft | SingleLine, left );
+ TQRect tarea = area;
+ TQFontMetrics fm(l->font);
+ tarea.rLeft() += fm.width(left);
+ TQFont f(l->font);
+ f.setUnderline(true);
+ p->setFont ( f );
+ p->drawText( tarea, AlignLeft | SingleLine, TQString(cText.at(cAccel)));
+ tarea.rLeft() += fm.width(cText.at(cAccel));
+ p->setFont( l->font );
+ p->drawText( tarea, AlignLeft | SingleLine, right);
+ } else {
+ p->drawText( area, AlignLeft | SingleLine, cText);
+ }
+}
+
+void
+KdmLabel::statusChanged()
+{
+ KdmItem::statusChanged();
+ if (!label.active.present && !label.prelight.present)
+ return;
+ if ((state == Sprelight && !label.prelight.present) ||
+ (state == Sactive && !label.active.present))
+ return;
+ needUpdate();
+}
+
+void
+KdmLabel::update()
+{
+ TQString text = lookupText( label.text );
+ if (text != cText) {
+ setTextInt(text);
+ needUpdate();
+ }
+}
+
+static const struct {
+ const char *type, *text;
+} stocks[] = {
+ { "language", I18N_NOOP("Language") },
+ { "session", I18N_NOOP("Session Type") },
+ { "system", I18N_NOOP("Menu") }, // i18n("Actions");
+ { "admin", I18N_NOOP("&Administration") },
+ { "disconnect", I18N_NOOP("Disconnect") },
+ { "quit", I18N_NOOP("Quit") },
+ { "halt", I18N_NOOP("Power Off") },
+ { "suspend", I18N_NOOP("Suspend") },
+ { "reboot", I18N_NOOP("Reboot") },
+ { "chooser", I18N_NOOP("XDMCP Chooser") },
+ { "config", I18N_NOOP("Configure") },
+ { "caps-lock-warning", I18N_NOOP("Caps Lock is enabled.") },
+ { "timed-label", I18N_NOOP("User %s will login in %d seconds") },
+ { "welcome-label", I18N_NOOP("Welcome to %h") }, // _greetString
+ { "username-label", I18N_NOOP("Username:") },
+ { "password-label", I18N_NOOP("Password:") },
+ { "domain-label", I18N_NOOP("Domain:") },
+ { "login", I18N_NOOP("Login") }
+};
+
+TQString
+KdmLabel::lookupStock( const TQString &stock )
+{
+ //FIXME add key accels!
+ TQString type( stock.lower() );
+
+ for (uint i = 0; i < sizeof(stocks)/sizeof(stocks[0]); i++)
+ if (type == stocks[i].type)
+ return i18n(stocks[i].text);
+
+ kdDebug() << timestamp() << " Invalid <stock> element. Check your theme!" << endl;
+ return stock;
+}
+
+TQString
+KdmLabel::lookupText( const TQString &t )
+{
+ TQString text = t;
+
+ text.replace( '_', '&' );
+
+ TQMap<TQChar,TQString> m;
+ struct utsname uts;
+ uname( &uts );
+ m['n'] = TQString::fromLocal8Bit( uts.nodename );
+ char buf[256];
+ buf[sizeof(buf) - 1] = '\0';
+ m['h'] = gethostname( buf, sizeof(buf) - 1 ) ? "localhost" : TQString::fromLocal8Bit( buf );
+#ifdef HAVE_GETDOMAINNAME
+ m['o'] = getdomainname( buf, sizeof(buf) - 1 ) ? "localdomain" : TQString::fromLocal8Bit( buf );
+#elif defined(HAVE_SYSINFO)
+ m['o'] = (unsigned)sysinfo( SI_SRPC_DOMAIN, buf, sizeof(buf) ) > sizeof(buf) ? "localdomain" : TQString::fromLocal8Bit( buf );
+#endif
+ m['d'] = TQString::number( KThemedGreeter::timedDelay );
+ m['s'] = KThemedGreeter::timedUser;
+ // xgettext:no-c-format
+ KGlobal::locale()->setDateFormat( i18n("date format", "%a %d %B") );
+ m['c'] = KGlobal::locale()->formatDateTime( TQDateTime::currentDateTime(), false, false );
+
+ return KMacroExpander::expandMacros( text, m );
+}
+
+#include "tdmlabel.moc"
diff --git a/tdm/kfrontend/themer/tdmlabel.h b/tdm/kfrontend/themer/tdmlabel.h
new file mode 100644
index 000000000..8b955fca5
--- /dev/null
+++ b/tdm/kfrontend/themer/tdmlabel.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2003 by Unai Garro <[email protected]>
+ * Copyright (C) 2004 by Enrico Ros <[email protected]>
+ * Copyright (C) 2004 by Stephan Kulow <[email protected]>
+ * Copyright (C) 2004 by Oswald Buddenhagen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KDELABEL_H
+#define KDELABEL_H
+
+#include "tdmitem.h"
+
+#include <tqcolor.h>
+#include <tqfont.h>
+
+class TQTimer;
+
+/*
+ * KdmLabel. A label element
+ */
+
+class KdmLabel : public KdmItem {
+ Q_OBJECT
+
+public:
+ KdmLabel( KdmItem *parent, const TQDomNode &node, const char *name = 0 );
+ void setText( const TQString &txt );
+
+protected:
+ // reimplemented; returns the minimum size of rendered text
+ virtual TQSize sizeHint();
+
+ // draw the label
+ virtual void drawContents( TQPainter *p, const TQRect &r );
+
+ // handle switching between normal / active / prelight configurations
+ virtual void statusChanged();
+
+public:
+ struct LabelStruct {
+ TQString text;
+ bool isTimer;
+ bool hasId;
+ TQString id;
+ struct LabelClass {
+ TQColor color;
+ TQFont font;
+ bool present;
+ } normal, active, prelight;
+ int maximumWidth;
+ } label;
+
+ TQTimer *timer;
+
+public slots:
+ void update();
+ void slotAccel();
+
+private:
+ /* Method to lookup the caption associated with an item */
+ TQString lookupStock( const TQString &stock );
+
+ /* Lookup variables in the text */
+ TQString lookupText( const TQString &t );
+
+ TQString cText;
+ int cAccel;
+ TQAccel *myAccel;
+
+ void setTextInt(const TQString &);
+};
+
+#endif
diff --git a/tdm/kfrontend/themer/tdmlayout.cpp b/tdm/kfrontend/themer/tdmlayout.cpp
new file mode 100644
index 000000000..9a277a7a3
--- /dev/null
+++ b/tdm/kfrontend/themer/tdmlayout.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2003 by Unai Garro <[email protected]>
+ * Copyright (C) 2004 by Enrico Ros <[email protected]>
+ * Copyright (C) 2004 by Stephan Kulow <[email protected]>
+ * Copyright (C) 2004 by Oswald Buddenhagen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "tdmlayout.h"
+#include "tdmconfig.h"
+#include "tdmitem.h"
+
+#include <kdebug.h>
+
+#include <tqdom.h>
+#include <tqrect.h>
+
+KdmLayoutFixed::KdmLayoutFixed( const TQDomNode &/*node*/ )
+{
+ //Parsing FIXED parameters on 'node' [NONE!]
+}
+
+void
+KdmLayoutFixed::update( const TQRect &parentGeometry, bool force )
+{
+ kdDebug() << timestamp() << " KdmLayoutFixed::update " << parentGeometry << endl;
+
+ // I can't layout children if the parent rectangle is not valid
+ if (parentGeometry.width() < 0 || parentGeometry.height() < 0) {
+ kdDebug() << timestamp() << " invalid\n";
+ return;
+ }
+ // For each child in list I ask their hinted size and set it!
+ for (TQValueList<KdmItem *>::ConstIterator it = m_children.begin(); it != m_children.end(); ++it)
+ (*it)->setGeometry( (*it)->placementHint( parentGeometry ), force );
+}
+
+KdmLayoutBox::KdmLayoutBox( const TQDomNode &node )
+{
+ //Parsing BOX parameters
+ TQDomNode n = node;
+ TQDomElement el = n.toElement();
+ box.isVertical = el.attribute( "orientation", "vertical" ) != "horizontal";
+ box.xpadding = el.attribute( "xpadding", "0" ).toInt();
+ box.ypadding = el.attribute( "ypadding", "0" ).toInt();
+ box.spacing = el.attribute( "spacing", "0" ).toInt();
+ box.minwidth = el.attribute( "min-width", "0" ).toInt();
+ box.minheight = el.attribute( "min-height", "0" ).toInt();
+ box.homogeneous = el.attribute( "homogeneous", "false" ) == "true";
+}
+
+void
+KdmLayoutBox::update( const TQRect &parentGeometry, bool force )
+{
+ kdDebug() << this << " update " << parentGeometry << endl;
+
+ // I can't layout children if the parent rectangle is not valid
+ if (!parentGeometry.isValid() || parentGeometry.isEmpty())
+ return;
+
+ // Check if box size was computed. If not compute it
+ // TODO check if this prevents updating changing items
+// if (!hintedSize.isValid())
+// sizeHint();
+
+// kdDebug() << this << " hintedSize " << hintedSize << endl;
+
+ //XXX why was this asymmetric? it broke things big time.
+ TQRect childrenRect = /*box.isVertical ? TQRect( parentGeometry.topLeft(), hintedSize ) :*/ parentGeometry;
+ // Begin cutting the parent rectangle to attach children on the right place
+ childrenRect.addCoords( box.xpadding, box.ypadding, -box.xpadding, -box.ypadding );
+
+ kdDebug() << this << " childrenRect " << childrenRect << endl;
+
+ // For each child in list ...
+ if (box.homogeneous) {
+ int ccnt = 0;
+ for (TQValueList<KdmItem *>::ConstIterator it = m_children.begin(); it != m_children.end(); ++it)
+ if (!(*it)->isExplicitlyHidden())
+ ccnt++;
+ int height = (childrenRect.height() - (ccnt - 1) * box.spacing) / ccnt;
+ int width = (childrenRect.width() - (ccnt - 1) * box.spacing) / ccnt;
+
+ for (TQValueList<KdmItem *>::ConstIterator it = m_children.begin(); it != m_children.end(); ++it) {
+ if ((*it)->isExplicitlyHidden())
+ continue;
+ if (box.isVertical) {
+ TQRect temp( childrenRect.left(), childrenRect.top(), childrenRect.width(), height );
+ (*it)->setGeometry( temp, force );
+ childrenRect.setTop( childrenRect.top() + height + box.spacing );
+ } else {
+ TQRect temp( childrenRect.left(), childrenRect.top(), width, childrenRect.height() );
+ kdDebug() << timestamp() << " placement " << *it << " " << temp << " " << (*it)->placementHint( temp ) << endl;
+ temp = (*it)->placementHint( temp );
+ (*it)->setGeometry( temp, force );
+ childrenRect.setLeft( childrenRect.left() + width + box.spacing );
+ }
+ }
+ } else {
+ for (TQValueList<KdmItem *>::ConstIterator it = m_children.begin(); it != m_children.end(); ++it) {
+ if ((*it)->isExplicitlyHidden())
+ continue;
+
+ TQRect temp = childrenRect, itemRect;
+ if (box.isVertical) {
+ temp.setHeight( 0 );
+ itemRect = (*it)->placementHint( temp );
+ temp.setHeight( itemRect.height() );
+ childrenRect.setTop( childrenRect.top() + itemRect.size().height() + box.spacing );
+ } else {
+ temp.setWidth( 0 );
+ itemRect = (*it)->placementHint( temp );
+ kdDebug() << this << " placementHint " << *it << " " << temp << " " << itemRect << endl;
+ temp.setWidth( itemRect.width() );
+ childrenRect.setLeft( childrenRect.left() + itemRect.size().width() + box.spacing );
+ kdDebug() << timestamp() << " childrenRect after " << *it << " " << childrenRect << endl;
+ }
+ itemRect = (*it)->placementHint( temp );
+ kdDebug() << this << " placementHint2 " << *it << " " << temp << " " << itemRect << endl;
+ (*it)->setGeometry( itemRect, force );
+ }
+ }
+}
+
+//FIXME truly experimental (is so close to greeter_geometry.c)
+TQSize
+KdmLayoutBox::sizeHint()
+{
+ // Sum up area taken by children
+ int w = 0, h = 0;
+ for (TQValueList<KdmItem *>::ConstIterator it = m_children.begin(); it != m_children.end(); ++it) {
+ TQSize s = (*it)->placementHint( TQRect() ).size();
+ if (box.isVertical) {
+ if (s.width() > w)
+ w = s.width();
+ h += s.height();
+ } else {
+ if (s.height() > h)
+ h = s.height();
+ w += s.width();
+ }
+ }
+
+ // Add padding and items spacing
+ w += 2 * box.xpadding;
+ h += 2 * box.ypadding;
+ if (box.isVertical)
+ h += box.spacing * (m_children.count() - 1);
+ else
+ w += box.spacing * (m_children.count() - 1);
+
+ // Make hint at least equal to minimum size (if set)
+ return TQSize( w < box.minwidth ? box.minwidth : w,
+ h < box.minheight ? box.minheight : h );
+}
diff --git a/tdm/kfrontend/themer/tdmlayout.h b/tdm/kfrontend/themer/tdmlayout.h
new file mode 100644
index 000000000..c147fd329
--- /dev/null
+++ b/tdm/kfrontend/themer/tdmlayout.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2003 by Unai Garro <[email protected]>
+ * Copyright (C) 2004 by Enrico Ros <[email protected]>
+ * Copyright (C) 2004 by Stephan Kulow <[email protected]>
+ * Copyright (C) 2004 by Oswald Buddenhagen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TDMLAYOUT_H
+#define TDMLAYOUT_H
+
+/**
+ * this is a container for a lot of other stuff
+ * but can be treated like a usual widget
+ */
+
+#include <tqvaluelist.h>
+#include <tqsize.h>
+
+class KdmItem;
+
+class TQDomNode;
+class TQRect;
+
+class KdmLayout {
+
+public:
+// virtual ~KdmLayout() {};
+
+ // Adds an item that will be managed
+ void addItem( KdmItem *item ) { m_children.append( item ); }
+
+ // Return false if any item are managed by this layouter
+ bool isEmpty() { return m_children.isEmpty(); }
+
+ // Updates the layout of all items knowing that the parent
+ // has the @p parentGeometry geometry
+// virtual void update( const TQRect &parentGeometry ) = 0;
+
+protected:
+ TQValueList<KdmItem *> m_children;
+};
+
+class KdmLayoutFixed : public KdmLayout {
+
+public:
+ KdmLayoutFixed( const TQDomNode &node );
+
+ // Updates the layout of all boxed items knowing that the parent
+ // has the @p parentGeometry geometry
+ void update( const TQRect &parentGeometry, bool force );
+};
+
+/**
+ * this is a container for a lot of other stuff
+ * but can be treated like a usual widget
+ */
+
+class KdmLayoutBox : public KdmLayout {
+
+public:
+ KdmLayoutBox( const TQDomNode &node );
+
+ // Updates the layout of all boxed items knowing that they
+ // should fit into @p parentGeometry container
+ void update( const TQRect &parentGeometry, bool force );
+
+ // Computes the size hint of the box, telling which is the
+ // smallest size inside which boxed items will fit
+ TQSize sizeHint();
+
+private:
+ struct {
+ bool isVertical;
+ int spacing;
+ int xpadding;
+ int ypadding;
+ int minwidth;
+ int minheight;
+ bool homogeneous;
+ } box;
+// TQSize hintedSize;
+};
+
+#endif
diff --git a/tdm/kfrontend/themer/tdmpixmap.cpp b/tdm/kfrontend/themer/tdmpixmap.cpp
new file mode 100644
index 000000000..7a8d1a3d2
--- /dev/null
+++ b/tdm/kfrontend/themer/tdmpixmap.cpp
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2003 by Unai Garro <[email protected]>
+ * Copyright (C) 2004 by Enrico Ros <[email protected]>
+ * Copyright (C) 2004 by Stephan Kulow <[email protected]>
+ * Copyright (C) 2004 by Oswald Buddenhagen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+
+#include "tdmpixmap.h"
+#include <tdmconfig.h>
+
+#include <kimageeffect.h>
+#ifdef HAVE_LIBART
+#include <ksvgiconengine.h>
+#endif
+
+#include <kdebug.h>
+#include <kstandarddirs.h>
+
+#include <tqfile.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqimage.h>
+
+extern bool argb_visual_available;
+
+KdmPixmap::KdmPixmap( KdmItem *parent, const TQDomNode &node, const char *name )
+ : KdmItem( parent, node, name )
+{
+ itemType = "pixmap";
+
+ // Set default values for pixmap (note: strings are already Null)
+ pixmap.normal.tint.setRgb( 0x800000 );
+ pixmap.normal.alpha = 0.0;
+ pixmap.active.present = false;
+ pixmap.prelight.present = false;
+ bool true_transparency = false;
+
+ // Read PIXMAP ID
+ // it rarely happens that a pixmap can be a button too!
+ TQDomNode n = node;
+ TQDomElement elPix = n.toElement();
+
+ // Read PIXMAP TAGS
+ TQDomNodeList childList = node.childNodes();
+ for (uint nod = 0; nod < childList.count(); nod++) {
+ TQDomNode child = childList.item( nod );
+ TQDomElement el = child.toElement();
+ TQString tagName = el.tagName();
+
+ if (tagName == "normal") {
+ pixmap.normal.fullpath = fullPath( el.attribute( "file", "" ) );
+ parseColor( el.attribute( "tint", "#ffffff" ), pixmap.normal.tint );
+ pixmap.normal.alpha = el.attribute( "alpha", "1.0" ).toFloat();
+
+ if (el.attribute( "file", "" ) == "@@@TDMBACKGROUND@@@") {
+ if ((_compositor.isEmpty()) || (!argb_visual_available)) {
+ // Software blend only (no compositing support)
+ // Use the preset TDM background...
+ KStandardDirs *m_pDirs = KGlobal::dirs();
+ KSimpleConfig *config = new KSimpleConfig( TQFile::decodeName( _backgroundCfg ) );
+ config->setGroup("Desktop0");
+ pixmap.normal.fullpath = m_pDirs->findResource("wallpaper", config->readPathEntry("Wallpaper"));
+ // TODO: Detect when there is no wallpaper and use the background settings instead
+ delete config;
+ }
+ else {
+ true_transparency = true;
+ pixmap.normal.alpha = 0.0;
+ }
+ }
+
+ } else if (tagName == "active") {
+ pixmap.active.present = true;
+ pixmap.active.fullpath = fullPath( el.attribute( "file", "" ) );
+ parseColor( el.attribute( "tint", "#ffffff" ), pixmap.active.tint );
+ pixmap.active.alpha = el.attribute( "alpha", "1.0" ).toFloat();
+ } else if (tagName == "prelight") {
+ pixmap.prelight.present = true;
+ pixmap.prelight.fullpath = fullPath(el.attribute( "file", "" ) );
+ parseColor( el.attribute( "tint", "#ffffff" ), pixmap.prelight.tint );
+ pixmap.prelight.alpha = el.attribute( "alpha", "1.0" ).toFloat();
+ }
+ }
+
+ // look if we have to have the aspect ratio ready
+ if (((pos.wType == DTnone && pos.hType != DTnone) ||
+ (pos.wType != DTnone && pos.hType == DTnone) ||
+ (pos.wType == DTnone && pos.hType == DTnone)) &&
+ !pixmap.normal.fullpath.endsWith( ".svg" ))
+ loadPixmap( &pixmap.normal );
+}
+
+TQSize
+KdmPixmap::sizeHint()
+{
+ // choose the correct pixmap class
+ PixmapStruct::PixmapClass * pClass = &pixmap.normal;
+ if (state == Sactive && pixmap.active.present)
+ pClass = &pixmap.active;
+ if (state == Sprelight && pixmap.prelight.present)
+ pClass = &pixmap.prelight;
+ // use the pixmap size as the size hint
+ if (!pClass->pixmap.isNull())
+ return pClass->pixmap.size();
+ return KdmItem::sizeHint();
+}
+
+void
+KdmPixmap::setGeometry( const TQRect &newGeometry, bool force )
+{
+ KdmItem::setGeometry( newGeometry, force );
+ pixmap.active.readyPixmap.resize( 0, 0 );
+ pixmap.prelight.readyPixmap.resize( 0, 0 );
+ pixmap.normal.readyPixmap.resize( 0, 0 );
+}
+
+
+TQString
+KdmPixmap::fullPath( const TQString &fileName)
+{
+ if (fileName.isEmpty())
+ return TQString::null;
+
+ TQString fullName = fileName;
+ if (fullName.at( 0 ) != '/')
+ fullName = baseDir() + "/" + fileName;
+ return fullName;
+}
+
+void
+KdmPixmap::renderSvg( PixmapStruct::PixmapClass *pClass, const TQRect &area )
+{
+#ifdef HAVE_LIBART
+ // Special stuff for SVG icons
+ KSVGIconEngine *svgEngine = new KSVGIconEngine();
+
+ if (svgEngine->load( area.width(), area.height(), pClass->fullpath )) {
+ TQImage *t = svgEngine->image();
+ pClass->pixmap = *t;
+ pClass->readyPixmap.resize( 0, 0 );
+ delete t;
+ } else {
+ kdWarning() << "failed to load " << pClass->fullpath << endl;
+ pClass->fullpath = TQString::null;
+ }
+
+ delete svgEngine;
+#else
+ Q_UNUSED(pClass);
+ Q_UNUSED(area);
+#endif
+}
+
+void
+KdmPixmap::loadPixmap( PixmapStruct::PixmapClass *pClass )
+{
+ TQString fullpath = pClass->fullpath;
+
+ kdDebug() << timestamp() << " load " << fullpath << endl;
+ int index = fullpath.findRev('.');
+ TQString ext = fullpath.right(fullpath.length() - index);
+ fullpath = fullpath.left(index);
+ kdDebug() << timestamp() << " ext " << ext << " " << fullpath << endl;
+ TQString testpath = TQString("-%1x%2").arg(area.width()).arg(area.height()) + ext;
+ kdDebug() << timestamp() << " testing for " << fullpath + testpath << endl;
+ if (KStandardDirs::exists(fullpath + testpath))
+ pClass->pixmap.load(fullpath + testpath);
+ else
+ pClass->pixmap.load( fullpath + ext );
+ kdDebug() << timestamp() << " done\n";
+}
+
+void
+KdmPixmap::drawContents( TQPainter *p, const TQRect &r )
+{
+ // choose the correct pixmap class
+ PixmapStruct::PixmapClass *pClass = &pixmap.normal;
+ if (state == Sactive && pixmap.active.present)
+ pClass = &pixmap.active;
+ if (state == Sprelight && pixmap.prelight.present)
+ pClass = &pixmap.prelight;
+
+ kdDebug() << "draw " << id << " " << pClass->pixmap.isNull() << endl;
+
+ if (pClass->pixmap.isNull()) {
+ if (pClass->fullpath.isEmpty()) // if neither is set, we're empty
+ return;
+
+ if (!pClass->fullpath.endsWith( ".svg" ) ) {
+ loadPixmap(pClass);
+ } else {
+ kdDebug() << timestamp() << " renderSVG\n";
+ renderSvg( pClass, area );
+ kdDebug() << timestamp() << " done\n";
+ }
+ }
+
+ int px = area.left() + r.left();
+ int py = area.top() + r.top();
+ int sx = r.x();
+ int sy = r.y();
+ int sw = r.width();
+ int sh = r.height();
+ if (px < 0) {
+ px *= -1;
+ sx += px;
+ px = 0;
+ }
+ if (py < 0) {
+ py *= -1;
+ sy += py;
+ py = 0;
+ }
+
+
+ if (pClass->readyPixmap.isNull()) {
+
+ bool haveTint = pClass->tint.rgb() != 0xFFFFFF;
+ bool haveAlpha = pClass->alpha < 1.0;
+
+ TQImage scaledImage;
+
+ // use the loaded pixmap or a scaled version if needed
+
+ kdDebug() << timestamp() << " prepare readyPixmap " << pClass->fullpath << " " << area.size() << " " << pClass->pixmap.size() << endl;
+ if (area.size() != pClass->pixmap.size()) {
+ if (pClass->fullpath.endsWith( ".svg" )) {
+ kdDebug() << timestamp() << " renderSVG\n";
+ renderSvg( pClass, area );
+ scaledImage = pClass->pixmap.convertToImage();
+ } else {
+ kdDebug() << timestamp() << " convertFromImage smoothscale\n";
+ if (pClass->pixmap.isNull()) {
+ scaledImage = TQImage();
+ }
+ else {
+ TQImage tempImage = pClass->pixmap.convertToImage();
+ kdDebug() << timestamp() << " convertToImage done\n";
+ scaledImage = tempImage.smoothScale( area.width(), area.height() );
+ }
+ kdDebug() << timestamp() << " done\n";
+ }
+ } else {
+ if (haveTint || haveAlpha)
+ {
+ scaledImage = pClass->pixmap.convertToImage();
+ // enforce rgba values for the latter
+ if (!scaledImage.isNull()) scaledImage = scaledImage.convertDepth( 32 );
+ }
+ else
+ pClass->readyPixmap = pClass->pixmap;
+ }
+
+ if (haveTint || haveAlpha) {
+ // blend image(pix) with the given tint
+
+ if (!scaledImage.isNull()) scaledImage = scaledImage.convertDepth( 32 );
+ int w = scaledImage.width();
+ int h = scaledImage.height();
+ float tint_red = float( pClass->tint.red() ) / 255;
+ float tint_green = float( pClass->tint.green() ) / 255;
+ float tint_blue = float( pClass->tint.blue() ) / 255;
+ float tint_alpha = pClass->alpha;
+
+ for (int y = 0; y < h; ++y) {
+ QRgb *ls = (QRgb *)scaledImage.scanLine( y );
+ for (int x = 0; x < w; ++x) {
+ QRgb l = ls[x];
+ int r = int( tqRed( l ) * tint_red );
+ int g = int( tqGreen( l ) * tint_green );
+ int b = int( tqBlue( l ) * tint_blue );
+ int a = int( tqAlpha( l ) * tint_alpha );
+ ls[x] = tqRgba( r, g, b, a );
+ }
+ }
+ }
+ if ((_compositor.isEmpty()) || (!argb_visual_available)) {
+ // Software blend only (no compositing support)
+ }
+ else {
+ // We have a compositor!
+ // Apply the alpha in the same manner as above, exept we are now
+ // using the hardware blending engine for all painting
+ scaledImage = pClass->readyPixmap;
+ if (!scaledImage.isNull()) scaledImage = scaledImage.convertDepth( 32 );
+ int w = scaledImage.width();
+ int h = scaledImage.height();
+
+ for (int y = 0; y < h; ++y) {
+ QRgb *ls = (QRgb *)scaledImage.scanLine( y );
+ for (int x = 0; x < w; ++x) {
+ QRgb l = ls[x];
+ float alpha_adjust = (tqAlpha( l )/256.0);
+ int r = int( tqRed( l ) * alpha_adjust );
+ int g = int( tqGreen( l ) * alpha_adjust );
+ int b = int( tqBlue( l ) * alpha_adjust );
+ int a = int( tqAlpha( l ) * 1 );
+ ls[x] = tqRgba( r, g, b, a );
+ }
+ }
+ }
+
+ if (!scaledImage.isNull()) {
+ kdDebug() << timestamp() << " convertFromImage " << id << " " << area << endl;
+ pClass->readyPixmap.convertFromImage( scaledImage );
+ }
+ }
+ kdDebug() << timestamp() << " Pixmap::drawContents " << pClass->readyPixmap.size() << " " << px << " " << py << " " << sx << " " << sy << " " << sw << " " << sh << endl;
+ p->drawPixmap( px, py, pClass->readyPixmap, sx, sy, sw, sh );
+}
+
+void
+KdmPixmap::statusChanged()
+{
+ KdmItem::statusChanged();
+ if (!pixmap.active.present && !pixmap.prelight.present)
+ return;
+ if ((state == Sprelight && !pixmap.prelight.present) ||
+ (state == Sactive && !pixmap.active.present))
+ return;
+ needUpdate();
+}
+
+#include "tdmpixmap.moc"
diff --git a/tdm/kfrontend/themer/tdmpixmap.h b/tdm/kfrontend/themer/tdmpixmap.h
new file mode 100644
index 000000000..faa71a034
--- /dev/null
+++ b/tdm/kfrontend/themer/tdmpixmap.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2003 by Unai Garro <[email protected]>
+ * Copyright (C) 2004 by Enrico Ros <[email protected]>
+ * Copyright (C) 2004 by Stephan Kulow <[email protected]>
+ * Copyright (C) 2004 by Oswald Buddenhagen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TDMPIXMAP_H
+#define TDMPIXMAP_H
+
+#include "tdmitem.h"
+
+//#include <tqrect.h>
+#include <tqpixmap.h>
+
+#include <ksimpleconfig.h>
+#include <kstandarddirs.h>
+
+/*
+ * KdmPixmap. A pixmap element
+ */
+
+class KdmPixmap : public KdmItem {
+ Q_OBJECT
+
+public:
+ KdmPixmap( KdmItem *parent, const TQDomNode &node, const char *name = 0 );
+
+protected:
+ // reimplemented; returns the size of loaded pixmap
+ virtual TQSize sizeHint();
+
+ // draw the pixmap
+ virtual void drawContents( TQPainter *p, const TQRect &r );
+
+ // handle switching between normal / active / prelight configurations
+ virtual void statusChanged();
+
+ virtual void setGeometry( const TQRect &newGeometry, bool force );
+
+ struct PixmapStruct {
+ struct PixmapClass {
+ TQString fullpath;
+ TQPixmap pixmap;
+ TQPixmap readyPixmap;
+ TQColor tint;
+ float alpha; //TODO added: not in greeter.dtd
+ bool present;
+ } normal, active, prelight;
+ } pixmap;
+
+private:
+ // Method to load the pixmap path given by the theme
+ TQString fullPath( const TQString &fileName );
+ void renderSvg( PixmapStruct::PixmapClass *pClass, const TQRect &area );
+ void loadPixmap( PixmapStruct::PixmapClass *pClass );
+};
+
+#endif
diff --git a/tdm/kfrontend/themer/tdmrect.cpp b/tdm/kfrontend/themer/tdmrect.cpp
new file mode 100644
index 000000000..9056a513c
--- /dev/null
+++ b/tdm/kfrontend/themer/tdmrect.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2003 by Unai Garro <[email protected]>
+ * Copyright (C) 2004 by Enrico Ros <[email protected]>
+ * Copyright (C) 2004 by Stephan Kulow <[email protected]>
+ * Copyright (C) 2004 by Oswald Buddenhagen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "tdmrect.h"
+#include "tdmthemer.h"
+#include "tdmconfig.h"
+
+#include <kimageeffect.h>
+#include <kdebug.h>
+
+#include <tqimage.h>
+#include <tqpainter.h>
+#include <tqwidget.h>
+#include <tqlayout.h>
+
+extern bool argb_visual_available;
+
+KdmRect::KdmRect( KdmItem *parent, const TQDomNode &node, const char *name )
+ : KdmItem( parent, node, name )
+{
+ init( node, name );
+}
+
+KdmRect::KdmRect( TQWidget *parent, const TQDomNode &node, const char *name )
+ : KdmItem( parent, node, name )
+{
+ init( node, name );
+}
+
+void
+KdmRect::init( const TQDomNode &node, const char * )
+{
+ itemType = "rect";
+
+ // Set default values for rect (note: strings are already Null)
+ rect.normal.alpha = 1;
+ rect.active.present = false;
+ rect.prelight.present = false;
+ rect.hasBorder = false;
+
+ // A rect can have no properties (defaults to parent ones)
+ if (node.isNull())
+ return;
+
+ // Read RECT ID
+ TQDomNode n = node;
+ TQDomElement elRect = n.toElement();
+
+ // Read RECT TAGS
+ TQDomNodeList childList = node.childNodes();
+ for (uint nod = 0; nod < childList.count(); nod++) {
+ TQDomNode child = childList.item( nod );
+ TQDomElement el = child.toElement();
+ TQString tagName = el.tagName();
+
+ if (tagName == "normal") {
+ parseColor( el.attribute( "color", TQString::null ), rect.normal.color );
+ rect.normal.alpha = el.attribute( "alpha", "1.0" ).toFloat();
+ parseFont( el.attribute( "font", "Sans 14" ), rect.normal.font );
+ } else if (tagName == "active") {
+ rect.active.present = true;
+ parseColor( el.attribute( "color", TQString::null ), rect.active.color );
+ rect.active.alpha = el.attribute( "alpha", "1.0" ).toFloat();
+ parseFont( el.attribute( "font", "Sans 14" ), rect.active.font );
+ } else if (tagName == "prelight") {
+ rect.prelight.present = true;
+ parseColor( el.attribute( "color", TQString::null ), rect.prelight.color );
+ rect.prelight.alpha = el.attribute( "alpha", "1.0" ).toFloat();
+ parseFont( el.attribute( "font", "Sans 14" ), rect.prelight.font );
+ } else if (tagName == "border")
+ rect.hasBorder = true;
+ }
+}
+
+void
+KdmRect::drawContents( TQPainter *p, const TQRect &r )
+{
+ // choose the correct rect class
+ RectStruct::RectClass *rClass = &rect.normal;
+ if (state == Sactive && rect.active.present)
+ rClass = &rect.active;
+ if (state == Sprelight && rect.prelight.present)
+ rClass = &rect.prelight;
+
+ if (rClass->alpha <= 0 || !rClass->color.isValid())
+ return;
+
+ if (rClass->alpha == 1)
+ p->fillRect( area, TQBrush( rClass->color ) );
+ else {
+// if ((_compositor.isEmpty()) || (!argb_visual_available)) {
+ // Software blend only (no compositing support)
+ TQRect backRect = r;
+ backRect.moveBy( area.x(), area.y() );
+ TQPixmap backPixmap( backRect.size() );
+ bitBlt( &backPixmap, TQPoint( 0, 0 ), p->device(), backRect );
+ TQImage backImage = backPixmap.convertToImage();
+ KImageEffect::blend( rClass->color, backImage, rClass->alpha );
+ p->drawImage( backRect.x(), backRect.y(), backImage );
+ // area.moveBy(1,1);
+// }
+// else {
+// // We have compositing support!
+// }
+ }
+}
+
+void
+KdmRect::statusChanged()
+{
+ KdmItem::statusChanged();
+ if (!rect.active.present && !rect.prelight.present)
+ return;
+ if ((state == Sprelight && !rect.prelight.present) ||
+ (state == Sactive && !rect.active.present))
+ return;
+ needUpdate();
+}
+
+/*
+void
+KdmRect::setAttribs( TQWidget *widget )
+{
+ widget->setFont( rect.normal.font );
+}
+
+void
+KdmRect::recursiveSetAttribs( TQLayoutItem *li )
+{
+ TQWidget *w;
+ TQLayout *l;
+
+ if ((w = li->widget()))
+ setAttribs( w );
+ else if ((l = li->layout())) {
+ TQLayoutIterator it = l->iterator();
+ for (TQLayoutItem *itm = it.current(); itm; itm = ++it)
+ recursiveSetAttribs( itm );
+ }
+}
+
+void
+KdmRect::setLayoutItem( TQLayoutItem *item )
+{
+ KdmItem::setLayoutItem( item );
+ recursiveSetAttribs( item );
+}
+*/
+
+void
+KdmRect::setWidget( TQWidget *widget )
+{
+ if ( rect.normal.color.isValid() && widget )
+ {
+ TQPalette p = widget->palette();
+ p.setColor( TQPalette::Normal, TQColorGroup::Text, rect.normal.color );
+ widget->setPalette(p);
+ }
+ KdmItem::setWidget( widget );
+ //setAttribs( widget );
+}
+
+#include "tdmrect.moc"
diff --git a/tdm/kfrontend/themer/tdmrect.h b/tdm/kfrontend/themer/tdmrect.h
new file mode 100644
index 000000000..6dfdc126a
--- /dev/null
+++ b/tdm/kfrontend/themer/tdmrect.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2003 by Unai Garro <[email protected]>
+ * Copyright (C) 2004 by Enrico Ros <[email protected]>
+ * Copyright (C) 2004 by Stephan Kulow <[email protected]>
+ * Copyright (C) 2004 by Oswald Buddenhagen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TDMRECT_H
+#define TDMRECT_H
+
+#include "tdmitem.h"
+
+#include <tqcolor.h>
+#include <tqfont.h>
+
+/*
+ * KdmRect: A themed rectangular element
+ */
+
+class KdmRect : public KdmItem {
+ Q_OBJECT
+
+public:
+ KdmRect( KdmItem *parent, const TQDomNode &node, const char *name = 0 );
+ KdmRect( TQWidget *parent, const TQDomNode &node, const char *name = 0 );
+
+protected:
+ // draw the rect
+ virtual void drawContents( TQPainter *p, const TQRect &r );
+
+ // handle switching between normal / active / prelight configurations
+ virtual void statusChanged();
+
+ struct RectStruct {
+ struct RectClass {
+ float alpha;
+ TQColor color;
+ bool present;
+ TQFont font;
+ } normal, active, prelight;
+ bool hasBorder;
+ } rect;
+
+ virtual void setWidget( TQWidget *widget );
+// virtual void setLayoutItem( TQLayoutItem *item );
+ void init( const TQDomNode &node, const char *name );
+
+private:
+ void setAttribs( TQWidget *widget );
+ void recursiveSetAttribs( TQLayoutItem *item );
+};
+
+#endif
diff --git a/tdm/kfrontend/themer/tdmthemer.cpp b/tdm/kfrontend/themer/tdmthemer.cpp
new file mode 100644
index 000000000..d2dc77935
--- /dev/null
+++ b/tdm/kfrontend/themer/tdmthemer.cpp
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2003 by Unai Garro <[email protected]>
+ * Copyright (C) 2004 by Enrico Ros <[email protected]>
+ * Copyright (C) 2004 by Stephan Kulow <[email protected]>
+ * Copyright (C) 2004 by Oswald Buddenhagen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "tdmthemer.h"
+#include "tdmitem.h"
+#include "tdmpixmap.h"
+#include "tdmrect.h"
+#include "tdmlabel.h"
+
+#include <tdmconfig.h>
+#include <kfdialog.h>
+
+#include <kiconloader.h>
+#include <kimageeffect.h>
+#include <klocale.h>
+#include <ksimpleconfig.h>
+#include <kdebug.h>
+
+#include <tqfile.h>
+#include <tqfileinfo.h>
+#include <tqtimer.h> // animation timer - TODO
+#include <tqobjectlist.h>
+#include <tqpainter.h>
+#include <tqwidget.h>
+#include <tqregion.h>
+#include <tqlineedit.h>
+#include <tqapplication.h>
+
+#include <unistd.h>
+
+extern bool argb_visual_available;
+
+/*
+ * KdmThemer. The main theming interface
+ */
+KdmThemer::KdmThemer( const TQString &_filename, const TQString &mode, TQWidget *parent )
+ : TQObject( parent )
+ , rootItem( 0 )
+ , backBuffer( 0 )
+{
+ // Set the mode we're working in
+ m_currentMode = mode;
+
+ // read the XML file and create DOM tree
+ TQString filename = _filename;
+ if (!::access( TQFile::encodeName( filename + "/GdmGreeterTheme.desktop" ), R_OK )) {
+ KSimpleConfig cfg( filename + "/GdmGreeterTheme.desktop" );
+ cfg.setGroup( "GdmGreeterTheme" );
+ filename += '/' + cfg.readEntry( "Greeter" );
+ }
+ TQFile opmlFile( filename );
+ if (!opmlFile.open( IO_ReadOnly )) {
+ FDialog::box( widget(), errorbox, i18n( "Cannot open theme file %1" ).arg(filename) );
+ return;
+ }
+ if (!domTree.setContent( &opmlFile )) {
+ FDialog::box( widget(), errorbox, i18n( "Cannot parse theme file %1" ).arg(filename) );
+ return;
+ }
+ // Set the root (screen) item
+ rootItem = new KdmRect( parent, TQDomNode(), "tdm root" );
+
+ connect( rootItem, TQT_SIGNAL(needUpdate( int, int, int, int )),
+ widget(), TQT_SLOT(update( int, int, int, int )) );
+
+ rootItem->setBaseDir( TQFileInfo( filename ).dirPath( true ) );
+
+ // generate all the items defined in the theme
+ generateItems( rootItem );
+
+ connect( rootItem, TQT_SIGNAL(activated( const TQString & )), TQT_SIGNAL(activated( const TQString & )) );
+ connect( rootItem, TQT_SIGNAL(activated( const TQString & )), TQT_SLOT(slotActivated( const TQString & )) );
+
+ TQTimer::singleShot(800, this, TQT_SLOT(slotPaintRoot()));
+
+/* *TODO*
+ // Animation timer
+ TQTimer *time = new TQTimer( this );
+ time->start( 500 );
+ connect( time, TQT_SIGNAL(timeout()), TQT_SLOT(update()) )
+*/
+}
+
+KdmThemer::~KdmThemer()
+{
+ delete rootItem;
+ delete backBuffer;
+}
+
+inline TQWidget *
+KdmThemer::widget()
+{
+ return static_cast<TQWidget *>(parent());
+}
+
+KdmItem *
+KdmThemer::findNode( const TQString &item ) const
+{
+ return rootItem->findNode( item );
+}
+
+void
+KdmThemer::updateGeometry( bool force )
+{
+ rootItem->setGeometry( TQRect( TQPoint(), widget()->size() ), force );
+}
+
+// BEGIN other functions
+
+void
+KdmThemer::widgetEvent( TQEvent *e )
+{
+ if (!rootItem)
+ return;
+ switch (e->type()) {
+ case TQEvent::MouseMove:
+ {
+ TQMouseEvent *me = TQT_TQMOUSEEVENT(e);
+ rootItem->mouseEvent( me->x(), me->y() );
+ }
+ break;
+ case TQEvent::MouseButtonPress:
+ {
+ TQMouseEvent *me = TQT_TQMOUSEEVENT(e);
+ rootItem->mouseEvent( me->x(), me->y(), true );
+ }
+ break;
+ case TQEvent::MouseButtonRelease:
+ {
+ TQMouseEvent *me = TQT_TQMOUSEEVENT(e);
+ rootItem->mouseEvent( me->x(), me->y(), false, true );
+ }
+ break;
+ case TQEvent::Show:
+ rootItem->show();
+ break;
+ case TQEvent::Resize:
+ updateGeometry( false );
+ showStructure( rootItem );
+ break;
+ case TQEvent::Paint:
+ {
+ TQRect paintRect = TQT_TQPAINTEVENT(e)->rect();
+ kdDebug() << timestamp() << " paint on: " << paintRect << endl;
+
+ if ((_compositor.isEmpty()) || (!argb_visual_available)) {
+ // Software blend only (no compositing support)
+ if (!backBuffer)
+ backBuffer = new TQPixmap( widget()->size() );
+ if (backBuffer->size() != widget()->size())
+ backBuffer->resize( widget()->size() );
+
+ TQPainter p;
+ p.begin( backBuffer );
+ rootItem->paint( &p, paintRect );
+ p.end();
+
+ bitBlt( widget(), paintRect.topLeft(), backBuffer, paintRect );
+ }
+ else {
+ // We have compositing support!
+ TQRgb blend_color = tqRgba(0, 0, 0, 0); // RGBA
+ float alpha = tqAlpha(blend_color) / 255.;
+ int pixel = tqAlpha(blend_color) << 24 |
+ int(tqRed(blend_color) * alpha) << 16 |
+ int(tqGreen(blend_color) * alpha) << 8 |
+ int(tqBlue(blend_color) * alpha);
+ TQPainter p1;
+ p1.begin( widget() );
+ p1.fillRect( paintRect, TQColor(blend_color, pixel) );
+ rootItem->paint( &p1, paintRect );
+ p1.end();
+ }
+
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+void
+KdmThemer::pixmap( const TQRect &r, TQPixmap *px )
+{
+ bitBlt( px, TQPoint( 0, 0 ), widget(), r );
+}
+*/
+
+void
+KdmThemer::generateItems( KdmItem *parent, const TQDomNode &node )
+{
+ if (!parent)
+ return;
+
+ TQDomNodeList subnodeList; //List of subnodes of this node
+
+ /*
+ * Get the child nodes
+ */
+ if (node.isNull()) { // It's the first node, get its child nodes
+ TQDomElement theme = domTree.documentElement();
+
+ // Get its tag, and check it's correct ("greeter")
+ if (theme.tagName() != "greeter") {
+ kdDebug() << timestamp() << " This does not seem to be a correct theme file." << endl;
+ return;
+ }
+ // Get the list of child nodes
+ subnodeList = theme.childNodes();
+ } else
+ subnodeList = node.childNodes();
+
+ /*
+ * Go through each of the child nodes
+ */
+ for (uint nod = 0; nod < subnodeList.count(); nod++) {
+ TQDomNode subnode = subnodeList.item( nod );
+ TQDomElement el = subnode.toElement();
+ TQString tagName = el.tagName();
+
+ if (tagName == "item") {
+ if (!willDisplay( subnode ))
+ continue;
+ TQString id = el.attribute("id");
+ if (id.startsWith("plugin-specific-")) {
+ id = id.mid(strlen("plugin-specific-"));
+ if (!_pluginsLogin.contains(id))
+ continue;
+ }
+
+ // It's a new item. Draw it
+ TQString type = el.attribute( "type" );
+
+ KdmItem *newItem = 0;
+
+ if (type == "label")
+ newItem = new KdmLabel( parent, subnode );
+ else if (type == "pixmap")
+ newItem = new KdmPixmap( parent, subnode );
+ else if (type == "rect")
+ newItem = new KdmRect( parent, subnode );
+ else if (type == "entry" || type == "list") {
+ newItem = new KdmRect( parent, subnode );
+ newItem->setType( type );
+ }
+ // newItem = new KdmEntry( parent, subnode );
+ else if (type == "svg")
+ newItem = new KdmPixmap( parent, subnode );
+ if (newItem) {
+ generateItems( newItem, subnode );
+ if (el.attribute( "button", "false" ) == "true")
+ newItem->inheritFromButton( newItem );
+ }
+ } else if (tagName == "box") {
+ if (!willDisplay( subnode ))
+ continue;
+ // It's a new box. Draw it
+ parent->setBoxLayout( subnode );
+ generateItems( parent, subnode );
+ } else if (tagName == "fixed") {
+ if (!willDisplay( subnode ))
+ continue;
+ // It's a new box. Draw it
+ parent->setFixedLayout( subnode );
+ generateItems( parent, subnode );
+ }
+ }
+}
+
+bool KdmThemer::willDisplay( const TQDomNode &node )
+{
+ TQDomNode showNode = node.namedItem( "show" );
+
+ // No "show" node means this item can be displayed at all times
+ if (showNode.isNull())
+ return true;
+
+ TQDomElement el = showNode.toElement();
+
+ TQString modes = el.attribute( "modes" );
+ if (!modes.isNull()) {
+ TQStringList modeList = TQStringList::split( ",", modes );
+
+ // If current mode isn't in this list, do not display item
+ if (modeList.find( m_currentMode ) == modeList.end())
+ return false;
+ }
+
+ TQString type = el.attribute( "type" );
+ if (type == "config" || type == "suspend")
+ return false; // not implemented (yet)
+ if (type == "timed")
+ return _autoLoginDelay != 0;
+ if (type == "chooser")
+#ifdef XDMCP
+ return _loginMode != LOGIN_LOCAL_ONLY;
+#else
+ return false;
+#endif
+ if (type == "halt" || type == "reboot")
+ return _allowShutdown != SHUT_NONE;
+ else if (type == "userlist")
+ return _userList;
+ else if ( type == "!userlist" )
+ return !_userList;
+
+// if (type == "system")
+// return true;
+
+ // All tests passed, item will be displayed
+ return true;
+}
+
+void
+KdmThemer::showStructure( TQObject *obj )
+{
+
+ const TQObjectList wlist = obj->childrenListObject();
+ static int counter = 0;
+ if (counter == 0)
+ kdDebug() << timestamp() << " \n\n<======= Widget tree =================" << endl;
+ if (!wlist.isEmpty()) {
+ counter++;
+ TQObjectListIterator it( wlist );
+ TQObject *object;
+
+ while ((object = it.current()) != 0) {
+ ++it;
+ TQString node;
+ for (int i = 1; i < counter; i++)
+ node += "-";
+
+ if (object->inherits( "KdmItem" )) {
+ KdmItem *widget = (KdmItem *)object;
+ kdDebug() << node << "|" << widget->type() << " me=" << widget->id << " " << widget->area << endl;
+ }
+
+ showStructure( object );
+ }
+ counter--;
+ }
+ if (counter == 0)
+ kdDebug() << timestamp() << " \n\n<======= Widget tree =================\n\n" << endl;
+}
+
+void
+KdmThemer::slotActivated( const TQString &id )
+{
+ TQString toactivate;
+ if (id == "username-label")
+ toactivate = "user-entry";
+ else if (id == "password-label")
+ toactivate = "pw-entry";
+ else
+ return;
+
+ KdmItem *item = findNode(toactivate);
+ if (!item || !item->widget())
+ return;
+
+ item->widget()->setFocus();
+ TQLineEdit *le = (TQLineEdit*)item->widget()->qt_cast(TQLINEEDIT_OBJECT_NAME_STRING);
+ if (le)
+ le->selectAll();
+}
+
+void
+KdmThemer::slotPaintRoot()
+{
+ KdmItem *back_item = findNode("background");
+ if (!back_item)
+ return;
+
+ TQRect screen = TQApplication::desktop()->screenGeometry(0);
+ TQPixmap pm(screen.size());
+
+ TQPainter painter( &pm, true );
+ back_item->paint( &painter, back_item->rect());
+ painter.end();
+
+ TQT_TQWIDGET(TQApplication::desktop()->screen())->setErasePixmap(pm);
+ TQT_TQWIDGET(TQApplication::desktop()->screen())->erase();
+}
+
+#include "tdmthemer.moc"
diff --git a/tdm/kfrontend/themer/tdmthemer.h b/tdm/kfrontend/themer/tdmthemer.h
new file mode 100644
index 000000000..2b8865b4d
--- /dev/null
+++ b/tdm/kfrontend/themer/tdmthemer.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2003 by Unai Garro <[email protected]>
+ * Copyright (C) 2004 by Enrico Ros <[email protected]>
+ * Copyright (C) 2004 by Stephan Kulow <[email protected]>
+ * Copyright (C) 2004 by Oswald Buddenhagen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TDMTHEMER_H
+#define TDMTHEMER_H
+
+#include <tqobject.h>
+#include <tqdom.h>
+#include <tqimage.h>
+
+class KdmThemer;
+class KdmItem;
+class KdmPixmap;
+class KdmRect;
+class KdmBox;
+
+class TQRect;
+class TQWidget;
+class TQEvent;
+
+/**
+* @author Unai Garro
+*/
+
+
+
+/*
+* The themer widget. Whatever drawn here is just themed
+* according to a XML file set by the user.
+*/
+
+
+class KdmThemer : public TQObject {
+ Q_OBJECT
+
+public:
+ /*
+ * Construct and destruct the interface
+ */
+
+ KdmThemer( const TQString &path, const TQString &mode, TQWidget *parent );
+ ~KdmThemer();
+
+ bool isOK() { return rootItem != 0; }
+ /*
+ * Gives a sizeHint to the widget (parent size)
+ */
+ //TQSize sizeHint() const{ return parentWidget()->size(); }
+
+ /*
+ * Takes a shot of the current widget
+ */
+// void pixmap( const TQRect &r, TQPixmap *px );
+
+ virtual // just to put the reference in the vmt
+ KdmItem *findNode( const TQString & ) const;
+
+ void updateGeometry( bool force ); // force = true for external calls
+
+ // must be called by parent widget
+ void widgetEvent( TQEvent *e );
+
+signals:
+ void activated( const TQString &id );
+
+protected slots:
+ void slotActivated( const TQString &id );
+ void slotPaintRoot();
+
+private:
+ /*
+ * Our display mode (e.g. console, remote, ...)
+ */
+ TQString m_currentMode;
+
+ /*
+ * The config file being used
+ */
+ TQDomDocument domTree;
+
+ /*
+ * Stores the root of the theme
+ */
+ KdmItem *rootItem;
+
+ /*
+ * The backbuffer
+ */
+ TQPixmap *backBuffer;
+
+ // methods
+
+ /*
+ * Test whether item needs to be displayed
+ */
+ bool willDisplay( const TQDomNode &node );
+
+ /*
+ * Parses the XML file looking for the
+ * item list and adds those to the themer
+ */
+ void generateItems( KdmItem *parent = 0, const TQDomNode &node = TQDomNode() );
+
+ void showStructure( TQObject *obj );
+
+ TQWidget *widget();
+};
+
+
+#endif