00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "clock.h"
00023
00024 #include <math.h>
00025
00026 #include <QtGui/QPainter>
00027 #include <QtGui/QStyleOptionGraphicsItem>
00028 #include <QtGui/QSpinBox>
00029 #include <QtCore/QTimeLine>
00030 #include <QtGui/QGraphicsView>
00031 #include <QtGui/QGraphicsSceneMouseEvent>
00032 #include <QtCore/QDate>
00033
00034 #include <KDebug>
00035 #include <KLocale>
00036 #include <KIcon>
00037 #include <KSharedConfig>
00038 #include <KTimeZoneWidget>
00039 #include <KDialog>
00040 #include <KColorScheme>
00041 #include <KGlobalSettings>
00042 #include <KConfigDialog>
00043 #include <KDatePicker>
00044 #include <Plasma/Theme>
00045 #include <Plasma/Dialog>
00046 #include <Plasma/ToolTipManager>
00047
00048
00049 Clock::Clock(QObject *parent, const QVariantList &args)
00050 : ClockApplet(parent, args),
00051 m_plainClockFont(KGlobalSettings::generalFont()),
00052 m_useCustomColor(false),
00053 m_plainClockColor(),
00054 m_showDate(false),
00055 m_showYear(false),
00056 m_showDay(false),
00057 m_showSeconds(false),
00058 m_showTimezone(false),
00059 m_dateTimezoneBesides(false),
00060 m_dateString(0),
00061 m_layout(0)
00062 {
00063 KGlobal::locale()->insertCatalog("libplasmaclock");
00064 setHasConfigurationInterface(true);
00065 resize(150, 75);
00066 }
00067
00068 Clock::~Clock()
00069 {
00070 }
00071
00072 void Clock::init()
00073 {
00074 ClockApplet::init();
00075
00076 KConfigGroup cg = config();
00077
00078 m_showTimezone = cg.readEntry("showTimezone", !isLocalTimezone());
00079
00080 kDebug() << "showTimezone:" << m_showTimezone;
00081
00082 m_showDate = cg.readEntry("showDate", false);
00083 m_showYear = cg.readEntry("showYear", false);
00084 m_showDay = cg.readEntry("showDay", true);
00085
00086 m_showSeconds = cg.readEntry("showSeconds", false);
00087 m_plainClockFont = cg.readEntry("plainClockFont", m_plainClockFont);
00088 m_useCustomColor = cg.readEntry("useCustomColor", false);
00089 if (m_useCustomColor) {
00090 m_plainClockColor = cg.readEntry("plainClockColor", m_plainClockColor);
00091 } else {
00092 m_plainClockColor = KColorScheme(QPalette::Active, KColorScheme::View, Plasma::Theme::defaultTheme()->colorScheme()).foreground().color();
00093 }
00094
00095 QFontMetricsF metrics(KGlobalSettings::smallestReadableFont());
00096 QString timeString = KGlobal::locale()->formatTime(QTime(23, 59), m_showSeconds);
00097 setMinimumSize(metrics.size(Qt::TextSingleLine, timeString));
00098
00099 dataEngine("time")->connectSource(currentTimezone(), this, updateInterval(), intervalAlignment());
00100 connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(updateColors()));
00101 }
00102
00103 void Clock::constraintsEvent(Plasma::Constraints constraints)
00104 {
00105 ClockApplet::constraintsEvent(constraints);
00106
00107 if (constraints & Plasma::SizeConstraint) {
00108 updateSize();
00109 }
00110 }
00111
00112 void Clock::updateSize()
00113 {
00114 Plasma::FormFactor f = formFactor();
00115
00116 if (f != Plasma::Vertical && f != Plasma::Horizontal) {
00117 QFontMetricsF metrics(KGlobalSettings::smallestReadableFont());
00118
00119 QString timeString = KGlobal::locale()->formatTime(QTime(23, 59), m_showSeconds);
00120 setMinimumSize(metrics.size(Qt::TextSingleLine, timeString));
00121 }
00122
00123
00124 int aspect = 2;
00125 if (m_showSeconds) {
00126 aspect = 3;
00127 }
00128
00129 int w, h;
00130 if (m_showDate || showTimezone()) {
00131 QFont f(KGlobalSettings::smallestReadableFont());
00132 QFontMetrics metrics(f);
00133
00134 if (contentsRect().height() < f.pointSize() * 6) {
00135 QSize s = metrics.size(Qt::TextSingleLine, m_dateString);
00136 w = s.width() + metrics.width(" ");
00137 h = s.height();
00138
00139 } else {
00140 QSize s = metrics.size(Qt::TextWordWrap, m_dateString);
00141 w = s.width();
00142 h = s.height();
00143
00144 }
00145
00146 if (!m_dateTimezoneBesides) {
00147 w = qMax(w, (int)(contentsRect().height() * aspect));
00148 h = h+(int)(contentsRect().width() / aspect);
00149 } else {
00150 w = w+(int)(contentsRect().height() * aspect);
00151 h = qMax(h, (int)(contentsRect().width() / aspect));
00152 }
00153 } else {
00154 w = (int)(contentsRect().height() * aspect);
00155 h = (int)(contentsRect().width() / aspect);
00156 }
00157
00158 if (f == Plasma::Horizontal) {
00159
00160 setMinimumWidth(w);
00161 setMinimumHeight(0);
00162
00163
00164 } else {
00165
00166 setMinimumHeight(h);
00167 setMinimumWidth(0);
00168 }
00169
00170 }
00171
00172 bool Clock::showTimezone() const
00173 {
00174 return m_showTimezone || shouldDisplayTimezone();
00175 }
00176
00177 void Clock::dataUpdated(const QString &source, const Plasma::DataEngine::Data &data)
00178 {
00179 Q_UNUSED(source);
00180 m_time = data["Time"].toTime();
00181 m_date = data["Date"].toDate();
00182
00183 if (Plasma::ToolTipManager::self()->isVisible(this)) {
00184 updateTipContent();
00185 }
00186
00187
00188 if ((m_showSeconds && m_time.second() != m_lastTimeSeen.second()) ||
00189 m_time.minute() != m_lastTimeSeen.minute()) {
00190 m_lastTimeSeen = m_time;
00191 update();
00192 }
00193 }
00194
00195 void Clock::createClockConfigurationInterface(KConfigDialog *parent)
00196 {
00197
00198 QWidget *widget = new QWidget();
00199 ui.setupUi(widget);
00200 parent->addPage(widget, i18n("General"), icon());
00201
00202 ui.showDate->setChecked(m_showDate);
00203 ui.showYear->setChecked(m_showYear);
00204 ui.showDay->setChecked(m_showDay);
00205 ui.secondsCheckbox->setChecked(m_showSeconds);
00206 ui.showTimeZone->setChecked(m_showTimezone);
00207 ui.plainClockFontBold->setChecked(m_plainClockFont.bold());
00208 ui.plainClockFontItalic->setChecked(m_plainClockFont.italic());
00209 ui.plainClockFont->setCurrentFont(m_plainClockFont);
00210 ui.useCustomColor->setChecked(m_useCustomColor);
00211 ui.plainClockColor->setColor(m_plainClockColor);
00212 }
00213
00214 void Clock::clockConfigAccepted()
00215 {
00216 KConfigGroup cg = config();
00217
00218 m_showTimezone = ui.showTimeZone->isChecked();
00219 cg.writeEntry("showTimezone", m_showTimezone);
00220
00221 m_plainClockFont = ui.plainClockFont->currentFont();
00222
00223
00224 if (m_showSeconds != ui.secondsCheckbox->isChecked()) {
00225 m_showSeconds = !m_showSeconds;
00226 cg.writeEntry("showSeconds", m_showSeconds);
00227
00228 dataEngine("time")->disconnectSource(currentTimezone(), this);
00229 dataEngine("time")->connectSource(currentTimezone(), this, updateInterval(), intervalAlignment());
00230 }
00231
00232 m_showDate = ui.showDate->checkState() == Qt::Checked;
00233 cg.writeEntry("showDate", m_showDate);
00234 m_showYear = ui.showYear->checkState() == Qt::Checked;
00235 cg.writeEntry("showYear", m_showYear);
00236 m_showDay = ui.showDay->checkState() == Qt::Checked;
00237 cg.writeEntry("showDay", m_showDay);
00238 m_showSeconds = ui.secondsCheckbox->checkState() == Qt::Checked;
00239 cg.writeEntry("showSeconds", m_showSeconds);
00240
00241 m_useCustomColor = ui.useCustomColor->isChecked();
00242 if (m_useCustomColor) {
00243 m_plainClockColor = ui.plainClockColor->color();
00244 } else {
00245 m_plainClockColor = KColorScheme(QPalette::Active, KColorScheme::View, Plasma::Theme::defaultTheme()->colorScheme()).foreground().color();
00246 }
00247
00248 m_plainClockFont.setBold(ui.plainClockFontBold->checkState() == Qt::Checked);
00249 m_plainClockFont.setItalic(ui.plainClockFontItalic->checkState() == Qt::Checked);
00250
00251 cg.writeEntry("plainClockFont", m_plainClockFont);
00252 cg.writeEntry("useCustomColor", m_useCustomColor);
00253 cg.writeEntry("plainClockColor", m_plainClockColor);
00254
00255 constraintsEvent(Plasma::SizeConstraint);
00256 update();
00257 emit sizeHintChanged(Qt::PreferredSize);
00258 emit configNeedsSaving();
00259 }
00260
00261 void Clock::changeEngineTimezone(const QString &oldTimezone, const QString &newTimezone)
00262 {
00263 dataEngine("time")->disconnectSource(oldTimezone, this);
00264 dataEngine("time")->connectSource(newTimezone, this, updateInterval(), intervalAlignment());
00265 }
00266
00267 QRectF Clock::normalLayout(int subtitleWidth, int subtitleHeight, const QRect &contentsRect)
00268 {
00269 Q_UNUSED(subtitleWidth);
00270
00271 QRectF myRect = QRectF(contentsRect.left(),
00272 contentsRect.bottom() - subtitleHeight,
00273 contentsRect.width(),
00274 contentsRect.bottom());
00275
00276
00277
00278
00279 m_timeRect = QRect(contentsRect.left(),
00280 contentsRect.top(),
00281 contentsRect.width(),
00282 contentsRect.height() - subtitleHeight);
00283
00284 return myRect;
00285 }
00286
00287 QRectF Clock::sideBySideLayout(int subtitleWidth, int subtitleHeight, const QRect &contentsRect)
00288 {
00289 QRectF myRect = QRectF(contentsRect.right()-subtitleWidth,
00290 (contentsRect.bottom()-subtitleHeight)/2,
00291 subtitleWidth,
00292 subtitleHeight);
00293
00294
00295
00296
00297 m_timeRect = QRect(contentsRect.left(),
00298 contentsRect.top(),
00299 contentsRect.right() - subtitleWidth,
00300 contentsRect.bottom());
00301
00302 return myRect;
00303 }
00304
00305 void Clock::paintInterface(QPainter *p, const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
00306 {
00307 Q_UNUSED(option);
00308
00309 if (!m_time.isValid() || !m_date.isValid()) {
00310 return;
00311 }
00312
00313 p->setPen(QPen(m_plainClockColor));
00314 p->setRenderHint(QPainter::SmoothPixmapTransform);
00315 p->setRenderHint(QPainter::Antialiasing);
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 QRectF dateRect;
00327 QString timeString = KGlobal::locale()->formatTime(m_time, m_showSeconds);
00328 QFont smallFont = KGlobalSettings::smallestReadableFont();
00329
00330 if (m_showDate || showTimezone()) {
00331 QString dateString;
00332 if (m_showDate) {
00333 KLocale tmpLocale(*KGlobal::locale());
00334 tmpLocale.setDateFormat("%e");
00335 QString day = tmpLocale.formatDate(m_date);
00336 tmpLocale.setDateFormat("%b");
00337 QString month = tmpLocale.formatDate(m_date);
00338
00339 if (m_showYear) {
00340 tmpLocale.setDateFormat("%Y");
00341 QString year = tmpLocale.formatDate(m_date);
00342 dateString = i18nc("@label Short date: "
00343 "%1 day in the month, %2 short month name, %3 year",
00344 "%1 %2 %3", day, month, year);
00345 } else {
00346 dateString = i18nc("@label Short date: "
00347 "%1 day in the month, %2 short month name",
00348 "%1 %2", day, month);
00349 }
00350
00351 if (m_showDay) {
00352 tmpLocale.setDateFormat("%a");
00353 QString weekday = tmpLocale.formatDate(m_date);
00354 dateString = i18nc("@label Day of the week with date: "
00355 "%1 short day name, %2 short date",
00356 "%1, %2", weekday, dateString);
00357 }
00358
00359 if (showTimezone()) {
00360 QString currentTimezone = prettyTimezone();
00361 dateString = i18nc("@label Date with currentTimezone: "
00362 "%1 day of the week with date, %2 currentTimezone",
00363 "%1 %2", dateString, currentTimezone);
00364 }
00365 } else if (showTimezone()) {
00366 dateString = prettyTimezone();
00367 }
00368
00369 dateString = dateString.trimmed();
00370
00371 if (m_dateString != dateString) {
00372
00373
00374 m_dateString = dateString;
00375 updateSize();
00376 }
00377
00378
00379
00380
00381 QFontMetrics fm(smallFont);
00382 smallFont.setPixelSize(qMax(contentsRect.height()/10, fm.ascent()));
00383
00384
00385
00386 m_dateRect = preparePainter(p, contentsRect, smallFont, dateString);
00387
00388
00389 int subtitleHeight = m_dateRect.height();
00390 int subtitleWidth = m_dateRect.width();
00391
00392
00393
00394 if (m_dateTimezoneBesides) {
00395
00396 if (contentsRect.height() - subtitleHeight >= smallFont.pixelSize() || formFactor() != Plasma::Horizontal) {
00397
00398
00399
00400 m_dateTimezoneBesides = false;
00401 dateRect = normalLayout(subtitleWidth, subtitleHeight, contentsRect);
00402 } else {
00403 dateRect = sideBySideLayout(subtitleWidth, subtitleHeight, contentsRect);
00404 }
00405 } else {
00406
00407
00408
00409 if (contentsRect.height() - subtitleHeight < smallFont.pixelSize() && formFactor() == Plasma::Horizontal) {
00410
00411
00412
00413 m_dateTimezoneBesides = true;
00414 dateRect = sideBySideLayout(subtitleWidth, subtitleHeight, contentsRect);
00415 } else {
00416 dateRect = normalLayout(subtitleWidth, subtitleHeight, contentsRect);
00417 }
00418 }
00419 } else {
00420 m_timeRect = contentsRect;
00421 }
00422
00423
00424
00425
00426
00427 m_plainClockFont.setPointSizeF(qMax(m_timeRect.height(), KGlobalSettings::smallestReadableFont().pointSize()));
00428 preparePainter(p, m_timeRect, m_plainClockFont, timeString, true);
00429
00430 if (!m_dateString.isEmpty()) {
00431 if (m_dateTimezoneBesides) {
00432 QFontMetrics fm(m_plainClockFont);
00433
00434 QRect br = fm.boundingRect(m_timeRect, Qt::AlignCenter, timeString);
00435
00436 QFontMetrics smallfm(smallFont);
00437 dateRect.moveLeft(br.right() + qMin(0, br.left()) + smallfm.width(" "));
00438 }
00439
00440
00441 QFont f = p->font();
00442 p->setFont(smallFont);
00443
00444 if (formFactor() == Plasma::Horizontal && (contentsRect.height() < smallFont.pointSize()*6)) {
00445 p->drawText(dateRect, Qt::TextSingleLine | Qt::AlignHCenter, m_dateString);
00446 } else {
00447 p->drawText(dateRect, Qt::TextWordWrap | Qt::AlignHCenter, m_dateString);
00448 }
00449
00450 p->setFont(f);
00451 }
00452
00453 QTextOption textOption(m_dateTimezoneBesides ? Qt::AlignCenter | Qt::AlignVCenter : Qt::AlignCenter);
00454 textOption.setWrapMode(QTextOption::NoWrap);
00455 p->drawText(m_timeRect, timeString, textOption);
00456 }
00457
00458 QRect Clock::preparePainter(QPainter *p, const QRect &rect, const QFont &font, const QString &text, bool singleline)
00459 {
00460 QRect tmpRect;
00461 QFont tmpFont = font;
00462 bool first = true;
00463
00464
00465
00466 do {
00467 if (first) {
00468 first = false;
00469 } else {
00470 tmpFont.setPointSize(qMax(KGlobalSettings::smallestReadableFont().pointSize(), tmpFont.pointSize() - 1));
00471 }
00472
00473 QFontMetrics fm(tmpFont);
00474 int flags = (singleline || ((formFactor() == Plasma::Horizontal) &&
00475 (contentsRect().height() < tmpFont.pointSize()*6))) ?
00476 Qt::TextSingleLine : Qt::TextWordWrap;
00477
00478 tmpRect = fm.boundingRect(rect, flags, text);
00479 } while (tmpFont.pointSize() > KGlobalSettings::smallestReadableFont().pointSize() &&
00480 (tmpRect.width() > rect.width() || tmpRect.height() > rect.height()));
00481
00482 p->setFont(tmpFont);
00483 return tmpRect;
00484 }
00485
00486 int Clock::updateInterval() const
00487 {
00488 return m_showSeconds ? 1000 : 60000;
00489 }
00490
00491 Plasma::IntervalAlignment Clock::intervalAlignment() const
00492 {
00493 return m_showSeconds ? Plasma::NoAlignment : Plasma::AlignToMinute;
00494 }
00495
00496 void Clock::updateColors()
00497 {
00498 if (!m_useCustomColor) {
00499 m_plainClockColor = KColorScheme(QPalette::Active, KColorScheme::View, Plasma::Theme::defaultTheme()->colorScheme()).foreground().color();
00500 update();
00501 }
00502 }
00503 #include "clock.moc"