]> vaikene.ee Git - evaf/blobdiff - src/apps/ScosTime/gui.cpp
Merge branch 'ScosTime' into qt5
[evaf] / src / apps / ScosTime / gui.cpp
index 1a978afa34612aafc6ac15ce13bfbd3472596a04..e8c2ae9d1d6f2a40dbbb390cae20a6d97096865c 100644 (file)
@@ -36,9 +36,238 @@ VER_EXPORT_VERSION_INFO()
 using namespace eVaf;
 using namespace eVaf::ScosTime;
 
+
+//-------------------------------------------------------------------
+
+Internal::DateTime::DateTime()
+    : mType(Invalid)
+    , mEpoch(QDateTime(QDate(1970, 1, 1), QTime(0, 0), Qt::UTC))
+    , mRxIso(new QRegExp("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d{3})?)?$"))
+    , mRxAsd(new QRegExp("^\\d{4}\\.\\d{3}\\.\\d{2}\\.\\d{2}(\\.\\d{2}(\\.\\d{3})?)?$"))
+    , mRxCUC(new QRegExp("^[0-9a-f]{8}([0-9a-f]{4})?$", Qt::CaseInsensitive))
+{}
+
+Internal::DateTime::~DateTime()
+{
+    delete mRxCUC;
+    delete mRxAsd;
+    delete mRxIso;
+}
+
+Internal::DateTime::Type Internal::DateTime::setDateTime(QString const & s, QDateTime const & epoch)
+{
+    mEpoch = epoch;
+    return setDateTime(s);
+}
+
+Internal::DateTime::Type Internal::DateTime::setDateTime(QString const & s)
+{
+    // Detect the type of the date/time string
+    mType = getDateTimeType(s);
+    if (mType == Invalid)
+    {
+        return mType;
+    }
+
+    // Convert the string to a date/time value
+    mDateTime = strToDateTime(s, mType);
+    if (!mDateTime.isValid())
+    {
+        mType = Invalid;
+    }
+
+
+    return mType;
+}
+
+void Internal::DateTime::setEpoch(QDateTime const & epoch)
+{
+    if (!epoch.isValid())
+    {
+        return;
+    }
+
+    if (epoch != mEpoch)
+    {
+        // Adjust the date/time if the value was set from a CUC HEX string
+        if (mType == CUC && mDateTime.isValid())
+        {
+            qint64 diff = mEpoch.msecsTo(epoch);
+            mDateTime = mDateTime.addMSecs(diff);
+        }
+        mEpoch = epoch;
+    }
+}
+
+Internal::DateTime::Type Internal::DateTime::getDateTimeType(QString const & s) const
+{
+    if (mRxIso->exactMatch(s))
+    {
+        return ISO;
+    }
+    else if (mRxAsd->exactMatch(s))
+    {
+        return ASD;
+    }
+    else if (mRxCUC->exactMatch(s))
+    {
+        return CUC;
+    }
+    return Invalid;
+}
+
+QDateTime Internal::DateTime::strToDateTime(QString const & s, Type type) const
+{
+    switch (type)
+    {
+        case ASD:
+        {
+            // 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 ISO:
+        {
+            // Using the ISO format yyyy-MM-ddThh:mm:ss[.zzz]
+            QString tmp = s;
+            if (tmp.length() < 19)
+            {
+                tmp += ":00";
+            }
+            QDateTime dt = QDateTime::fromString(tmp, Qt::ISODate);
+            dt.setTimeSpec(Qt::UTC);
+            return dt;
+            break;
+        }
+        case CUC:
+        {
+            // Get the CUC coarse and fine values
+            bool ok = false;
+            int coarse = s.left(8).toLong(&ok, 16);
+            if (!ok)
+            {
+                return QDateTime();
+            }
+            int fine = 0;
+            if (s.size() == 12)
+            {
+                fine = s.mid(8, 4).toLong(&ok, 16);
+                if (!ok)
+                {
+                    return QDateTime();
+                }
+            }
+
+            // Get the date/time value
+            QDateTime tm = mEpoch.addSecs(coarse);
+            tm = tm.addMSecs(rint((double(fine) / 58.0 * 885.0) / 1000.0));
+            return tm;
+
+            break;
+        }
+        default:
+        {
+            return QDateTime();
+        }
+    }
+}
+
+QString Internal::DateTime::asISOstring() const
+{
+    if (mDateTime.isValid())
+    {
+        return mDateTime.toString("yyyy-MM-ddThh:mm:ss.zzz"); 
+    }
+    return QString();
+}
+
+QString Internal::DateTime::asASDstring() const
+{
+    if (mDateTime.isValid())
+    {
+        return QString("%1.%2.%3.%4.%5.%6")
+            .arg(mDateTime.date().year(), 4, 10, QChar('0'))
+            .arg(mDateTime.date().dayOfYear(), 3, 10, QChar('0'))
+            .arg(mDateTime.time().hour(), 2, 10, QChar('0'))
+            .arg(mDateTime.time().minute(), 2, 10, QChar('0'))
+            .arg(mDateTime.time().second(), 2, 10, QChar('0'))
+            .arg(mDateTime.time().msec(), 3, 10, QChar('0'));
+    }
+    return QString();
+}
+
+QString Internal::DateTime::asCUChexString() const
+{
+    if (!mDateTime.isValid())
+    {
+        return QString();
+    }
+
+    // Convert to CUC coarse and fine values
+    qint64 msecs = mEpoch.msecsTo(mDateTime);
+    quint32 coarse = quint32(msecs / 1000);
+    quint32 fine = quint32(rint(1000.0 * double(msecs % 1000) * 58.0 / 885.0));
+
+    // Set the CUC hex string
+    return QString("%1%2").arg(coarse, 8, 16, QChar('0')).arg(fine, 4, 16, QChar('0'));
+}
+
+
+//-------------------------------------------------------------------
+
 Module::Module()
     : Plugins::iPlugin()
     , mReady(false)
+    , mLastDateTimeType(Internal::DateTime::Invalid)
 {
     setObjectName(QString("%1.%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__));
 
@@ -75,7 +304,12 @@ bool Module::init(QString const & args)
     wEpoch = new QComboBox;
     l->setBuddy(wEpoch);
     wEpoch->setEditable(true);
+    {
+        QRegExp rx("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?$");
+        wEpoch->setValidator(new QRegExpValidator(rx, 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);
 
@@ -85,27 +319,32 @@ 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})?$");
-    wDateTime->setValidator(new QRegExpValidator(rxDateTime, wDateTime));
+    {
+        QRegExp rx("^(\\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(rx, 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);
+    {
+        QRegExp rx("^[0-9a-f]{8}([0-9a-f]{4})?$", Qt::CaseInsensitive);
+        wCucHex->setValidator(new QRegExpValidator(rx, wCucHex));
+    }
+    connect(wCucHex, SIGNAL(textEdited(QString)), this, SLOT(cucHexEdited(QString)));
+    g->addWidget(wCucHex, 2, 1);
 
     v->addStretch();
 
@@ -132,73 +371,137 @@ void Module::done()
     EVAF_INFO("%s finalized", qPrintable(objectName()));
 }
 
-QDateTime Module::strToDateTime(QString const & s) const
-{
-    QStringList tok = s.split(QChar('.'));
-    if (tok.size() < 5)
-        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 = tok.at(4).toInt(&ok);
-    if (!ok)
-        return QDateTime();
-    int msecs = 0;
-    if (tok.size() > 5) {
-        msecs = tok.at(5).toInt(&ok);
-        if (!ok)
-            return QDateTime();
+void Module::dateTimeClicked()
+{
+    if (!mDateTime.isValid())
+    {
+        return;
     }
 
-    QDate dt(year, 1, 1);
-    dt = dt.addDays(days - 1);
+    // Convert to another type
+    switch (mLastDateTimeType)
+    {
+        case Internal::DateTime::ISO:
+        {
+            mLastDateTimeType = Internal::DateTime::ASD;
+            wDateTime->setText(mDateTime.asASDstring());
+            wConvertDateTime->setText(tr("&to ISO", VER_MODULE_NAME_STR));
+            break;
+        }
+        case Internal::DateTime::ASD:
+        {
+            mLastDateTimeType = Internal::DateTime::ISO;
+            wDateTime->setText(mDateTime.asISOstring());
+            wConvertDateTime->setText(tr("&to ASD", VER_MODULE_NAME_STR));
+            break;
+        }
+        default:
+            break;
+    }
+}
+
+void Module::dateTimeEdited(QString const & s)
+{
+    wConvertDateTime->setDisabled(true);
+    wConvertDateTime->setText(QString());
+    mLastDateTimeType = Internal::DateTime::Invalid;
 
-    return QDateTime(dt, QTime(hours, minutes, secs, msecs), Qt::UTC);
+    if (s.isEmpty())
+    {
+        return;
+    }
+
+    mDateTime.setDateTime(s);
+    if (!mDateTime.isValid())
+    {
+        return;
+    }
+
+    mLastDateTimeType = mDateTime.type();
+
+    // Set the CUC hex string from this date/time string
+    wCucHex->setText(mDateTime.asCUChexString());
+
+    // Enable the button that converts between ISO and ASD date/time strings
+    if (mDateTime.type() == Internal::DateTime::ISO)
+    {
+        wConvertDateTime->setEnabled(true);
+        wConvertDateTime->setText(tr("&to ASD", VER_MODULE_NAME_STR));
+    }
+    else if (mDateTime.type() == Internal::DateTime::ISO)
+    {
+        wConvertDateTime->setEnabled(true);
+        wConvertDateTime->setText(tr("&to ISO", VER_MODULE_NAME_STR));
+    }
 }
 
-void Module::dateTimeClicked()
+void Module::cucHexEdited(QString const & s)
 {
-    QDateTime epoch = QDateTime::fromString(wEpoch->currentText(), Qt::ISODate);
-    epoch.setTimeSpec(Qt::UTC);
-    QDateTime tm = strToDateTime(wDateTime->text());
-    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')));
+    if (s.isEmpty() || s.size() < 8)
+    {
+        return;
+    }
+
+    mDateTime.setDateTime(s);
+    if (!mDateTime.isValid())
+    {
+        return;
+    }
+
+    if (mLastDateTimeType == Internal::DateTime::Invalid)
+    {
+        mLastDateTimeType = Internal::DateTime::ASD;
+    }
+
+    // Set the date/time string in the last used format
+    if (mLastDateTimeType == Internal::DateTime::ASD)
+    {
+        wDateTime->setText(mDateTime.asASDstring());
+        wConvertDateTime->setEnabled(true);
+        wConvertDateTime->setText(tr("&to ISO", VER_MODULE_NAME_STR));
+    }
+    else if (mLastDateTimeType == Internal::DateTime::ISO)
+    {
+        wDateTime->setText(mDateTime.asISOstring());
+        wConvertDateTime->setEnabled(true);
+        wConvertDateTime->setText(tr("&to ASD", VER_MODULE_NAME_STR));
+    }
 }
 
-void Module::hexClicked()
+void Module::epochChanged(QString const & s)
 {
-    bool ok = false;
-    int coarse = wHex->text().left(8).toLong(&ok, 16);
-    if (!ok)
+    if (s.isEmpty())
         return;
-    int fine = 0;
-    if (wHex->text().size() > 8)
-        fine = wHex->text().mid(8, 4).toLong(&ok, 16);
-    if (!ok)
+    QRegExp rx("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?$");
+    if (!rx.exactMatch(s))
         return;
 
-    QDateTime epoch = QDateTime::fromString(wEpoch->currentText(), Qt::ISODate);
-    epoch.setTimeSpec(Qt::UTC);
-    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')));
+    QDateTime dt = QDateTime::fromString(s, Qt::ISODate);
+    dt.setTimeSpec(Qt::UTC);
+    mDateTime.setEpoch(dt);
+
+    // If there is a valid entry, do the conversion
+    switch (mDateTime.type())
+    {
+        case Internal::DateTime::ISO:
+        case Internal::DateTime::ASD:
+        {
+            wCucHex->setText(mDateTime.asCUChexString());
+            break;
+        }
+        case Internal::DateTime::CUC:
+        {
+            if (mLastDateTimeType == Internal::DateTime::ASD)
+            {
+                wDateTime->setText(mDateTime.asASDstring());
+            }
+            else if (mLastDateTimeType == Internal::DateTime::ISO)
+            {
+                wDateTime->setText(mDateTime.asISOstring());
+            }
+            break;
+        }
+        default:
+            break;
+    }
 }