Qt3to4
[kdeartwork.git] / kscreensaver / kdesavers / kclock.cpp
blob831ca299cca51d32945bec859ebf4cbb03b86b98
1 // $Id$
2 //
3 // kclock - Clock screen saver for KDE
4 // Copyright (c) 2003 Melchior FRANZ
5 //
6 // License: GPL v2
7 // Author: Melchior FRANZ <mfranz@kde.org>
8 // Dependencies: libart_lgpl_2 http://www.levien.com/libart/
9 //
10 #include <stdlib.h>
11 #include <string.h>
13 #include <qcheckbox.h>
14 #include <qcolor.h>
15 #include <qdatetime.h>
16 #include <q3groupbox.h>
17 #include <q3hbox.h>
18 #include <qimage.h>
19 #include <qlabel.h>
20 #include <qlayout.h>
21 #include <qpainter.h>
22 #include <qslider.h>
23 //Added by qt3to4:
24 #include <QGridLayout>
25 #include <QHBoxLayout>
26 #include <QVBoxLayout>
28 #include <kapplication.h>
29 #include <kcolorbutton.h>
30 #include <kconfig.h>
31 #include <kglobal.h>
32 #include <klocale.h>
33 #include <kmessagebox.h>
35 #include <libart_lgpl/art_affine.h>
36 #include <libart_lgpl/art_misc.h>
37 #include <libart_lgpl/art_rgb.h>
38 #include <libart_lgpl/art_rgb_svp.h>
39 #include <libart_lgpl/art_svp_vpath.h>
40 #include <libart_lgpl/art_svp_vpath_stroke.h>
41 #include <libart_lgpl/art_vpath.h>
43 #include "kclock.h"
44 #include "kclock.moc"
47 const int COLOR_BUTTON_WIDTH = 80;
48 const int TIMER_INTERVALL = 100;
49 const int MAX_CLOCK_SIZE = 10;
50 const int DEFAULT_CLOCK_SIZE = 3;
51 const bool DEFAULT_KEEP_CENTERED = false;
56 extern "C" {
57 KDE_EXPORT const char *kss_applicationName = "kclock.kss";
58 KDE_EXPORT const char *kss_description = I18N_NOOP("Clock");
59 KDE_EXPORT const char *kss_version = "1.0";
61 KDE_EXPORT KScreenSaver *kss_create(WId id) {
62 return new KClockSaver(id);
65 KDE_EXPORT QDialog *kss_setup() {
66 return new KClockSetup();
73 //-----------------------------------------------------------------------------
75 KClockSetup::KClockSetup(QWidget *parent, const char *name)
76 : KDialogBase(parent, name, true, i18n( "Setup Clock Screen Saver" ),
77 Ok|Cancel|Help, Ok, true),
78 m_saver(0)
80 readSettings();
82 setButtonText( Help, i18n( "A&bout" ) );
83 QWidget *main = makeMainWidget();
85 QVBoxLayout *top = new QVBoxLayout(main, 0, spacingHint());
87 QHBoxLayout *hbox = new QHBoxLayout;
88 top->addLayout( hbox );
90 Q3GroupBox *colgroup = new Q3GroupBox(i18n("Colors"), main);
91 colgroup->setColumnLayout( 0, Horizontal );
92 QGridLayout *grid = new QGridLayout( colgroup->layout(),
93 5, 2, spacingHint() );
95 QLabel *label = new QLabel(i18n("&Hour-hand:"), colgroup);
96 KColorButton *colorButton = new KColorButton(m_hourColor, colgroup);
97 colorButton->setFixedWidth(COLOR_BUTTON_WIDTH);
98 label->setBuddy(colorButton);
99 connect(colorButton, SIGNAL(changed(const QColor &)),
100 SLOT(slotHourColor(const QColor &)));
101 grid->addWidget( label, 1, 1 );
102 grid->addWidget( colorButton, 1, 2 );
104 label = new QLabel(i18n("&Minute-hand:"), colgroup);
105 colorButton = new KColorButton(m_minColor, colgroup);
106 colorButton->setFixedWidth(COLOR_BUTTON_WIDTH);
107 label->setBuddy(colorButton);
108 connect(colorButton, SIGNAL(changed(const QColor &)),
109 SLOT(slotMinColor(const QColor &)));
110 grid->addWidget( label, 2, 1 );
111 grid->addWidget( colorButton, 2, 2 );
113 label = new QLabel(i18n("&Second-hand:"), colgroup);
114 colorButton = new KColorButton(m_secColor, colgroup);
115 colorButton->setFixedWidth(COLOR_BUTTON_WIDTH);
116 label->setBuddy(colorButton);
117 connect(colorButton, SIGNAL(changed(const QColor &)),
118 SLOT(slotSecColor(const QColor &)));
119 grid->addWidget( label, 3, 1 );
120 grid->addWidget( colorButton, 3, 2 );
122 label = new QLabel(i18n("Scal&e:"), colgroup);
123 colorButton = new KColorButton(m_scaleColor, colgroup);
124 colorButton->setFixedWidth(COLOR_BUTTON_WIDTH);
125 label->setBuddy(colorButton);
126 connect(colorButton, SIGNAL(changed(const QColor &)),
127 SLOT(slotScaleColor(const QColor &)));
128 grid->addWidget( label, 4, 1 );
129 grid->addWidget( colorButton, 4, 2 );
131 label = new QLabel(i18n("&Background:"), colgroup);
132 colorButton = new KColorButton(m_bgndColor, colgroup);
133 colorButton->setFixedWidth(COLOR_BUTTON_WIDTH);
134 label->setBuddy(colorButton);
135 connect(colorButton, SIGNAL(changed(const QColor &)),
136 SLOT(slotBgndColor(const QColor &)));
137 grid->addWidget( label, 5, 1 );
138 grid->addWidget( colorButton, 5, 2 );
140 hbox->addWidget(colgroup);
142 QWidget *m_preview = new QWidget(main);
143 m_preview->setFixedSize(220, 165);
144 m_preview->show();
145 m_saver = new KClockSaver(m_preview->winId());
146 hbox->addWidget(m_preview);
148 label = new QLabel( i18n( "Si&ze:" ), main );
149 top->addWidget( label );
150 QSlider *qs = new QSlider(0, MAX_CLOCK_SIZE, 1, m_size, Horizontal, main);
151 label->setBuddy( qs );
152 qs->setTickInterval(1);
153 qs->setTickmarks(QSlider::Below);
154 connect(qs, SIGNAL(valueChanged(int)), this, SLOT(slotSliderMoved(int)));
155 top->addWidget( qs );
157 bool rtl = kapp->reverseLayout();
158 Q3HBox *qsscale = new Q3HBox(main);
159 label = new QLabel(i18n("Small"), qsscale);
160 label->setAlignment(rtl ? AlignRight : AlignLeft);
161 label = new QLabel(i18n("Medium"), qsscale);
162 label->setAlignment(AlignHCenter);
163 label = new QLabel(i18n("Big"), qsscale);
164 label->setAlignment(rtl ? AlignLeft : AlignRight);
165 top->addWidget(qsscale);
167 QCheckBox *keepCentered = new QCheckBox(i18n("&Keep clock centered"), main);
168 keepCentered->setChecked(m_keepCentered);
169 connect(keepCentered, SIGNAL(stateChanged(int)), SLOT(slotKeepCenteredChanged(int)));
170 top->addWidget(keepCentered);
171 top->addStretch();
174 KClockSetup::~KClockSetup()
176 delete m_saver;
179 void KClockSetup::readSettings()
181 KConfig *config = KGlobal::config();
183 config->setGroup("Settings");
184 m_keepCentered = config->readBoolEntry("KeepCentered", DEFAULT_KEEP_CENTERED);
185 m_size = config->readUnsignedNumEntry("Size", DEFAULT_CLOCK_SIZE);
186 if (m_size > MAX_CLOCK_SIZE)
187 m_size = MAX_CLOCK_SIZE;
189 config->setGroup("Colors");
190 QColor c = Qt::black;
191 m_bgndColor = config->readColorEntry("Background", &c);
193 c = Qt::white;
194 m_scaleColor = config->readColorEntry("Scale", &c);
195 m_hourColor = config->readColorEntry("HourHand", &c);
196 m_minColor = config->readColorEntry("MinuteHand", &c);
198 c = Qt::red;
199 m_secColor = config->readColorEntry("SecondHand", &c);
201 if (m_saver) {
202 m_saver->setBgndColor(m_bgndColor);
203 m_saver->setScaleColor(m_scaleColor);
204 m_saver->setHourColor(m_hourColor);
205 m_saver->setMinColor(m_minColor);
206 m_saver->setSecColor(m_secColor);
211 void KClockSetup::slotOk()
213 KConfig *config = KGlobal::config();
214 config->setGroup("Settings");
215 config->writeEntry("Size", m_size);
216 config->writeEntry("KeepCentered", m_keepCentered);
218 config->setGroup("Colors");
219 config->writeEntry("Background", m_bgndColor);
220 config->writeEntry("Scale", m_scaleColor);
221 config->writeEntry("HourHand", m_hourColor);
222 config->writeEntry("MinuteHand", m_minColor);
223 config->writeEntry("SecondHand", m_secColor);
224 config->sync();
225 accept();
229 void KClockSetup::slotHelp()
231 KMessageBox::about(this, "<qt>" + i18n(
232 "Clock Screen Saver<br>"
233 "Version 1.0<br>"
234 "<nobr>Melchior FRANZ (c) 2003</nobr>") +
235 "<br><a href=\"mailto:mfranz@kde.org\">mfranz@kde.org</a>"
236 "</qt>", QString::null, KMessageBox::AllowLink);
240 void KClockSetup::slotBgndColor(const QColor &color)
242 m_bgndColor = color;
243 if (m_saver)
244 m_saver->setBgndColor(m_bgndColor);
248 void KClockSetup::slotScaleColor(const QColor &color)
250 m_scaleColor = color;
251 if (m_saver)
252 m_saver->setScaleColor(m_scaleColor);
256 void KClockSetup::slotHourColor(const QColor &color)
258 m_hourColor = color;
259 if (m_saver)
260 m_saver->setHourColor(m_hourColor);
264 void KClockSetup::slotMinColor(const QColor &color)
266 m_minColor = color;
267 if (m_saver)
268 m_saver->setMinColor(m_minColor);
272 void KClockSetup::slotSecColor(const QColor &color)
274 m_secColor = color;
275 if (m_saver)
276 m_saver->setSecColor(m_secColor);
280 void KClockSetup::slotSliderMoved(int v)
282 if (m_saver)
283 m_saver->restart(m_size = v);
287 void KClockSetup::slotKeepCenteredChanged(int c)
289 if (m_saver)
290 m_saver->setKeepCentered(m_keepCentered = c);
297 //-----------------------------------------------------------------------------
299 KClockPainter::KClockPainter(int width, int height)
300 : m_width(width),
301 m_height(height)
303 m_buf = new Q_UINT8[m_width * m_height * 3];
304 // build Cartesian coordinate system ranging from -1000 to +1000;
305 // points with positive x and y are in the top right quarter
306 m_matrix[0] = m_width / 2000.0;
307 m_matrix[1] = 0;
308 m_matrix[2] = 0;
309 m_matrix[3] = m_height / -2000.0;
310 m_matrix[4] = m_width / 2.0;
311 m_matrix[5] = m_height / 2.0;
315 KClockPainter::~KClockPainter()
317 delete[] m_buf;
321 void KClockPainter::copy(KClockPainter *p)
323 memcpy(m_buf, p->image(), m_width * m_height * 3);
327 void KClockPainter::drawToImage(QImage *q, int xoffs = 0, int yoffs = 0)
329 unsigned char *src = (unsigned char *)image();
330 for (int y = 0; y < m_height; y++) {
331 QRgb *dest = reinterpret_cast<QRgb *>(q->scanLine(y + yoffs)) + xoffs;
332 for (int x = 0; x < m_width; x++, src += 3)
333 *dest++ = qRgba(src[0], src[1], src[2], 255);
338 void KClockPainter::setColor(const QColor &c)
340 m_color = (c.red() << 24) | (c.green() << 16) | (c.blue() << 8) | 255;
344 void KClockPainter::setShadowColor(const QColor &c)
346 m_shadow = (c.red() << 24) | (c.green() << 16) | (c.blue() << 8) | 255;
350 void KClockPainter::fill(const QColor &c)
352 art_rgb_fill_run(m_buf, c.red(), c.green(), c.blue(), m_width * m_height);
356 void KClockPainter::drawRadial(double alpha, double r0, double r1, double width)
358 ArtVpath *vx, *v = art_new(ArtVpath, 3);
359 v[0].code = ART_MOVETO_OPEN;
360 v[0].x = r0;
361 v[0].y = 0;
362 v[1].code = ART_LINETO;
363 v[1].x = r1;
364 v[1].y = 0;
365 v[2].code = ART_END;
367 double m[6] = {0, 0, 0, 0, 0, 0};
368 art_affine_rotate(m, 90 - alpha);
369 vx = art_vpath_affine_transform(v, m);
370 art_free(v);
371 v = art_vpath_affine_transform(vx, m_matrix);
372 art_free(vx);
374 double w = width * m_matrix[0];
375 if (w < 1.0)
376 w = 1.0;
378 ArtSVP *path = art_svp_vpath_stroke(v, ART_PATH_STROKE_JOIN_MITER,
379 ART_PATH_STROKE_CAP_BUTT, w, 4, .5);
380 art_rgb_svp_alpha(path, 0, 0, m_width, m_height, m_color, m_buf, 3 * m_width, 0);
381 art_svp_free(path);
382 art_free(v);
386 void KClockPainter::drawDisc(double r)
388 ArtVpath *v, *vx = art_vpath_new_circle(0, 0, r);
389 v = art_vpath_affine_transform(vx, m_matrix);
390 art_free(vx);
392 ArtSVP *path = art_svp_from_vpath(v);
393 art_rgb_svp_alpha(path, 0, 0, m_width, m_height, m_color, m_buf, 3 * m_width, 0);
394 art_svp_free(path);
396 path = art_svp_vpath_stroke(v, ART_PATH_STROKE_JOIN_MITER,
397 ART_PATH_STROKE_CAP_BUTT, 2, 4, .5);
398 art_free(v);
400 art_rgb_svp_alpha(path, 0, 0, m_width, m_height, m_color, m_buf, 3 * m_width, 0);
401 art_svp_free(path);
405 void KClockPainter::drawHand(const QColor &c, double angle, double length,
406 double width, bool disc = true)
408 const double shadow_width = 1.0;
409 setColor(m_shadow);
410 if (disc)
411 drawDisc(width * 1.3 + shadow_width);
412 drawRadial(angle, .75 * width, length + shadow_width, width + shadow_width);
414 setColor(c);
415 if (disc)
416 drawDisc(width * 1.3);
417 drawRadial(angle, .75 * width, length, width);
425 //-----------------------------------------------------------------------------
427 KClockSaver::KClockSaver(WId id)
428 : KScreenSaver(id),
429 m_showSecond(true)
431 readSettings();
432 setBackgroundColor(m_bgndColor);
433 connect(&m_timer, SIGNAL(timeout()), SLOT(slotTimeout()));
434 start(m_size);
435 m_timer.start(TIMER_INTERVALL);
439 KClockSaver::~KClockSaver()
441 m_timer.stop();
442 stop();
446 void KClockSaver::start(int size)
448 m_diameter = int(QMIN(width(), height()) * (size + 4) / 14.0);
449 m_x = (width() - m_diameter) / 2;
450 m_y = (height() - m_diameter) / 2;
452 m_image = new QImage(m_diameter, m_diameter, 32);
453 m_scale = new KClockPainter(m_diameter, m_diameter);
454 m_clock = new KClockPainter(m_diameter, m_diameter);
456 m_clock->setShadowColor(qRgb((m_bgndColor.red() + m_scaleColor.red()) / 2,
457 (m_bgndColor.green() + m_scaleColor.green()) / 2,
458 (m_bgndColor.blue() + m_scaleColor.blue()) / 2));
459 drawScale();
460 forceRedraw();
464 void KClockSaver::stop()
466 delete m_clock;
467 delete m_scale;
468 delete m_image;
472 void KClockSaver::restart(int size)
474 m_timer.stop();
475 stop();
476 start(size);
477 drawScale();
478 m_timer.start(TIMER_INTERVALL);
482 void KClockSaver::setKeepCentered(bool b)
484 m_keepCentered = b;
485 if (b) {
486 m_x = (width() - m_diameter) / 2;
487 m_y = (height() - m_diameter) / 2;
489 forceRedraw();
493 void KClockSaver::readSettings()
495 KConfig *config = KGlobal::config();
497 config->setGroup("Settings");
498 m_keepCentered = config->readBoolEntry("KeepCentered", DEFAULT_KEEP_CENTERED);
499 m_size = config->readUnsignedNumEntry("Size", DEFAULT_CLOCK_SIZE);
500 if (m_size > MAX_CLOCK_SIZE)
501 m_size = MAX_CLOCK_SIZE;
503 config->setGroup("Colors");
504 QColor c = Qt::black;
505 m_bgndColor = config->readColorEntry("Background", &c);
507 c = Qt::white;
508 m_scaleColor = config->readColorEntry("Scale", &c);
509 m_hourColor = config->readColorEntry("HourHand", &c);
510 m_minColor = config->readColorEntry("MinuteHand", &c);
512 c = Qt::red;
513 m_secColor = config->readColorEntry("SecondHand", &c);
517 void KClockSaver::drawScale()
519 m_scale->fill(m_bgndColor);
520 m_scale->setColor(m_scaleColor);
522 for (int i = 0; i < 360; i += 6)
523 if (i % 30)
524 m_scale->drawRadial(i, 920, 980, 15);
525 else
526 m_scale->drawRadial(i, 825, 980, 40);
528 forceRedraw();
532 void KClockSaver::drawClock()
534 double hour_angle = m_hour * 30.0 + m_minute * .5;
535 double minute_angle = m_minute * 6.0 + m_second * .1;
536 double second_angle = m_second * 6.0;
538 m_clock->copy(m_scale);
539 m_clock->drawHand(m_hourColor, hour_angle, 600, 55, false);
540 m_clock->drawHand(m_minColor, minute_angle, 900, 40);
542 if (m_showSecond)
543 m_clock->drawHand(m_secColor, second_angle, 900, 30);
547 void KClockSaver::slotTimeout()
549 QTime t = QTime::currentTime();
550 int s = t.second();
551 if (s == m_second)
552 return;
554 m_second = m_showSecond ? s : 0;
555 m_hour = t.hour();
556 m_minute = t.minute();
558 drawClock();
559 QPainter p(this);
561 if (width() < 256) {
562 // intended for the control module preview: always fill the whole area
563 QImage *img = new QImage(width(), height(), 32);
564 img->fill(qRgb(m_bgndColor.red(), m_bgndColor.green(), m_bgndColor.blue()));
565 m_clock->drawToImage(img, m_x, m_y);
566 p.drawImage(0, 0, *img);
567 delete img;
568 } else {
569 m_clock->drawToImage(m_image);
570 p.drawImage(m_x, m_y, *m_image);
573 if (!m_keepCentered) {
574 static int xstep = 1;
575 static int ystep = -1;
576 int i;
578 m_x += xstep;
579 if (m_x <= 0)
580 m_x = 0, xstep = 1;
581 else if (m_x >= (i = width() - m_diameter))
582 m_x = i, xstep = -1;
584 m_y += ystep;
585 if (m_y <= 0)
586 m_y = 0, ystep = 1;
587 else if (m_y >= (i = height() - m_diameter))
588 m_y = i, ystep = -1;