/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXDE-Qt - a lightweight, Qt based, desktop toolset * http://razor-qt.org * * Copyright: 2010-2013 Razor team * Authors: * Christopher "VdoP" Regali * Alexander Sokoloff * Maciej PÅ‚aza * Kuzma Shapran * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "lxqtclock.h" #include #include #include #include #include #include #include #include #include #include /** * @file lxqtclock.cpp * @brief implements LxQtclock and LxQtclockgui * @author Christopher "VdoP" Regali * @author Kuzma Shapran */ /** * @brief constructor */ LxQtClock::LxQtClock(const ILxQtPanelPluginStartupInfo &startupInfo): QObject(), ILxQtPanelPlugin(startupInfo), mAutoRotate(true) { mMainWidget = new QWidget(); mRotatedWidget = new LxQt::RotatedWidget(*(new QWidget()), mMainWidget); mContent = mRotatedWidget->content(); mTimeLabel = new QLabel(mContent); mDateLabel = new QLabel(mContent); QVBoxLayout *borderLayout = new QVBoxLayout(mMainWidget); borderLayout->setContentsMargins(0, 0, 0, 0); borderLayout->setSpacing(0); borderLayout->addWidget(mRotatedWidget, 0, Qt::AlignCenter); mTimeLabel->setObjectName("TimeLabel"); mDateLabel->setObjectName("DateLabel"); mTimeLabel->setAlignment(Qt::AlignCenter); mDateLabel->setAlignment(Qt::AlignCenter); QVBoxLayout *contentLayout = new QVBoxLayout(mContent); contentLayout->setContentsMargins(0, 0, 0, 0); contentLayout->setSpacing(1); contentLayout->addWidget(mTimeLabel, 0, Qt::AlignCenter); contentLayout->addWidget(mDateLabel, 0, Qt::AlignCenter); mContent->setLayout(contentLayout); mTimeLabel->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); mDateLabel->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); mContent->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); mRotatedWidget->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); mMainWidget->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); mClockTimer = new QTimer(this); connect (mClockTimer, SIGNAL(timeout()), SLOT(updateTime())); mClockFormat = "hh:mm"; mCalendarPopup = new CalendarPopup(mContent); mMainWidget->installEventFilter(this); settingsChanged(); } /** * @brief destructor */ LxQtClock::~LxQtClock() { delete mMainWidget; } QDateTime LxQtClock::currentDateTime() { return QDateTime(mUseUTC ? QDateTime::currentDateTimeUtc() : QDateTime::currentDateTime()); } /** * @brief updates the time * Color and font settings can be configured in Qt CSS */ void LxQtClock::updateTime() { QDateTime now = currentDateTime(); if (now.time().msec() > 500) restartTimer(now); showTime(now); } void LxQtClock::showTime(const QDateTime &now) { if (mDateOnNewLine) { mTimeLabel->setText(QLocale::system().toString(now, mTimeFormat)); mDateLabel->setText(QLocale::system().toString(now, mDateFormat)); } else { mTimeLabel->setText(QLocale::system().toString(now, mClockFormat)); } mRotatedWidget->adjustContentSize(); mRotatedWidget->update(); } void LxQtClock::restartTimer(const QDateTime &now) { if (mClockTimer->isActive()) mClockTimer->stop(); int updateInterval = mClockTimer->interval(); int delay = static_cast((updateInterval + 100 /* ms after time change */ - ((now.time().msec() + now.time().second() * 1000) % updateInterval)) % updateInterval); QTimer::singleShot(delay, this, SLOT(updateTime())); QTimer::singleShot(delay, mClockTimer, SLOT(start())); } void LxQtClock::settingsChanged() { mTimeFormat = settings()->value("timeFormat", QLocale::system().timeFormat(QLocale::ShortFormat).toUpper().contains("AP") ? "h:mm AP" : "HH:mm").toString(); mUseUTC = settings()->value("UTC", false).toBool(); if (mUseUTC) mTimeFormat += "' Z'"; mDateFormat = settings()->value("dateFormat", Qt::SystemLocaleShortDate).toString(); bool dateBeforeTime = (settings()->value("showDate", "no").toString().toLower() == "before"); bool dateAfterTime = (settings()->value("showDate", "no").toString().toLower() == "after"); mDateOnNewLine = (settings()->value("showDate", "no").toString().toLower() == "below"); bool autoRotate = settings()->value("autoRotate", true).toBool(); if (autoRotate != mAutoRotate) { mAutoRotate = autoRotate; realign(); } if (dateBeforeTime) mClockFormat = QString("%1 %2").arg(mDateFormat).arg(mTimeFormat); else if (dateAfterTime) mClockFormat = QString("%1 %2").arg(mTimeFormat).arg(mDateFormat); else mClockFormat = mTimeFormat; mDateLabel->setVisible(mDateOnNewLine); updateMinWidth(); // mDateFormat usually does not contain time portion, but since it's possible to use custom date format - it has to be supported. [Kuzma Shapran] int updateInterval = QString(mTimeFormat + " " + mDateFormat).replace(QRegExp("'[^']*'"),"").contains("s") ? 1000 : 60000; QDateTime now = currentDateTime(); showTime(now); if (mClockTimer->interval() != updateInterval) { mClockTimer->setInterval(updateInterval); restartTimer(now); } } void LxQtClock::realign() { if (mAutoRotate) switch (panel()->position()) { case ILxQtPanel::PositionTop: case ILxQtPanel::PositionBottom: mRotatedWidget->setOrigin(Qt::TopLeftCorner); break; case ILxQtPanel::PositionLeft: mRotatedWidget->setOrigin(Qt::BottomLeftCorner); break; case ILxQtPanel::PositionRight: mRotatedWidget->setOrigin(Qt::TopRightCorner); break; } else mRotatedWidget->setOrigin(Qt::TopLeftCorner); } static QDate getMaxDate(const QFontMetrics &metrics, const QString &format) { QDate d(QDate::currentDate().year(), 1, 1); QDateTime dt(d); QDate res; int maxWidth = 0; while (dt.date().year() == d.year()) { int w = metrics.boundingRect(dt.toString(format)).width(); //qDebug() << "*" << dt.toString(format) << w; if (w > maxWidth) { res = dt.date(); maxWidth = w; } dt = dt.addDays(1); } //qDebug() << "Max date:" << res.toString(format); return res; } static QTime getMaxTime(const QFontMetrics &metrics, const QString &format) { int maxMinSec = 0; for (int width=0, i=0; i<60; ++i) { int w = metrics.boundingRect(QString("%1").arg(i, 2, 10, QChar('0'))).width(); if (w > width) { maxMinSec = i; width = w; } } QTime res; QDateTime dt(QDate(1, 1, 1), QTime(0, maxMinSec, maxMinSec)); int maxWidth = 0; while (dt.date().day() == 1) { int w = metrics.boundingRect(dt.toString(format)).width(); //qDebug() << "*" << dt.toString(format) << w; if (w > maxWidth) { res = dt.time(); maxWidth = w; } dt = dt.addSecs(3600); } //qDebug() << "Max time:" << res.toString(); return res; } /************************************************ Issue #18: Panel clock plugin changes your size ************************************************/ void LxQtClock::updateMinWidth() { QFontMetrics timeLabelMetrics(mTimeLabel->font()); QFontMetrics dateLabelMetrics(mDateLabel->font()); QDate maxDate = getMaxDate(mDateOnNewLine ? dateLabelMetrics : timeLabelMetrics, mDateFormat); QTime maxTime = getMaxTime(timeLabelMetrics, mTimeFormat); QDateTime dt(maxDate, maxTime); //qDebug() << "T:" << metrics.boundingRect(dt.toString(mTimeFormat)).width(); //qDebug() << "C:" << metrics.boundingRect(QTime::currentTime().toString(mTimeFormat)).width() << QTime::currentTime().toString(mTimeFormat); //qDebug() << "D:" << metrics.boundingRect(dt.toString(mDateFormat)).width(); int width; int height; if (mDateOnNewLine) { QRect rect1(timeLabelMetrics.boundingRect(dt.toString(mTimeFormat))); mTimeLabel->setMinimumSize(rect1.size()); QRect rect2(dateLabelMetrics.boundingRect(dt.toString(mDateFormat))); mDateLabel->setMinimumSize(rect2.size()); width = qMax(rect1.width(), rect2.width()); height = rect1.height() + rect2.height(); // qDebug() << "LxQtClock Recalc size" << width << height << dt.toString(mTimeFormat) << dt.toString(mDateFormat); } else { QRect rect(timeLabelMetrics.boundingRect(dt.toString(mClockFormat))); mTimeLabel->setMinimumSize(rect.size()); mDateLabel->setMinimumSize(0, 0); width = rect.width(); height = rect.height(); // qDebug() << "LxQtClock Recalc size" << width << height << dt.toString(mClockFormat); } mContent->setMinimumSize(width, height); } void LxQtClock::activated(ActivationReason reason) { if (reason != ILxQtPanelPlugin::Trigger) return; if (!mCalendarPopup->isVisible()) { QRect pos = calculatePopupWindowPos(mCalendarPopup->size()); mCalendarPopup->move(pos.topLeft()); mCalendarPopup->show(); } else { mCalendarPopup->hide(); } } QDialog * LxQtClock::configureDialog() { return new LxQtClockConfiguration(*settings()); } bool LxQtClock::eventFilter(QObject *watched, QEvent *event) { if (watched == mMainWidget) { if (event->type() == QEvent::ToolTip) mMainWidget->setToolTip(QDateTime::currentDateTime().toString(Qt::DefaultLocaleLongDate)); return false; } return false; }