add more spacing
[personal-kdebase.git] / workspace / kdm / kfrontend / themer / kdmlabel.cpp
bloba2e176abf322cec5f870958db9f7a915c56b9b01
1 /*
2 * Copyright (C) 2003 by Unai Garro <ugarro@users.sourceforge.net>
3 * Copyright (C) 2004 by Enrico Ros <rosenric@dei.unipd.it>
4 * Copyright (C) 2004 by Stephan Kulow <coolo@kde.org>
5 * Copyright (C) 2004 by Oswald Buddenhagen <ossi@kde.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "kdmlabel.h"
24 #include <config-workspace.h>
25 #include <config-kdm.h>
27 #include "kdmthemer.h"
29 #include <kglobal.h>
30 #include <klocale.h>
31 #include <kmacroexpander.h>
33 #include <QAction>
34 #include <QDateTime>
35 #include <QFontMetrics>
36 #include <QHash>
37 #include <QPainter>
38 #include <QTimer>
39 #include <QX11Info>
41 #include <X11/Xlib.h>
43 #include <unistd.h>
44 #include <sys/utsname.h>
45 #if !defined(HAVE_GETDOMAINNAME) && defined(HAVE_SYS_SYSTEMINFO)
46 # include <sys/systeminfo.h>
47 #endif
49 KdmLabel::KdmLabel( QObject *parent, const QDomNode &node )
50 : KdmItem( parent, node )
51 , action( 0 )
53 itemType = "label";
54 if (!isVisible())
55 return;
57 // Set default values for label (note: strings are already Null)
58 label.normal.font = label.active.font = label.prelight.font = style.font;
59 label.normal.color = label.active.color = label.prelight.color =
60 style.palette.isBrushSet( QPalette::Normal, QPalette::WindowText ) ?
61 style.palette.color( QPalette::Normal, QPalette::WindowText ) :
62 QColor( Qt::white );
63 label.active.present = false;
64 label.prelight.present = false;
66 const QString locale = KGlobal::locale()->language();
68 // Read LABEL TAGS
69 QDomNodeList childList = node.childNodes();
70 bool stockUsed = false;
71 for (int nod = 0; nod < childList.count(); nod++) {
72 QDomNode child = childList.item( nod );
73 QDomElement el = child.toElement();
74 QString tagName = el.tagName();
76 if (tagName == "normal") {
77 parseColor( el, label.normal.color );
78 parseFont( el, label.normal.font );
79 } else if (tagName == "active") {
80 label.active.present = true;
81 parseColor( el, label.active.color );
82 parseFont( el, label.active.font );
83 } else if (tagName == "prelight") {
84 label.prelight.present = true;
85 parseColor( el, label.prelight.color );
86 parseFont( el, label.prelight.font );
87 } else if (tagName == "text" && el.attributes().count() == 0 && !stockUsed) {
88 label.text = el.text();
89 } else if (tagName == "text" && !stockUsed) {
90 QString lang = el.attribute( "xml:lang", "" );
91 if (lang == locale)
92 label.text = el.text();
93 } else if (tagName == "stock") {
94 label.text = lookupStock( el.attribute( "type", "" ) );
95 stockUsed = true;
99 label.isTimer = label.text.indexOf( "%c" ) >= 0;
100 if (label.isTimer) {
101 timer = new QTimer( this );
102 timer->start( 1000 );
103 connect( timer, SIGNAL(timeout()), SLOT(update()) );
106 zeroWidth = QFontMetrics( label.normal.font.font ).width( '0' );
108 label.text.replace( '\n', ' ' );
109 setCText( lookupText( label.text ) );
112 void
113 KdmLabel::setText( const QString &txt )
115 label.text = txt;
116 label.text.replace( '\n', ' ' );
117 update();
120 void
121 KdmLabel::setCText( const QString &txt )
123 delete action;
124 action = 0;
125 pText = cText = txt;
126 pAccelOff = txt.indexOf( '_' );
127 if (pAccelOff >= 0) {
128 action = new QAction( this );
129 action->setShortcut( Qt::ALT + txt[pAccelOff + 1].unicode() );
130 connect( action, SIGNAL(triggered( bool )), SLOT(activate()) );
131 emit needPlugging();
132 pText.remove( pAccelOff, 1 );
134 QRect bbox = QFontMetrics( label.normal.font.font ).boundingRect( pText );
135 QSize newSize = bbox.size();
136 if (newSize.width() > pTextSize.width() ||
137 (newSize.width() < (pTextSize.width() - zeroWidth)))
139 if (label.isTimer)
140 newSize.rwidth() += zeroWidth;
141 pTextSize = newSize;
142 emit needPlacement();
144 pTextIndent = bbox.left();
147 void
148 KdmLabel::activate()
150 KdmItem *cp = this;
151 do {
152 if (cp->isButton) {
153 emit activated( cp->objectName() );
154 return;
156 cp = qobject_cast<KdmItem *>(cp->parent());
157 } while (cp);
158 if (!buddy.isEmpty())
159 activateBuddy();
162 void
163 KdmLabel::doPlugActions( bool plug )
165 if (action) {
166 QWidget *w = themer()->widget();
167 if (plug)
168 w->addAction( action );
169 else
170 w->removeAction( action );
174 QSize
175 KdmLabel::sizeHint()
177 return pTextSize;
180 void
181 KdmLabel::drawContents( QPainter *p, const QRect &r )
183 // choose the correct label class
184 struct LabelStruct::LabelClass *l = &label.normal;
185 if (state == Sactive && label.active.present)
186 l = &label.active;
187 else if (state == Sprelight && label.prelight.present)
188 l = &label.prelight;
189 // draw the label
190 p->setFont( l->font.font );
191 p->setPen( l->color );
192 p->setClipRect( r );
193 if (pAccelOff != -1) {
194 QRect tarea( area );
195 tarea.setLeft( tarea.left() - pTextIndent );
196 QFontMetrics fm( l->font.font );
197 QString left = pText.left( pAccelOff );
198 p->drawText( area, 0, left );
199 tarea.setLeft( tarea.left() + fm.width( left ) );
200 QFont f( l->font.font );
201 f.setUnderline( true );
202 p->setFont( f );
203 QString acc( pText[pAccelOff] );
204 p->drawText( tarea, 0, acc );
205 tarea.setLeft( tarea.left() + fm.width( acc ) );
206 p->setFont( l->font.font );
207 p->drawText( tarea, 0, pText.mid( pAccelOff + 1 ) );
208 } else
209 p->drawText( area, 0, cText );
210 p->setClipping( false );
213 void
214 KdmLabel::statusChanged( bool descend )
216 KdmItem::statusChanged( descend );
217 if (!label.active.present && !label.prelight.present)
218 return;
219 if ((state == Sprelight && !label.prelight.present) ||
220 (state == Sactive && !label.active.present))
221 return;
222 needUpdate();
225 void
226 KdmLabel::update()
228 KdmItem::update();
229 QString text = lookupText( label.text );
230 if (text != cText) {
231 setCText( text );
232 needUpdate();
236 #undef I18N_NOOP
237 #define I18N_NOOP(t) 0, t
238 #undef I18N_NOOP2
239 #define I18N_NOOP2(c,t) c, t
241 static const struct {
242 const char *type, *comment, *text;
243 } stocks[] = {
244 { "language", I18N_NOOP2("@action:button", "Lan_guage") },
245 { "session", I18N_NOOP2("@action:button", "Session _Type") },
246 { "system", I18N_NOOP2("@action:button", "_Menu") }, // i18n("Actions");
247 { "disconnect", I18N_NOOP2("@action:button ... from XDMCP server", "Disconn_ect") },
248 { "quit", I18N_NOOP2("@action:button", "_Quit") },
249 { "halt", I18N_NOOP2("@action:button", "Power o_ff") },
250 // { "suspend", I18N_NOOP2("@action:button", "_Suspend") },
251 { "reboot", I18N_NOOP2("@action:button", "Re_boot") },
252 { "chooser", I18N_NOOP2("@action:button", "_Remote login") },
253 { "caps-lock-warning", I18N_NOOP("Caps Lock is enabled") },
254 { "timed-label", I18N_NOOP("User %u will log in in %t") },
255 { "welcome-label", I18N_NOOP("Welcome to %h") }, // _greetString
256 { "domain-label", I18N_NOOP("_Domain:") },
257 { "username-label", I18N_NOOP("_Username:") },
258 { "password-label", I18N_NOOP("_Password:") },
259 { "login", I18N_NOOP2("@action:button", "_Login") }
262 // public static
263 QString
264 KdmLabel::lookupStock( const QString &stock )
266 QString type( stock.toLower() );
268 for (uint i = 0; i < sizeof(stocks)/sizeof(stocks[0]); i++)
269 if (type == stocks[i].type) {
270 if (stocks[i].comment)
271 return i18nc(stocks[i].comment, stocks[i].text);
272 else
273 return i18n(stocks[i].text);
276 kWarning() << "Invalid <stock> element '" << stock << "'. Check your theme!";
277 return stock;
280 QString KdmLabel::timedUser = QString();
281 int KdmLabel::timedDelay = -1;
282 QHash<QChar,QString> KdmLabel::expandoMap;
283 bool KdmLabel::dateFormatSet = false;
285 bool
286 KdmLabel::expandMacro( QChar chr, QStringList &ret )
288 switch (chr.unicode()) {
289 case 't':
290 ret << i18ncp( "will login in ...", "1 second", "%1 seconds", timedDelay );
291 return true;
292 case 'u':
293 ret << timedUser;
294 return true;
295 case 'c':
296 if (!dateFormatSet) {
297 // xgettext:no-c-format
298 KGlobal::locale()->setDateFormat( i18nc("date format", "%a %d %B") );
299 dateFormatSet = true;
301 ret << KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(), KLocale::LongDate );
302 return true;
305 if (expandoMap.isEmpty()) {
306 struct utsname uts;
307 uname( &uts );
308 expandoMap['d'] = QString::fromLocal8Bit( DisplayString( QX11Info::display() ) );
309 expandoMap['n'] = QString::fromLocal8Bit( uts.nodename );
310 expandoMap['s'] = QString::fromLocal8Bit( uts.sysname );
311 expandoMap['r'] = QString::fromLocal8Bit( uts.release );
312 expandoMap['m'] = QString::fromLocal8Bit( uts.machine );
313 char buf[256];
314 buf[sizeof(buf) - 1] = '\0';
315 expandoMap['h'] = gethostname( buf, sizeof(buf) - 1 ) ? "localhost" : QString::fromLocal8Bit( buf );
316 #ifdef HAVE_GETDOMAINNAME
317 expandoMap['o'] = getdomainname( buf, sizeof(buf) - 1 ) ? "localdomain" : QString::fromLocal8Bit( buf );
318 #elif defined(HAVE_SYS_SYSTEMINFO)
319 expandoMap['o'] = (unsigned)sysinfo( SI_SRPC_DOMAIN, buf, sizeof(buf) ) > sizeof(buf) ? "localdomain" : QString::fromLocal8Bit( buf );
320 #endif
322 QHash<QChar,QString>::const_iterator mi = expandoMap.constFind(chr);
323 if (mi != expandoMap.constEnd()) {
324 ret << mi.value();
325 return true;
328 return false;
331 QString
332 KdmLabel::lookupText( const QString &t )
334 QString text = t;
335 expandMacros( text );
336 return text;
339 #include "kdmlabel.moc"