+/**
+ * @file ScosTime/gui.cpp
+ * @brief GUI for the ScosTime application
+ * @author Enar Vaikene
+ *
+ * Copyright (c) 2012 Enar Vaikene
+ *
+ * This file is part of the eVaf C++ cross-platform application development framework.
+ *
+ * This file can be used under the terms of the GNU General Public License
+ * version 3.0 as published by the Free Software Foundation and appearing in
+ * the file LICENSE included in the packaging of this file. Please review the
+ * the following information to ensure the GNU General Public License version
+ * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+ *
+ * Alternatively, this file may be used in accordance with the Commercial License
+ * Agreement provided with the Software.
+ */
+
+#include "gui.h"
+#include "version.h"
+
+#include <Common/Globals>
+#include <Common/iLogger>
+#include <Common/iRegistry>
+#include <SdiWindow/iSdiWindow>
+#include <Gui/Panel>
+
+#include <QtGui>
+
+
+VER_EXPORT_VERSION_INFO()
+Q_EXPORT_PLUGIN2(VER_MODULE_NAME_STR, eVaf::ScosTime::Module)
+
+
+//-------------------------------------------------------------------
+
+using namespace eVaf;
+using namespace eVaf::ScosTime;
+
+Module::Module()
+ : Plugins::iPlugin()
+ , mReady(false)
+{
+ setObjectName(QString("%1.%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__));
+
+ EVAF_INFO("%s created", qPrintable(objectName()));
+}
+
+Module::~Module()
+{
+ EVAF_INFO("%s destroyed", qPrintable(objectName()));
+}
+
+bool Module::init(QString const & args)
+{
+ Q_UNUSED(args);
+
+ // Get the main window interface and fill it with the widgets
+ SdiWindow::iSdiWindow * win = evafQueryInterface<SdiWindow::iSdiWindow>("iSdiWindow");
+ EVAF_TEST_X(win, "No iSdiWindow interface");
+
+ Gui::Panel * panel = new Gui::Panel;
+ win->addPanel("PswGen", panel);
+
+ QVBoxLayout * v = new QVBoxLayout;
+ panel->setLayout(v);
+
+ QGridLayout * g = new QGridLayout;
+ v->addLayout(g);
+ g->setColumnStretch(1, 2);
+
+ QLabel * l = new QLabel(tr("&Epoch:", VER_MODULE_NAME_STR));
+ l->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+ g->addWidget(l, 0, 0);
+
+ wEpoch = new QComboBox;
+ l->setBuddy(wEpoch);
+ wEpoch->setEditable(true);
+ wEpoch->addItems(QStringList() << "1970-01-01T00:00:00.000" << "1999-08-22T00:00:00.000");
+ g->addWidget(wEpoch, 0, 1);
+ panel->setFocusProxy(wEpoch);
+
+ l = new QLabel(tr("&Date/time:", VER_MODULE_NAME_STR));
+ l->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+ g->addWidget(l, 1, 0);
+
+ 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));
+ g->addWidget(wDateTime, 1, 1);
+
+ QPushButton * btn = new QPushButton(tr("Convert", VER_MODULE_NAME_STR));
+ g->addWidget(btn, 1, 2);
+ connect(btn, SIGNAL(clicked()), this, SLOT(dateTimeClicked()));
+
+ l = new QLabel(tr("&HEX:", 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()));
+
+ v->addStretch();
+
+ QHBoxLayout * h = new QHBoxLayout;
+ h->addStretch();
+ v->addLayout(h);
+
+ QAction * a = new QAction(panel);
+ a->setShortcut(Qt::Key_Escape);
+ connect(a, SIGNAL(triggered()), qApp, SLOT(quit()));
+ panel->addAction(a);
+
+ mReady = true;
+
+ EVAF_INFO("%s initialized", qPrintable(objectName()));
+
+ return true;
+}
+
+void Module::done()
+{
+ mReady = false;
+
+ 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();
+ }
+
+ QDate dt(year, 1, 1);
+ dt = dt.addDays(days - 1);
+
+ return QDateTime(dt, QTime(hours, minutes, secs, msecs), Qt::UTC);
+}
+
+void Module::dateTimeClicked()
+{
+ 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')));
+}
+
+void Module::hexClicked()
+{
+ bool ok = false;
+ int coarse = wHex->text().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 (!ok)
+ 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')));
+}