From: Enar Vaikene Date: Tue, 14 Aug 2012 07:05:20 +0000 (+0300) Subject: Making the ScosTime application more user friendly (unfinished). X-Git-Url: https://vaikene.ee/gitweb/gitweb.cgi?p=evaf;a=commitdiff_plain;h=8c1076918aee67a8d6adae31fc14156c9779d471 Making the ScosTime application more user friendly (unfinished). --- diff --git a/src/apps/ScosTime/gui.cpp b/src/apps/ScosTime/gui.cpp index 1ea9ba1..6efd962 100644 --- a/src/apps/ScosTime/gui.cpp +++ b/src/apps/ScosTime/gui.cpp @@ -38,17 +38,34 @@ Q_EXPORT_PLUGIN2(VER_MODULE_NAME_STR, eVaf::ScosTime::Module) using namespace eVaf; using namespace eVaf::ScosTime; + +//------------------------------------------------------------------- + +Internal::DateTime::DateTime(QString const & s, QString const & epoch) +{ + +} + + +//------------------------------------------------------------------- + Module::Module() : Plugins::iPlugin() , mReady(false) + , mLastValidEntry(NoValidEntry) { setObjectName(QString("%1.%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__)); + rxIsoDateTime = new QRegExp("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(.\\d{3})?)?$"); + rxAsdDateTime = new QRegExp("^\\d{4}\\.\\d{3}\\.\\d{2}\\.\\d{2}(\\.\\d{2}(\\.\\d{3})?)?$"); + EVAF_INFO("%s created", qPrintable(objectName())); } Module::~Module() { + delete rxIsoDateTime; + delete rxAsdDateTime; EVAF_INFO("%s destroyed", qPrintable(objectName())); } @@ -77,7 +94,9 @@ bool Module::init(QString const & args) wEpoch = new QComboBox; l->setBuddy(wEpoch); wEpoch->setEditable(true); + wEpoch->setValidator(new QRegExpValidator(*rxIsoDateTime, wEpoch)); wEpoch->addItems(QStringList() << "1970-01-01T00:00:00.000" << "1999-08-22T00:00:00.000"); + connect(wEpoch, SIGNAL(editTextChanged(QString)), this, SLOT(epochChanged(QString))); g->addWidget(wEpoch, 0, 1); panel->setFocusProxy(wEpoch); @@ -87,27 +106,27 @@ bool Module::init(QString const & args) wDateTime = new QLineEdit; l->setBuddy(wDateTime); - QRegExp rxDateTime("^\\d{4}\\.\\d{3}\\.\\d{2}\\.\\d{2}\\.\\d{2}(\\.\\d{3})?$"); + QRegExp rxDateTime("^(\\d{4}\\.\\d{3}\\.\\d{2}\\.\\d{2}\\.\\d{2}(\\.\\d{3})?)|(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(.\\d{3})?)$"); wDateTime->setValidator(new QRegExpValidator(rxDateTime, wDateTime)); + connect(wDateTime, SIGNAL(textEdited(QString)), this, SLOT(dateTimeEdited(QString))); g->addWidget(wDateTime, 1, 1); - QPushButton * btn = new QPushButton(tr("Convert", VER_MODULE_NAME_STR)); + QPushButton * btn = new QPushButton(); + btn->setDisabled(true); g->addWidget(btn, 1, 2); connect(btn, SIGNAL(clicked()), this, SLOT(dateTimeClicked())); + wConvertDateTime = btn; - l = new QLabel(tr("&HEX:", VER_MODULE_NAME_STR)); + l = new QLabel(tr("&CUC:", VER_MODULE_NAME_STR)); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); g->addWidget(l, 2, 0); - wHex = new QLineEdit; - l->setBuddy(wHex); - wHex->setMaxLength(12); - wHex->setInputMask(">HHHHHHHHhhhh"); - g->addWidget(wHex, 2, 1); - - btn = new QPushButton(tr("Convert", VER_MODULE_NAME_STR)); - g->addWidget(btn, 2, 2); - connect(btn, SIGNAL(clicked()), this, SLOT(hexClicked())); + wCucHex = new QLineEdit; + l->setBuddy(wCucHex); + wCucHex->setMaxLength(12); + wCucHex->setInputMask(">HHHHHHHHhhhh"); + connect(wCucHex, SIGNAL(textEdited(QString)), this, SLOT(cucHexEdited(QString))); + g->addWidget(wCucHex, 2, 1); v->addStretch(); @@ -134,73 +153,217 @@ void Module::done() EVAF_INFO("%s finalized", qPrintable(objectName())); } -QDateTime Module::strToDateTime(QString const & s) const +Module::DateTimeType Module::getDateTimeType(QString const & s) const { - QStringList tok = s.split(QChar('.')); - if (tok.size() < 5) - return QDateTime(); + if (rxIsoDateTime->exactMatch(s)) + return IsoDateTime; + else if (rxAsdDateTime->exactMatch(s)) + return AsdDateTime; + else + return InvalidDateTime; +} - bool ok = false; - int year = tok.at(0).toInt(&ok); - if (!ok) - return QDateTime(); - int days = tok.at(1).toInt(&ok); - if (!ok) - return QDateTime(); - int hours = tok.at(2).toInt(&ok); - if (!ok) - return QDateTime(); - int minutes = tok.at(3).toInt(&ok); - if (!ok) - return QDateTime(); - int secs = tok.at(4).toInt(&ok); - if (!ok) - return QDateTime(); - int msecs = 0; - if (tok.size() > 5) { - msecs = tok.at(5).toInt(&ok); - if (!ok) +QDateTime Module::strToDateTime(QString const & s, DateTimeType type) const +{ + switch (type) + { + case AsdDateTime: + { + // Using the yyyy.ddd.hh.mm.ss[.zzz] format + QStringList tok = s.split(QChar('.')); + if (tok.size() < 4) + return QDateTime(); + + bool ok = false; + int year = tok.at(0).toInt(&ok); + if (!ok) + return QDateTime(); + int days = tok.at(1).toInt(&ok); + if (!ok) + return QDateTime(); + int hours = tok.at(2).toInt(&ok); + if (!ok) + return QDateTime(); + int minutes = tok.at(3).toInt(&ok); + if (!ok) + return QDateTime(); + int secs = 0; + int msecs = 0; + if (tok.size() > 4) { + secs = tok.at(4).toInt(&ok); + if (!ok) + return QDateTime(); + if (tok.size() > 5) { + msecs = tok.at(5).toInt(&ok); + if (!ok) + return QDateTime(); + } + } + + QDate dt(year, 1, 1); + dt = dt.addDays(days - 1); + + return QDateTime(dt, QTime(hours, minutes, secs, msecs), Qt::UTC); + break; + } + case IsoDateTime: + { + // Using the ISO format yyyy-MM-ddThh:mm:ss[.zzz] + QDateTime dt = QDateTime::fromString(s, Qt::ISODate); + dt.setTimeSpec(Qt::UTC); + return dt; + break; + } + default: return QDateTime(); } +} - QDate dt(year, 1, 1); - dt = dt.addDays(days - 1); +QString Module::dateTimeToAsdStr(QDateTime const & tm) const +{ + return QString("%1.%2.%3.%4.%5.%6") + .arg(tm.date().year(), 4, 10, QChar('0')) + .arg(tm.date().dayOfYear(), 3, 10, QChar('0')) + .arg(tm.time().hour(), 2, 10, QChar('0')) + .arg(tm.time().minute(), 2, 10, QChar('0')) + .arg(tm.time().second(), 2, 10, QChar('0')) + .arg(tm.time().msec(), 3, 10, QChar('0')); +} + +void Module::setDateTimeFromCucHex(QString const & s) +{ - return QDateTime(dt, QTime(hours, minutes, secs, msecs), Qt::UTC); } -void Module::dateTimeClicked() +void Module::setCucHexFromDateTime(QString const & s, DateTimeType type) { + // Get the epoch QDateTime epoch = QDateTime::fromString(wEpoch->currentText(), Qt::ISODate); epoch.setTimeSpec(Qt::UTC); - QDateTime tm = strToDateTime(wDateTime->text()); + + // Convert the date/time string to a QDateTime type + QDateTime tm = strToDateTime(s, type); + + // Convert to CUC coarse and fine values qint64 msecs = epoch.msecsTo(tm); quint32 coarse = quint32(msecs / 1000); quint32 fine = quint32(rint(1000.0 * double(msecs % 1000) * 58.0 / 885.0)); - wHex->setText(QString("%1%2").arg(coarse, 8, 16, QChar('0')).arg(fine, 4, 16, QChar('0'))); + + // Set the CUC hex string + wCucHex->setText(QString("%1%2").arg(coarse, 8, 16, QChar('0')).arg(fine, 4, 16, QChar('0'))); } -void Module::hexClicked() +void Module::dateTimeClicked() { + // Get the date/time string, type and QDateTime value + QString s = wDateTime->text(); + DateTimeType type = getDateTimeType(s); + QDateTime tm = strToDateTime(s, type); + + // Convert to another type + switch (type) + { + case IsoDateTime: + { + wDateTime->setText(dateTimeToAsdStr(tm)); + wConvertDateTime->setText(tr("&to ISO", VER_MODULE_NAME_STR)); + break; + } + case AsdDateTime: + { + wDateTime->setText(tm.toString("yyyy-MM-ddThh:mm:ss.zzz")); + wConvertDateTime->setText(tr("&to ASD", VER_MODULE_NAME_STR)); + break; + } + default: + break; + } +} + +void Module::dateTimeEdited(QString const & s) +{ + if (mLastValidEntry == DateTimeEntry) + mLastValidEntry = NoValidEntry; + wConvertDateTime->setDisabled(true); + wConvertDateTime->setText(QString()); + + if (s.isEmpty()) + return; + + // Detect the type of the date/time string + DateTimeType type = getDateTimeType(s); + if (type == InvalidDateTime) + return; + + // Set the date/time field as the last valid entry done by the user + mLastValidEntry = DateTimeEntry; + + // Set the CUC hex string from this date/time string + setCucHexFromDateTime(s); + + // Enable the button that converts between ISO and ASD date/time strings + if (type == IsoDateTime) { + wConvertDateTime->setEnabled(true); + wConvertDateTime->setText(tr("&to ASD", VER_MODULE_NAME_STR)); + } + else if (type == AsdDateTime) { + wConvertDateTime->setEnabled(true); + wConvertDateTime->setText(tr("&to ISO", VER_MODULE_NAME_STR)); + } +} + +void Module::cucHexEdited(QString const & s) +{ + if (mLastValidEntry == CUCEntry) + mLastValidEntry = NoValidEntry; + if (s.isEmpty() || s.size() < 8) + return; + + // Get the CUC coarse and fine values bool ok = false; - int coarse = wHex->text().left(8).toLong(&ok, 16); + int coarse = s.left(8).toLong(&ok, 16); if (!ok) return; int fine = 0; - if (wHex->text().size() > 8) - fine = wHex->text().mid(8, 4).toLong(&ok, 16); + if (s.size() == 12) + fine = s.mid(8, 4).toLong(&ok, 16); if (!ok) return; + // Set the CUC field as the last valid entry done by the user + mLastValidEntry = CUCEntry; + + // Get the epoch QDateTime epoch = QDateTime::fromString(wEpoch->currentText(), Qt::ISODate); epoch.setTimeSpec(Qt::UTC); + + // Get the date/time value QDateTime tm = epoch.addSecs(coarse); tm = tm.addMSecs(rint((double(fine) / 58.0 * 885.0) / 1000.0)); - wDateTime->setText(QString("%1.%2.%3.%4.%5.%6") - .arg(tm.date().year(), 4, 10, QChar('0')) - .arg(tm.date().dayOfYear(), 3, 10, QChar('0')) - .arg(tm.time().hour(), 2, 10, QChar('0')) - .arg(tm.time().minute(), 2, 10, QChar('0')) - .arg(tm.time().second(), 2, 10, QChar('0')) - .arg(tm.time().msec(), 3, 10, QChar('0'))); + + // Set the date/time string in ASD format + wDateTime->setText(dateTimeToAsdStr(tm)); + + // Enable conversion to ISO format + wConvertDateTime->setEnabled(true); + wConvertDateTime->setText(tr("&to ISO", VER_MODULE_NAME_STR)); +} + +void Module::epochChanged(QString const & s) +{ + if (s.isEmpty()) + return; + if (!rxIsoDateTime->exactMatch(s)) + return; + + // If there is a valid entry, do the conversion + switch (mLastValidEntry) + { + case DateTimeEntry: + break; + case CUCEntry: + break; + default: + break; + } } diff --git a/src/apps/ScosTime/gui.h b/src/apps/ScosTime/gui.h index fe6b5e3..90f33c2 100644 --- a/src/apps/ScosTime/gui.h +++ b/src/apps/ScosTime/gui.h @@ -28,10 +28,73 @@ class QLineEdit; class QComboBox; +class QRegExp; +class QPushButton; namespace eVaf { namespace ScosTime { +namespace Internal { + +/** + * SCOS date/time class + */ +class DateTime +{ +public: + + /** + * Creates an invalid date/time value + */ + DateTime() {} + + /** + * Creates a date/time value from the string. + * @param s Input string + * @param epoch Epoch + * + * The input string can be: + * @li Date/time in ISO format yyyy-MM-ddThh:mm[:ss[.zzz]] + * @li Date/time in ASD format yyyy.ddd.hh.mm[.ss[.zzz]] + * @li CUC hex string cccccccc[ffff] + * + * If the string is invalid, creates an invalid date/time value. + */ + DateTime(String const & s, String const & epoch); + + /** + * Returns true if the date/time value is valid. + */ + bool isValid() const { return mDateTime.isValid(); } + + /** + * Returns the date/time value a string in the ISO format yyyy-MM-ddThh:mm:ss.zzz + */ + QString asIsoString() const; + + /** + * Returns the date/time value as a string in the ASD format yyyy.ddd.hh.mm.ss.zzz + */ + QString asAsdString() const; + + /** + * Returns the date/time value as a CUC hex string in the format ccccccccffff + */ + QString asCucHexString() const; + + +private: + + /// Date/time value + QDateTime mDateTime; + + /// Epoch + QDateTime mEpoch; + +}; + +} // namespace eVaf::ScosTime::Internal + /** * Graphical User Interface for the ScosTime application. * @@ -42,6 +105,20 @@ class Module : public Plugins::iPlugin Q_OBJECT Q_INTERFACES(eVaf::Plugins::iPlugin) + enum DateTimeType + { + InvalidDateTime, + AsdDateTime, + IsoDateTime + }; + + enum ValidEntry + { + NoValidEntry, + DateTimeEntry, + CUCEntry + }; + public: Module(); @@ -57,24 +134,45 @@ public: private slots: + void epochChanged(QString const & s); + void dateTimeClicked(); - void hexClicked(); + void dateTimeEdited(QString const & s); + + void cucHexEdited(QString const & s); private: // Methods - QDateTime strToDateTime(QString const & s) const; + DateTimeType getDateTimeType(QString const & s) const; + + QDateTime strToDateTime(QString const & s, DateTimeType type) const; + + QString dateTimeToAsdStr(QDateTime const & tm) const; + + void setDateTimeFromCucHex(QString const & s); + + void setCucHexFromDateTime(QString const & s, DateTimeType type); + private: // Members /// Flag indicating that the module is ready bool mReady; + /// Last valid entry (field modified by the user) + ValidEntry mLastValidEntry; + + /// Regular expressions + QRegExp * rxIsoDateTime; + QRegExp * rxAsdDateTime; + /// Widgets on the screen QComboBox * wEpoch; QLineEdit * wDateTime; - QLineEdit * wHex; + QPushButton * wConvertDateTime; + QLineEdit * wCucHex; };