2014-11-13 19:30:51 +02:00
|
|
|
/*
|
|
|
|
* dtime.cpp
|
|
|
|
*
|
|
|
|
* Copyright (C) 1998 Luca Montecchiani <m.luca@usa.net>
|
|
|
|
*
|
|
|
|
* Plasma analog-clock drawing code:
|
|
|
|
*
|
|
|
|
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
|
|
|
* Copyright 2007 by Riccardo Iaconelli <riccardo@kde.org>
|
|
|
|
*
|
|
|
|
* 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 "dtime.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#include <QComboBox>
|
2016-04-22 18:09:33 +00:00
|
|
|
#include <QGroupBox>
|
2014-11-13 19:30:51 +02:00
|
|
|
#include <QPushButton>
|
|
|
|
#include <QPainter>
|
2016-04-22 18:09:33 +00:00
|
|
|
#include <QDateTimeEdit>
|
2014-11-13 19:30:51 +02:00
|
|
|
#include <QCheckBox>
|
2015-08-12 13:11:16 +03:00
|
|
|
#include <QtGui/qevent.h>
|
2014-11-13 19:30:51 +02:00
|
|
|
#include <QGridLayout>
|
|
|
|
#include <QHBoxLayout>
|
|
|
|
#include <QVBoxLayout>
|
2016-04-22 18:09:33 +00:00
|
|
|
|
2014-11-13 19:30:51 +02:00
|
|
|
#include <kdebug.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <kdialog.h>
|
|
|
|
#include <kconfig.h>
|
|
|
|
#include <ksystemtimezone.h>
|
|
|
|
|
|
|
|
#include <Plasma/Svg>
|
|
|
|
|
2015-02-27 09:28:46 +00:00
|
|
|
#include "moc_dtime.cpp"
|
2014-11-13 19:30:51 +02:00
|
|
|
|
|
|
|
#include "helper.h"
|
|
|
|
|
|
|
|
Dtime::Dtime(QWidget * parent)
|
|
|
|
: QWidget(parent)
|
|
|
|
{
|
|
|
|
KGlobal::locale()->insertCatalog( "timezones4" );
|
|
|
|
setupUi(this);
|
|
|
|
|
|
|
|
connect(setDateTimeAuto, SIGNAL(toggled(bool)), this, SLOT(serverTimeCheck()));
|
|
|
|
connect(setDateTimeAuto, SIGNAL(toggled(bool)), SLOT(configChanged()));
|
|
|
|
|
|
|
|
timeServerList->setEditable(false);
|
|
|
|
connect(timeServerList, SIGNAL(activated(int)), SLOT(configChanged()));
|
|
|
|
connect(timeServerList, SIGNAL(editTextChanged(QString)), SLOT(configChanged()));
|
|
|
|
connect(setDateTimeAuto, SIGNAL(toggled(bool)), timeServerList, SLOT(setEnabled(bool)));
|
|
|
|
timeServerList->setEnabled(false);
|
|
|
|
timeServerList->setEditable(true);
|
|
|
|
findNTPutility();
|
|
|
|
if (ntpUtility.isEmpty()) {
|
|
|
|
setDateTimeAuto->setEnabled(false);
|
|
|
|
setDateTimeAuto->setToolTip(i18n("No NTP utility has been found. "
|
|
|
|
"Install 'ntpdate' or 'rdate' command to enable automatic "
|
|
|
|
"updating of date and time."));
|
|
|
|
}
|
|
|
|
|
|
|
|
QVBoxLayout *v2 = new QVBoxLayout( timeBox );
|
|
|
|
v2->setMargin( 0 );
|
|
|
|
|
|
|
|
kclock = new Kclock( timeBox );
|
|
|
|
kclock->setObjectName("Kclock");
|
|
|
|
kclock->setMinimumSize(150,150);
|
|
|
|
v2->addWidget( kclock );
|
|
|
|
|
|
|
|
v2->addSpacing( KDialog::spacingHint() );
|
|
|
|
|
|
|
|
QHBoxLayout *v3 = new QHBoxLayout( );
|
|
|
|
v2->addLayout( v3 );
|
|
|
|
|
|
|
|
v3->addStretch();
|
|
|
|
|
|
|
|
timeEdit = new QTimeEdit( timeBox );
|
|
|
|
timeEdit->setWrapping(true);
|
|
|
|
timeEdit->setDisplayFormat(KGlobal::locale()->use12Clock() ? "hh:mm:ss ap" : "HH:mm:ss");
|
|
|
|
v3->addWidget(timeEdit);
|
|
|
|
|
|
|
|
v3->addStretch();
|
|
|
|
|
|
|
|
QString 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.");
|
|
|
|
timeEdit->setWhatsThis( wtstr );
|
|
|
|
|
|
|
|
connect( timeEdit, SIGNAL(timeChanged(QTime)), SLOT(set_time()) );
|
|
|
|
connect( cal, SIGNAL(dateChanged(QDate)), SLOT(changeDate(QDate)));
|
|
|
|
|
|
|
|
connect( &internalTimer, SIGNAL(timeout()), SLOT(timeout()) );
|
|
|
|
|
|
|
|
kclock->setEnabled(false);
|
|
|
|
|
|
|
|
//Timezone
|
|
|
|
connect( tzonelist, SIGNAL(itemSelectionChanged()), SLOT(configChanged()) );
|
|
|
|
tzonesearch->setTreeWidget(tzonelist);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dtime::currentZone()
|
|
|
|
{
|
|
|
|
KTimeZone localZone = KSystemTimeZones::local();
|
|
|
|
|
|
|
|
if (localZone.abbreviations().isEmpty()) {
|
|
|
|
m_local->setText(i18nc("%1 is name of time zone", "Current local time zone: %1",
|
|
|
|
KTimeZoneWidget::displayName(localZone)));
|
|
|
|
} else {
|
|
|
|
m_local->setText(i18nc("%1 is name of time zone, %2 is its abbreviation",
|
|
|
|
"Current local time zone: %1 (%2)",
|
|
|
|
KTimeZoneWidget::displayName(localZone),
|
|
|
|
QString::fromUtf8(localZone.abbreviations().first())));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dtime::serverTimeCheck() {
|
|
|
|
bool enabled = !setDateTimeAuto->isChecked();
|
|
|
|
cal->setEnabled(enabled);
|
|
|
|
timeEdit->setEnabled(enabled);
|
|
|
|
//kclock->setEnabled(enabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dtime::findNTPutility()
|
|
|
|
{
|
2022-10-29 04:57:31 +03:00
|
|
|
static const QStringList possible_ntputilities = QStringList()
|
|
|
|
<< QString::fromLatin1("ntpdate")
|
|
|
|
<< QString::fromLatin1("rdate");
|
|
|
|
foreach(const QString &possible_ntputility, possible_ntputilities) {
|
2021-02-16 22:43:53 +02:00
|
|
|
ntpUtility = KStandardDirs::findRootExe(possible_ntputility);
|
2014-11-13 19:30:51 +02:00
|
|
|
if (!ntpUtility.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dtime::set_time()
|
|
|
|
{
|
|
|
|
if( ontimeout )
|
|
|
|
return;
|
|
|
|
|
|
|
|
internalTimer.stop();
|
|
|
|
|
|
|
|
time = timeEdit->time();
|
|
|
|
kclock->setTime( time );
|
|
|
|
|
|
|
|
emit timeChanged( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dtime::changeDate(const QDate &d)
|
|
|
|
{
|
|
|
|
date = d;
|
|
|
|
emit timeChanged( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dtime::configChanged(){
|
|
|
|
emit timeChanged( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dtime::load()
|
|
|
|
{
|
|
|
|
// The config is actually written to the system config, but the user does not have any local config,
|
|
|
|
// since there is nothing writing it.
|
|
|
|
KConfig _config( "kcmclockrc", KConfig::NoGlobals );
|
|
|
|
KConfigGroup config(&_config, "NTP");
|
|
|
|
timeServerList->clear();
|
|
|
|
timeServerList->addItems(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")).split(',', QString::SkipEmptyParts));
|
|
|
|
setDateTimeAuto->setChecked(config.readEntry("enabled", false));
|
|
|
|
|
|
|
|
// Reset to the current date and time
|
|
|
|
time = QTime::currentTime();
|
|
|
|
date = QDate::currentDate();
|
|
|
|
cal->setDate(date);
|
|
|
|
|
|
|
|
// start internal timer
|
|
|
|
internalTimer.start( 1000 );
|
|
|
|
|
|
|
|
timeout();
|
|
|
|
|
|
|
|
//Timezone
|
|
|
|
currentZone();
|
|
|
|
|
|
|
|
// read the currently set time zone
|
|
|
|
tzonelist->setSelected(KSystemTimeZones::local().name(), true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dtime::save( QVariantMap& helperargs )
|
|
|
|
{
|
|
|
|
// Save the order, but don't duplicate!
|
|
|
|
QStringList list;
|
|
|
|
if( timeServerList->count() != 0)
|
|
|
|
list.append(timeServerList->currentText());
|
|
|
|
for ( int i=0; i<timeServerList->count();i++ ) {
|
|
|
|
QString text = timeServerList->itemText(i);
|
|
|
|
if( !list.contains(text) )
|
|
|
|
list.append(text);
|
|
|
|
// Limit so errors can go away and not stored forever
|
|
|
|
if( list.count() == 10)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
helperargs["ntp"] = true;
|
|
|
|
helperargs["ntpServers"] = list;
|
|
|
|
helperargs["ntpEnabled"] = setDateTimeAuto->isChecked();
|
|
|
|
|
|
|
|
if(setDateTimeAuto->isChecked() && !ntpUtility.isEmpty()){
|
|
|
|
// NTP Time setting - done in helper
|
|
|
|
timeServer = timeServerList->currentText();
|
|
|
|
kDebug() << "Setting date from time server " << timeServer;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// User time setting
|
|
|
|
QDateTime dt(date, QTime(timeEdit->time()));
|
|
|
|
|
|
|
|
kDebug() << "Set date " << dt;
|
|
|
|
|
|
|
|
helperargs["date"] = true;
|
|
|
|
helperargs["newdate"] = QString::number(dt.toTime_t());
|
|
|
|
helperargs["olddate"] = QString::number(::time(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
// restart time
|
|
|
|
internalTimer.start( 1000 );
|
|
|
|
|
|
|
|
QStringList selectedZones(tzonelist->selection());
|
|
|
|
|
|
|
|
if (selectedZones.count() > 0) {
|
|
|
|
QString selectedzone(selectedZones[0]);
|
|
|
|
helperargs["tz"] = true;
|
|
|
|
helperargs["tzone"] = selectedzone;
|
|
|
|
} else {
|
|
|
|
helperargs["tzreset"] = true; // // make the helper reset the timezone
|
|
|
|
}
|
|
|
|
|
|
|
|
currentZone();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dtime::processHelperErrors( int code )
|
|
|
|
{
|
|
|
|
if( code & ClockHelper::NTPError ) {
|
|
|
|
KMessageBox::error( this, i18n("Unable to contact time server: %1.", timeServer) );
|
|
|
|
setDateTimeAuto->setChecked( false );
|
|
|
|
}
|
|
|
|
if( code & ClockHelper::DateError ) {
|
|
|
|
KMessageBox::error( this, i18n("Can not set date."));
|
|
|
|
}
|
|
|
|
if( code & ClockHelper::TimezoneError)
|
|
|
|
KMessageBox::error( this, i18n("Error setting new time zone."),
|
|
|
|
i18n("Time zone Error"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dtime::timeout()
|
|
|
|
{
|
|
|
|
// get current time
|
|
|
|
time = QTime::currentTime();
|
|
|
|
|
|
|
|
ontimeout = true;
|
|
|
|
timeEdit->setTime(time);
|
|
|
|
ontimeout = false;
|
|
|
|
|
|
|
|
kclock->setTime( time );
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Dtime::quickHelp() const
|
|
|
|
{
|
|
|
|
return i18n("<h1>Date & Time</h1> This system settings 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 System Settings as root. If you do not have"
|
|
|
|
" the root password, but feel the system time should be corrected, please contact your system"
|
|
|
|
" administrator.");
|
|
|
|
}
|
|
|
|
|
|
|
|
Kclock::Kclock(QWidget *parent)
|
|
|
|
: QWidget(parent)
|
|
|
|
{
|
|
|
|
m_theme = new Plasma::Svg(this);
|
|
|
|
m_theme->setImagePath("widgets/clock");
|
|
|
|
m_theme->setContainsMultipleImages(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
Kclock::~Kclock()
|
|
|
|
{
|
|
|
|
delete m_theme;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Kclock::showEvent( QShowEvent *event )
|
|
|
|
{
|
|
|
|
setClockSize( size() );
|
|
|
|
QWidget::showEvent( event );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Kclock::resizeEvent( QResizeEvent * )
|
|
|
|
{
|
|
|
|
setClockSize( size() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Kclock::setClockSize(const QSize &size)
|
|
|
|
{
|
|
|
|
int dim = qMin(size.width(), size.height());
|
|
|
|
QSize newSize = QSize(dim, dim);
|
|
|
|
|
|
|
|
if (newSize != m_faceCache.size()) {
|
|
|
|
m_faceCache = QPixmap(newSize);
|
|
|
|
m_handsCache = QPixmap(newSize);
|
|
|
|
m_glassCache = QPixmap(newSize);
|
|
|
|
|
|
|
|
m_theme->resize(newSize);
|
|
|
|
m_repaintCache = RepaintAll;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Kclock::setTime(const QTime &time)
|
|
|
|
{
|
|
|
|
if (time.minute() != this->time.minute() || time.hour() != this->time.hour()) {
|
|
|
|
if (m_repaintCache == RepaintNone) {
|
|
|
|
m_repaintCache = RepaintHands;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this->time = time;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Kclock::drawHand(QPainter *p, const QRect &rect, const qreal verticalTranslation, const qreal rotation, const QString &handName)
|
|
|
|
{
|
|
|
|
// this code assumes the following conventions in the svg file:
|
|
|
|
// - the _vertical_ position of the hands should be set with respect to the center of the face
|
|
|
|
// - the _horizontal_ position of the hands does not matter
|
|
|
|
// - the _shadow_ elements should have the same vertical position as their _hand_ element counterpart
|
|
|
|
|
|
|
|
QRectF elementRect;
|
|
|
|
QString name = handName + "HandShadow";
|
|
|
|
if (m_theme->hasElement(name)) {
|
|
|
|
p->save();
|
|
|
|
|
|
|
|
elementRect = m_theme->elementRect(name);
|
|
|
|
if( rect.height() < 64 )
|
|
|
|
elementRect.setWidth( elementRect.width() * 2.5 );
|
|
|
|
static const QPoint offset = QPoint(2, 3);
|
|
|
|
|
|
|
|
p->translate(rect.x() + (rect.width() / 2) + offset.x(), rect.y() + (rect.height() / 2) + offset.y());
|
|
|
|
p->rotate(rotation);
|
|
|
|
p->translate(-elementRect.width()/2, elementRect.y()-verticalTranslation);
|
|
|
|
m_theme->paint(p, QRectF(QPointF(0, 0), elementRect.size()), name);
|
|
|
|
|
|
|
|
p->restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
p->save();
|
|
|
|
|
|
|
|
name = handName + "Hand";
|
|
|
|
elementRect = m_theme->elementRect(name);
|
|
|
|
if (rect.height() < 64) {
|
|
|
|
elementRect.setWidth(elementRect.width() * 2.5);
|
|
|
|
}
|
|
|
|
|
|
|
|
p->translate(rect.x() + rect.width()/2, rect.y() + rect.height()/2);
|
|
|
|
p->rotate(rotation);
|
|
|
|
p->translate(-elementRect.width()/2, elementRect.y()-verticalTranslation);
|
|
|
|
m_theme->paint(p, QRectF(QPointF(0, 0), elementRect.size()), name);
|
|
|
|
|
|
|
|
p->restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Kclock::paintInterface(QPainter *p, const QRect &rect)
|
|
|
|
{
|
|
|
|
const bool m_showSecondHand = true;
|
|
|
|
|
|
|
|
// compute hand angles
|
|
|
|
const qreal minutes = 6.0 * time.minute() - 180;
|
|
|
|
const qreal hours = 30.0 * time.hour() - 180 +
|
|
|
|
((time.minute() / 59.0) * 30.0);
|
|
|
|
qreal seconds = 0;
|
|
|
|
if (m_showSecondHand) {
|
|
|
|
static const double anglePerSec = 6;
|
|
|
|
seconds = anglePerSec * time.second() - 180;
|
|
|
|
}
|
|
|
|
|
|
|
|
// paint face and glass cache
|
|
|
|
QRect faceRect = m_faceCache.rect();
|
|
|
|
if (m_repaintCache == RepaintAll) {
|
|
|
|
m_faceCache.fill(Qt::transparent);
|
|
|
|
m_glassCache.fill(Qt::transparent);
|
|
|
|
|
|
|
|
QPainter facePainter(&m_faceCache);
|
|
|
|
QPainter glassPainter(&m_glassCache);
|
|
|
|
facePainter.setRenderHint(QPainter::SmoothPixmapTransform);
|
|
|
|
glassPainter.setRenderHint(QPainter::SmoothPixmapTransform);
|
|
|
|
|
|
|
|
m_theme->paint(&facePainter, m_faceCache.rect(), "ClockFace");
|
|
|
|
|
|
|
|
glassPainter.save();
|
|
|
|
QRectF elementRect = QRectF(QPointF(0, 0), m_theme->elementSize("HandCenterScrew"));
|
|
|
|
glassPainter.translate(faceRect.width() / 2 - elementRect.width() / 2, faceRect.height() / 2 - elementRect.height() / 2);
|
|
|
|
m_theme->paint(&glassPainter, elementRect, "HandCenterScrew");
|
|
|
|
glassPainter.restore();
|
|
|
|
|
|
|
|
m_theme->paint(&glassPainter, faceRect, "Glass");
|
|
|
|
|
|
|
|
// get vertical translation, see drawHand() for more details
|
|
|
|
m_verticalTranslation = m_theme->elementRect("ClockFace").center().y();
|
|
|
|
}
|
|
|
|
|
|
|
|
// paint hour and minute hands cache
|
|
|
|
if (m_repaintCache == RepaintHands || m_repaintCache == RepaintAll) {
|
|
|
|
m_handsCache.fill(Qt::transparent);
|
|
|
|
|
|
|
|
QPainter handsPainter(&m_handsCache);
|
|
|
|
handsPainter.drawPixmap(faceRect, m_faceCache, faceRect);
|
|
|
|
handsPainter.setRenderHint(QPainter::SmoothPixmapTransform);
|
|
|
|
|
|
|
|
drawHand(&handsPainter, faceRect, m_verticalTranslation, hours, "Hour");
|
|
|
|
drawHand(&handsPainter, faceRect, m_verticalTranslation, minutes, "Minute");
|
|
|
|
}
|
|
|
|
|
|
|
|
// reset repaint cache flag
|
|
|
|
m_repaintCache = RepaintNone;
|
|
|
|
|
|
|
|
// paint caches and second hand
|
|
|
|
QRect targetRect = faceRect;
|
|
|
|
if (targetRect.width() < rect.width()) {
|
|
|
|
targetRect.moveLeft((rect.width() - targetRect.width()) / 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
p->drawPixmap(targetRect, m_handsCache, faceRect);
|
|
|
|
if (m_showSecondHand) {
|
|
|
|
p->setRenderHint(QPainter::SmoothPixmapTransform);
|
|
|
|
drawHand(p, targetRect, m_verticalTranslation, seconds, "Second");
|
|
|
|
}
|
|
|
|
p->drawPixmap(targetRect, m_glassCache, faceRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Kclock::paintEvent( QPaintEvent * )
|
|
|
|
{
|
|
|
|
QPainter paint(this);
|
|
|
|
|
|
|
|
paint.setRenderHint(QPainter::Antialiasing);
|
|
|
|
paintInterface(&paint, rect());
|
|
|
|
}
|
|
|
|
|