4
* Copyright (C) 1998 Luca Montecchiani <m.luca@usa.net>
6
* Plasma analog-clock drawing code:
8
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
9
* Copyright 2007 by Riccardo Iaconelli <riccardo@kde.org>
11
* This program is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License as published by
13
* the Free Software Foundation; either version 2 of the License, or
14
* (at your option) any later version.
16
* This program is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU General Public License for more details.
21
* You should have received a copy of the GNU General Public License
22
* along with this program; if not, write to the Free Software
23
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31
#include <sys/types.h>
34
#include <QtGui/QGroupBox>
35
#include <QPushButton>
40
#include <QPaintEvent>
41
#include <QGridLayout>
42
#include <QHBoxLayout>
43
#include <QVBoxLayout>
47
#include <kstandarddirs.h>
48
#include <kmessagebox.h>
51
#include <kcolorscheme.h>
52
#include <ksystemtimezone.h>
53
#include <KTreeWidgetSearchLine>
61
Dtime::Dtime(QWidget * parent)
64
KGlobal::locale()->insertCatalog( "timezones4" );
67
connect(setDateTimeAuto, SIGNAL(toggled(bool)), this, SLOT(serverTimeCheck()));
68
connect(setDateTimeAuto, SIGNAL(toggled(bool)), SLOT(configChanged()));
70
timeServerList->setEditable(false);
71
connect(timeServerList, SIGNAL(activated(int)), SLOT(configChanged()));
72
connect(timeServerList, SIGNAL(editTextChanged(const QString &)), SLOT(configChanged()));
73
connect(setDateTimeAuto, SIGNAL(toggled(bool)), timeServerList, SLOT(setEnabled(bool)));
74
timeServerList->setEnabled(false);
75
timeServerList->setEditable(true);
77
if (ntpUtility.isEmpty()) {
78
setDateTimeAuto->setEnabled(false);
79
setDateTimeAuto->setToolTip(i18n("No NTP utility has been found. "
80
"Install 'ntpdate' or 'rdate' command to enable automatic "
81
"updating of date and time."));
84
QVBoxLayout *v2 = new QVBoxLayout( timeBox );
87
kclock = new Kclock( timeBox );
88
kclock->setObjectName("Kclock");
89
kclock->setMinimumSize(150,150);
90
v2->addWidget( kclock );
92
v2->addSpacing( KDialog::spacingHint() );
94
QHBoxLayout *v3 = new QHBoxLayout( );
99
timeEdit = new QTimeEdit( timeBox );
100
timeEdit->setWrapping(true);
101
timeEdit->setDisplayFormat("HH:mm:ss");
102
v3->addWidget(timeEdit);
106
QString wtstr = i18n("Here you can change the system time. Click into the"
107
" hours, minutes or seconds field to change the relevant value, either"
108
" using the up and down buttons to the right or by entering a new value.");
109
timeEdit->setWhatsThis( wtstr );
111
connect( timeEdit, SIGNAL(timeChanged(QTime)), SLOT(set_time()) );
112
connect( cal, SIGNAL(dateChanged(QDate)), SLOT(changeDate(QDate)));
114
connect( &internalTimer, SIGNAL(timeout()), SLOT(timeout()) );
116
kclock->setEnabled(false);
119
connect( tzonelist, SIGNAL(itemSelectionChanged()), SLOT(configChanged()) );
120
tzonesearch->setTreeWidget(tzonelist);
123
void Dtime::currentZone()
125
QByteArray result(100, '\0');
127
time_t now = ::time(0);
129
strftime(result.data(), result.size(), "%Z", localtime(&now));
130
m_local->setText(i18n("Current local time zone: %1 (%2)",
131
KTimeZoneWidget::displayName(KSystemTimeZones::local()),
132
QLatin1String(result)));
135
void Dtime::serverTimeCheck() {
136
bool enabled = !setDateTimeAuto->isChecked();
137
cal->setEnabled(enabled);
138
timeEdit->setEnabled(enabled);
139
//kclock->setEnabled(enabled);
142
void Dtime::findNTPutility(){
143
QByteArray envpath = qgetenv("PATH");
144
if (!envpath.isEmpty() && envpath[0] == ':') {
145
envpath = envpath.mid(1);
148
QString path = "/sbin:/usr/sbin:";
149
if (!envpath.isEmpty()) {
150
path += QString::fromLocal8Bit(envpath);
152
path += QLatin1String("/bin:/usr/bin");
155
foreach(const QString &possible_ntputility, QStringList() << "ntpdate" << "rdate" ) {
156
if( !((ntpUtility = KStandardDirs::findExe(possible_ntputility, path)).isEmpty()) ) {
157
kDebug() << "ntpUtility = " << ntpUtility;
162
kDebug() << "ntpUtility not found!";
165
void Dtime::set_time()
170
internalTimer.stop();
172
time = timeEdit->time();
173
kclock->setTime( time );
175
emit timeChanged( true );
178
void Dtime::changeDate(const QDate &d)
181
emit timeChanged( true );
184
void Dtime::configChanged(){
185
emit timeChanged( true );
190
// The config is actually written to the system config, but the user does not have any local config,
191
// since there is nothing writing it.
192
KConfig _config( "kcmclockrc", KConfig::NoGlobals );
193
KConfigGroup config(&_config, "NTP");
194
timeServerList->clear();
195
timeServerList->addItems(config.readEntry("servers",
196
i18n("Public Time Server (pool.ntp.org),\
198
europe.pool.ntp.org,\
199
north-america.pool.ntp.org,\
200
oceania.pool.ntp.org")).split(',', QString::SkipEmptyParts));
201
setDateTimeAuto->setChecked(config.readEntry("enabled", false));
203
// Reset to the current date and time
204
time = QTime::currentTime();
205
date = QDate::currentDate();
208
// start internal timer
209
internalTimer.start( 1000 );
216
// read the currently set time zone
217
tzonelist->setSelected(KSystemTimeZones::local().name(), true);
220
void Dtime::save( QVariantMap& helperargs )
222
// Save the order, but don't duplicate!
224
if( timeServerList->count() != 0)
225
list.append(timeServerList->currentText());
226
for ( int i=0; i<timeServerList->count();i++ ) {
227
QString text = timeServerList->itemText(i);
228
if( !list.contains(text) )
230
// Limit so errors can go away and not stored forever
231
if( list.count() == 10)
235
helperargs["ntp"] = true;
236
helperargs["ntpServers"] = list;
237
helperargs["ntpEnabled"] = setDateTimeAuto->isChecked();
238
helperargs["ntpUtility"] = ntpUtility;
240
if(setDateTimeAuto->isChecked() && !ntpUtility.isEmpty()){
241
// NTP Time setting - done in helper
242
timeServer = timeServerList->currentText();
243
kDebug() << "Setting date from time server " << timeServer;
247
QDateTime dt(date, QTime(timeEdit->time()));
249
kDebug() << "Set date " << dt;
251
helperargs["date"] = true;
252
helperargs["newdate"] = QString::number(dt.toTime_t());
253
helperargs["olddate"] = QString::number(::time(0));
257
internalTimer.start( 1000 );
259
QStringList selectedZones(tzonelist->selection());
261
if (selectedZones.count() > 0) {
262
QString selectedzone(selectedZones[0]);
263
helperargs["tz"] = true;
264
helperargs["tzone"] = selectedzone;
266
helperargs["tzreset"] = true; // // make the helper reset the timezone
272
void Dtime::processHelperErrors( int code )
274
if( code & ClockHelper::NTPError ) {
275
KMessageBox::error( this, i18n("Unable to contact time server: %1.", timeServer) );
276
setDateTimeAuto->setChecked( false );
278
if( code & ClockHelper::DateError ) {
279
KMessageBox::error( this, i18n("Can not set date."));
281
if( code & ClockHelper::TimezoneError)
282
KMessageBox::error( this, i18n("Error setting new time zone."),
283
i18n("Time zone Error"));
286
void Dtime::timeout()
289
time = QTime::currentTime();
292
timeEdit->setTime(time);
295
kclock->setTime( time );
298
QString Dtime::quickHelp() const
300
return i18n("<h1>Date & Time</h1> This system settings module can be used to set the system date and"
301
" time. As these settings do not only affect you as a user, but rather the whole system, you"
302
" can only change these settings when you start the System Settings as root. If you do not have"
303
" the root password, but feel the system time should be corrected, please contact your system"
307
Kclock::Kclock(QWidget *parent)
310
m_theme = new Plasma::Svg(this);
311
m_theme->setImagePath("widgets/clock");
312
m_theme->setContainsMultipleImages(true);
320
void Kclock::showEvent( QShowEvent *event )
322
setClockSize( size() );
323
QWidget::showEvent( event );
326
void Kclock::resizeEvent( QResizeEvent * )
328
setClockSize( size() );
331
void Kclock::setClockSize(const QSize &size)
333
int dim = qMin(size.width(), size.height());
334
QSize newSize = QSize(dim, dim);
336
if (newSize != m_faceCache.size()) {
337
m_faceCache = QPixmap(newSize);
338
m_handsCache = QPixmap(newSize);
339
m_glassCache = QPixmap(newSize);
341
m_theme->resize(newSize);
342
m_repaintCache = RepaintAll;
346
void Kclock::setTime(const QTime &time)
348
if (time.minute() != this->time.minute() || time.hour() != this->time.hour()) {
349
if (m_repaintCache == RepaintNone) {
350
m_repaintCache = RepaintHands;
357
void Kclock::drawHand(QPainter *p, const QRect &rect, const qreal verticalTranslation, const qreal rotation, const QString &handName)
359
// this code assumes the following conventions in the svg file:
360
// - the _vertical_ position of the hands should be set with respect to the center of the face
361
// - the _horizontal_ position of the hands does not matter
362
// - the _shadow_ elements should have the same vertical position as their _hand_ element counterpart
365
QString name = handName + "HandShadow";
366
if (m_theme->hasElement(name)) {
369
elementRect = m_theme->elementRect(name);
370
if( rect.height() < 64 )
371
elementRect.setWidth( elementRect.width() * 2.5 );
372
static const QPoint offset = QPoint(2, 3);
374
p->translate(rect.x() + (rect.width() / 2) + offset.x(), rect.y() + (rect.height() / 2) + offset.y());
376
p->translate(-elementRect.width()/2, elementRect.y()-verticalTranslation);
377
m_theme->paint(p, QRectF(QPointF(0, 0), elementRect.size()), name);
384
name = handName + "Hand";
385
elementRect = m_theme->elementRect(name);
386
if (rect.height() < 64) {
387
elementRect.setWidth(elementRect.width() * 2.5);
390
p->translate(rect.x() + rect.width()/2, rect.y() + rect.height()/2);
392
p->translate(-elementRect.width()/2, elementRect.y()-verticalTranslation);
393
m_theme->paint(p, QRectF(QPointF(0, 0), elementRect.size()), name);
398
void Kclock::paintInterface(QPainter *p, const QRect &rect)
400
const bool m_showSecondHand = true;
402
// compute hand angles
403
const qreal minutes = 6.0 * time.minute() - 180;
404
const qreal hours = 30.0 * time.hour() - 180 +
405
((time.minute() / 59.0) * 30.0);
407
if (m_showSecondHand) {
408
static const double anglePerSec = 6;
409
seconds = anglePerSec * time.second() - 180;
412
// paint face and glass cache
413
QRect faceRect = m_faceCache.rect();
414
if (m_repaintCache == RepaintAll) {
415
m_faceCache.fill(Qt::transparent);
416
m_glassCache.fill(Qt::transparent);
418
QPainter facePainter(&m_faceCache);
419
QPainter glassPainter(&m_glassCache);
420
facePainter.setRenderHint(QPainter::SmoothPixmapTransform);
421
glassPainter.setRenderHint(QPainter::SmoothPixmapTransform);
423
m_theme->paint(&facePainter, m_faceCache.rect(), "ClockFace");
426
QRectF elementRect = QRectF(QPointF(0, 0), m_theme->elementSize("HandCenterScrew"));
427
glassPainter.translate(faceRect.width() / 2 - elementRect.width() / 2, faceRect.height() / 2 - elementRect.height() / 2);
428
m_theme->paint(&glassPainter, elementRect, "HandCenterScrew");
429
glassPainter.restore();
431
m_theme->paint(&glassPainter, faceRect, "Glass");
433
// get vertical translation, see drawHand() for more details
434
m_verticalTranslation = m_theme->elementRect("ClockFace").center().y();
437
// paint hour and minute hands cache
438
if (m_repaintCache == RepaintHands || m_repaintCache == RepaintAll) {
439
m_handsCache.fill(Qt::transparent);
441
QPainter handsPainter(&m_handsCache);
442
handsPainter.drawPixmap(faceRect, m_faceCache, faceRect);
443
handsPainter.setRenderHint(QPainter::SmoothPixmapTransform);
445
drawHand(&handsPainter, faceRect, m_verticalTranslation, hours, "Hour");
446
drawHand(&handsPainter, faceRect, m_verticalTranslation, minutes, "Minute");
449
// reset repaint cache flag
450
m_repaintCache = RepaintNone;
452
// paint caches and second hand
453
QRect targetRect = faceRect;
454
if (targetRect.width() < rect.width()) {
455
targetRect.moveLeft((rect.width() - targetRect.width()) / 2);
458
p->drawPixmap(targetRect, m_handsCache, faceRect);
459
if (m_showSecondHand) {
460
p->setRenderHint(QPainter::SmoothPixmapTransform);
461
drawHand(p, targetRect, m_verticalTranslation, seconds, "Second");
463
p->drawPixmap(targetRect, m_glassCache, faceRect);
466
void Kclock::paintEvent( QPaintEvent * )
468
QPainter paint(this);
470
paint.setRenderHint(QPainter::Antialiasing);
471
paintInterface(&paint, rect());