• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDEUI

ktimecombobox.cpp
Go to the documentation of this file.
00001 /*
00002     Copyright 2011 John Layt <john@layt.net>
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License as published by the Free Software Foundation; either
00007     version 2 of the License, or (at your option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017     Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "ktimecombobox.h"
00021 
00022 #include <QtCore/QTime>
00023 #include <QtGui/QKeyEvent>
00024 #include <QtGui/QLineEdit>
00025 
00026 #include "kglobal.h"
00027 #include "kdebug.h"
00028 #include "klocale.h"
00029 #include "kcombobox.h"
00030 #include "kmessagebox.h"
00031 
00032 class KTimeComboBoxPrivate
00033 {
00034 public:
00035 
00036     KTimeComboBoxPrivate(KTimeComboBox *q);
00037     virtual ~KTimeComboBoxPrivate();
00038 
00039     QTime defaultMinTime();
00040     QTime defaultMaxTime();
00041 
00042     QString timeFormatToInputMask(const QString &format, bool nullMask = false);
00043     QTime nearestIntervalTime(const QTime &time);
00044     QString formatTime(const QTime &time);
00045     QString convertDigits(const QString &digits);
00046 
00047     void initTimeWidget();
00048     void updateTimeWidget();
00049 
00050 // Q_PRIVATE_SLOTs
00051     void selectTime(int index);
00052     void editTime(const QString &text);
00053     void enterTime(const QTime &time);
00054     void parseTime();
00055     void warnTime();
00056 
00057     KTimeComboBox *const q;
00058 
00059     QTime m_time;
00060     KTimeComboBox::Options m_options;
00061     QTime m_minTime;
00062     QTime m_maxTime;
00063     QString m_minWarnMsg;
00064     QString m_maxWarnMsg;
00065     QString m_nullString;
00066     bool m_warningShown;
00067     KLocale::TimeFormatOptions m_displayFormat;
00068     int m_timeListInterval;
00069     QList<QTime> m_timeList;
00070 };
00071 
00072 KTimeComboBoxPrivate::KTimeComboBoxPrivate(KTimeComboBox *q)
00073                      :q(q),
00074                       m_time(QTime(0, 0, 0)),
00075                       m_warningShown(false),
00076                       m_displayFormat(KLocale::TimeDefault),
00077                       m_timeListInterval(15)
00078 {
00079     m_options = KTimeComboBox::EditTime | KTimeComboBox::SelectTime;
00080     m_minTime = defaultMinTime();
00081     m_maxTime = defaultMaxTime();
00082 }
00083 
00084 KTimeComboBoxPrivate::~KTimeComboBoxPrivate()
00085 {
00086 }
00087 
00088 QTime KTimeComboBoxPrivate::defaultMinTime()
00089 {
00090     return QTime(0, 0, 0, 0);
00091 }
00092 
00093 QTime KTimeComboBoxPrivate::defaultMaxTime()
00094 {
00095     return QTime(23, 59, 59, 999);
00096 }
00097 
00098 QString KTimeComboBoxPrivate::timeFormatToInputMask(const QString &format, bool nullMask)
00099 {
00100     //TODO not sure this will always work, does it support DigitSets, am/pm is dodgy?
00101     QString mask = formatTime(QTime(12,34,56,789));
00102     QString null = mask;
00103     mask.replace(convertDigits(QLatin1String("12")), QLatin1String("09"));
00104     null.replace(convertDigits(QLatin1String("12")), QLatin1String(""));
00105     mask.replace(convertDigits(QLatin1String("34")), QLatin1String("99"));
00106     null.replace(convertDigits(QLatin1String("34")), QLatin1String(""));
00107     mask.replace(convertDigits(QLatin1String("56")), QLatin1String("99"));
00108     null.replace(convertDigits(QLatin1String("56")), QLatin1String(""));
00109     mask.replace(convertDigits(QLatin1String("789")), QLatin1String("900"));
00110     null.replace(convertDigits(QLatin1String("789")), QLatin1String(""));
00111     if (format.contains(QLatin1String("%p")) ||
00112         format.contains(QLatin1String("%P"))) {
00113         QString am = KGlobal::locale()->dayPeriodText(QTime(0, 0, 0));
00114         QString pm = KGlobal::locale()->dayPeriodText(QTime(12, 0, 0));
00115         int ampmLen = qMax(am.length(), pm.length());
00116         QString ampmMask;
00117         for (int i = 0; i < ampmLen; ++i) {
00118             ampmMask.append(QLatin1Char('a'));
00119         }
00120         mask.replace(pm, ampmMask);
00121         null.replace(pm, QLatin1String(""));
00122     }
00123 
00124     if (nullMask) {
00125         return null;
00126     } else {
00127         return mask;
00128     }
00129 }
00130 
00131 QTime KTimeComboBoxPrivate::nearestIntervalTime(const QTime &time)
00132 {
00133     int i = 0;
00134     while (q->itemData(i).toTime() < time) {
00135         ++i;
00136     }
00137     QTime before = q->itemData(i).toTime();
00138     QTime after = q->itemData(i + 1).toTime();
00139     if (before.secsTo(time) <= time.secsTo(after)) {
00140         return before;
00141     } else {
00142         return after;
00143     }
00144 }
00145 
00146 QString KTimeComboBoxPrivate::formatTime(const QTime &time)
00147 {
00148     return KGlobal::locale()->formatTime(time, m_displayFormat);
00149 }
00150 
00151 QString KTimeComboBoxPrivate::convertDigits(const QString &digits)
00152 {
00153     return KGlobal::locale()->convertDigits(digits, KGlobal::locale()->dateTimeDigitSet());
00154 }
00155 
00156 void KTimeComboBoxPrivate::initTimeWidget()
00157 {
00158     q->blockSignals(true);
00159     q->clear();
00160 
00161     // Set the input mask from the current format
00162     q->lineEdit()->setInputMask(timeFormatToInputMask(KGlobal::locale()->timeFormat()));
00163     m_nullString = timeFormatToInputMask(KGlobal::locale()->timeFormat(), true);
00164 
00165     // If EditTime then set the line edit
00166     q->lineEdit()->setReadOnly((m_options &KTimeComboBox::EditTime) != KTimeComboBox::EditTime);
00167 
00168     // If SelectTime then make list items visible
00169     if ((m_options &KTimeComboBox::SelectTime) == KTimeComboBox::SelectTime) {
00170         q->setMaxVisibleItems(10);
00171     } else {
00172         q->setMaxVisibleItems(0);
00173     }
00174 
00175     // Populate the drop-down time list
00176     // If no time list set the use the time interval
00177     if (m_timeList.isEmpty()) {
00178         QTime startTime = m_minTime;
00179         QTime thisTime(startTime.hour(), 0, 0, 0);
00180         while (thisTime.isValid() && thisTime <= startTime) {
00181             thisTime = thisTime.addSecs(m_timeListInterval * 60);
00182         }
00183         QTime endTime = m_maxTime;
00184         q->addItem(formatTime(startTime), startTime);
00185         while (thisTime.isValid() && thisTime < endTime) {
00186             q->addItem(formatTime(thisTime), thisTime);
00187             QTime newTime = thisTime.addSecs(m_timeListInterval * 60);
00188             if (newTime.isValid() && newTime > thisTime) {
00189                 thisTime = newTime;
00190             } else {
00191                 thisTime = QTime();
00192             }
00193         }
00194         q->addItem(formatTime(endTime), endTime);
00195     } else {
00196         foreach (const QTime &thisTime, m_timeList) {
00197             if (thisTime.isValid() && thisTime >= m_minTime && thisTime <= m_maxTime) {
00198                 q->addItem(formatTime(thisTime), thisTime);
00199             }
00200         }
00201     }
00202     q->blockSignals(false);
00203 }
00204 
00205 void KTimeComboBoxPrivate::updateTimeWidget()
00206 {
00207     q->blockSignals(true);
00208     int pos = q->lineEdit()->cursorPosition();
00209     //Set index before setting text otherwise it overwrites
00210     int i = 0;
00211     if (!m_time.isValid() || m_time < m_minTime) {
00212         i = 0;
00213     } else if (m_time > m_maxTime) {
00214         i = q->count() - 1;
00215     } else {
00216         while (q->itemData(i).toTime() < m_time && i < q->count() - 1) {
00217             ++i;
00218         }
00219     }
00220     q->setCurrentIndex(i);
00221     if (m_time.isValid()) {
00222         q->lineEdit()->setText(formatTime(m_time));
00223     } else {
00224         q->lineEdit()->setText(QString());
00225     }
00226     q->lineEdit()->setCursorPosition(pos);
00227     q->blockSignals(false);
00228 }
00229 
00230 void KTimeComboBoxPrivate::selectTime(int index)
00231 {
00232     enterTime(q->itemData(index).toTime());
00233 }
00234 
00235 void KTimeComboBoxPrivate::editTime(const QString &text)
00236 {
00237     m_warningShown = false;
00238     emit q->timeEdited(KGlobal::locale()->readTime(text));
00239 }
00240 
00241 void KTimeComboBoxPrivate::parseTime()
00242 {
00243     m_time = KGlobal::locale()->readTime(q->lineEdit()->text());
00244 }
00245 
00246 void KTimeComboBoxPrivate::enterTime(const QTime &time)
00247 {
00248     q->setTime(time);
00249     warnTime();
00250     emit q->timeEntered(m_time);
00251 }
00252 
00253 void KTimeComboBoxPrivate::warnTime()
00254 {
00255     if (!m_warningShown && !q->isValid() &&
00256         (m_options &KTimeComboBox::WarnOnInvalid) == KTimeComboBox::WarnOnInvalid) {
00257         QString warnMsg;
00258         if (!m_time.isValid()) {
00259             warnMsg = i18nc("@info", "The time you entered is invalid");
00260         } else if (m_time < m_minTime) {
00261             if (m_minWarnMsg.isEmpty()) {
00262                 warnMsg = i18nc("@info", "Time cannot be earlier than %1", formatTime(m_minTime));
00263             } else {
00264                 warnMsg = m_minWarnMsg;
00265                 warnMsg.replace("%1", formatTime(m_minTime));
00266             }
00267         } else if (m_time > m_maxTime) {
00268             if (m_maxWarnMsg.isEmpty()) {
00269                 warnMsg = i18nc("@info", "Time cannot be later than %1", formatTime(m_maxTime));
00270             } else {
00271                 warnMsg = m_maxWarnMsg;
00272                 warnMsg.replace("%1", formatTime(m_maxTime));
00273             }
00274         }
00275         m_warningShown = true;
00276         KMessageBox::sorry(q, warnMsg);
00277     }
00278 }
00279 
00280 KTimeComboBox::KTimeComboBox(QWidget *parent)
00281               :KComboBox(parent),
00282                d(new KTimeComboBoxPrivate(this))
00283 {
00284     setEditable(true);
00285     setInsertPolicy(QComboBox::NoInsert);
00286     setSizeAdjustPolicy(QComboBox::AdjustToContents);
00287     d->initTimeWidget();
00288     d->updateTimeWidget();
00289 
00290     connect( this, SIGNAL(activated(int)),
00291              this, SLOT(selectTime(int)));
00292     connect( this, SIGNAL(editTextChanged(const QString&)),
00293              this, SLOT(editTime(const QString&)));
00294 }
00295 
00296 KTimeComboBox::~KTimeComboBox()
00297 {
00298     delete d;
00299 }
00300 
00301 QTime KTimeComboBox::time() const
00302 {
00303     d->parseTime();
00304     return d->m_time;
00305 }
00306 
00307 void KTimeComboBox::setTime(const QTime &time)
00308 {
00309     if (time == d->m_time) {
00310         return;
00311     }
00312 
00313     if ((d->m_options &KTimeComboBox::ForceTime) == KTimeComboBox::ForceTime) {
00314         assignTime(d->nearestIntervalTime(time));
00315     } else {
00316         assignTime(time);
00317     }
00318 
00319     d->updateTimeWidget();
00320     emit timeChanged(d->m_time);
00321 }
00322 
00323 void KTimeComboBox::assignTime(const QTime &time)
00324 {
00325     d->m_time = time;
00326 }
00327 
00328 bool KTimeComboBox::isValid() const
00329 {
00330     d->parseTime();
00331     return d->m_time.isValid() &&
00332            d->m_time >= d->m_minTime &&
00333            d->m_time <= d->m_maxTime;
00334 }
00335 
00336 bool KTimeComboBox::isNull() const
00337 {
00338     return lineEdit()->text() == d->m_nullString;
00339 }
00340 
00341 KTimeComboBox::Options KTimeComboBox::options() const
00342 {
00343     return d->m_options;
00344 }
00345 
00346 void KTimeComboBox::setOptions(Options options)
00347 {
00348     if (options != d->m_options) {
00349         d->m_options = options;
00350         d->initTimeWidget();
00351         d->updateTimeWidget();
00352     }
00353 }
00354 
00355 QTime KTimeComboBox::minimumTime() const
00356 {
00357     return d->m_minTime;
00358 }
00359 
00360 void KTimeComboBox::setMinimumTime(const QTime &minTime, const QString &minWarnMsg)
00361 {
00362     setTimeRange(minTime, d->m_maxTime, minWarnMsg, d->m_maxWarnMsg);
00363 }
00364 
00365 void KTimeComboBox::resetMinimumTime()
00366 {
00367     setTimeRange(d->defaultMinTime(), d->m_maxTime, QString(), d->m_maxWarnMsg);
00368 }
00369 
00370 QTime KTimeComboBox::maximumTime() const
00371 {
00372     return d->m_maxTime;
00373 }
00374 
00375 void KTimeComboBox::setMaximumTime(const QTime &maxTime, const QString &maxWarnMsg)
00376 {
00377     setTimeRange(d->m_minTime, maxTime, d->m_minWarnMsg, maxWarnMsg);
00378 }
00379 
00380 void KTimeComboBox::resetMaximumTime()
00381 {
00382     setTimeRange(d->m_minTime, d->defaultMaxTime(), d->m_minWarnMsg, QString());
00383 }
00384 
00385 void KTimeComboBox::setTimeRange(const QTime &minTime, const QTime &maxTime,
00386                                  const QString &minWarnMsg, const QString &maxWarnMsg)
00387 {
00388     if (!minTime.isValid() || !maxTime.isValid() || minTime > maxTime) {
00389         return;
00390     }
00391 
00392     if (minTime != d->m_minTime || maxTime != d->m_maxTime ||
00393         minWarnMsg != d->m_minWarnMsg || maxWarnMsg != d->m_maxWarnMsg) {
00394         d->m_minTime = minTime;
00395         d->m_maxTime = maxTime;
00396         d->m_minWarnMsg = minWarnMsg;
00397         d->m_maxWarnMsg = maxWarnMsg;
00398         d->initTimeWidget();
00399         d->updateTimeWidget();
00400     }
00401 }
00402 
00403 void KTimeComboBox::resetTimeRange()
00404 {
00405     setTimeRange(d->defaultMinTime(), d->defaultMaxTime(), QString(), QString());
00406 }
00407 
00408 KLocale::TimeFormatOptions KTimeComboBox::displayFormat() const
00409 {
00410     return d->m_displayFormat;
00411 }
00412 
00413 void KTimeComboBox::setDisplayFormat(KLocale::TimeFormatOptions format)
00414 {
00415     if (format != d->m_displayFormat) {
00416         d->m_displayFormat = format;
00417         d->initTimeWidget();
00418         d->updateTimeWidget();
00419     }
00420 }
00421 
00422 int KTimeComboBox::timeListInterval() const
00423 {
00424     return d->m_timeListInterval;
00425 }
00426 
00427 void KTimeComboBox::setTimeListInterval(int minutes)
00428 {
00429     if (minutes != d->m_timeListInterval) {
00430         //Must be able to exactly divide the valid time period
00431         int lowMins = (d->m_minTime.hour() * 60) + d->m_minTime.minute();
00432         int hiMins = (d->m_maxTime.hour() * 60) + d->m_maxTime.minute();
00433         if (d->m_minTime.minute() == 0 && d->m_maxTime.minute() == 59) {
00434             ++hiMins;
00435         }
00436         if ((hiMins - lowMins) % minutes == 0) {
00437             d->m_timeListInterval = minutes;
00438             d->m_timeList.clear();
00439         } else {
00440             return;
00441         }
00442         d->initTimeWidget();
00443     }
00444 }
00445 
00446 QList<QTime> KTimeComboBox::timeList() const
00447 {
00448     //Return the drop down list as it is what can be selected currently
00449     QList<QTime> list;
00450     int c = count();
00451     for (int i = 0; i < c; ++i) {
00452         list.append(itemData(i).toTime());
00453     }
00454     return list;
00455 }
00456 
00457 void KTimeComboBox::setTimeList(QList<QTime> timeList,
00458                                 const QString &minWarnMsg, const QString &maxWarnMsg)
00459 {
00460     if (timeList != d->m_timeList) {
00461         d->m_timeList.clear();
00462         foreach (const QTime &time, timeList) {
00463             if (time.isValid() && !d->m_timeList.contains(time)) {
00464                 d->m_timeList.append(time);
00465             }
00466         }
00467         qSort(d->m_timeList);
00468         // Does the updateTimeWidget call for us
00469         setTimeRange(d->m_timeList.first(), d->m_timeList.last(),
00470                     minWarnMsg, maxWarnMsg);
00471     }
00472 }
00473 
00474 bool KTimeComboBox::eventFilter(QObject *object, QEvent *event)
00475 {
00476     return KComboBox::eventFilter(object, event);
00477 }
00478 
00479 void KTimeComboBox::keyPressEvent(QKeyEvent *keyEvent)
00480 {
00481     QTime temp;
00482     switch (keyEvent->key()) {
00483     case Qt::Key_Down:
00484         temp = d->m_time.addSecs(-60);
00485         break;
00486     case Qt::Key_Up:
00487         temp = d->m_time.addSecs(60);
00488         break;
00489     case Qt::Key_PageDown:
00490         temp = d->m_time.addSecs(-3600);
00491         break;
00492     case Qt::Key_PageUp:
00493         temp = d->m_time.addSecs(3600);
00494         break;
00495     default:
00496         KComboBox::keyPressEvent(keyEvent);
00497         return;
00498     }
00499     if (temp.isValid() && temp >= d->m_minTime && temp <= d->m_maxTime) {
00500         d->enterTime(temp);
00501     }
00502 }
00503 
00504 void KTimeComboBox::focusOutEvent(QFocusEvent *event)
00505 {
00506     d->parseTime();
00507     d->warnTime();
00508     KComboBox::focusOutEvent(event);
00509 }
00510 
00511 void KTimeComboBox::showPopup()
00512 {
00513     KComboBox::showPopup();
00514 }
00515 
00516 void KTimeComboBox::hidePopup()
00517 {
00518     KComboBox::hidePopup();
00519 }
00520 
00521 void KTimeComboBox::mousePressEvent(QMouseEvent *event)
00522 {
00523     KComboBox::mousePressEvent(event);
00524 }
00525 
00526 void KTimeComboBox::wheelEvent(QWheelEvent *event)
00527 {
00528     KComboBox::wheelEvent(event);
00529 }
00530 
00531 void KTimeComboBox::focusInEvent(QFocusEvent *event)
00532 {
00533     KComboBox::focusInEvent(event);
00534 }
00535 
00536 void KTimeComboBox::resizeEvent(QResizeEvent *event)
00537 {
00538     KComboBox::resizeEvent(event);
00539 }
00540 
00541 #include "ktimecombobox.moc"

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal