]> vaikene.ee Git - evaf/blob - src/apps/ScosTime/gui.cpp
6efd962c5e791f4e7f03ae2e04cc2d78fccc2778
[evaf] / src / apps / ScosTime / gui.cpp
1 /**
2 * @file ScosTime/gui.cpp
3 * @brief GUI for the ScosTime application
4 * @author Enar Vaikene
5 *
6 * Copyright (c) 2012 Enar Vaikene
7 *
8 * This file is part of the eVaf C++ cross-platform application development framework.
9 *
10 * This file can be used under the terms of the GNU General Public License
11 * version 3.0 as published by the Free Software Foundation and appearing in
12 * the file LICENSE included in the packaging of this file. Please review the
13 * the following information to ensure the GNU General Public License version
14 * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
15 *
16 * Alternatively, this file may be used in accordance with the Commercial License
17 * Agreement provided with the Software.
18 */
19
20 #include "gui.h"
21 #include "version.h"
22
23 #include <Common/Globals>
24 #include <Common/iLogger>
25 #include <Common/iRegistry>
26 #include <SdiWindow/iSdiWindow>
27 #include <Gui/Panel>
28
29 #include <QtGui>
30
31
32 VER_EXPORT_VERSION_INFO()
33 Q_EXPORT_PLUGIN2(VER_MODULE_NAME_STR, eVaf::ScosTime::Module)
34
35
36 //-------------------------------------------------------------------
37
38 using namespace eVaf;
39 using namespace eVaf::ScosTime;
40
41
42 //-------------------------------------------------------------------
43
44 Internal::DateTime::DateTime(QString const & s, QString const & epoch)
45 {
46
47 }
48
49
50 //-------------------------------------------------------------------
51
52 Module::Module()
53 : Plugins::iPlugin()
54 , mReady(false)
55 , mLastValidEntry(NoValidEntry)
56 {
57 setObjectName(QString("%1.%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__));
58
59 rxIsoDateTime = new QRegExp("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(.\\d{3})?)?$");
60 rxAsdDateTime = new QRegExp("^\\d{4}\\.\\d{3}\\.\\d{2}\\.\\d{2}(\\.\\d{2}(\\.\\d{3})?)?$");
61
62 EVAF_INFO("%s created", qPrintable(objectName()));
63 }
64
65 Module::~Module()
66 {
67 delete rxIsoDateTime;
68 delete rxAsdDateTime;
69 EVAF_INFO("%s destroyed", qPrintable(objectName()));
70 }
71
72 bool Module::init(QString const & args)
73 {
74 Q_UNUSED(args);
75
76 // Get the main window interface and fill it with the widgets
77 SdiWindow::iSdiWindow * win = evafQueryInterface<SdiWindow::iSdiWindow>("iSdiWindow");
78 EVAF_TEST_X(win, "No iSdiWindow interface");
79
80 Gui::Panel * panel = new Gui::Panel;
81 win->addPanel("PswGen", panel);
82
83 QVBoxLayout * v = new QVBoxLayout;
84 panel->setLayout(v);
85
86 QGridLayout * g = new QGridLayout;
87 v->addLayout(g);
88 g->setColumnStretch(1, 2);
89
90 QLabel * l = new QLabel(tr("&Epoch:", VER_MODULE_NAME_STR));
91 l->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
92 g->addWidget(l, 0, 0);
93
94 wEpoch = new QComboBox;
95 l->setBuddy(wEpoch);
96 wEpoch->setEditable(true);
97 wEpoch->setValidator(new QRegExpValidator(*rxIsoDateTime, wEpoch));
98 wEpoch->addItems(QStringList() << "1970-01-01T00:00:00.000" << "1999-08-22T00:00:00.000");
99 connect(wEpoch, SIGNAL(editTextChanged(QString)), this, SLOT(epochChanged(QString)));
100 g->addWidget(wEpoch, 0, 1);
101 panel->setFocusProxy(wEpoch);
102
103 l = new QLabel(tr("&Date/time:", VER_MODULE_NAME_STR));
104 l->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
105 g->addWidget(l, 1, 0);
106
107 wDateTime = new QLineEdit;
108 l->setBuddy(wDateTime);
109 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})?)$");
110 wDateTime->setValidator(new QRegExpValidator(rxDateTime, wDateTime));
111 connect(wDateTime, SIGNAL(textEdited(QString)), this, SLOT(dateTimeEdited(QString)));
112 g->addWidget(wDateTime, 1, 1);
113
114 QPushButton * btn = new QPushButton();
115 btn->setDisabled(true);
116 g->addWidget(btn, 1, 2);
117 connect(btn, SIGNAL(clicked()), this, SLOT(dateTimeClicked()));
118 wConvertDateTime = btn;
119
120 l = new QLabel(tr("&CUC:", VER_MODULE_NAME_STR));
121 l->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
122 g->addWidget(l, 2, 0);
123
124 wCucHex = new QLineEdit;
125 l->setBuddy(wCucHex);
126 wCucHex->setMaxLength(12);
127 wCucHex->setInputMask(">HHHHHHHHhhhh");
128 connect(wCucHex, SIGNAL(textEdited(QString)), this, SLOT(cucHexEdited(QString)));
129 g->addWidget(wCucHex, 2, 1);
130
131 v->addStretch();
132
133 QHBoxLayout * h = new QHBoxLayout;
134 h->addStretch();
135 v->addLayout(h);
136
137 QAction * a = new QAction(panel);
138 a->setShortcut(Qt::Key_Escape);
139 connect(a, SIGNAL(triggered()), qApp, SLOT(quit()));
140 panel->addAction(a);
141
142 mReady = true;
143
144 EVAF_INFO("%s initialized", qPrintable(objectName()));
145
146 return true;
147 }
148
149 void Module::done()
150 {
151 mReady = false;
152
153 EVAF_INFO("%s finalized", qPrintable(objectName()));
154 }
155
156 Module::DateTimeType Module::getDateTimeType(QString const & s) const
157 {
158 if (rxIsoDateTime->exactMatch(s))
159 return IsoDateTime;
160 else if (rxAsdDateTime->exactMatch(s))
161 return AsdDateTime;
162 else
163 return InvalidDateTime;
164 }
165
166 QDateTime Module::strToDateTime(QString const & s, DateTimeType type) const
167 {
168 switch (type)
169 {
170 case AsdDateTime:
171 {
172 // Using the yyyy.ddd.hh.mm.ss[.zzz] format
173 QStringList tok = s.split(QChar('.'));
174 if (tok.size() < 4)
175 return QDateTime();
176
177 bool ok = false;
178 int year = tok.at(0).toInt(&ok);
179 if (!ok)
180 return QDateTime();
181 int days = tok.at(1).toInt(&ok);
182 if (!ok)
183 return QDateTime();
184 int hours = tok.at(2).toInt(&ok);
185 if (!ok)
186 return QDateTime();
187 int minutes = tok.at(3).toInt(&ok);
188 if (!ok)
189 return QDateTime();
190 int secs = 0;
191 int msecs = 0;
192 if (tok.size() > 4) {
193 secs = tok.at(4).toInt(&ok);
194 if (!ok)
195 return QDateTime();
196 if (tok.size() > 5) {
197 msecs = tok.at(5).toInt(&ok);
198 if (!ok)
199 return QDateTime();
200 }
201 }
202
203 QDate dt(year, 1, 1);
204 dt = dt.addDays(days - 1);
205
206 return QDateTime(dt, QTime(hours, minutes, secs, msecs), Qt::UTC);
207 break;
208 }
209 case IsoDateTime:
210 {
211 // Using the ISO format yyyy-MM-ddThh:mm:ss[.zzz]
212 QDateTime dt = QDateTime::fromString(s, Qt::ISODate);
213 dt.setTimeSpec(Qt::UTC);
214 return dt;
215 break;
216 }
217 default:
218 return QDateTime();
219 }
220 }
221
222 QString Module::dateTimeToAsdStr(QDateTime const & tm) const
223 {
224 return QString("%1.%2.%3.%4.%5.%6")
225 .arg(tm.date().year(), 4, 10, QChar('0'))
226 .arg(tm.date().dayOfYear(), 3, 10, QChar('0'))
227 .arg(tm.time().hour(), 2, 10, QChar('0'))
228 .arg(tm.time().minute(), 2, 10, QChar('0'))
229 .arg(tm.time().second(), 2, 10, QChar('0'))
230 .arg(tm.time().msec(), 3, 10, QChar('0'));
231 }
232
233 void Module::setDateTimeFromCucHex(QString const & s)
234 {
235
236 }
237
238 void Module::setCucHexFromDateTime(QString const & s, DateTimeType type)
239 {
240 // Get the epoch
241 QDateTime epoch = QDateTime::fromString(wEpoch->currentText(), Qt::ISODate);
242 epoch.setTimeSpec(Qt::UTC);
243
244 // Convert the date/time string to a QDateTime type
245 QDateTime tm = strToDateTime(s, type);
246
247 // Convert to CUC coarse and fine values
248 qint64 msecs = epoch.msecsTo(tm);
249 quint32 coarse = quint32(msecs / 1000);
250 quint32 fine = quint32(rint(1000.0 * double(msecs % 1000) * 58.0 / 885.0));
251
252 // Set the CUC hex string
253 wCucHex->setText(QString("%1%2").arg(coarse, 8, 16, QChar('0')).arg(fine, 4, 16, QChar('0')));
254 }
255
256 void Module::dateTimeClicked()
257 {
258 // Get the date/time string, type and QDateTime value
259 QString s = wDateTime->text();
260 DateTimeType type = getDateTimeType(s);
261 QDateTime tm = strToDateTime(s, type);
262
263 // Convert to another type
264 switch (type)
265 {
266 case IsoDateTime:
267 {
268 wDateTime->setText(dateTimeToAsdStr(tm));
269 wConvertDateTime->setText(tr("&to ISO", VER_MODULE_NAME_STR));
270 break;
271 }
272 case AsdDateTime:
273 {
274 wDateTime->setText(tm.toString("yyyy-MM-ddThh:mm:ss.zzz"));
275 wConvertDateTime->setText(tr("&to ASD", VER_MODULE_NAME_STR));
276 break;
277 }
278 default:
279 break;
280 }
281 }
282
283 void Module::dateTimeEdited(QString const & s)
284 {
285 if (mLastValidEntry == DateTimeEntry)
286 mLastValidEntry = NoValidEntry;
287 wConvertDateTime->setDisabled(true);
288 wConvertDateTime->setText(QString());
289
290 if (s.isEmpty())
291 return;
292
293 // Detect the type of the date/time string
294 DateTimeType type = getDateTimeType(s);
295 if (type == InvalidDateTime)
296 return;
297
298 // Set the date/time field as the last valid entry done by the user
299 mLastValidEntry = DateTimeEntry;
300
301 // Set the CUC hex string from this date/time string
302 setCucHexFromDateTime(s);
303
304 // Enable the button that converts between ISO and ASD date/time strings
305 if (type == IsoDateTime) {
306 wConvertDateTime->setEnabled(true);
307 wConvertDateTime->setText(tr("&to ASD", VER_MODULE_NAME_STR));
308 }
309 else if (type == AsdDateTime) {
310 wConvertDateTime->setEnabled(true);
311 wConvertDateTime->setText(tr("&to ISO", VER_MODULE_NAME_STR));
312 }
313 }
314
315 void Module::cucHexEdited(QString const & s)
316 {
317 if (mLastValidEntry == CUCEntry)
318 mLastValidEntry = NoValidEntry;
319 if (s.isEmpty() || s.size() < 8)
320 return;
321
322 // Get the CUC coarse and fine values
323 bool ok = false;
324 int coarse = s.left(8).toLong(&ok, 16);
325 if (!ok)
326 return;
327 int fine = 0;
328 if (s.size() == 12)
329 fine = s.mid(8, 4).toLong(&ok, 16);
330 if (!ok)
331 return;
332
333 // Set the CUC field as the last valid entry done by the user
334 mLastValidEntry = CUCEntry;
335
336 // Get the epoch
337 QDateTime epoch = QDateTime::fromString(wEpoch->currentText(), Qt::ISODate);
338 epoch.setTimeSpec(Qt::UTC);
339
340 // Get the date/time value
341 QDateTime tm = epoch.addSecs(coarse);
342 tm = tm.addMSecs(rint((double(fine) / 58.0 * 885.0) / 1000.0));
343
344 // Set the date/time string in ASD format
345 wDateTime->setText(dateTimeToAsdStr(tm));
346
347 // Enable conversion to ISO format
348 wConvertDateTime->setEnabled(true);
349 wConvertDateTime->setText(tr("&to ISO", VER_MODULE_NAME_STR));
350 }
351
352 void Module::epochChanged(QString const & s)
353 {
354 if (s.isEmpty())
355 return;
356 if (!rxIsoDateTime->exactMatch(s))
357 return;
358
359 // If there is a valid entry, do the conversion
360 switch (mLastValidEntry)
361 {
362 case DateTimeEntry:
363 break;
364 case CUCEntry:
365 break;
366 default:
367 break;
368 }
369 }