dtor first
[personal-kdebase.git] / workspace / kcontrol / dateandtime / dtime.cpp
blob6d44fcd91dce92859f92a685fa0facf66b868f0f
1 /*
2 * dtime.cpp
4 * Copyright (C) 1998 Luca Montecchiani <m.luca@usa.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "dtime.h"
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <time.h>
26 #include <sys/types.h>
28 #include <QComboBox>
29 #include <QtGui/QGroupBox>
30 #include <QPushButton>
31 #include <QPainter>
32 #include <QLayout>
33 #include <QLabel>
35 #include <QCheckBox>
36 #include <QRegExp>
37 #include <QPaintEvent>
38 #include <QGridLayout>
39 #include <QHBoxLayout>
40 #include <QVBoxLayout>
41 #include <QApplication>
42 #include <QPolygon>
43 #include <kdebug.h>
44 #include <klocale.h>
45 #include <kprocess.h>
46 #include <kstandarddirs.h>
47 #include <kmessagebox.h>
48 #include <kdialog.h>
49 #include <kconfig.h>
50 #include <kcolorscheme.h>
52 #include "dtime.moc"
54 #include "helper.h"
56 HMSTimeWidget::HMSTimeWidget(QWidget *parent) :
57 KIntSpinBox(parent)
61 QString HMSTimeWidget::mapValueToText(int value)
63 QString s = QString::number(value);
64 if( value < 10 ) {
65 s = '0' + s;
67 return s;
70 Dtime::Dtime(QWidget * parent)
71 : QWidget(parent)
73 // *************************************************************
74 // Start Dialog
75 // *************************************************************
77 // Time Server
79 privateLayoutWidget = new QWidget( this );
80 QHBoxLayout *layout1 = new QHBoxLayout( privateLayoutWidget );
81 layout1->setObjectName( "ntplayout" );
82 layout1->setSpacing( 0 );
83 layout1->setMargin( 0 );
85 setDateTimeAuto = new QCheckBox( privateLayoutWidget );
86 setDateTimeAuto->setObjectName( "setDateTimeAuto" );
87 setDateTimeAuto->setText(i18n("Set date and time &automatically:"));
88 connect(setDateTimeAuto, SIGNAL(toggled(bool)), this, SLOT(serverTimeCheck()));
89 connect(setDateTimeAuto, SIGNAL(toggled(bool)), SLOT(configChanged()));
90 layout1->addWidget( setDateTimeAuto );
92 timeServerList = new QComboBox( privateLayoutWidget );
93 timeServerList->setObjectName( "timeServerList" );
94 timeServerList->setEditable(false);
95 connect(timeServerList, SIGNAL(activated(int)), SLOT(configChanged()));
96 connect(timeServerList, SIGNAL(editTextChanged(const QString &)), SLOT(configChanged()));
97 connect(setDateTimeAuto, SIGNAL(toggled(bool)), timeServerList, SLOT(setEnabled(bool)));
98 timeServerList->setEnabled(false);
99 timeServerList->setEditable(true);
100 layout1->addWidget( timeServerList );
101 findNTPutility();
103 // Date box
104 QGroupBox* dateBox = new QGroupBox( this );
105 dateBox->setObjectName( QLatin1String( "dateBox" ) );
107 QVBoxLayout *l1 = new QVBoxLayout( dateBox );
108 l1->setMargin( 0 );
109 l1->setSpacing( KDialog::spacingHint() );
111 cal = new KDatePicker( dateBox );
112 cal->setMinimumSize(cal->sizeHint());
113 l1->addWidget( cal );
114 cal->setWhatsThis( i18n("Here you can change the system date's day of the month, month and year.") );
116 // Time frame
117 QGroupBox* timeBox = new QGroupBox( this );
118 timeBox->setObjectName( QLatin1String( "timeBox" ) );
120 QVBoxLayout *v2 = new QVBoxLayout( timeBox );
121 v2->setMargin( 0 );
122 v2->setSpacing( KDialog::spacingHint() );
124 kclock = new Kclock( timeBox );
125 kclock->setObjectName("Kclock");
126 kclock->setMinimumSize(150,150);
127 v2->addWidget( kclock );
129 QGridLayout *v3 = new QGridLayout( );
130 v2->addItem( v3 );
132 // Even if the module's widgets are reversed (usually when using RTL
133 // languages), the placing of the time fields must always be H:M:S, from
134 // left to right.
135 bool isRTL = QApplication::isRightToLeft();
137 QSpacerItem *spacer1 = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
138 v3->addItem(spacer1, 0, 1, 2, 1);
140 hour = new HMSTimeWidget( timeBox );
141 hour->setWrapping(true);
142 hour->setMaximum(23);
143 #ifdef __GNUC__
144 #warning fixme hour->setValidator(new KStrictIntValidator(0, 23, hour));
145 #endif
146 v3->addWidget(hour, 0, isRTL ? 6 : 2, 2, 1);
148 QLabel *dots1 = new QLabel(":", timeBox);
149 dots1->setMinimumWidth( 7 );
150 dots1->setAlignment( Qt::AlignCenter );
151 v3->addWidget(dots1, 0, 3, 2, 1);
153 minute = new HMSTimeWidget( timeBox );
154 minute->setWrapping(true);
155 minute->setMinimum(0);
156 minute->setMaximum(59);
157 #ifdef __GNUC__
158 #warning fixme minute->setValidator(new KStrictIntValidator(0, 59, minute));
159 #endif
160 v3->addWidget(minute, 0, 4, 2, 1);
162 QLabel *dots2 = new QLabel(":", timeBox);
163 dots2->setMinimumWidth( 7 );
164 dots2->setAlignment( Qt::AlignCenter );
165 v3->addWidget(dots2, 0, 5, 2, 1);
167 second = new HMSTimeWidget( timeBox );
168 second->setWrapping(true);
169 second->setMinimum(0);
170 second->setMaximum(59);
171 #ifdef __GNUC__
172 #warning fixme second->setValidator(new KStrictIntValidator(0, 59, second));
173 #endif
174 v3->addWidget(second, 0, isRTL ? 2 : 6, 2, 1);
176 v3->addItem(new QSpacerItem(7, 0), 0, 7);
178 QString wtstr = i18n("Here you can change the system time. Click into the"
179 " hours, minutes or seconds field to change the relevant value, either"
180 " using the up and down buttons to the right or by entering a new value.");
181 hour->setWhatsThis( wtstr );
182 minute->setWhatsThis( wtstr );
183 second->setWhatsThis( wtstr );
185 QSpacerItem *spacer3 = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
186 v3->addItem(spacer3, 0, 9, 2, 1);
188 QGridLayout *top = new QGridLayout( this );
189 top->setMargin( 0 );
190 top->setSpacing( KDialog::spacingHint() );
192 top->addWidget(dateBox, 1,0);
193 top->addWidget(timeBox, 1,1);
194 top->addWidget(privateLayoutWidget, 0, 0, 1, 2 );
196 // *************************************************************
197 // End Dialog
198 // *************************************************************
200 connect( hour, SIGNAL(valueChanged(int)), SLOT(set_time()) );
201 connect( minute, SIGNAL(valueChanged(int)), SLOT(set_time()) );
202 connect( second, SIGNAL(valueChanged(int)), SLOT(set_time()) );
203 connect( cal, SIGNAL(dateChanged(QDate)), SLOT(changeDate(QDate)));
205 connect( &internalTimer, SIGNAL(timeout()), SLOT(timeout()) );
207 load();
209 kclock->setEnabled(false);
212 void Dtime::serverTimeCheck() {
213 bool enabled = !setDateTimeAuto->isChecked();
214 cal->setEnabled(enabled);
215 hour->setEnabled(enabled);
216 minute->setEnabled(enabled);
217 second->setEnabled(enabled);
218 //kclock->setEnabled(enabled);
221 void Dtime::findNTPutility(){
222 if(!KStandardDirs::findExe("ntpdate").isEmpty()) {
223 ntpUtility = "ntpdate";
224 kDebug() << "ntpUtility = " << ntpUtility;
225 return;
227 if(!KStandardDirs::findExe("rdate").isEmpty()) {
228 ntpUtility = "rdate";
229 kDebug() << "ntpUtility = " << ntpUtility;
230 return;
232 privateLayoutWidget->hide();
233 kDebug() << "ntpUtility not found!";
236 void Dtime::set_time()
238 if( ontimeout )
239 return;
241 internalTimer.stop();
243 time.setHMS( hour->value(), minute->value(), second->value() );
244 kclock->setTime( time );
246 emit timeChanged( true );
249 void Dtime::changeDate(const QDate &d)
251 date = d;
252 emit timeChanged( true );
255 void Dtime::configChanged(){
256 emit timeChanged( true );
259 void Dtime::load()
261 // The config is actually written to the system config, but the user does not have any local config,
262 // since there is nothing writing it.
263 KConfig _config( "kcmclockrc", KConfig::NoGlobals );
264 KConfigGroup config(&_config, "NTP");
265 timeServerList->addItems(config.readEntry("servers",
266 i18n("Public Time Server (pool.ntp.org),\
267 asia.pool.ntp.org,\
268 europe.pool.ntp.org,\
269 north-america.pool.ntp.org,\
270 oceania.pool.ntp.org")).split(',', QString::SkipEmptyParts));
271 setDateTimeAuto->setChecked(config.readEntry("enabled", false));
273 // Reset to the current date and time
274 time = QTime::currentTime();
275 date = QDate::currentDate();
276 cal->setDate(date);
278 // start internal timer
279 internalTimer.start( 1000 );
281 timeout();
284 void Dtime::save( QStringList& helperargs )
286 // Save the order, but don't duplicate!
287 QStringList list;
288 if( timeServerList->count() != 0)
289 list.append(timeServerList->currentText());
290 for ( int i=0; i<timeServerList->count();i++ ) {
291 QString text = timeServerList->itemText(i);
292 if( !list.contains(text) )
293 list.append(text);
294 // Limit so errors can go away and not stored forever
295 if( list.count() == 10)
296 break;
298 helperargs << "ntp" << QString::number( list.count()) << list
299 << ( setDateTimeAuto->isChecked() ? "enabled" : "disabled" );
301 if(setDateTimeAuto->isChecked() && !ntpUtility.isEmpty()){
302 // NTP Time setting - done in helper
303 timeServer = timeServerList->currentText();
304 kDebug() << "Setting date from time server " << timeServer;
306 else {
307 // User time setting
308 QDateTime dt(date,
309 QTime(hour->value(), minute->value(), second->value()));
311 kDebug() << "Set date " << dt;
313 helperargs << "date" << QString::number(dt.toTime_t())
314 << QString::number(::time(0));
317 // restart time
318 internalTimer.start( 1000 );
321 void Dtime::processHelperErrors( int code )
323 if( code & ERROR_DTIME_NTP ) {
324 KMessageBox::error( this, i18n("Unable to contact time server: %1.", timeServer) );
325 setDateTimeAuto->setChecked( false );
327 if( code & ERROR_DTIME_DATE ) {
328 KMessageBox::error( this, i18n("Can not set date."));
332 void Dtime::timeout()
334 // get current time
335 time = QTime::currentTime();
337 ontimeout = true;
338 second->setValue(time.second());
339 minute->setValue(time.minute());
340 hour->setValue(time.hour());
341 ontimeout = false;
343 kclock->setTime( time );
346 QString Dtime::quickHelp() const
348 return i18n("<h1>Date & Time</h1> This control module can be used to set the system date and"
349 " time. As these settings do not only affect you as a user, but rather the whole system, you"
350 " can only change these settings when you start the Control Center as root. If you do not have"
351 " the root password, but feel the system time should be corrected, please contact your system"
352 " administrator.");
355 void Kclock::setTime(const QTime &time)
357 this->time = time;
358 repaint();
361 void Kclock::paintEvent( QPaintEvent * )
363 if ( !isVisible() )
364 return;
366 QPainter paint;
367 paint.begin( this );
369 paint.setRenderHint(QPainter::Antialiasing);
371 QPolygon pts;
372 QPoint cp = rect().center();
373 int d = qMin(width(),height());
375 KColorScheme colorScheme( QPalette::Normal );
376 QColor hands = colorScheme.foreground(KColorScheme::NormalText).color();
378 paint.setPen( hands );
379 paint.setBrush( hands );
380 paint.setViewport(4,4,width(),height());
382 QTransform matrix;
383 matrix.translate( cp.x(), cp.y() );
384 matrix.scale( d/1000.0F, d/1000.0F );
386 // hour hand
387 float h_angle = 30*(time.hour()%12-3) + time.minute()/2;
388 matrix.rotate( h_angle );
389 paint.setWorldTransform( matrix );
390 pts.setPoints( 4, -20,0, 0,-20, 300,0, 0,20 );
391 paint.drawPolygon( pts );
392 matrix.rotate( -h_angle );
394 // minute hand
395 float m_angle = (time.minute()-15)*6;
396 matrix.rotate( m_angle );
397 paint.setWorldTransform( matrix );
398 pts.setPoints( 4, -10,0, 0,-10, 400,0, 0,10 );
399 paint.drawPolygon( pts );
400 matrix.rotate( -m_angle );
402 // second hand
403 float s_angle = (time.second()-15)*6;
404 matrix.rotate( s_angle );
405 paint.setWorldTransform( matrix );
406 pts.setPoints(4,0,0,0,0,400,0,0,0);
407 paint.drawPolygon( pts );
408 matrix.rotate( -s_angle );
410 // clock face
411 for ( int i=0 ; i < 60 ; i++ ) {
412 paint.setWorldTransform( matrix );
413 if ( (i % 5) == 0 )
414 paint.drawLine( 450,0, 500,0 ); // draw hour lines
415 else paint.drawPoint( 480,0 ); // draw second lines
416 matrix.rotate( 6 );
419 paint.end();
422 QValidator::State KStrictIntValidator::validate( QString & input, int & d ) const
424 if( input.isEmpty() )
425 return Intermediate;
427 State st = QIntValidator::validate( input, d );
429 if( st == Intermediate )
430 return Invalid;
432 return st;