--- kdm/kfrontend/kdm_greet.c.old +++ kdm/kfrontend/kdm_greet.c @@ -44,8 +44,8 @@ # include #endif +# include #if defined(HAVE_XTEST) || defined(HAVE_XKB) -# include # include #endif --- kdm/kfrontend/themer/kdmrect.h.old +++ kdm/kfrontend/themer/kdmrect.h @@ -36,6 +36,7 @@ public: KdmRect( KdmItem *parent, const QDomNode &node, const char *name = 0 ); + KdmRect( QWidget *parent, const QDomNode &node, const char *name = 0 ); protected: // draw the rect @@ -54,8 +55,9 @@ bool hasBorder; } rect; -// virtual void setWidget( QWidget *widget ); + virtual void setWidget( QWidget *widget ); // virtual void setLayoutItem( QLayoutItem *item ); + void init( const QDomNode &node, const char *name ); private: void setAttribs( QWidget *widget ); --- kdm/kfrontend/themer/kdmitem.h.old +++ kdm/kfrontend/themer/kdmitem.h @@ -90,6 +90,8 @@ * Item constructor and destructor */ KdmItem( KdmItem *parent, const QDomNode &node = QDomNode(), const char *name = 0 ); + KdmItem( QWidget *parent, const QDomNode &node = QDomNode(), const char *name = 0 ); // for the root + virtual ~KdmItem(); /** @@ -151,6 +153,7 @@ KdmItem *findNode( const QString &id ) const; virtual void setWidget( QWidget *widget ); + QWidget *widget() const { return myWidget; } virtual void setLayoutItem( QLayoutItem *item ); virtual void hide( bool force = false ); @@ -160,6 +163,9 @@ bool isExplicitlyHidden() const { return isShown == ExplicitlyHidden; } QRect rect() const { return area; } + QWidget *parentWidget() const; + QString getId() const { return id; } + signals: void needUpdate( int x, int y, int w, int h ); void activated( const QString &id ); @@ -237,6 +243,7 @@ void parseColor( const QString &, QColor & ); void inheritFromButton( KdmItem *button ); + void init( const QDomNode &node = QDomNode(), const char *name = 0 ); QString itemType, id; QValueList m_children; --- kdm/kfrontend/themer/kdmpixmap.h.old +++ kdm/kfrontend/themer/kdmpixmap.h @@ -61,9 +61,10 @@ } pixmap; private: - // Method to load the pixmap given by the theme - void loadPixmap( const QString &fileName, QPixmap &p, QString &path ); + // Method to load the pixmap path given by the theme + QString fullPath( const QString &fileName ); void renderSvg( PixmapStruct::PixmapClass *pClass, const QRect &area ); + void loadPixmap( PixmapStruct::PixmapClass *pClass ); }; #endif --- kdm/kfrontend/themer/kdmlabel.h.old +++ kdm/kfrontend/themer/kdmlabel.h @@ -67,6 +67,7 @@ public slots: void update(); + void slotAccel(); private: /* Method to lookup the caption associated with an item */ @@ -76,6 +77,10 @@ QString lookupText( const QString &t ); QString cText; + int cAccel; + QAccel *myAccel; + + void setTextInt(const QString &); }; #endif --- kdm/kfrontend/themer/kdmthemer.cpp.old +++ kdm/kfrontend/themer/kdmthemer.cpp @@ -36,11 +36,13 @@ #include #include -//#include // animation timer - TODO +#include // animation timer - TODO #include #include #include #include +#include +#include #include @@ -72,7 +74,8 @@ return; } // Set the root (screen) item - rootItem = new KdmRect( 0, QDomNode(), "kdm root" ); + rootItem = new KdmRect( parent, QDomNode(), "kdm root" ); + connect( rootItem, SIGNAL(needUpdate( int, int, int, int )), widget(), SLOT(update( int, int, int, int )) ); @@ -82,7 +85,10 @@ generateItems( rootItem ); connect( rootItem, SIGNAL(activated( const QString & )), SIGNAL(activated( const QString & )) ); + connect( rootItem, SIGNAL(activated( const QString & )), SLOT(slotActivated( const QString & )) ); + QTimer::singleShot(800, this, SLOT(slotPaintRoot())); + /* *TODO* // Animation timer QTimer *time = new QTimer( this ); @@ -151,7 +157,7 @@ case QEvent::Paint: { QRect paintRect = static_cast(e)->rect(); - kdDebug() << "paint on: " << paintRect << endl; + kdDebug() << timestamp() << " paint on: " << paintRect << endl; if (!backBuffer) backBuffer = new QPixmap( widget()->size() ); @@ -195,7 +201,7 @@ // Get its tag, and check it's correct ("greeter") if (theme.tagName() != "greeter") { - kdDebug() << "This does not seem to be a correct theme file." << endl; + kdDebug() << timestamp() << " This does not seem to be a correct theme file." << endl; return; } // Get the list of child nodes @@ -214,6 +220,13 @@ if (tagName == "item") { if (!willDisplay( subnode )) continue; + QString 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 QString type = el.attribute( "type" ); @@ -225,13 +238,11 @@ newItem = new KdmPixmap( parent, subnode ); else if (type == "rect") newItem = new KdmRect( parent, subnode ); - else if (type == "entry") { + else if (type == "entry" || type == "list") { newItem = new KdmRect( parent, subnode ); newItem->setType( type ); } // newItem = new KdmEntry( parent, subnode ); - //else if (type=="list") - // newItem = new KdmList( parent, subnode ); else if (type == "svg") newItem = new KdmPixmap( parent, subnode ); if (newItem) { @@ -287,6 +298,11 @@ #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; @@ -301,7 +317,7 @@ const QObjectList *wlist = obj->children(); static int counter = 0; if (counter == 0) - kdDebug() << "\n\n<======= Widget tree =================" << endl; + kdDebug() << timestamp() << " \n\n<======= Widget tree =================" << endl; if (wlist) { counter++; QObjectListIterator it( *wlist ); @@ -323,7 +339,46 @@ counter--; } if (counter == 0) - kdDebug() << "\n\n<======= Widget tree =================\n\n" << endl; + kdDebug() << timestamp() << " \n\n<======= Widget tree =================\n\n" << endl; } +void +KdmThemer::slotActivated( const QString &id ) +{ + QString 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(); + QLineEdit *le = (QLineEdit*)item->widget()->qt_cast("QLineEdit"); + if (le) + le->selectAll(); +} + +void +KdmThemer::slotPaintRoot() +{ + KdmItem *back_item = findNode("background"); + if (!back_item) + return; + + QRect screen = QApplication::desktop()->screenGeometry(0); + QPixmap pm(screen.size()); + + QPainter painter( &pm, true ); + back_item->paint( &painter, back_item->rect()); + painter.end(); + + QApplication::desktop()->screen()->setErasePixmap(pm); + QApplication::desktop()->screen()->erase(); +} + #include "kdmthemer.moc" --- kdm/kfrontend/themer/kdmthemer.h.old +++ kdm/kfrontend/themer/kdmthemer.h @@ -80,6 +80,10 @@ signals: void activated( const QString &id ); +protected slots: + void slotActivated( const QString &id ); + void slotPaintRoot(); + private: /* * Our display mode (e.g. console, remote, ...) --- kdm/kfrontend/themer/kdmlayout.cpp.old +++ kdm/kfrontend/themer/kdmlayout.cpp @@ -20,6 +20,7 @@ */ #include "kdmlayout.h" +#include "kdmconfig.h" #include "kdmitem.h" #include @@ -35,11 +36,11 @@ void KdmLayoutFixed::update( const QRect &parentGeometry, bool force ) { - kdDebug() << "KdmLayoutFixed::update " << parentGeometry << endl; + 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() << "invalid\n"; + kdDebug() << timestamp() << " invalid\n"; return; } // For each child in list I ask their hinted size and set it! @@ -102,7 +103,7 @@ childrenRect.setTop( childrenRect.top() + height + box.spacing ); } else { QRect temp( childrenRect.left(), childrenRect.top(), width, childrenRect.height() ); - kdDebug() << "placement " << *it << " " << temp << " " << (*it)->placementHint( temp ) << endl; + kdDebug() << timestamp() << " placement " << *it << " " << temp << " " << (*it)->placementHint( temp ) << endl; temp = (*it)->placementHint( temp ); (*it)->setGeometry( temp, force ); childrenRect.setLeft( childrenRect.left() + width + box.spacing ); @@ -125,7 +126,7 @@ kdDebug() << this << " placementHint " << *it << " " << temp << " " << itemRect << endl; temp.setWidth( itemRect.width() ); childrenRect.setLeft( childrenRect.left() + itemRect.size().width() + box.spacing ); - kdDebug() << "childrenRect after " << *it << " " << childrenRect << endl; + kdDebug() << timestamp() << " childrenRect after " << *it << " " << childrenRect << endl; } itemRect = (*it)->placementHint( temp ); kdDebug() << this << " placementHint2 " << *it << " " << temp << " " << itemRect << endl; --- kdm/kfrontend/themer/kdmrect.cpp.old +++ kdm/kfrontend/themer/kdmrect.cpp @@ -33,6 +33,18 @@ KdmRect::KdmRect( KdmItem *parent, const QDomNode &node, const char *name ) : KdmItem( parent, node, name ) { + init( node, name ); +} + +KdmRect::KdmRect( QWidget *parent, const QDomNode &node, const char *name ) + : KdmItem( parent, node, name ) +{ + init( node, name ); +} + +void +KdmRect::init( const QDomNode &node, const char * ) +{ itemType = "rect"; // Set default values for rect (note: strings are already Null) @@ -137,13 +149,6 @@ } void -KdmRect::setWidget( QWidget *widget ) -{ - KdmItem::setWidget( widget ); - setAttribs( widget ); -} - -void KdmRect::setLayoutItem( QLayoutItem *item ) { KdmItem::setLayoutItem( item ); @@ -151,4 +156,17 @@ } */ +void +KdmRect::setWidget( QWidget *widget ) +{ + if ( rect.normal.color.isValid() && widget ) + { + QPalette p = widget->palette(); + p.setColor( QPalette::Normal, QColorGroup::Text, rect.normal.color ); + widget->setPalette(p); + } + KdmItem::setWidget( widget ); + //setAttribs( widget ); +} + #include "kdmrect.moc" --- kdm/kfrontend/themer/kdmitem.cpp.old +++ kdm/kfrontend/themer/kdmitem.cpp @@ -23,10 +23,11 @@ * Generic Kdm Item */ -//#define DRAW_OUTLINE 1 // for debugging only +// #define DRAW_OUTLINE 1 // for debugging only #include "kdmitem.h" #include "kdmlayout.h" +#include "kdmconfig.h" #include #include @@ -35,9 +36,7 @@ #include #include #include -#ifdef DRAW_OUTLINE -# include -#endif +#include KdmItem::KdmItem( KdmItem *parent, const QDomNode &node, const char *name ) : QObject( parent, name ) @@ -48,6 +47,25 @@ , myLayoutItem( 0 ) , buttonParent( 0 ) { + init(node, name); +} + + +KdmItem::KdmItem( QWidget *parent, const QDomNode &node, const char *name ) + : QObject( parent, name ) + , boxManager( 0 ) + , fixedManager( 0 ) + , image( 0 ) + , myWidget( 0 ) + , myLayoutItem( 0 ) + , buttonParent( 0 ) +{ + init(node, name); +} + +void +KdmItem::init( const QDomNode &node, const char * ) +{ // Set default layout for every item currentManager = MNone; pos.x = pos.y = 0; @@ -62,7 +80,7 @@ state = Snormal; // The "toplevel" node (the screen) is really just like a fixed node - if (!parent || !parent->inherits( "KdmItem" )) { + if (!parent() || !parent()->inherits( "KdmItem" )) { setFixedLayout(); return; } @@ -87,7 +105,7 @@ id = tnode.toElement().attribute( "id", QString::number( (ulong)this, 16 ) ); // Tell 'parent' to add 'me' to its children - KdmItem *parentItem = static_cast( parent ); + KdmItem *parentItem = static_cast( parent() ); parentItem->addChildItem( this ); } @@ -195,7 +213,7 @@ if (frame) frame->setFrameStyle( QFrame::NoFrame ); - myWidget->setGeometry(area); + setGeometry(area, true); connect( myWidget, SIGNAL(destroyed()), SLOT(widgetGone()) ); } @@ -236,15 +254,21 @@ area = newGeometry; - if (myWidget) - myWidget->setGeometry( newGeometry ); + if (myWidget) { + QRect 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 ); @@ -258,8 +282,16 @@ if (isHidden()) return; - if (myWidget || (myLayoutItem && myLayoutItem->widget())) - return; + if (myWidget || (myLayoutItem && myLayoutItem->widget())) { + // KListView because it's missing a Q_OBJECT + if ( myWidget && myWidget->isA( "KListView" ) ) { + QPixmap copy( myWidget->size() ); + kdDebug() << myWidget->geometry() << " " << area << " " << myWidget->size() << endl; + bitBlt( ©, QPoint( 0, 0), p->device(), myWidget->geometry(), Qt::CopyROP ); + myWidget->setPaletteBackgroundPixmap( copy ); + } + return; + } if (area.intersects( rect )) { QRect contentsRect = area.intersect( rect ); @@ -280,6 +312,8 @@ QValueList::Iterator it; for (it = m_children.begin(); it != m_children.end(); ++it) (*it)->paint( p, rect ); + + } KdmItem *KdmItem::currentActive = 0; @@ -287,8 +321,11 @@ 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 ); + buttonParent->mouseEvent( x, y, pressed, released ); return; } @@ -362,7 +399,8 @@ w = parentRect.width(), h = parentRect.height(); - kdDebug() << "KdmItem::placementHint parentRect=" << id << parentRect << " hintedSize=" << hintedSize << endl; + 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) @@ -372,7 +410,7 @@ return parentRect; boxHint = boxManager->sizeHint(); } - kdDebug() << " => boxHint " << boxHint << endl; + kdDebug() << timestamp() << " boxHint " << boxHint << endl; } if (pos.xType == DTpixel) @@ -380,25 +418,25 @@ else if (pos.xType == DTnpixel) x = parentRect.right() - pos.x; else if (pos.xType == DTpercent) - x += int( parentRect.width() / 100.0 * pos.x ); + x += qRound( 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 += int( parentRect.height() / 100.0 * pos.y ); + y += qRound( 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 = int( parentRect.width() / 100.0 * pos.width ); + w = qRound( parentRect.width() / 100.0 * pos.width ); else if (pos.wType == DTbox) w = boxHint.width(); else if (hintedSize.width() > 0) - w = hintedSize.width(); + w = hintedSize.width(); else w = 0; @@ -407,14 +445,22 @@ else if (pos.hType == DTnpixel) h -= pos.height; else if (pos.hType == DTpercent) - h = int( parentRect.height() / 100.0 * pos.height ); + h = qRound( parentRect.height() / 100.0 * pos.height ); else if (pos.hType == DTbox) h = boxHint.height(); - else if (hintedSize.height() > 0) - h = hintedSize.height(); - else + 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 = qRound(float(hintedSize.width() * h) / hintedSize.height()); + } + // defaults to center int dx = -w / 2, dy = -h / 2; @@ -430,7 +476,7 @@ dx = -w; } // KdmItem *p = static_cast( parent() ); - kdDebug() << "KdmItem::placementHint " << id << " x=" << x << " dx=" << dx << " w=" << w << " y=" << y << " dy=" << dy << " h=" << h << " " << parentRect << endl; + kdDebug() << timestamp() << " placementHint " << this << " x=" << x << " dx=" << dx << " w=" << w << " y=" << y << " dy=" << dy << " h=" << h << " " << parentRect << endl; y += dy; x += dx; @@ -529,4 +575,17 @@ currentManager = MFixed; } +QWidget * +KdmItem::parentWidget() const +{ + if (myWidget) + return myWidget; + if (!this->parent()) + return 0; + + if (parent()->qt_cast("QWidget")) + return (QWidget*)parent(); + return ((KdmItem*)parent())->parentWidget(); +} + #include "kdmitem.moc" --- kdm/kfrontend/themer/kdmpixmap.cpp.old +++ kdm/kfrontend/themer/kdmpixmap.cpp @@ -22,6 +22,7 @@ #include #include "kdmpixmap.h" +#include #include #ifdef HAVE_LIBART @@ -29,6 +30,7 @@ #endif #include +#include #include #include @@ -58,21 +60,28 @@ QString tagName = el.tagName(); if (tagName == "normal") { - loadPixmap( el.attribute( "file", "" ), pixmap.normal.pixmap, pixmap.normal.fullpath ); + pixmap.normal.fullpath = fullPath( el.attribute( "file", "" ) ); parseColor( el.attribute( "tint", "#ffffff" ), pixmap.normal.tint ); pixmap.normal.alpha = el.attribute( "alpha", "1.0" ).toFloat(); } else if (tagName == "active") { pixmap.active.present = true; - loadPixmap( el.attribute( "file", "" ), pixmap.active.pixmap, pixmap.active.fullpath ); + 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; - loadPixmap( el.attribute( "file", "" ), pixmap.prelight.pixmap, pixmap.prelight.fullpath ); + 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 ); } QSize @@ -100,19 +109,16 @@ } -void -KdmPixmap::loadPixmap( const QString &fileName, QPixmap &map, QString &fullName ) +QString +KdmPixmap::fullPath( const QString &fileName) { - if (fileName.isEmpty()) - return; + if (fileName.isEmpty()) + return QString::null; - fullName = fileName; + QString fullName = fileName; if (fullName.at( 0 ) != '/') fullName = baseDir() + "/" + fileName; - - if (!fullName.endsWith( ".svg" )) // we delay it for svgs - if (!map.load( fullName )) - fullName = QString::null; + return fullName; } void @@ -140,6 +146,25 @@ } void +KdmPixmap::loadPixmap( PixmapStruct::PixmapClass *pClass ) +{ + QString fullpath = pClass->fullpath; + + kdDebug() << timestamp() << " load " << fullpath << endl; + int index = fullpath.findRev('.'); + QString ext = fullpath.right(fullpath.length() - index); + fullpath = fullpath.left(index); + kdDebug() << timestamp() << " ext " << ext << " " << fullpath << endl; + QString testpath = QString("-%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( QPainter *p, const QRect &r ) { // choose the correct pixmap class @@ -149,12 +174,20 @@ 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 + + if (pClass->fullpath.isEmpty()) // if neither is set, we're empty return; - - kdDebug() << "renderSVG\n"; - renderSvg( pClass, area ); + + 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(); @@ -176,26 +209,38 @@ if (pClass->readyPixmap.isNull()) { + + bool haveTint = pClass->tint.rgb() != 0xFFFFFF; + bool haveAlpha = pClass->alpha < 1.0; + QImage 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() << "renderSVG\n"; + kdDebug() << timestamp() << " renderSVG\n"; renderSvg( pClass, area ); scaledImage = pClass->pixmap.convertToImage(); } else { - kdDebug() << "convertFromImage\n"; + kdDebug() << timestamp() << " convertFromImage smoothscale\n"; QImage tempImage = pClass->pixmap.convertToImage(); + kdDebug() << timestamp() << " convertToImage done\n"; scaledImage = tempImage.smoothScale( area.width(), area.height() ); + kdDebug() << timestamp() << " done\n"; } - } else + } else { + if (haveTint || haveAlpha) + { scaledImage = pClass->pixmap.convertToImage(); + // enforce rgba values for the later + scaledImage = scaledImage.convertDepth( 32 ); + } + else + pClass->readyPixmap = pClass->pixmap; + } - bool haveTint = pClass->tint.rgb() != 0xFFFFFF; - bool haveAlpha = pClass->alpha < 1.0; - if (haveTint || haveAlpha) { // blend image(pix) with the given tint @@ -220,9 +265,12 @@ } - pClass->readyPixmap.convertFromImage( scaledImage ); + if (!scaledImage.isNull()) { + kdDebug() << timestamp() << " convertFromImage " << id << " " << area << endl; + pClass->readyPixmap.convertFromImage( scaledImage ); + } } - // kdDebug() << "Pixmap::drawContents " << pClass->readyPixmap.size() << " " << px << " " << py << " " << sx << " " << sy << " " << sw << " " << sh << endl; + kdDebug() << timestamp() << " Pixmap::drawContents " << pClass->readyPixmap.size() << " " << px << " " << py << " " << sx << " " << sy << " " << sw << " " << sh << endl; p->drawPixmap( px, py, pClass->readyPixmap, sx, sy, sw, sh ); } --- kdm/kfrontend/themer/kdmlabel.cpp.old +++ kdm/kfrontend/themer/kdmlabel.cpp @@ -19,8 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include #include "kdmlabel.h" -#include +#include "kdmconfig.h" +#include "../kgreeter.h" #include #include @@ -31,6 +33,7 @@ #include #include #include +#include #include #include @@ -39,7 +42,7 @@ #endif KdmLabel::KdmLabel( KdmItem *parent, const QDomNode &node, const char *name ) - : KdmItem( parent, node, name ) + : KdmItem( parent, node, name ), myAccel(0) { itemType = "label"; @@ -92,21 +95,46 @@ } } - // Check if this is a timer label + // Check if this is a timer label) label.isTimer = label.text.find( "%c" ) >= 0; if (label.isTimer) { timer = new QTimer( this ); timer->start( 1000 ); connect( timer, SIGNAL(timeout()), SLOT(update()) ); } - cText = lookupText( label.text ); + setTextInt( lookupText( label.text ) ); } void +KdmLabel::setTextInt( const QString &txt) +{ + // TODO: catch && + cText = txt; + cAccel = txt.find('&'); + delete myAccel; + myAccel = 0; + if (cAccel != -1) { + cText.remove('&'); + myAccel = new QAccel(parentWidget()); + myAccel->insertItem(ALT + UNICODE_ACCEL + cText.at(cAccel).lower().unicode()); + connect(myAccel, SIGNAL(activated(int)), SLOT(slotAccel())); + } +} + +void +KdmLabel::slotAccel() +{ + if (buttonParent) + emit activated(buttonParent->getId()); + else + emit activated(id); +} + +void KdmLabel::setText( const QString &txt ) { label.text = txt; - update(); + setTextInt( lookupText( label.text ) ); } QSize @@ -139,7 +167,23 @@ p->setFont( l->font ); p->setPen( l->color ); //TODO paint clipped (tested but not working..) - p->drawText( area, AlignLeft | SingleLine, cText ); + if (cAccel != -1 && (!id.isEmpty() || buttonParent) ) { + QString left = cText.left(cAccel); + QString right = cText.mid(cAccel + 1); + p->drawText( area, AlignLeft | SingleLine, left ); + QRect tarea = area; + QFontMetrics fm(l->font); + tarea.rLeft() += fm.width(left); + QFont f(l->font); + f.setUnderline(true); + p->setFont ( f ); + p->drawText( tarea, AlignLeft | SingleLine, QString(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 @@ -159,7 +203,7 @@ { QString text = lookupText( label.text ); if (text != cText) { - cText = text; + setTextInt(text); needUpdate(); } } @@ -167,22 +211,23 @@ static const struct { const char *type, *text; } stocks[] = { - { "language", I18N_NOOP("Language") }, - { "session", I18N_NOOP("Session Type") }, - { "system", I18N_NOOP("Menu") }, // i18n("Actions"); - { "disconnect", I18N_NOOP("Disconnect") }, - { "quit", I18N_NOOP("Quit") }, - { "halt", I18N_NOOP("Power off") }, - { "suspend", I18N_NOOP("Suspend") }, - { "reboot", I18N_NOOP("Reboot") }, + { "language", I18N_NOOP("&Language") }, + { "session", I18N_NOOP("Session &Type") }, + { "system", I18N_NOOP("&System") }, // i18n("Actions"); + { "disconnect", I18N_NOOP("&Disconnect") }, + { "quit", I18N_NOOP("&Quit") }, + { "halt", I18N_NOOP("Power O&ff") }, + { "suspend", I18N_NOOP("S&uspend") }, + { "reboot", I18N_NOOP("&Reboot") }, { "chooser", I18N_NOOP("XDMCP Chooser") }, { "config", I18N_NOOP("Configure") }, - { "caps-lock-warning", I18N_NOOP("You have got caps lock on.") }, - { "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:") }, - { "login", I18N_NOOP("Login") } + { "caps-lock-warning", I18N_NOOP("Caps Lock is enabled.") }, + { "timed-label", I18N_NOOP("User %s will log in 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("L&ogin") } }; QString @@ -195,7 +240,7 @@ if (type == stocks[i].type) return i18n(stocks[i].text); - kdDebug() << "Invalid element. Check your theme!" << endl; + kdDebug() << timestamp() << " Invalid element. Check your theme!" << endl; return stock; } @@ -205,7 +250,6 @@ QString text = t; text.replace( '_', '&' ); -// text.remove( '_' ); // FIXME add key accels, remove underscores for now QMap m; struct utsname uts; --- kdm/kfrontend/kdmconfig.h.old +++ kdm/kfrontend/kdmconfig.h @@ -35,6 +35,7 @@ #include #include #include +#include extern QString _stsFile; extern bool _isLocal; @@ -46,6 +47,19 @@ struct dpySpec; void decodeSess( dpySpec *sess, QString &user, QString &loc ); +extern struct timeval st; + +inline QString timestamp() { + struct timeval nst; + gettimeofday(&nst, 0); + if (!st.tv_sec) + gettimeofday(&st, 0); + + QString ret; + ret.sprintf("[%07ld]", (nst.tv_sec - st.tv_sec) * 1000 + (nst.tv_usec - st.tv_usec) / 1000); + return ret; +} + extern "C" #endif void init_config( void ); --- kdm/kfrontend/kgreeter.h.old +++ kdm/kfrontend/kgreeter.h @@ -73,9 +73,10 @@ void slotUserEntered(); protected: + void readFacesList(); void installUserList(); void insertUser( const QImage &, const QString &, struct passwd * ); - void insertUsers(); + void insertUsers( int limit = -1); void putSession( const QString &, const QString &, bool, const char * ); void insertSessions(); virtual void pluginSetup(); @@ -87,10 +88,13 @@ QStringList *userList; QPopupMenu *sessMenu; QValueVector sessionTypes; + QStringList randomFaces; + QMap randomFacesMap; int nNormals, nSpecials; int curPrev, curSel; bool prevValid; bool needLoad; + bool themed; static int curPlugin; static PluginList pluginList; --- kdm/kfrontend/kgdialog.cpp.old +++ kdm/kfrontend/kgdialog.cpp @@ -29,6 +29,7 @@ #include "kdm_greet.h" #include +#include #include #include @@ -58,7 +59,7 @@ #ifdef HAVE_VTS if (_isLocal) { dpyMenu = new QPopupMenu( this ); - int id = inserten( i18n("Sw&itch User"), ALT+Key_I, dpyMenu ); + int id = inserten( i18n("Sw&itch User"), CTRL + Key_I, dpyMenu ); connect( dpyMenu, SIGNAL(activated( int )), SLOT(slotDisplaySelected( int )) ); connect( dpyMenu, SIGNAL(aboutToShow()), @@ -71,7 +72,7 @@ if (_allowClose) inserten( _isLocal ? i18n("R&estart X Server") : i18n("Clos&e Connection"), - ALT+Key_E, SLOT(slotExit()) ); + 0, SLOT(slotExit()) ); #ifdef XDMCP if (_isLocal && _loginMode != _switchIf) { @@ -81,10 +82,11 @@ #endif if (_hasConsole) - inserten( i18n("Co&nsole Login"), ALT+Key_N, SLOT(slotConsole()) ); + inserten( i18n("Co&nsole Login"), CTRL+Key_N, SLOT(slotConsole()) ); if (_allowShutdown != SHUT_NONE) { - inserten( i18n("&Shutdown..."), ALT+Key_S, SLOT(slotShutdown( int )) ); + ensureMenu(); + optMenu->insertItem(SmallIconSet( "exit" ), i18n("&Shutdown..."), this, SLOT(slotShutdown(int)), CTRL+Key_S ); QAccel *accel = new QAccel( this ); accel->insertItem( ALT+CTRL+Key_Delete ); connect( accel, SIGNAL(activated( int )), SLOT(slotShutdown( int )) ); --- kdm/kfrontend/kdmconfig.cpp.old +++ kdm/kfrontend/kdmconfig.cpp @@ -33,6 +33,8 @@ #include #include +struct timeval st = {0, 0}; + CONF_GREET_DEFS QString _stsFile; --- kdm/kfrontend/kgapp.cpp.old +++ kdm/kfrontend/kgapp.cpp @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include #include @@ -130,6 +132,7 @@ static char *argv[] = { (char *)"kdmgreet", 0 }; KCmdLineArgs::init( 1, argv, *argv, 0, 0, 0, true ); + kdDebug() << timestamp() << "start" << endl; kde_have_kipc = false; KApplication::disableAutoDcopRegistration(); KCrash::setSafer( true ); @@ -166,6 +169,7 @@ GSendInt( G_Ready ); + kdDebug() << timestamp() << " main1" << endl; setCursor( dpy, app.desktop()->winId(), XC_left_ptr ); for (;;) { @@ -206,6 +210,7 @@ if (_useTheme && !_theme.isEmpty()) { KThemedGreeter *tgrt; dialog = tgrt = new KThemedGreeter; + kdDebug() << timestamp() << " themed" << endl; if (!tgrt->isOK()) { delete tgrt; dialog = new KStdGreeter; --- kdm/kfrontend/kgreeter.cpp.old +++ kdm/kfrontend/kgreeter.cpp @@ -38,12 +38,14 @@ #include #include #include +#include #undef Unsorted // x headers suck - make qdir.h work with --enable-final #include #include #include #include +#include #include #include #include @@ -60,27 +62,46 @@ #include #include #include +#include +#include #include class UserListView : public KListView { public: - UserListView( QWidget *parent = 0, const char *name = 0 ) + UserListView( bool _them, QWidget *parent = 0, const char *name = 0 ) : KListView( parent, name ) - , cachedSizeHint( -1, 0 ) + , themed(_them), cachedSizeHint( -1, 0 ) { setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Ignored ); header()->hide(); addColumn( QString::null ); setColumnAlignment( 0, AlignVCenter ); setResizeMode( QListView::LastColumn ); + if (themed) { + setBackgroundMode( Qt::NoBackground ); + viewport()->setBackgroundMode( Qt::NoBackground ); + setFrameStyle( QFrame::NoFrame ); + } } + bool themed; mutable QSize cachedSizeHint; - protected: + int sumHeight() const + { + int sum = 0; + for (QListViewItem *itm = firstChild(); itm; itm = itm->nextSibling()) { + sum += itm->height(); + } + return sum; + } +public: virtual QSize sizeHint() const { + if (themed) + return KListView::sizeHint(); + if (!cachedSizeHint.isValid()) { constPolish(); uint maxw = 0; @@ -95,9 +116,24 @@ } return cachedSizeHint; } + virtual void paintEmptyArea ( QPainter * p, const QRect & rect ) + { + if (!themed) + return KListView::paintEmptyArea(p, rect ); + + const QPixmap *pm = paletteBackgroundPixmap(); + if (!pm || pm->isNull()) + return; + + kdDebug() << "paintEmpty " << rect << endl; + QRect devRect = p->xForm( rect ); + kdDebug() << "paintEmpty2 " << devRect << endl; + p->drawPixmap(0, 0, *pm, devRect.left(), devRect.top() ); + } + + QPixmap background; }; - int KGreeter::curPlugin = -1; PluginList KGreeter::pluginList; @@ -112,12 +148,14 @@ , curSel( -1 ) , prevValid( true ) , needLoad( false ) + , themed( framed ) { stsFile = new KSimpleConfig( _stsFile ); stsFile->setGroup( "PrevUser" ); if (_userList) { - userView = new UserListView( this ); + readFacesList(); + userView = new UserListView( framed, this ); connect( userView, SIGNAL(clicked( QListViewItem * )), SLOT(slotUserClicked( QListViewItem * )) ); connect( userView, SIGNAL(doubleClicked( QListViewItem * )), @@ -125,10 +163,8 @@ } if (_userCompletion) userList = new QStringList; - if (userView || userList) - insertUsers(); - sessMenu = new QPopupMenu( this ); + sessMenu = new QPopupMenu( this ); connect( sessMenu, SIGNAL(activated( int )), SLOT(slotSessionSelected( int )) ); insertSessions(); @@ -147,6 +183,33 @@ delete stsFile; } +void KGreeter::readFacesList() +{ + FILE *f = fopen( QFile::encodeName( _faceDir + "/.randomlist" ), "rt" ); + if ( !f ) + return; + QTextIStream is( f ); + while ( !is.eof() ) + { + QString line = is.readLine().simplifyWhiteSpace(); + if ( line.isEmpty() ) + continue; + QString icon; + int index = line.find( ' ' ); + if ( index > 0 ) { + icon = line.left( index ); + line = line.mid( index ); + } else { + icon = line; + line = QString::null; + } + randomFaces.push_back( icon ); + QStringList list = QStringList::split( ' ', line ); + for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it ) + randomFacesMap[*it] = icon; + } +} + class UserListViewItem : public KListViewItem { public: UserListViewItem( UserListView *parent, const QString &text, @@ -160,6 +223,14 @@ parent->cachedSizeHint.setWidth( -1 ); } + virtual void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) + { + if (((UserListView*)listView())->themed) + QListViewItem::paintCell(p, cg, column, width, alignment); + else + KListViewItem::paintCell(p, cg, column, width, alignment); + } + QString login; }; @@ -188,12 +259,25 @@ QSize ns( 48, 48 ); if (p.size() != ns) p = p.convertDepth( 32 ).smoothScale( ns, QImage::ScaleMin ); - goto gotit; + break; } dp = 1 - dp; } while (--nd >= 0); - p = default_pix; - gotit: + + if ( p.isNull() && randomFaces.count() ) { + QString randomFace = randomFacesMap[username]; + if ( randomFace.isNull() ) { + QStringList::size_type index = 0; + for ( size_t i = 0; i < username.length(); ++i ) + index += ( 0x7f - username.at( i ).latin1() ) % 37; + randomFace = randomFaces[ index % randomFaces.count() ]; + } + p.load( _faceDir + "/../pics/users/" + randomFace + ".png" ); + } + + if ( p.isNull() ) + p = default_pix; + QString realname = KStringHandler::from8Bit( ps->pw_gecos ); realname.truncate( realname.find( ',' ) ); if (realname.isEmpty() || realname == username) @@ -244,7 +328,7 @@ } void -KGreeter::insertUsers() +KGreeter::insertUsers(int limit_users) { struct passwd *ps; @@ -271,6 +355,8 @@ if (_showUsers == SHOW_ALL) { UserList noUsers( _noUsers ); QDict dupes( 1000 ); + QStringList toinsert; + int count = 0; for (setpwent(); (ps = getpwent()) != 0;) { if (*ps->pw_dir && *ps->pw_shell && (ps->pw_uid >= (unsigned)_lowUserId || @@ -282,10 +368,53 @@ QString username( QFile::decodeName( ps->pw_name ) ); if (!dupes.find( username )) { dupes.insert( username, (int *)-1 ); - insertUser( default_pix, username, ps ); + toinsert.append( username ); + + if ( limit_users >= 0 && ++count > limit_users ) + break; } } } + if ( limit_users >= 0 && ++count > limit_users ) { + utmpname( _PATH_WTMP ); + setutxent(); + toinsert = QStringList(); + dupes.clear(); + + for ( count = 0; count < limit_users; ) { + struct utmpx * ent = getutxent(); + if ( !ent ) + break; + struct passwd *ps = getpwnam( ent->ut_user ); + if (ps && *ps->pw_dir && *ps->pw_shell && + (ps->pw_uid >= (unsigned)_lowUserId || + !ps->pw_uid && _showRoot) && + ps->pw_uid <= (unsigned)_highUserId && + !noUsers.hasUser( ps->pw_name ) && + !noUsers.hasGroup( ps->pw_gid )) + { + QString username( QFile::decodeName( ent->ut_user ) ); + if (!dupes.find( username )) { + dupes.insert( username, (int *)-1 ); + toinsert.append( username ); + count++; + } + } + + + } + endutxent(); + } + + for ( QStringList::ConstIterator it = toinsert.begin(); + it != toinsert.end(); ++it ) + { + // pretty stupid to do another lookup round, but the number is limited + // and caching struct passwd is pretty ugly + struct passwd *ps = getpwnam( QFile::encodeName( *it ) ); + if ( ps ) + insertUser( default_pix, *it, ps ); + } } else { UserList users( _users ); if (users.hasGroups()) { @@ -687,21 +816,24 @@ hbox2->addStretch( 1 ); if (sessMenu->count() > 1) { - inserten( i18n("Session &Type"), ALT+Key_T, sessMenu ); + inserten( i18n("Session &Type"), 0, sessMenu ); needSep = true; } if (plugMenu) { - inserten( i18n("&Authentication Method"), ALT+Key_A, plugMenu ); + inserten( i18n("&Authentication Method"), 0, plugMenu ); needSep = true; } #ifdef XDMCP - completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18n("&Remote Login"), ALT+Key_R ); + completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18n("&Remote Login"), 0 ); #else completeMenu(); #endif + if (userView || userList) + insertUsers(); + if (optMenu) menuButton->setPopup( optMenu ); else @@ -793,6 +925,9 @@ if (xauth_warning && (_authorized || !_authComplain)) xauth_warning->hide( true ); + if (userView || userList) + insertUsers( 7 ); // TODO: find out how many are a good value + // if (!_greetString.isEmpty()) { // } // clock = new KdmClock( this, "clock" ); @@ -818,37 +953,31 @@ if ((itm = themer->findNode( "session_button" ))) { if (sessMenu->count() <= 1) itm->hide( true ); - else { - session_button = itm; - QAccel *accel = new QAccel( this ); - accel->insertItem( ALT+Key_T, 0 ); - connect( accel, SIGNAL(activated( int )), SLOT(slotSessMenu()) ); - } + else + session_button = itm; } else { if (sessMenu->count() > 1) { - inserten( i18n("Session &Type"), ALT+Key_T, sessMenu ); + inserten( i18n("Session &Type"), 0, sessMenu ); needSep = true; } } if (plugMenu) { - inserten( i18n("&Authentication Method"), ALT+Key_A, plugMenu ); + inserten( i18n("&Authentication Method"), 0, plugMenu ); needSep = true; } #ifdef XDMCP - completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18n("&Remote Login"), ALT+Key_R ); + completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18n("&Remote Login"), 0 ); #else completeMenu(); #endif system_button = themer->findNode( "system_button" ); - QAccel *accel = new QAccel( this ); - accel->insertItem( ALT+Key_M, 0 ); - connect( accel, SIGNAL(activated( int )), SLOT(slotActionMenu()) ); pluginSetup(); + verify->start(); } @@ -866,8 +995,8 @@ inherited::pluginSetup(); if (userView && verify->entitiesLocal() && verify->entityPresettable() && userlist_rect) { + userView->setMaximumHeight( userView->sumHeight() ); userlist_rect->setWidget( userView ); - userView->show(); } else { if (userView) userView->hide(); @@ -883,12 +1012,17 @@ { // goButton->setEnabled( false ); inherited::verifyFailed(); + if (userView) + userView->setEnabled(false); } void KThemedGreeter::verifyRetry() { // goButton->setEnabled( true ); + if (userView) + userView->setEnabled(true); + } QString KThemedGreeter::timedUser = QString::null;