You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/kdm/kfrontend/themer/kdmthemer.cpp

405 lines
10 KiB

/*
* Copyright (C) 2003 by Unai Garro <ugarro@users.sourceforge.net>
* Copyright (C) 2004 by Enrico Ros <rosenric@dei.unipd.it>
* Copyright (C) 2004 by Stephan Kulow <coolo@kde.org>
* Copyright (C) 2004 by Oswald Buddenhagen <ossi@kde.org>
*
* 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 "kdmthemer.h"
#include "kdmitem.h"
#include "kdmpixmap.h"
#include "kdmrect.h"
#include "kdmlabel.h"
#include <kdmconfig.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(), "kdm 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 "kdmthemer.moc"