Back to index

kdeartwork  4.3.2
kclock.cpp
Go to the documentation of this file.
00001 // kclock - Clock screen saver for KDE
00002 //
00003 // Copyright (c) 2003, 2006, 2007, 2008 Melchior FRANZ <mfranz # kde : org>
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018 
00019 #include <QCheckBox>
00020 #include <QColor>
00021 #include <QGridLayout>
00022 #include <QGroupBox>
00023 #include <QHBoxLayout>
00024 #include <QImage>
00025 #include <QLabel>
00026 #include <QSlider>
00027 #include <QVBoxLayout>
00028 
00029 #include <KColorButton>
00030 #include <KConfig>
00031 #include <KGlobal>
00032 #include <KHBox>
00033 #include <KLocale>
00034 #include <KMessageBox>
00035 
00036 #include "kclock.h"
00037 #include "kclock.moc"
00038 
00039 
00040 const int COLOR_BUTTON_WIDTH = 80;
00041 const int TIMER_INTERVAL = 100;
00042 const int MAX_CLOCK_SIZE = 10;
00043 const unsigned int DEFAULT_CLOCK_SIZE = 8;
00044 const bool DEFAULT_KEEP_CENTERED = false;
00045 
00046 
00047 
00048 class KClockSaverInterface : public KScreenSaverInterface {
00049 public:
00050        virtual KAboutData *aboutData() {
00051               return new KAboutData("kclock.kss", "klock", ki18n("Clock"), "2.0", ki18n("Clock"));
00052        }
00053 
00054        virtual KScreenSaver *create(WId id) {
00055               return new KClockSaver(id);
00056        }
00057 
00058        virtual QDialog *setup() {
00059               return new KClockSetup();
00060        }
00061 };
00062 
00063 
00064 int main(int argc, char *argv[])
00065 {
00066        KClockSaverInterface kss;
00067        return kScreenSaverMain(argc, argv, kss);
00068 }
00069 
00070 
00071 //-----------------------------------------------------------------------------
00072 
00073 
00074 KClockSetup::KClockSetup(QWidget *parent) :
00075        KDialog(parent),
00076        _saver(0)
00077 {
00078        setCaption(i18n("Setup Clock Screen Saver"));
00079        setModal(true);
00080        setButtons(Ok|Cancel|Help);
00081        setDefaultButton(Ok);
00082 
00083        readSettings();
00084 
00085        setButtonText(Help, i18n("A&bout"));
00086        QWidget *main = new QWidget(this);
00087        setMainWidget(main);
00088 
00089        QVBoxLayout *top = new QVBoxLayout(main);
00090 
00091        QHBoxLayout *hbox = new QHBoxLayout;
00092        top->addLayout(hbox);
00093 
00094 
00095        QGroupBox *colgroup = new QGroupBox(i18n("Colors"), main);
00096        QGridLayout *grid = new QGridLayout();
00097 
00098        QLabel *label;
00099        KColorButton *colorButton;
00100 
00101        label = new QLabel(i18n("&Hour-hand:"));
00102        colorButton = new KColorButton(_hourColor);
00103        colorButton->setFixedWidth(COLOR_BUTTON_WIDTH);
00104        label->setBuddy(colorButton);
00105        connect(colorButton, SIGNAL(changed(const QColor &)),
00106                      SLOT(slotHourColor(const QColor &)));
00107        grid->addWidget(label, 1, 1);
00108        grid->addWidget(colorButton, 1, 2);
00109 
00110        label = new QLabel(i18n("&Minute-hand:"));
00111        colorButton = new KColorButton(_minColor);
00112        colorButton->setFixedWidth(COLOR_BUTTON_WIDTH);
00113        label->setBuddy(colorButton);
00114        connect(colorButton, SIGNAL(changed(const QColor &)),
00115                      SLOT(slotMinColor(const QColor &)));
00116        grid->addWidget(label, 2, 1);
00117        grid->addWidget(colorButton, 2, 2);
00118 
00119        label = new QLabel(i18n("&Second-hand:"));
00120        colorButton = new KColorButton(_secColor);
00121        colorButton->setFixedWidth(COLOR_BUTTON_WIDTH);
00122        label->setBuddy(colorButton);
00123        connect(colorButton, SIGNAL(changed(const QColor &)),
00124                      SLOT(slotSecColor(const QColor &)));
00125        grid->addWidget(label, 3, 1);
00126        grid->addWidget(colorButton, 3, 2);
00127 
00128        label = new QLabel(i18n("Scal&e:"));
00129        colorButton = new KColorButton(_scaleColor);
00130        colorButton->setFixedWidth(COLOR_BUTTON_WIDTH);
00131        label->setBuddy(colorButton);
00132        connect(colorButton, SIGNAL(changed(const QColor &)),
00133                      SLOT(slotScaleColor(const QColor &)));
00134        grid->addWidget(label, 4, 1);
00135        grid->addWidget(colorButton, 4, 2);
00136 
00137        label = new QLabel(i18n("&Background:"));
00138        colorButton = new KColorButton(_bgndColor);
00139        colorButton->setFixedWidth(COLOR_BUTTON_WIDTH);
00140        label->setBuddy(colorButton);
00141        connect(colorButton, SIGNAL(changed(const QColor &)),
00142                      SLOT(slotBgndColor(const QColor &)));
00143        grid->addWidget(label, 5, 1);
00144        grid->addWidget(colorButton, 5, 2);
00145 
00146        hbox->addWidget(colgroup);
00147        colgroup->setLayout(grid);
00148 
00149 
00150        QWidget *_preview = new QWidget(main);
00151        _preview->setFixedSize(220, 165);
00152        _preview->show();
00153        _saver = new KClockSaver(_preview->winId());
00154        hbox->addWidget(_preview);
00155 
00156        label = new QLabel(i18n("Si&ze:"), main);
00157        top->addWidget(label);
00158        QSlider *qs = new QSlider(Qt::Horizontal);
00159        label->setBuddy(qs);
00160        qs->setRange(0, MAX_CLOCK_SIZE);
00161        qs->setSliderPosition(_size);
00162        qs->setTickInterval(1);
00163        qs->setTickPosition(QSlider::TicksBelow);
00164        connect(qs, SIGNAL(valueChanged(int)), this, SLOT(slotSliderMoved(int)));
00165        top->addWidget(qs);
00166 
00167        KHBox *qsscale = new KHBox(main);
00168        label = new QLabel(i18n("Small"), qsscale);
00169        label->setAlignment(Qt::AlignLeading);
00170        label = new QLabel(i18n("Medium"), qsscale);
00171        label->setAlignment(Qt::AlignHCenter);
00172        label = new QLabel(i18n("Big"), qsscale);
00173        label->setAlignment(Qt::AlignTrailing);
00174        top->addWidget(qsscale);
00175 
00176        QCheckBox *keepCentered = new QCheckBox(i18n("&Keep clock centered"), main);
00177        keepCentered->setChecked(_keepCentered);
00178        connect(keepCentered, SIGNAL(stateChanged(int)), SLOT(slotKeepCenteredChanged(int)));
00179        top->addWidget(keepCentered);
00180        top->addStretch();
00181 
00182        connect(this, SIGNAL(okClicked()), this, SLOT(slotOk()));
00183        connect(this, SIGNAL(helpClicked()), this, SLOT(slotHelp()));
00184 }
00185 
00186 
00187 KClockSetup::~KClockSetup()
00188 {
00189        delete _saver;
00190 }
00191 
00192 
00193 void KClockSetup::readSettings()
00194 {
00195        KConfigGroup settings(KGlobal::config(), "Settings");
00196 
00197        _keepCentered = settings.readEntry("KeepCentered", DEFAULT_KEEP_CENTERED);
00198        _size = settings.readEntry("Size", DEFAULT_CLOCK_SIZE);
00199        if (_size > MAX_CLOCK_SIZE)
00200               _size = MAX_CLOCK_SIZE;
00201 
00202        KConfigGroup colors(KGlobal::config(), "Colors");
00203        QColor c = Qt::black;
00204        _bgndColor = colors.readEntry("Background", c);
00205 
00206        c = Qt::white;
00207        _scaleColor = colors.readEntry("Scale", c);
00208        _hourColor = colors.readEntry("HourHand", c);
00209        _minColor = colors.readEntry("MinuteHand", c);
00210 
00211        c = Qt::red;
00212        _secColor = colors.readEntry("SecondHand", c);
00213 
00214        if (_saver) {
00215               _saver->setBgndColor(_bgndColor);
00216               _saver->setScaleColor(_scaleColor);
00217               _saver->setHourColor(_hourColor);
00218               _saver->setMinColor(_minColor);
00219               _saver->setSecColor(_secColor);
00220        }
00221 }
00222 
00223 
00224 void KClockSetup::slotOk()
00225 {
00226        KConfigGroup settings(KGlobal::config(), "Settings");
00227        settings.writeEntry("Size", _size);
00228        settings.writeEntry("KeepCentered", _keepCentered);
00229        settings.sync();
00230 
00231        KConfigGroup colors(KGlobal::config(), "Colors");
00232        colors.writeEntry("Background", _bgndColor);
00233        colors.writeEntry("Scale", _scaleColor);
00234        colors.writeEntry("HourHand", _hourColor);
00235        colors.writeEntry("MinuteHand", _minColor);
00236        colors.writeEntry("SecondHand", _secColor);
00237        colors.sync();
00238        accept();
00239 }
00240 
00241 
00242 void KClockSetup::slotHelp()
00243 {
00244        KMessageBox::about(this, "<qt>" + i18n(
00245                      "Clock Screen Saver<br>"
00246                      "Version 2.0<br>"
00247                      "<nobr>Melchior FRANZ (c) 2003, 2006, 2007</nobr>") +
00248                      "<br><a href=\"mailto:mfranz@kde.org\">mfranz@kde.org</a>"
00249                      "</qt>", QString(), KMessageBox::AllowLink);
00250 }
00251 
00252 
00253 void KClockSetup::slotBgndColor(const QColor &color)
00254 {
00255        _bgndColor = color;
00256        if (_saver)
00257               _saver->setBgndColor(_bgndColor);
00258 }
00259 
00260 
00261 void KClockSetup::slotScaleColor(const QColor &color)
00262 {
00263        _scaleColor = color;
00264        if (_saver)
00265               _saver->setScaleColor(_scaleColor);
00266 }
00267 
00268 
00269 void KClockSetup::slotHourColor(const QColor &color)
00270 {
00271        _hourColor = color;
00272        if (_saver)
00273               _saver->setHourColor(_hourColor);
00274 }
00275 
00276 
00277 void KClockSetup::slotMinColor(const QColor &color)
00278 {
00279        _minColor = color;
00280        if (_saver)
00281               _saver->setMinColor(_minColor);
00282 }
00283 
00284 
00285 void KClockSetup::slotSecColor(const QColor &color)
00286 {
00287        _secColor = color;
00288        if (_saver)
00289               _saver->setSecColor(_secColor);
00290 }
00291 
00292 
00293 void KClockSetup::slotSliderMoved(int v)
00294 {
00295        if (_saver)
00296               _saver->resizeClock(_size = v);
00297 }
00298 
00299 
00300 void KClockSetup::slotKeepCenteredChanged(int c)
00301 {
00302        if (_saver)
00303               _saver->setKeepCentered(_keepCentered = c);
00304 }
00305 
00306 
00307 //-----------------------------------------------------------------------------
00308 
00309 
00310 ClockPainter::ClockPainter(QPaintDevice *device, int diameter) :
00311        QPainter(device)
00312 {
00313        setRenderHint(QPainter::Antialiasing);
00314        translate(diameter / 2.0, diameter / 2.0);
00315        scale(diameter / 2000.0, -diameter / 2000.0);
00316        setPen(Qt::NoPen);
00317 }
00318 
00319 
00320 void ClockPainter::drawTick(double angle, double from, double to, double width, const QColor &color, bool shadow)
00321 {
00322        save();
00323        rotate(90.0 - angle);
00324 
00325        if (shadow) {
00326               width += 1.0;
00327               setBrush(QColor(100, 100, 100));
00328        } else {
00329               setBrush(color);
00330        }
00331        drawRect(QRectF(from, -width / 2.0, to - from, width));
00332        restore();
00333 }
00334 
00335 
00336 void ClockPainter::drawDisc(double width, const QColor &color, bool shadow)
00337 {
00338        if (shadow) {
00339               width += 1.0;
00340               setBrush(QColor(100, 100, 100));
00341        } else {
00342               setBrush(color);
00343        }
00344        drawEllipse(QRectF(-width, -width, 2.0 * width, 2.0 * width));
00345 }
00346 
00347 
00348 void ClockPainter::drawHand(double angle, double length, double width, const QColor &color, bool disc)
00349 {
00350        if (disc)
00351               drawDisc(width * 1.3, color, true);
00352        drawTick(angle, 0.0, length, width, color, true);
00353 
00354        if (disc)
00355               drawDisc(width * 1.3, color, false);
00356        drawTick(angle, 0.0, length, width, color, false);
00357 
00358 }
00359 
00360 
00361 void ClockPainter::drawScale(const QColor &color)
00362 {
00363        for (int i = 0; i < 360; i += 6)
00364               if (i % 30)
00365                      drawTick(i, 920.0, 980.0, 15.0, color);
00366               else
00367                      drawTick(i, 825.0, 980.0, 40.0, color);
00368 }
00369 
00370 
00371 
00372 //-----------------------------------------------------------------------------
00373 
00374 
00375 
00376 KClockSaver::KClockSaver(WId id) :
00377        KScreenSaver(id),
00378        _timer(this),
00379        _xstep(1),
00380        _ystep(-1),
00381        _hour(-1),
00382        _minute(-1),
00383        _second(-1)
00384 {
00385        setAttribute(Qt::WA_NoSystemBackground);
00386        setMinimumSize(50, 50);
00387        readSettings();
00388        resizeClock(_size);
00389 
00390        QPalette p = palette();
00391        p.setColor(backgroundRole(), _bgndColor);
00392        setPalette(p);
00393 
00394        connect(&_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
00395        show();
00396 }
00397 
00398 
00399 void KClockSaver::readSettings()
00400 {
00401        KConfigGroup settings(KGlobal::config(), "Settings");
00402        _keepCentered = settings.readEntry("KeepCentered", DEFAULT_KEEP_CENTERED);
00403        _size = settings.readEntry("Size", DEFAULT_CLOCK_SIZE);
00404        if (_size > MAX_CLOCK_SIZE)
00405               _size = MAX_CLOCK_SIZE;
00406 
00407        KConfigGroup colors(KGlobal::config(), "Colors");
00408        QColor c = Qt::black;
00409        setBgndColor(colors.readEntry("Background", c));
00410 
00411        c = Qt::white;
00412        setScaleColor(colors.readEntry("Scale", c));
00413        setHourColor(colors.readEntry("HourHand", c));
00414        setMinColor(colors.readEntry("MinuteHand", c));
00415 
00416        c = Qt::red;
00417        setSecColor(colors.readEntry("SecondHand", c));
00418 }
00419 
00420 
00421 void KClockSaver::setKeepCentered(bool b)
00422 {
00423        _keepCentered = b;
00424        if (b) {
00425               _x = (width() - _diameter) / 2;
00426               _y = (height() - _diameter) / 2;
00427        }
00428        update();
00429 }
00430 
00431 
00432 void KClockSaver::resizeClock(int size)
00433 {
00434        _size = size;
00435        _diameter = qMin(width(), height()) * (_size + 4) / 14;
00436        _x = (width() - _diameter) / 2;
00437        _y = (height() - _diameter) / 2;
00438        update();
00439 }
00440 
00441 
00442 void KClockSaver::resizeEvent(QResizeEvent *)
00443 {
00444        resizeClock(_size);
00445 }
00446 
00447 
00448 void KClockSaver::showEvent(QShowEvent *)
00449 {
00450        _second = -1;
00451        slotTimeout();
00452        _timer.start(TIMER_INTERVAL);
00453 }
00454 
00455 
00456 void KClockSaver::hideEvent(QHideEvent *)
00457 {
00458        _timer.stop();
00459 }
00460 
00461 
00462 void KClockSaver::slotTimeout()
00463 {
00464        QTime t = QTime::currentTime();
00465        int s = t.second();
00466        if (s == _second)
00467               return;
00468 
00469        _second = _secColor != _bgndColor ? s : 0;
00470        _hour = t.hour();
00471        _minute = t.minute();
00472 
00473        if (!_keepCentered) {
00474               int i;
00475               _x += _xstep;
00476               if (_x <= 0)
00477                      _x = 0, _xstep = 1;
00478               else if (_x >= (i = width() - _diameter))
00479                      _x = i, _xstep = -1;
00480 
00481               _y += _ystep;
00482               if (_y <= 0)
00483                      _y = 0, _ystep = 1;
00484               else if (_y >= (i = height() - _diameter))
00485                      _y = i, _ystep = -1;
00486        }
00487        update();
00488 }
00489 
00490 
00491 void KClockSaver::paintEvent(QPaintEvent *)
00492 {
00493        double hour_angle = _hour * 30.0 + _minute * .5 + _second / 120.0;
00494        double minute_angle = _minute * 6.0 + _second * .1;
00495        double second_angle = _second * 6.0;
00496 
00497        QImage clock(_diameter, _diameter, QImage::Format_RGB32);
00498        ClockPainter c(&clock, _diameter);
00499        c.fillRect(-1000, -1000, 2000, 2000, _bgndColor);
00500 
00501        if (_scaleColor != _bgndColor)
00502               c.drawScale(_scaleColor);
00503        if (_hourColor != _bgndColor)
00504               c.drawHand(hour_angle, 600.0, 55.0, _hourColor, false);
00505        if (_minColor != _bgndColor)
00506               c.drawHand(minute_angle, 900.0, 40.0, _minColor);
00507        if (_secColor != _bgndColor)
00508               c.drawHand(second_angle, 900.0, 30.0, _secColor);
00509 
00510        QPainter p(this);
00511        p.drawImage(_x, _y, clock);
00512        p.eraseRect(0, 0, _x, height());                                        // left ver
00513        p.eraseRect(_x + _diameter, 0, width(), height());                      // right ver
00514        p.eraseRect(_x, 0, _diameter, _y);                                      // top hor
00515        p.eraseRect(_x, _y + _diameter, _diameter, height() - _y - _diameter);  // bottom hor
00516 }
00517 
00518