You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/kcontrol/clock/dtime.cpp

450 lines
13 KiB

/*
* dtime.cpp
*
* Copyright (C) 1998 Luca Montecchiani <m.luca@usa.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <tqcombobox.h>
#include <tqgroupbox.h>
#include <tqpushbutton.h>
#include <tqpainter.h>
#include <tqlayout.h>
#include <tqlabel.h>
#include <tqwhatsthis.h>
#include <tqcheckbox.h>
#include <tqregexp.h>
#include <kdebug.h>
#include <klocale.h>
#include <kprocess.h>
#include <kmessagebox.h>
#include <kdialog.h>
#include <kconfig.h>
#include "dtime.h"
#include "dtime.moc"
HMSTimeWidget::HMSTimeWidget(TQWidget *parent, const char *name) :
KIntSpinBox(parent, name)
{
}
TQString HMSTimeWidget::mapValueToText(int value)
{
TQString s = TQString::number(value);
if( value < 10 ) {
s = "0" + s;
}
return s;
}
Dtime::Dtime(TQWidget * parent, const char *name)
: TQWidget(parent, name)
{
// *************************************************************
// Start Dialog
// *************************************************************
// Time Server
privateLayoutWidget = new TQWidget( this, "layout1" );
TQHBoxLayout *layout1 = new TQHBoxLayout( privateLayoutWidget, 0, 0, "ntplayout");
setDateTimeAuto = new TQCheckBox( privateLayoutWidget, "setDateTimeAuto" );
setDateTimeAuto->setText(i18n("Set date and time &automatically:"));
connect(setDateTimeAuto, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(serverTimeCheck()));
connect(setDateTimeAuto, TQT_SIGNAL(toggled(bool)), TQT_SLOT(configChanged()));
layout1->addWidget( setDateTimeAuto );
timeServerList = new TQComboBox( false, privateLayoutWidget, "timeServerList" );
connect(timeServerList, TQT_SIGNAL(activated(int)), TQT_SLOT(configChanged()));
connect(timeServerList, TQT_SIGNAL(textChanged(const TQString &)), TQT_SLOT(configChanged()));
connect(setDateTimeAuto, TQT_SIGNAL(toggled(bool)), timeServerList, TQT_SLOT(setEnabled(bool)));
timeServerList->setEnabled(false);
timeServerList->setEditable(true);
layout1->addWidget( timeServerList );
findNTPutility();
// Date box
TQGroupBox* dateBox = new TQGroupBox( this, "dateBox" );
TQVBoxLayout *l1 = new TQVBoxLayout( dateBox, KDialog::spacingHint() );
cal = new KDatePicker( dateBox );
cal->setMinimumSize(cal->tqsizeHint());
l1->addWidget( cal );
TQWhatsThis::add( cal, i18n("Here you can change the system date's day of the month, month and year.") );
// Time frame
TQGroupBox* timeBox = new TQGroupBox( this, "timeBox" );
TQVBoxLayout *v2 = new TQVBoxLayout( timeBox, KDialog::spacingHint() );
kclock = new Kclock( timeBox, "kclock" );
kclock->setMinimumSize(150,150);
v2->addWidget( kclock );
TQGridLayout *v3 = new TQGridLayout( v2, 2, 9 );
// Even if the module's widgets are reversed (usually when using RTL
// languages), the placing of the time fields must always be H:M:S, from
// left to right.
bool isRTL = TQApplication::reverseLayout();
TQSpacerItem *spacer1 = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
v3->addMultiCell(spacer1, 0, 1, 1, 1);
hour = new HMSTimeWidget( timeBox );
hour->setWrapping(true);
hour->setMaxValue(23);
hour->setValidator(new KStrictIntValidator(0, 23, hour));
v3->addMultiCellWidget(hour, 0, 1, isRTL ? 6 : 2, isRTL ? 6 : 2 );
TQLabel *dots1 = new TQLabel(":", timeBox);
dots1->setMinimumWidth( 7 );
dots1->tqsetAlignment( TQLabel::AlignCenter );
v3->addMultiCellWidget(dots1, 0, 1, 3, 3 );
minute = new HMSTimeWidget( timeBox );
minute->setWrapping(true);
minute->setMinValue(0);
minute->setMaxValue(59);
minute->setValidator(new KStrictIntValidator(0, 59, minute));
v3->addMultiCellWidget(minute, 0, 1, 4, 4 );
TQLabel *dots2 = new TQLabel(":", timeBox);
dots2->setMinimumWidth( 7 );
dots2->tqsetAlignment( TQLabel::AlignCenter );
v3->addMultiCellWidget(dots2, 0, 1, 5, 5 );
second = new HMSTimeWidget( timeBox );
second->setWrapping(true);
second->setMinValue(0);
second->setMaxValue(59);
second->setValidator(new KStrictIntValidator(0, 59, second));
v3->addMultiCellWidget(second, 0, 1, isRTL ? 2 : 6, isRTL ? 2 : 6 );
v3->addColSpacing(7, 7);
TQString wtstr = i18n("Here you can change the system time. Click into the"
" hours, minutes or seconds field to change the relevant value, either"
" using the up and down buttons to the right or by entering a new value.");
TQWhatsThis::add( hour, wtstr );
TQWhatsThis::add( minute, wtstr );
TQWhatsThis::add( second, wtstr );
TQSpacerItem *spacer3 = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
v3->addMultiCell(spacer3, 0, 1, 9, 9);
TQGridLayout *top = new TQGridLayout( this, 2,2, KDialog::spacingHint() );
top->addWidget(dateBox, 1,0);
top->addWidget(timeBox, 1,1);
top->addMultiCellWidget(privateLayoutWidget, 0,0, 0,1);
// *************************************************************
// End Dialog
// *************************************************************
connect( hour, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(set_time()) );
connect( minute, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(set_time()) );
connect( second, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(set_time()) );
connect( cal, TQT_SIGNAL(dateChanged(TQDate)), TQT_SLOT(changeDate(TQDate)));
connect( &internalTimer, TQT_SIGNAL(timeout()), TQT_SLOT(timeout()) );
load();
if (getuid() != 0)
{
cal->setEnabled(false);
hour->setEnabled(false);
minute->setEnabled(false);
second->setEnabled(false);
timeServerList->setEnabled(false);
setDateTimeAuto->setEnabled(false);
}
kclock->setEnabled(false);
}
void Dtime::serverTimeCheck() {
bool enabled = !setDateTimeAuto->isChecked();
cal->setEnabled(enabled);
hour->setEnabled(enabled);
minute->setEnabled(enabled);
second->setEnabled(enabled);
//kclock->setEnabled(enabled);
}
void Dtime::findNTPutility(){
KProcess proc;
proc << "which" << "ntpdate";
proc.start(KProcess::Block);
if(proc.exitStatus() == 0) {
ntpUtility = "ntpdate";
kdDebug() << "ntpUtility = " << ntpUtility.latin1() << endl;
return;
}
proc.clearArguments();
proc << "which" << "rdate";
proc.start(KProcess::Block);
if(proc.exitStatus() == 0) {
ntpUtility = "rdate";
kdDebug() << "ntpUtility = " << ntpUtility.latin1() << endl;
return;
}
privateLayoutWidget->hide();
kdDebug() << "ntpUtility not found!" << endl;
}
void Dtime::set_time()
{
if( ontimeout )
return;
internalTimer.stop();
time.setHMS( hour->value(), minute->value(), second->value() );
kclock->setTime( time );
emit timeChanged( TRUE );
}
void Dtime::changeDate(TQDate d)
{
date = d;
emit timeChanged( TRUE );
}
void Dtime::configChanged(){
emit timeChanged( TRUE );
}
void Dtime::load()
{
KConfig config("kcmclockrc", true, false);
config.setGroup("NTP");
timeServerList->insertStringList(TQStringList::split(',', config.readEntry("servers",
i18n("Public Time Server (pool.ntp.org),\
asia.pool.ntp.org,\
europe.pool.ntp.org,\
north-america.pool.ntp.org,\
oceania.pool.ntp.org"))));
setDateTimeAuto->setChecked(config.readBoolEntry("enabled", false));
// Reset to the current date and time
time = TQTime::currentTime();
date = TQDate::currentDate();
cal->setDate(date);
// start internal timer
internalTimer.start( 1000 );
timeout();
}
void Dtime::save()
{
KConfig config("kcmclockrc", false, false);
config.setGroup("NTP");
// Save the order, but don't duplicate!
TQStringList list;
if( timeServerList->count() != 0)
list.append(timeServerList->currentText());
for ( int i=0; i<timeServerList->count();i++ ) {
TQString text = timeServerList->text(i);
if( list.tqfind(text) == list.end())
list.append(text);
// Limit so errors can go away and not stored forever
if( list.count() == 10)
break;
}
config.writeEntry("servers", list.join(","));
config.writeEntry("enabled", setDateTimeAuto->isChecked());
if(setDateTimeAuto->isChecked() && !ntpUtility.isEmpty()){
// NTP Time setting
TQString timeServer = timeServerList->currentText();
if( timeServer.tqfind( TQRegExp(".*\\(.*\\)$") ) != -1 ) {
timeServer.tqreplace( TQRegExp(".*\\("), "" );
timeServer.tqreplace( TQRegExp("\\).*"), "" );
// Would this be better?: s/^.*\(([^)]*)\).*$/\1/
}
KProcess proc;
proc << ntpUtility << timeServer;
proc.start( KProcess::Block );
if( proc.exitStatus() != 0 ){
KMessageBox::error( this, i18n(TQString("Unable to contact time server: %1.").tqarg(timeServer).latin1()));
setDateTimeAuto->setChecked( false );
}
else {
// success
kdDebug() << "Set date from time server " << timeServer.latin1() << " success!" << endl;
}
}
else {
// User time setting
KProcess c_proc;
// BSD systems reverse year compared to Susv3
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
BufS.sprintf("%04d%02d%02d%02d%02d.%02d",
date.year(),
date.month(), date.day(),
hour->value(), minute->value(), second->value());
#else
BufS.sprintf("%02d%02d%02d%02d%04d.%02d",
date.month(), date.day(),
hour->value(), minute->value(),
date.year(), second->value());
#endif
kdDebug() << "Set date " << BufS << endl;
c_proc << "date" << BufS;
c_proc.start( KProcess::Block );
int result = c_proc.exitStatus();
if (result != 0
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
&& result != 2 // can only set local date, which is okay
#endif
) {
KMessageBox::error( this, i18n("Can not set date."));
return;
}
// try to set hardware clock. We do not care if it fails
KProcess hwc_proc;
hwc_proc << "hwclock" << "--systohc";
hwc_proc.start(KProcess::Block);
}
// restart time
internalTimer.start( 1000 );
}
void Dtime::timeout()
{
// get current time
time = TQTime::currentTime();
ontimeout = TRUE;
second->setValue(time.second());
minute->setValue(time.minute());
hour->setValue(time.hour());
ontimeout = FALSE;
kclock->setTime( time );
}
TQString Dtime::quickHelp() const
{
return i18n("<h1>Date & Time</h1> This control module can be used to set the system date and"
" time. As these settings do not only affect you as a user, but rather the whole system, you"
" can only change these settings when you start the Control Center as root. If you do not have"
" the root password, but feel the system time should be corrected, please contact your system"
" administrator.");
}
void Kclock::setTime(const TQTime &time)
{
this->time = time;
tqrepaint();
}
void Kclock::paintEvent( TQPaintEvent * )
{
if ( !isVisible() )
return;
TQPainter paint;
paint.begin( this );
TQPointArray pts;
TQPoint cp = rect().center();
int d = QMIN(width(),height());
TQColor hands = tqcolorGroup().dark();
TQColor shadow = tqcolorGroup().text();
paint.setPen( shadow );
paint.setBrush( shadow );
paint.setViewport(4,4,width(),height());
for ( int c=0 ; c < 2 ; c++ )
{
TQWMatrix matrix;
matrix.translate( cp.x(), cp.y() );
matrix.scale( d/1000.0F, d/1000.0F );
// lancetta delle ore
float h_angle = 30*(time.hour()%12-3) + time.minute()/2;
matrix.rotate( h_angle );
paint.setWorldMatrix( matrix );
pts.setPoints( 4, -20,0, 0,-20, 300,0, 0,20 );
paint.drawPolygon( pts );
matrix.rotate( -h_angle );
// lancetta dei minuti
float m_angle = (time.minute()-15)*6;
matrix.rotate( m_angle );
paint.setWorldMatrix( matrix );
pts.setPoints( 4, -10,0, 0,-10, 400,0, 0,10 );
paint.drawPolygon( pts );
matrix.rotate( -m_angle );
// lancetta dei secondi
float s_angle = (time.second()-15)*6;
matrix.rotate( s_angle );
paint.setWorldMatrix( matrix );
pts.setPoints(4,0,0,0,0,400,0,0,0);
paint.drawPolygon( pts );
matrix.rotate( -s_angle );
// quadrante
for ( int i=0 ; i < 60 ; i++ )
{
paint.setWorldMatrix( matrix );
if ( (i % 5) == 0 )
paint.drawLine( 450,0, 500,0 ); // draw hour lines
else paint.drawPoint( 480,0 ); // draw second lines
matrix.rotate( 6 );
}
paint.setPen( hands );
paint.setBrush( hands );
paint.setViewport(0,0,width(),height());
}
paint.end();
}
TQValidator::State KStrictIntValidator::validate( TQString & input, int & d ) const
{
if( input.isEmpty() )
return Valid;
State st = TQIntValidator::validate( input, d );
if( st == Intermediate )
return Invalid;
return st;
}