From 77c63e0de5ab85992cf9dd6627938ee42ddd5aee Mon Sep 17 00:00:00 2001 From: Sarah Mischke Date: Fri, 8 Aug 2025 12:49:31 +0200 Subject: [PATCH 1/8] first version of working ipc between qtdmm instances --- QtDMM.spec | 2 +- assets/translations/qtdmm_de.ts | 9 +- src/mainwin.cpp | 39 +++++++- src/mainwin.h | 4 + src/sharedstatemanager.cpp | 169 ++++++++++++++++++++++++++++++++ src/sharedstatemanager.h | 40 ++++++++ 6 files changed, 258 insertions(+), 5 deletions(-) create mode 100644 src/sharedstatemanager.cpp create mode 100644 src/sharedstatemanager.h diff --git a/QtDMM.spec b/QtDMM.spec index e49bc25..2e6da7b 100644 --- a/QtDMM.spec +++ b/QtDMM.spec @@ -1,5 +1,5 @@ Name: qtdmm -Version: 1.0.0-alpha.1+dc7490a +Version: 1.0.0-alpha.1-5-g8cbda17+8cbda17 Release: 1%{?dist} Summary: DMM Readout Software Including a Configurable Recorder. diff --git a/assets/translations/qtdmm_de.ts b/assets/translations/qtdmm_de.ts index 7bd3554..5e9c962 100644 --- a/assets/translations/qtdmm_de.ts +++ b/assets/translations/qtdmm_de.ts @@ -488,15 +488,20 @@ Ist das DMM angeschlossen und eingeschaltet? MainWin - + QtDMM: Welcome! QtDMM: Willkommen! - + <h1>QtDMM %1</h1><hr><div align=right><i>A simple recorder for DMM's</i></div><p><div align=justify>A simple display software for a variety of digital multimeter. Currently confirmed are:<table>%2</table>Other compatible models may work also.<p>QtDMM features min/max memory and a configurable recorder with import/export and printing function. Sampling may be started manually, at a given time or triggered by a measured threshold. Additionally an external program may be started when given thresholds are reached.</div><div align=justify><b>QtDMM</b> uses the platform independent toolkit <b>Qt</b> version %3 and is licensed under <b>GPL 3</b> (Versions prior to v0.9.0 where licensed under GPL 2)</div><br>&copy; 2001-2014 Matthias Toussaint &nbsp;-&nbsp;&nbsp;<font color=blue><u><a href='mailto:qtdmm@mtoussaint.de'>qtdmm@mtoussaint.de</a></u></font><p><br>The icons (except the DMM icon) have been taken from the KDE project.<p> <h1>QtDMM %1</h1><hr><div align=right><i>Ein einfacher Datenrekorder für DMM</i></div><p><div align=justify>Ein einfaches Anzeigeprogramm für eine Vielzahl von DMM's. Aktuell bestätigt sind:<table>%2</table>Andere kompatible Modelle sollten ebenfalls funktionieren.<p>QtDMM stellt die Funktionen Min/Max Werte halten, ein konfigurierbaren Datenrekorder mit Daten im/export Funktion sowie ein Druckfunktion zur Verfügung. Die Datenaufzeichnung kann manuell, durch einen Grenzwert oder durch eine Zeitfunktion ausgelöst werden. Desweiteren kann ein externes Programm beim erreichen eines Grenzwertes gestartet werden.</div><div align=justify><b>QtDMM</b> wurde mit der Platformunabhängigen <b>Qt</b> Bibliothek in der Version %3 welche unter der <b>GPLv3</b> lizensiert ist erstellt.(Versionen vor 0.9.0 wurden unter der GPLv2 Lizenz veröffentlicht)</div><br>&copy; 2001-2014 Matthias Toussaint &nbsp;-&nbsp;&nbsp;<font color=blue><u><a href='mailto:qtdmm@mtoussaint.de'>qtdmm@mtoussaint.de</a></u></font><p><br>Die Symbole (bis auf das DMM Symbol) stammen von dem KDE Projekt.<p> + + + Another instance is running. + + PortsPrefs diff --git a/src/mainwin.cpp b/src/mainwin.cpp index 9c0368c..e61d6ed 100644 --- a/src/mainwin.cpp +++ b/src/mainwin.cpp @@ -37,12 +37,14 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) { setupUi(this); setupIcons(); + QString config_id = parser.value("config-id"); + + m_stateMgr = new SharedStateManager(config_id.isEmpty()?"default":config_id,this); QWidget* spacer = new QWidget(); spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); this->toolBarMenu->addWidget(spacer); this->toolBarMenu->addAction(this->action_Menu); - QString config_id = parser.value("config-id"); QString version = APP_VERSION; int plusIndex = version.indexOf('+'); if (plusIndex != -1) @@ -98,7 +100,28 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) else resize(640, 480); } - QTimer::singleShot(1000, action_Connect, &QAction::trigger); + + connect(m_stateMgr, &SharedStateManager::stateChanged, this, [=](const QString& state){ + if (state == "RECORD") + { + qInfo() << "rec"; + action_Start->trigger(); + } + else if (state == "STOP") + { + qInfo() << "stop"; + action_Stop->trigger(); + } + }); + + connect(m_stateMgr, &SharedStateManager::instanceIdAlreadyInUse, this, [=](){ + QMessageBox::critical(this, APP_NAME,tr("Another instance is running.")); + qInfo() << "quit"; + qApp->quit(); + }); + + if ( m_stateMgr->registerInstance() ) + QTimer::singleShot(1000, action_Connect, &QAction::trigger); } void MainWin::setConsoleLogging(bool on) @@ -123,7 +146,9 @@ void MainWin::createActions() connect(action_Connect, SIGNAL(triggered(bool)), this, SLOT(connectSLOT(bool))); connect(action_Reset, SIGNAL(triggered()), m_wid, SLOT(resetSLOT())); connect(action_Start, SIGNAL(triggered()), m_wid, SLOT(startSLOT())); + connect(action_Start, SIGNAL(triggered()), this, SLOT(startSLOT())); connect(action_Stop, SIGNAL(triggered()), m_wid, SLOT(stopSLOT())); + connect(action_Stop, SIGNAL(triggered()), this, SLOT(stopSLOT())); connect(action_Clear, SIGNAL(triggered()), m_wid, SLOT(clearSLOT())); connect(action_Print, SIGNAL(triggered()), m_wid, SLOT(printSLOT())); connect(action_Import, SIGNAL(triggered()), m_wid, SLOT(importSLOT())); @@ -148,6 +173,16 @@ void MainWin::createActions() connect(new QShortcut(action_Quit->shortcut(), this), SIGNAL(activated()), action_Quit, SLOT(trigger())); } +void MainWin::startSLOT() +{ + m_stateMgr->writeState("RECORD"); +} + +void MainWin::stopSLOT() +{ + m_stateMgr->writeState("STOP"); +} + void MainWin::runningSLOT(bool on) { m_running = on; diff --git a/src/mainwin.h b/src/mainwin.h index 8f8fd7e..69fd015 100644 --- a/src/mainwin.h +++ b/src/mainwin.h @@ -28,6 +28,7 @@ #include #include "ui_uimainwin.h" +#include "sharedstatemanager.h" class MainWid; class DisplayWid; @@ -43,6 +44,8 @@ class MainWin : public QMainWindow, private Ui::UIMainWin protected Q_SLOTS: void runningSLOT(bool); void connectSLOT(bool); + void startSLOT(); + void stopSLOT(); void on_action_About_triggered(); void on_action_Menu_triggered(); void setConnectSLOT(bool); @@ -57,6 +60,7 @@ protected Q_SLOTS: QLabel *m_error; QLabel *m_info; QMenu *m_menu; + SharedStateManager* m_stateMgr; void setupIcons(); void createToolBars(); diff --git a/src/sharedstatemanager.cpp b/src/sharedstatemanager.cpp new file mode 100644 index 0000000..29a8fef --- /dev/null +++ b/src/sharedstatemanager.cpp @@ -0,0 +1,169 @@ +#include "sharedstatemanager.h" +#include +#include +#include +#include +#include +#include +#include + +SharedStateManager::SharedStateManager(const QString &instanceId, QObject *parent) + : QObject(parent), + m_memory("qtdmm_ipc_memory"), + m_lastState(), + m_instanceId(instanceId), + m_registered(false), + m_emit_inUse(false) +{ + m_timer.setInterval(500); + connect(&m_timer, &QTimer::timeout, this, &SharedStateManager::checkForChanges); + m_timer.start(); +} + +SharedStateManager::~SharedStateManager() +{ + unregisterInstance(); +} + +QJsonObject SharedStateManager::initialJson() +{ + QJsonObject data; + data["instances"] = QJsonArray(); + data["state"] = ""; + return data; +} + + +QJsonObject SharedStateManager::readJsonData() +{ + if (!m_memory.isAttached() && !m_memory.attach()) + return initialJson(); + + m_memory.lock(); + + QByteArray rawData(static_cast(m_memory.constData()), m_memory.size()); + int end = rawData.indexOf('\0'); + if (end != -1) + rawData.truncate(end); + + m_memory.unlock(); + QJsonParseError parseError; + QJsonDocument doc = QJsonDocument::fromJson(rawData, &parseError); + //qInfo() << QJsonDocument(doc).toJson(QJsonDocument::Compact); + + if (parseError.error != QJsonParseError::NoError || !doc.isObject()) + { + qInfo("parse error"); + return initialJson(); + } + + return doc.object(); +} + +bool SharedStateManager::writeJsonData(const QJsonObject &obj) +{ + if (!m_memory.isAttached() && !m_memory.attach()) + { + if (!m_memory.create(8192)) + return false; + } + QJsonDocument doc(obj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + if (jsonData.size() > m_memory.size()) + { + m_memory.detach(); + if (!m_memory.create(jsonData.size() + 1024)) + return false; + } + + m_memory.lock(); + char *to = static_cast(m_memory.data()); + const char* from = jsonData.constData(); + memset(to, 0, m_memory.size()); + memcpy(to, from, jsonData.size()); + + m_memory.unlock(); + + return true; +} + +bool SharedStateManager::registerInstance() +{ + if (!m_registered) + { + QJsonObject data = readJsonData(); + QJsonArray instances = data["instances"].toArray(); + + for (const QJsonValue &val : instances) + { + if (val.toString() == m_instanceId) + { + qWarning() << m_instanceId << "id exists"; + m_emit_inUse = true; + return false; + } + } + + instances.append(m_instanceId); + data["instances"] = instances; + + m_registered = writeJsonData(data); + if (!m_registered) + qInfo() << "reg failed"; + } + + return m_registered; +} + +void SharedStateManager::checkForChanges() +{ + if (m_registered) + { + QJsonObject data = readJsonData(); + + QString currentState = data["state"].toString(); + QVariantList instances = data["instances"].toArray().toVariantList(); + if (instances.count() != m_instances.count()) + { + m_instances = instances; + emit instanceCountChanged(m_instances); + } + + if (currentState != m_lastState) + { + qInfo() << currentState << QJsonDocument(data).toJson(QJsonDocument::Compact); + m_lastState = currentState; + Q_EMIT stateChanged(currentState); + } + } + if (m_emit_inUse) + Q_EMIT instanceIdAlreadyInUse(); + +} + +bool SharedStateManager::writeState(const QString &newState) +{ + QJsonObject data = readJsonData(); + data["state"] = newState; + return writeJsonData(data); +} + +void SharedStateManager::unregisterInstance() +{ + if (m_registered) + { + QJsonObject data = readJsonData(); + QJsonArray instances = data["instances"].toArray(); + + QJsonArray updated; + for (const QJsonValue &val : instances) + { + if (val.toString() != m_instanceId) + updated.append(val); + } + + data["instances"] = updated; + writeJsonData(data); + } +} diff --git a/src/sharedstatemanager.h b/src/sharedstatemanager.h new file mode 100644 index 0000000..c1ff64d --- /dev/null +++ b/src/sharedstatemanager.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include + +class SharedStateManager : public QObject +{ + Q_OBJECT + +public: + explicit SharedStateManager(const QString &instanceId, QObject *parent = nullptr); + ~SharedStateManager(); + + bool registerInstance(); + void unregisterInstance(); + + bool writeState(const QString &newState); + void checkForChanges(); + QVariantList instanceCount() { return m_instances; }; + +signals: + void stateChanged(const QString &newState); + void instanceIdAlreadyInUse(); + void instanceCountChanged(QVariantList &instances); + +private: + QJsonObject readJsonData(); + bool writeJsonData(const QJsonObject &obj); + QJsonObject initialJson(); + + QSharedMemory m_memory; + QTimer m_timer; + QString m_lastState; + QString m_instanceId; + bool m_registered; + bool m_emit_inUse; + QVariantList m_instances; +}; From e07025e7e486f5f931ec71b939df45a92ef8b37d Mon Sep 17 00:00:00 2001 From: Sarah Mischke Date: Sat, 9 Aug 2025 14:33:47 +0200 Subject: [PATCH 2/8] - ipc between instances via shared mem - fialog to manage instances --- QtDMM.spec | 2 +- assets/translations/qtdmm_de.ts | 166 ++++++++++++++++++++------------ src/configdlg.cpp | 7 +- src/configdlg.h | 3 +- src/instancesdlg.cpp | 85 ++++++++++++++++ src/instancesdlg.h | 27 ++++++ src/mainwid.cpp | 22 ++++- src/mainwid.h | 6 ++ src/mainwin.cpp | 55 +++++++++-- src/mainwin.h | 3 + src/settings.cpp | 62 ++++++++++-- src/settings.h | 10 +- src/sharedstatemanager.cpp | 9 +- src/sharedstatemanager.h | 6 +- src/ui/uiinstancesdlg.ui | 138 ++++++++++++++++++++++++++ src/ui/uimainwin.ui | 17 ++++ 16 files changed, 518 insertions(+), 100 deletions(-) create mode 100644 src/instancesdlg.cpp create mode 100644 src/instancesdlg.h create mode 100644 src/ui/uiinstancesdlg.ui diff --git a/QtDMM.spec b/QtDMM.spec index 2e6da7b..1141079 100644 --- a/QtDMM.spec +++ b/QtDMM.spec @@ -1,5 +1,5 @@ Name: qtdmm -Version: 1.0.0-alpha.1-5-g8cbda17+8cbda17 +Version: 1.0.0-alpha.1-6-g77c63e0+77c63e0 Release: 1%{?dist} Summary: DMM Readout Software Including a Configurable Recorder. diff --git a/assets/translations/qtdmm_de.ts b/assets/translations/qtdmm_de.ts index 5e9c962..e439ce1 100644 --- a/assets/translations/qtdmm_de.ts +++ b/assets/translations/qtdmm_de.ts @@ -4,24 +4,24 @@ ConfigDlg - - - + + + QtDMM: Welcome! QtDMM: Willkommen! - + <font size=+2><b>Welcome!</b></font><p>This seems to be your first invocation of QtDMM (Or you have deleted its configuration file).<p>QtDMM has created the file %1 in your home directory to save its settings. <font size+2><b>Willkommen!</b></font><p>Dies scheint der erste Aufruf von QtDMM zu sein, bzw. die Konfigurstion wurde gelöscht.<p>QtDMM hate eine neue Datei unter dem Pfad %1 angelegt. - + <font size=+2><b>Welcome!</b></font><p>You seem to have upgraded <b>QtDMM</b> from a version prior to 0.8.4. Please check your configuration. There are some new parameters to be configured.<p>Thank you for choosing <b>QtDMM</b>.<p><i>Matthias Toussaint</i> <font size=+2><b>Willkommen!</b><p>Wie es ausschaut, wurde <b>QtDMM</b> von einer Version vor 0.8.4 aktualisiert. Bitte überprüfen Sie die Konfiguration. Es gibt einige neue Parameter.<p>Danke das Sie <b>QtDMM</b> benutzen.<p><i>Matthias Toussaint</i> - + Your config file has been converted to the new format. Please check your color settings, because they couldn't be converted automatically. Your old config ~/.qtdmmrc was renamed to ~/.qtdmmrc.old. @@ -34,8 +34,8 @@ Die Datei ~/.qtdmmtc wurden zu ~/.qtdmmrc.old umbenannt. <font size+2><b>Willkommen!</b></font><p>Dies scheint der erste Aufruf von QtDMM zu sein, bzw. die Konfigurstion wurde gelöscht.<p>QtDMM hate eine neue Datei unter dem Pfad %1 angelegt. - - + + Continue Fortsetzen @@ -401,47 +401,47 @@ Ist das DMM angeschlossen und eingeschaltet? MainWid - + QtDMM: Unsaved data QtDMM: Ungesicherte Daten - + <font size=+2><b>Unsaved data</b></font><p>You still have unsaved measured data in memory. If you quit now it will be lost.<p>Do you want to export your unsaved data first? <font size=+2><b>Ungesicherte Daten</b></font><p>Es befinden sich ungesicherte Daten im Speicher. Wenn Sie das Programm beenden gehen diese verloren.<p>Sollen diese vorher exportiert werden? - + Export data first Daten erst exportieren - + Quit without saving Beenden ohne speichern - + Automatic start at %1 Automatisch starten bei %1 - + Raising threshold %1 Grenzwert steigent %1 - + Falling threshold %1 Grenzwert fallend %1 - + <font size=+2><b>Launch error</b></font><p>Application %1 is still running!<p>Do you want to kill it now? <font size=+2><b>Startfehler</b></font><p>Programm %s läuft noch!<p>Wollen sie es jetzt beenden? - + <font size=+2><b>Launch error</b></font><p>Couldn't launch %1 <font size=+2><b>Startfehler</b></font><p>Konnte %1 nicht starten @@ -450,18 +450,18 @@ Ist das DMM angeschlossen und eingeschaltet? <font size=+2><b>Startfehler</b></font><p>Programm %s is still running!<p>Do you want to kill it now - + Launched %1 %1 gestartet - + %1 terminated with exit code %2. %1 mit dem Rückgabecode %2 beendet. - - + + QtDMM: Launch error QtDMM: Startfehler @@ -470,17 +470,17 @@ Ist das DMM angeschlossen und eingeschaltet? <font size=+2><b>Startfehler</b></font><p>Programm %1 läuft noch.<p>Soll es getötet werden - + Yes, kill it! Ja, töten! - + No, keep running Nein, es laufen lassen - + Bummer! Reinfall! @@ -488,17 +488,17 @@ Ist das DMM angeschlossen und eingeschaltet? MainWin - + QtDMM: Welcome! QtDMM: Willkommen! - + <h1>QtDMM %1</h1><hr><div align=right><i>A simple recorder for DMM's</i></div><p><div align=justify>A simple display software for a variety of digital multimeter. Currently confirmed are:<table>%2</table>Other compatible models may work also.<p>QtDMM features min/max memory and a configurable recorder with import/export and printing function. Sampling may be started manually, at a given time or triggered by a measured threshold. Additionally an external program may be started when given thresholds are reached.</div><div align=justify><b>QtDMM</b> uses the platform independent toolkit <b>Qt</b> version %3 and is licensed under <b>GPL 3</b> (Versions prior to v0.9.0 where licensed under GPL 2)</div><br>&copy; 2001-2014 Matthias Toussaint &nbsp;-&nbsp;&nbsp;<font color=blue><u><a href='mailto:qtdmm@mtoussaint.de'>qtdmm@mtoussaint.de</a></u></font><p><br>The icons (except the DMM icon) have been taken from the KDE project.<p> <h1>QtDMM %1</h1><hr><div align=right><i>Ein einfacher Datenrekorder für DMM</i></div><p><div align=justify>Ein einfaches Anzeigeprogramm für eine Vielzahl von DMM's. Aktuell bestätigt sind:<table>%2</table>Andere kompatible Modelle sollten ebenfalls funktionieren.<p>QtDMM stellt die Funktionen Min/Max Werte halten, ein konfigurierbaren Datenrekorder mit Daten im/export Funktion sowie ein Druckfunktion zur Verfügung. Die Datenaufzeichnung kann manuell, durch einen Grenzwert oder durch eine Zeitfunktion ausgelöst werden. Desweiteren kann ein externes Programm beim erreichen eines Grenzwertes gestartet werden.</div><div align=justify><b>QtDMM</b> wurde mit der Platformunabhängigen <b>Qt</b> Bibliothek in der Version %3 welche unter der <b>GPLv3</b> lizensiert ist erstellt.(Versionen vor 0.9.0 wurden unter der GPLv2 Lizenz veröffentlicht)</div><br>&copy; 2001-2014 Matthias Toussaint &nbsp;-&nbsp;&nbsp;<font color=blue><u><a href='mailto:qtdmm@mtoussaint.de'>qtdmm@mtoussaint.de</a></u></font><p><br>Die Symbole (bis auf das DMM Symbol) stammen von dem KDE Projekt.<p> - + Another instance is running. @@ -1305,6 +1305,29 @@ Der Wert kann auch mit einem Suffix wie m, u, n, p, k, M, G oder T angegeben wer Tipp des Tages anzeigen + + UIInstancesDlg + + + Instances + + + + + Choose instance + + + + + + + + + + + - + + + UIIntegrationPrefs @@ -1511,39 +1534,54 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar - + Recorder Rekorder - + File Datei - + Help Hilfe - + + instances + + + + + open or create an instance + + + + + Ctrl+N + + + + Display Anzeige - - - + + + Menu Menü - + &Export &Export - + <html><head/><body><p><span style=" font-weight:600;">Export recorder graph</span></p><p>Here you can export the recorded data as tab separated list. Each line contains the following values (separated by a tab character): date (dd.mm.yyyy) time (hh:mm:ss) value (float) unit.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Rekorder Graphen exportieren</span></p><p>Hier können die aufgezeichneten Daten als eine Liste durch Tabulatoren getrennt exportiert werden. Jede Zeile enthält die folgenden Werte (getrennt durch einen Tabulator): Datum (tt.mm.jjjj) Zeit (ss:mm:SS) Wert (Fließkomma) Einheit.</p></body></html> @@ -1552,22 +1590,22 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+E - + &Import - + <html><head/><body><p><span style=" font-weight:600;">Import data into recorder</span></p><p>Here you can import previously exported data files. QtDMM tries to do an educated guess if the file format is correct and rejects import of files which to not match.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Importiert Daten in den Rekorder</span></p><p>Hier können zuvor exportierte Daten importiert werden. QtDMM versucht das Format zu lesen und verweigert den Import von ungültigen Dateien.</p></body></html> - + &Print &Drucken - + <html><head/><body><p><span style=" font-weight:600;">Print recorder graph</span></p><p>A dialog will open where you can define a title and a comment for your printout. The printer itself can also be configured here. To be able to print you need at least one working postscript printer configured in your system. Printing into a file is also supported.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Rekorder Graphen drucken</span></p><p>Es öffnet sich ein Fenster,indem der Titel und ein Kommentar für den Ausdruck festgelegt werden kann. Der Drucker selbst kann hier auch ausgewält werden. Der Ausdruck in eine Datei(PDF) ist ebenfalls möglich.</p></body></html> @@ -1576,25 +1614,25 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+D - - + + &Configure &Konfigurieren - - - + + + <html><head/><body><p><span style=" font-weight:600;">Configure QtDMM</span></p><p>This will open QtDMM's configuration dialog. Here you can configure it's visual appearance and all options regarding the multimeter hardware and the recorder.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">QtDMM konfigurieren</span></p><p>Dies öffnen das Konfugurationsfenster für QtDMM. Hier kann die visuelle Erscheinung, alle Optionen die die Datenaufzeichnung betreffen sowie die Einstellungen für das DMM festgelegt werden.</p></body></html> - + &Quit &Beenden - + <html><head/><body><p><span style=" font-weight:600;">Quit QtDMM</span></p><p>If the recorder contains unsaved data QtDMM will give you the option to savve your data first.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">QtDMM Beenden</span></p><p>Wenn der Datenrekorder ungespeicherte Daten enthällt, haben Sie die Möglichkeit diese vorher zu speichern.</p></body></html> @@ -1603,12 +1641,12 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+B - + &Connect &Verbinden - + <html><head/><body><p><span style=" font-weight:600;">Connect to the Multimeter</span></p><p>This will establish the serial connection to the dmm. If not connected the serial port is free and can be used by other software.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Verbindung zum DMM herstellen</span></p><p>Die baut die serielle Verbindung zum DMM auf.</p></body></html> @@ -1617,12 +1655,12 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+V - + &Reset &Zurücksetzen - + <html><head/><body><p><span style=" font-weight:600;">Reset min/max values</span></p><p>The min/max values in the display will be reset. You can activate this option at any time. </p></body></html> <html><head/><body><p><span style=" font-weight:600;">Min/Max Werte zurücksetzen</span></p><p>Die Min/Max Werte in der Anzeige werden zurückgesetzt. Diese Option kann jederzeit aktiviert werden. </p></body></html> @@ -1631,12 +1669,12 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+Z - + &Start &Starten - + <html><head/><body><p><span style=" font-weight:600;">Start the recorder</span></p><p>If you are in manual mode this will start the recorder. Press F2 to set the recorder options.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Rekorder starten</span></p><p>Startet den Rekorder wenn sich dieser im manuellen Modus befindet. F2 drücken für die Rekordereinstellungen.</p></body></html> @@ -1645,12 +1683,12 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+S - + S&top &Anhalten - + <html><head/><body><p><span style=" font-weight:600;">Stop the recorder</span></p><p>The recorder will be stopped. This is independent from the start mode of the recorder. </p></body></html> <html><head/><body><p><span style=" font-weight:600;">Hällt den Rekorder an</span></p><p>Der Rekoder wird angehalten. Dies ist unabhängig von dem gewählten Startmodus. </p></body></html> @@ -1659,12 +1697,12 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+A - + &Clear &Löschen - + <html><head/><body><p><span style=" font-weight:600;">Clear the recorder graph</span></p><p>If the recorder is already started it will clear the graph and continue recording.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Lösche den Graphen</span></p><p>Wenn der Rekorder läuft, wird der Graph gelöscht und es wird weiter aufgezeichnet.</p></body></html> @@ -1673,7 +1711,7 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Enf - + C&onfigure &Konfigurieren @@ -1682,7 +1720,7 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+F2 - + &About Ü&ber @@ -1691,12 +1729,12 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Ü&ber die Version - + <html><head/><body><p><span style=" font-weight:600;">Copyright information</span></p><p>Show copyright information and some blurb about QtDMM. </p></body></html> <html><head/><body><p><span style=" font-weight:600;">Urheber Information</span></p><p>Zeigt die Information zum Urheber sowie etwas Werbung zu QtDMM an. </p></body></html> - + &Tip of the day &Tipp des Tages @@ -1705,17 +1743,17 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar &Tipp des Tages - + <html><head/><body><p>Show tip of the day.</p></body></html> <html><head/><body><p>Zeigt den Tipp des Tages an.</p></body></html> - + &Direct Help &Direkte Hilfe - + <html><head/><body><p><span style=" font-weight:600;">Direct Help</span></p><p>Enter the direct help mode. You have done this already when reading this text :)</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Direkte Hilfe</span></p><p>Schalten in den direkten Hilfemodus um. Dies haben Sie bereits duch lesen des Textes getan :)</p></body></html> diff --git a/src/configdlg.cpp b/src/configdlg.cpp index a671dc6..3f794a0 100644 --- a/src/configdlg.cpp +++ b/src/configdlg.cpp @@ -39,15 +39,14 @@ #include -ConfigDlg::ConfigDlg(QString session_id, QString config_path, QWidget *parent) : QDialog(parent) +ConfigDlg::ConfigDlg(Settings* settings, QWidget *parent) + : QDialog(parent) + , m_settings(settings) { m_buttonBox_OK = false; setupUi(this); - m_settings = new Settings(this, session_id, config_path); - // Check if configuration file exists. If not welcome user - if (!m_settings->fileExists()) { QMessageBox welcome; diff --git a/src/configdlg.h b/src/configdlg.h index e2baae4..6cd0e67 100644 --- a/src/configdlg.h +++ b/src/configdlg.h @@ -57,8 +57,7 @@ class ConfigDlg : public QDialog, private Ui::UIConfigDlg NumItems, }; - ConfigDlg(QString session_id, QString config_path, QWidget *parent = Q_NULLPTR); - Settings *getSettings() { return m_settings; } + ConfigDlg(Settings* settings, QWidget *parent = Q_NULLPTR); QString device() const; int speed() const; int windowSeconds() const; diff --git a/src/instancesdlg.cpp b/src/instancesdlg.cpp new file mode 100644 index 0000000..caa819b --- /dev/null +++ b/src/instancesdlg.cpp @@ -0,0 +1,85 @@ +#include +#include + +#include "instancesdlg.h" + + +InstancesDlg::InstancesDlg(QString session_id, QString config_path, QWidget *parent) + : QDialog(parent) + , m_sessionId(session_id.isEmpty()? "default" : session_id) + , m_configPath(config_path) +{ + setupUi(this); + ui_instancesList->setStyleSheet("background-color: palette(window);"); +} + +void InstancesDlg::setInstancesOnline(QStringList instances) +{ + m_instancesOnline = instances; + updateInstancesListBox(); +} + +void InstancesDlg::setInstancesConfigured(QStringList instances) +{ + m_instancesConfigured = instances; + updateInstancesListBox(); +} + +void InstancesDlg::updateInstancesListBox() +{ + ui_instancesList->clear(); + + for (auto &instanceId : m_instancesConfigured) + { + // Platzhalter-Item (nur Container) + QListWidgetItem *wi_item = new QListWidgetItem(ui_instancesList); + wi_item->setSizeHint(QSize(150, 40)); + + // Button erstellen + QPushButton *btn = new QPushButton(instanceId, ui_instancesList); + btn->setProperty("instanceId", instanceId); + QFont font = btn->font(); + if (instanceId != m_sessionId) + font.setBold(true); + font.setPointSize(font.pointSize() + 2); + btn->setFont(font); + + // Falls es die aktuelle Session ist -> grau machen + if (instanceId == m_sessionId) + btn->setEnabled(false); + + // Klick-Handler + connect(btn, &QPushButton::clicked, this, [this, btn]() { + QString configId = btn->property("instanceId").toString(); + QString exePath = QCoreApplication::applicationFilePath(); + + if (configId == m_sessionId) + return; + + if (m_instancesOnline.contains(configId)) + { + Q_EMIT raiseApplicationWindow(configId); + } + else + { + QStringList args; + if (configId != "default") + args << "--config-id" << configId; + if (!m_configPath.isEmpty()) + args << "--config-dir" << m_configPath; + + QProcess::startDetached(exePath, args); + } + }); + + // Item + Button verbinden + ui_instancesList->addItem(wi_item); + ui_instancesList->setItemWidget(wi_item, btn); + } +} + + +void InstancesDlg::on_ui_instancesList_itemDoubleClicked(QListWidgetItem *item) +{ + +} diff --git a/src/instancesdlg.h b/src/instancesdlg.h new file mode 100644 index 0000000..0898745 --- /dev/null +++ b/src/instancesdlg.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include "ui_uiinstancesdlg.h" + +class InstancesDlg : public QDialog, private Ui::UIInstancesDlg +{ + Q_OBJECT +public: + InstancesDlg(QString session_id, QString config_path, QWidget *parent = Q_NULLPTR); + + void setInstancesOnline(QStringList instances); + void setInstancesConfigured(QStringList instances); + void updateInstancesListBox(); + +protected: + QStringList m_instancesOnline; + QStringList m_instancesConfigured; + QString m_configPath; + QString m_sessionId; + +protected Q_SLOTS: + void on_ui_instancesList_itemDoubleClicked(QListWidgetItem *item); + +Q_SIGNALS: + void raiseApplicationWindow(const QString &); +}; diff --git a/src/mainwid.cpp b/src/mainwid.cpp index b68f8c0..6463ba9 100644 --- a/src/mainwid.cpp +++ b/src/mainwid.cpp @@ -31,10 +31,13 @@ #include "dmm.h" #include "displaywid.h" #include "tipdlg.h" +#include "settings.h" + MainWid::MainWid(QString session_id, QString config_path, QWidget *parent) : QFrame(parent), m_display(0), - m_tipDlg(0) + m_tipDlg(0), + m_instancesDlg(session_id, config_path,this) { setupUi(this); setWindowIcon(QPixmap(":/Symbols/icon.xpm")); @@ -42,7 +45,8 @@ MainWid::MainWid(QString session_id, QString config_path, QWidget *parent) : QF m_dmm = new DMM(this); m_external = new QProcess(this); - m_configDlg = new ConfigDlg(session_id, config_path, this); + m_settings = new Settings(session_id, config_path, this); + m_configDlg = new ConfigDlg(m_settings, this); m_configDlg->hide(); m_configDlg->readPrinter(&m_printer); @@ -50,6 +54,8 @@ MainWid::MainWid(QString session_id, QString config_path, QWidget *parent) : QF m_printDlg = new qtdmm::PrintDlg(this); m_printDlg->hide(); + m_instancesDlg.setInstancesConfigured(m_settings->getConfigInstances()); + connect(&m_instancesDlg, SIGNAL(raiseApplicationWindow(const QString &)), parent, SLOT(sendRaiseApplicationWindow(const QString &))); connect(m_dmm, SIGNAL(value(double, const QString &, const QString &, const QString &, const QString &, bool, bool, int)), this, SLOT(valueSLOT(double, const QString &, const QString &, const QString &, const QString &, bool, bool, int))); connect(m_dmm, SIGNAL(error(const QString &)), this, SIGNAL(error(const QString &))); @@ -74,7 +80,7 @@ MainWid::MainWid(QString session_id, QString config_path, QWidget *parent) : QF connect(ui_graph, SIGNAL(thresholdChanged(DMMGraph::CursorMode, double)), m_configDlg, SLOT(thresholdChangedSLOT(DMMGraph::CursorMode, double))); - ui_graph->setSettings(m_configDlg->getSettings()); + ui_graph->setSettings(m_settings); //resetSLOT(); @@ -539,3 +545,13 @@ void MainWid::setToolbarVisibility(bool disp, bool dmm, bool graph, bool file) { m_configDlg->setToolbarVisibility(disp, dmm, graph, file); } + +void MainWid::instancesSLOT() +{ + m_instancesDlg.show(); +} + +void MainWid::instancesChangedSlot(QStringList& instances) +{ + m_instancesDlg.setInstancesOnline(instances); +} diff --git a/src/mainwid.h b/src/mainwid.h index 0071018..93737b5 100644 --- a/src/mainwid.h +++ b/src/mainwid.h @@ -27,6 +27,7 @@ #include #include "ui_uimainwid.h" +#include "instancesdlg.h" #include "printdlg.h" class DMM; @@ -34,6 +35,7 @@ class QProcess; class ConfigDlg; class DisplayWid; class TipDlg; +class Settings; class MainWid : public QFrame, private Ui::UIMainWid { @@ -79,6 +81,8 @@ public Q_SLOTS: void applySLOT(); void rejectSLOT(); void showTipsSLOT(); + void instancesSLOT(); + void instancesChangedSlot(QStringList&); protected: DMM *m_dmm; @@ -92,6 +96,8 @@ public Q_SLOTS: DisplayWid *m_display; double m_dval; TipDlg *m_tipDlg; + InstancesDlg m_instancesDlg; + Settings *m_settings; void readConfig(); QRect parentRect() const; diff --git a/src/mainwin.cpp b/src/mainwin.cpp index e61d6ed..ff87dd0 100644 --- a/src/mainwin.cpp +++ b/src/mainwin.cpp @@ -29,7 +29,6 @@ #include "mainwid.h" #include "displaywid.h" - MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) : QMainWindow(parent) , m_running(false) @@ -37,9 +36,9 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) { setupUi(this); setupIcons(); - QString config_id = parser.value("config-id"); + m_config_id = parser.value("config-id"); - m_stateMgr = new SharedStateManager(config_id.isEmpty()?"default":config_id,this); + m_stateMgr = new SharedStateManager(m_config_id.isEmpty()?"default":m_config_id,this); QWidget* spacer = new QWidget(); spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); @@ -51,7 +50,7 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) version = version.left(plusIndex); - m_wid = new MainWid(config_id, parser.value("config-dir"), this); + m_wid = new MainWid(m_config_id, parser.value("config-dir"), this); setCentralWidget(m_wid); setConsoleLogging(parser.isSet("debug")); @@ -61,7 +60,10 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) toolBarDisplay->addWidget(m_display); m_wid->setDisplay(m_display); - setWindowTitle(QString("%1 %2 %3").arg(APP_NAME).arg(version).arg(config_id)); + if (m_config_id.isEmpty()) + setWindowTitle(QString("%1 %2").arg(APP_NAME).arg(version)); + else + setWindowTitle(QString("%1 %2 [%3]").arg(APP_NAME).arg(version).arg(m_config_id)); connect(m_wid, SIGNAL(running(bool)), this, SLOT(runningSLOT(bool))); @@ -90,7 +92,6 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) m_wid->applySLOT(); - if (!winRect.isEmpty()) { if (m_wid->saveWindowPosition()) @@ -104,13 +105,16 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) connect(m_stateMgr, &SharedStateManager::stateChanged, this, [=](const QString& state){ if (state == "RECORD") { - qInfo() << "rec"; - action_Start->trigger(); + action_Start->trigger(); } else if (state == "STOP") { - qInfo() << "stop"; - action_Stop->trigger(); + action_Stop->trigger(); + } + else if (state == "RAISE_"+(m_config_id.isEmpty()?"default":m_config_id)) + { + bringMainWindowToFront(); + m_stateMgr->writeState("IDLE"); } }); @@ -124,6 +128,12 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) QTimer::singleShot(1000, action_Connect, &QAction::trigger); } +void MainWin::sendRaiseApplicationWindow(const QString & session_id) +{ + m_stateMgr->writeState("RAISE_"+session_id); +} + + void MainWin::setConsoleLogging(bool on) { m_wid->setConsoleLogging(on); @@ -160,6 +170,7 @@ void MainWin::createActions() connect(action_Quit, SIGNAL(triggered()), m_wid, SLOT(quitSLOT())); connect(action_Direct_help, SIGNAL(triggered()), m_wid, SLOT(helpSLOT())); connect(action_Tip_of_the_day, SIGNAL(triggered()), m_wid, SLOT(showTipsSLOT())); + connect(action_Instances, SIGNAL(triggered()), m_wid, SLOT(instancesSLOT())); connect(toolBarDisplay, SIGNAL(visibilityChanged(bool)), this, SLOT(setToolbarVisibilitySLOT())); connect(toolBarMenu, SIGNAL(visibilityChanged(bool)), this, SLOT(setToolbarVisibilitySLOT())); @@ -167,6 +178,8 @@ void MainWin::createActions() connect(toolBarRecorder, SIGNAL(visibilityChanged(bool)), this, SLOT(setToolbarVisibilitySLOT())); connect(toolBarDMM, SIGNAL(visibilityChanged(bool)), this, SLOT(setToolbarVisibilitySLOT())); + connect(m_stateMgr, SIGNAL(instancesChanged(QStringList&)), m_wid, SLOT(instancesChangedSlot(QStringList&))); + connect(new QShortcut(action_Configure->shortcut(), this), SIGNAL(activated()), action_Configure, SLOT(trigger())); connect(new QShortcut(action_Direct_help->shortcut(), this), SIGNAL(activated()), action_Direct_help, SLOT(trigger())); connect(new QShortcut(action_About->shortcut(), this), SIGNAL(activated()), action_About, SLOT(trigger())); @@ -286,3 +299,25 @@ void MainWin::setupIcons() this->action_Connect->setIcon(checked ? iconConnectOn : iconConnectOff); }); } + +void MainWin::bringMainWindowToFront() +{ + QWidget *mainWin = nullptr; + const auto topWidgets = QApplication::topLevelWidgets(); + + for (QWidget *w : topWidgets) + { + if (w->inherits("MainWin")) + { + mainWin = w; + break; + } + } + + if (!mainWin) + return; + + mainWin->showNormal(); + mainWin->raise(); + mainWin->activateWindow(); +} diff --git a/src/mainwin.h b/src/mainwin.h index 69fd015..53fcea2 100644 --- a/src/mainwin.h +++ b/src/mainwin.h @@ -46,6 +46,7 @@ protected Q_SLOTS: void connectSLOT(bool); void startSLOT(); void stopSLOT(); + void sendRaiseApplicationWindow(const QString &); void on_action_About_triggered(); void on_action_Menu_triggered(); void setConnectSLOT(bool); @@ -61,10 +62,12 @@ protected Q_SLOTS: QLabel *m_info; QMenu *m_menu; SharedStateManager* m_stateMgr; + QString m_config_id; void setupIcons(); void createToolBars(); void createActions(); void closeEvent(QCloseEvent *)Q_DECL_OVERRIDE; + void bringMainWindowToFront(); }; diff --git a/src/settings.cpp b/src/settings.cpp index 0a8f283..a903abb 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -34,25 +34,73 @@ Settings::~Settings() delete m_tmpConfig; } -Settings::Settings(QObject *parent, const QString &session_id, const QString &config_path) : Settings(parent) +Settings::Settings(const QString &session_id, const QString &config_path, QObject *parent) + : Settings(parent) { - if (!session_id.isEmpty()) + QFileInfo fileInfo(m_qsettings->fileName()); + m_configPath = fileInfo.absolutePath(); + m_configBaseFileName = fileInfo.baseName(); + m_configFileNameSuffix = fileInfo.suffix(); + m_sessionId = session_id.isEmpty() ? "default" : session_id; + + if (!session_id.isEmpty() || !config_path.isEmpty()) { - QSettings qsettings(this); - QFileInfo fileInfo(qsettings.fileName()); - QString fileDir = config_path.isEmpty() ? fileInfo.absolutePath() : config_path; + m_configPath = config_path.isEmpty() ? fileInfo.absolutePath() : config_path; + m_configBaseFileName = fileInfo.baseName(); + m_configFileNameSuffix = fileInfo.suffix(); + + QString session_fileName = m_configBaseFileName+(session_id.isEmpty() ? "" : "_"+session_id)+"."+m_configFileNameSuffix; + session_fileName.prepend(m_configPath+"/"); - QString session_fileName = fileDir+"/"+fileInfo.baseName()+"_"+session_id+"."+fileInfo.suffix(); delete m_qsettings; m_qsettings = new QSettings(session_fileName, QSettings::IniFormat, this); QFile file(m_qsettings->fileName()); m_fileExists = file.exists(); m_filename = m_qsettings->fileName(); m_fileConverted = false; - qInfo() << "config file: " << m_qsettings->fileName(); + //qInfo() << "config file: " << m_qsettings->fileName(); } } +QStringList Settings::getConfigInstances() +{ + QDir dir(m_configPath); + if (!dir.exists()) + return {}; + qInfo() << m_configPath << m_configBaseFileName << m_configFileNameSuffix; + QString pattern = QString("%1*%2") + .arg(m_configBaseFileName) + .arg(m_configFileNameSuffix.isEmpty() ? "" : "." + m_configFileNameSuffix); + + QStringList result; + result << m_sessionId; + for (const QString &file : dir.entryList({ pattern }, QDir::Files, QDir::Name)) + { + QString base = QFileInfo(file).completeBaseName(); + + if (base.startsWith(m_configBaseFileName)) + base = base.mid(m_configBaseFileName.length()); + + if (base.startsWith("_")) + base.remove(0, 1); + + result << (base.isEmpty() ? "default" : base); + } + + result.removeDuplicates(); + result.sort(Qt::CaseInsensitive); + if (result.contains("default")) + { + result.removeAll("default"); + result.prepend("default"); + } + + for (auto item : result) + qInfo() << item; + + return result; +} + int Settings::getInt(const QString &name, const int &def) const { return m_qsettings->value(name, def).toInt(); diff --git a/src/settings.h b/src/settings.h index 9c5aea4..b99df5b 100644 --- a/src/settings.h +++ b/src/settings.h @@ -25,14 +25,14 @@ class Settings : public QObject Q_OBJECT public: explicit Settings(QObject *parent = Q_NULLPTR); - explicit Settings(QObject *parent, const QString &session_id, const QString &config_path); + explicit Settings(const QString &session_id, const QString &config_path, QObject *parent = Q_NULLPTR); ~Settings(); const bool &fileExists() const { return m_fileExists; } const bool &fileConverted() const { return m_fileConverted; } + const QString &fileName() const { return m_filename; } - const QString &fileName()const { return m_filename; } - + QStringList getConfigInstances(); void save(); void clear(); @@ -53,5 +53,9 @@ class Settings : public QObject bool m_fileConverted; QString m_filename; QSettings *m_qsettings; + QString m_configPath; + QString m_configBaseFileName; + QString m_configFileNameSuffix; + QString m_sessionId; QHash *m_tmpConfig; }; diff --git a/src/sharedstatemanager.cpp b/src/sharedstatemanager.cpp index 29a8fef..05f27a3 100644 --- a/src/sharedstatemanager.cpp +++ b/src/sharedstatemanager.cpp @@ -123,16 +123,19 @@ void SharedStateManager::checkForChanges() QJsonObject data = readJsonData(); QString currentState = data["state"].toString(); - QVariantList instances = data["instances"].toArray().toVariantList(); + QStringList instances; + for (const QVariant &v : data["instances"].toArray().toVariantList()) + instances << v.toString(); + if (instances.count() != m_instances.count()) { m_instances = instances; - emit instanceCountChanged(m_instances); + Q_EMIT instancesChanged(m_instances); } if (currentState != m_lastState) { - qInfo() << currentState << QJsonDocument(data).toJson(QJsonDocument::Compact); + //qInfo() << currentState << QJsonDocument(data).toJson(QJsonDocument::Compact); m_lastState = currentState; Q_EMIT stateChanged(currentState); } diff --git a/src/sharedstatemanager.h b/src/sharedstatemanager.h index c1ff64d..05a4fe0 100644 --- a/src/sharedstatemanager.h +++ b/src/sharedstatemanager.h @@ -18,12 +18,12 @@ class SharedStateManager : public QObject bool writeState(const QString &newState); void checkForChanges(); - QVariantList instanceCount() { return m_instances; }; + QStringList instances() { return m_instances; }; signals: void stateChanged(const QString &newState); void instanceIdAlreadyInUse(); - void instanceCountChanged(QVariantList &instances); + void instancesChanged(QStringList &instances); private: QJsonObject readJsonData(); @@ -36,5 +36,5 @@ class SharedStateManager : public QObject QString m_instanceId; bool m_registered; bool m_emit_inUse; - QVariantList m_instances; + QStringList m_instances; }; diff --git a/src/ui/uiinstancesdlg.ui b/src/ui/uiinstancesdlg.ui new file mode 100644 index 0000000..b8af084 --- /dev/null +++ b/src/ui/uiinstancesdlg.ui @@ -0,0 +1,138 @@ + + + UIInstancesDlg + + + + 0 + 0 + 400 + 269 + + + + Instances + + + + + + 12 + + + 12 + + + + + Choose instance + + + + + + + + + false + + + QFrame::NoFrame + + + QFrame::Plain + + + 0 + + + + + + + + + + + + + + .. + + + + + + + - + + + + .. + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + + + + + ui_instances_buttonBox + accepted() + UIInstancesDlg + accept() + + + 248 + 254 + + + 157 + 268 + + + + + ui_instances_buttonBox + rejected() + UIInstancesDlg + reject() + + + 389 + 254 + + + 286 + 268 + + + + + diff --git a/src/ui/uimainwin.ui b/src/ui/uimainwin.ui index 149f25d..c67f998 100644 --- a/src/ui/uimainwin.ui +++ b/src/ui/uimainwin.ui @@ -41,6 +41,8 @@ false + + @@ -425,6 +427,21 @@ Ctrl+M + + + + :/Symbols/dmm_big.xpm:/Symbols/dmm_big.xpm + + + instances + + + open or create an instance + + + Ctrl+N + + From 602d80f216dc355d64546c47b9504d5fb82f066f Mon Sep 17 00:00:00 2001 From: Sarah Mischke Date: Sun, 10 Aug 2025 00:20:35 +0200 Subject: [PATCH 3/8] instances management via dialog --- QtDMM.spec | 2 +- assets/translations/qtdmm_de.ts | 64 ++++++++++----- src/instancesdlg.cpp | 135 +++++++++++++++++++++++--------- src/instancesdlg.h | 15 ++-- src/mainwid.cpp | 15 ++-- src/mainwid.h | 5 +- src/mainwin.cpp | 5 +- src/mainwin.h | 2 +- src/settings.cpp | 17 +++- src/settings.h | 2 + src/sharedstatemanager.cpp | 3 + src/sharedstatemanager.h | 4 +- src/ui/uiinstancesdlg.ui | 11 ++- 13 files changed, 199 insertions(+), 81 deletions(-) diff --git a/QtDMM.spec b/QtDMM.spec index 1141079..7af30e7 100644 --- a/QtDMM.spec +++ b/QtDMM.spec @@ -1,5 +1,5 @@ Name: qtdmm -Version: 1.0.0-alpha.1-6-g77c63e0+77c63e0 +Version: 1.0.0-alpha.1-7-ge07025e+e07025e Release: 1%{?dist} Summary: DMM Readout Software Including a Configurable Recorder. diff --git a/assets/translations/qtdmm_de.ts b/assets/translations/qtdmm_de.ts index e439ce1..0d395b8 100644 --- a/assets/translations/qtdmm_de.ts +++ b/assets/translations/qtdmm_de.ts @@ -385,6 +385,24 @@ Ist das DMM angeschlossen und eingeschaltet? <b>Hier wird das Erscheinungsbild von QtDMM eingestellt.</b> + + InstancesDlg + + + QtDMM - new instance + + + + + Instance name: + + + + + Instance already exists. + + + IntegrationPrefs @@ -401,47 +419,47 @@ Ist das DMM angeschlossen und eingeschaltet? MainWid - + QtDMM: Unsaved data QtDMM: Ungesicherte Daten - + <font size=+2><b>Unsaved data</b></font><p>You still have unsaved measured data in memory. If you quit now it will be lost.<p>Do you want to export your unsaved data first? <font size=+2><b>Ungesicherte Daten</b></font><p>Es befinden sich ungesicherte Daten im Speicher. Wenn Sie das Programm beenden gehen diese verloren.<p>Sollen diese vorher exportiert werden? - + Export data first Daten erst exportieren - + Quit without saving Beenden ohne speichern - + Automatic start at %1 Automatisch starten bei %1 - + Raising threshold %1 Grenzwert steigent %1 - + Falling threshold %1 Grenzwert fallend %1 - + <font size=+2><b>Launch error</b></font><p>Application %1 is still running!<p>Do you want to kill it now? <font size=+2><b>Startfehler</b></font><p>Programm %s läuft noch!<p>Wollen sie es jetzt beenden? - + <font size=+2><b>Launch error</b></font><p>Couldn't launch %1 <font size=+2><b>Startfehler</b></font><p>Konnte %1 nicht starten @@ -450,18 +468,18 @@ Ist das DMM angeschlossen und eingeschaltet? <font size=+2><b>Startfehler</b></font><p>Programm %s is still running!<p>Do you want to kill it now - + Launched %1 %1 gestartet - + %1 terminated with exit code %2. %1 mit dem Rückgabecode %2 beendet. - - + + QtDMM: Launch error QtDMM: Startfehler @@ -470,17 +488,17 @@ Ist das DMM angeschlossen und eingeschaltet? <font size=+2><b>Startfehler</b></font><p>Programm %1 läuft noch.<p>Soll es getötet werden - + Yes, kill it! Ja, töten! - + No, keep running Nein, es laufen lassen - + Bummer! Reinfall! @@ -1314,16 +1332,26 @@ Der Wert kann auch mit einem Suffix wie m, u, n, p, k, M, G oder T angegeben wer - Choose instance + Choose instance to open + add new instance + + + + + - + + remove instances + + + + - diff --git a/src/instancesdlg.cpp b/src/instancesdlg.cpp index caa819b..3a9bfb6 100644 --- a/src/instancesdlg.cpp +++ b/src/instancesdlg.cpp @@ -4,10 +4,11 @@ #include "instancesdlg.h" -InstancesDlg::InstancesDlg(QString session_id, QString config_path, QWidget *parent) +InstancesDlg::InstancesDlg(Settings *settings, QString session_id, QString config_path, QWidget *parent) : QDialog(parent) - , m_sessionId(session_id.isEmpty()? "default" : session_id) + , m_sessionId(session_id.isEmpty() ? "default" : session_id) , m_configPath(config_path) + , m_settings(settings) { setupUi(this); ui_instancesList->setStyleSheet("background-color: palette(window);"); @@ -19,47 +20,65 @@ void InstancesDlg::setInstancesOnline(QStringList instances) updateInstancesListBox(); } -void InstancesDlg::setInstancesConfigured(QStringList instances) +void InstancesDlg::updateInstancesListBox() { - m_instancesConfigured = instances; - updateInstancesListBox(); + ui_instancesList->clear(); + m_instancesConfigured = m_settings->getConfigInstances(); + + QStringList instances = m_instancesConfigured; + for (auto &instanceId : m_instancesOnline) + if (!instances.contains(instanceId)) + instances << instanceId; + + for (auto &instanceId : m_instancesConfigured) + { + QListWidgetItem *wi_item = new QListWidgetItem(ui_instancesList); + wi_item->setSizeHint(QSize(150, 40)); + + QPushButton *btn = new QPushButton(instanceId, ui_instancesList); + btn->setProperty("instanceId", instanceId); + QFont font = btn->font(); + if (instanceId != m_sessionId) + font.setBold(true); + font.setPointSize(font.pointSize() + 2); + btn->setFont(font); + + if (instanceId == m_sessionId || (m_onDelete && m_instancesOnline.contains(instanceId))) + btn->setEnabled(false); + else if (m_onDelete) + { + btn->setCheckable(true); + } + else + { + btn->setCheckable(false); + } + + connect(btn, SIGNAL(clicked()), this, SLOT(onInstanceButtonClicked())); + + ui_instancesList->addItem(wi_item); + ui_instancesList->setItemWidget(wi_item, btn); + } } -void InstancesDlg::updateInstancesListBox() + +void InstancesDlg::onInstanceButtonClicked() { - ui_instancesList->clear(); + if (m_onDelete) + return; - for (auto &instanceId : m_instancesConfigured) - { - // Platzhalter-Item (nur Container) - QListWidgetItem *wi_item = new QListWidgetItem(ui_instancesList); - wi_item->setSizeHint(QSize(150, 40)); - - // Button erstellen - QPushButton *btn = new QPushButton(instanceId, ui_instancesList); - btn->setProperty("instanceId", instanceId); - QFont font = btn->font(); - if (instanceId != m_sessionId) - font.setBold(true); - font.setPointSize(font.pointSize() + 2); - btn->setFont(font); - - // Falls es die aktuelle Session ist -> grau machen - if (instanceId == m_sessionId) - btn->setEnabled(false); - - // Klick-Handler - connect(btn, &QPushButton::clicked, this, [this, btn]() { - QString configId = btn->property("instanceId").toString(); + QPushButton *btn = qobject_cast(sender()); + if (!btn) + return; + + QString configId = btn->property("instanceId").toString(); QString exePath = QCoreApplication::applicationFilePath(); if (configId == m_sessionId) return; if (m_instancesOnline.contains(configId)) - { - Q_EMIT raiseApplicationWindow(configId); - } + Q_EMIT writeState("RAISE_"+configId); else { QStringList args; @@ -70,16 +89,56 @@ void InstancesDlg::updateInstancesListBox() QProcess::startDetached(exePath, args); } - }); +} - // Item + Button verbinden - ui_instancesList->addItem(wi_item); - ui_instancesList->setItemWidget(wi_item, btn); - } +void InstancesDlg::on_ui_instance_add_clicked() +{ + bool ok{}; + QString configId = QInputDialog::getText(this, tr("QtDMM - new instance"), tr("Instance name:"), QLineEdit::Normal, "", &ok).trimmed(); + if (!ok || configId.isEmpty() || configId == "default") + return; + + if (m_instancesOnline.contains(configId) || m_instancesConfigured.contains(configId) ) + { + QMessageBox::warning(this, APP_NAME,tr("Instance already exists.")); + return; + } + + QString exePath = QCoreApplication::applicationFilePath(); + + QStringList args; + if (configId != "default") + args << "--config-id" << configId; + if (!m_configPath.isEmpty()) + args << "--config-dir" << m_configPath; + + QProcess::startDetached(exePath, args); + Q_EMIT writeState("UPDATE_INSTANCES_"+QString::number(QDateTime::currentMSecsSinceEpoch())); } -void InstancesDlg::on_ui_instancesList_itemDoubleClicked(QListWidgetItem *item) +void InstancesDlg::on_ui_instance_del_clicked() { + if (m_onDelete && !ui_instance_del->isChecked()) + { + for (int i = 0; i < ui_instancesList->count(); ++i) + { + QListWidgetItem *item = ui_instancesList->item(i); + if (!item) + continue; + + auto btn = qobject_cast(ui_instancesList->itemWidget(item)); + if (!btn || !btn->isChecked()) + continue; + + QString configId = btn->property("instanceId").toString(); + m_settings->deleteConfig(configId); + } + Q_EMIT writeState("UPDATE_INSTANCES_"+QString::number(QDateTime::currentMSecsSinceEpoch())); + } + m_onDelete = ui_instance_del->isChecked(); + updateInstancesListBox(); } + + diff --git a/src/instancesdlg.h b/src/instancesdlg.h index 0898745..2e658b7 100644 --- a/src/instancesdlg.h +++ b/src/instancesdlg.h @@ -2,26 +2,31 @@ #include #include "ui_uiinstancesdlg.h" +#include "settings.h" class InstancesDlg : public QDialog, private Ui::UIInstancesDlg { Q_OBJECT public: - InstancesDlg(QString session_id, QString config_path, QWidget *parent = Q_NULLPTR); + InstancesDlg(Settings *settings, QString session_id, QString config_path, QWidget *parent = Q_NULLPTR); void setInstancesOnline(QStringList instances); - void setInstancesConfigured(QStringList instances); void updateInstancesListBox(); protected: QStringList m_instancesOnline; QStringList m_instancesConfigured; - QString m_configPath; - QString m_sessionId; + QString m_configPath; + QString m_sessionId; + Settings *m_settings; + bool m_onDelete; protected Q_SLOTS: - void on_ui_instancesList_itemDoubleClicked(QListWidgetItem *item); + void onInstanceButtonClicked(); + void on_ui_instance_add_clicked(); + void on_ui_instance_del_clicked(); Q_SIGNALS: void raiseApplicationWindow(const QString &); + void writeState(const QString &); }; diff --git a/src/mainwid.cpp b/src/mainwid.cpp index 6463ba9..1ade6f1 100644 --- a/src/mainwid.cpp +++ b/src/mainwid.cpp @@ -32,12 +32,11 @@ #include "displaywid.h" #include "tipdlg.h" #include "settings.h" - +#include "instancesdlg.h" MainWid::MainWid(QString session_id, QString config_path, QWidget *parent) : QFrame(parent), m_display(0), - m_tipDlg(0), - m_instancesDlg(session_id, config_path,this) + m_tipDlg(0) { setupUi(this); setWindowIcon(QPixmap(":/Symbols/icon.xpm")); @@ -48,14 +47,14 @@ MainWid::MainWid(QString session_id, QString config_path, QWidget *parent) : QF m_settings = new Settings(session_id, config_path, this); m_configDlg = new ConfigDlg(m_settings, this); m_configDlg->hide(); - m_configDlg->readPrinter(&m_printer); m_printDlg = new qtdmm::PrintDlg(this); m_printDlg->hide(); - m_instancesDlg.setInstancesConfigured(m_settings->getConfigInstances()); - connect(&m_instancesDlg, SIGNAL(raiseApplicationWindow(const QString &)), parent, SLOT(sendRaiseApplicationWindow(const QString &))); + m_instancesDlg = new InstancesDlg(m_settings, session_id, config_path,this); + + connect(m_instancesDlg, SIGNAL(writeState(const QString &)), parent, SLOT(sendStateSLOT(const QString &))); connect(m_dmm, SIGNAL(value(double, const QString &, const QString &, const QString &, const QString &, bool, bool, int)), this, SLOT(valueSLOT(double, const QString &, const QString &, const QString &, const QString &, bool, bool, int))); connect(m_dmm, SIGNAL(error(const QString &)), this, SIGNAL(error(const QString &))); @@ -548,10 +547,10 @@ void MainWid::setToolbarVisibility(bool disp, bool dmm, bool graph, bool file) void MainWid::instancesSLOT() { - m_instancesDlg.show(); + m_instancesDlg->show(); } void MainWid::instancesChangedSlot(QStringList& instances) { - m_instancesDlg.setInstancesOnline(instances); + m_instancesDlg->setInstancesOnline(instances); } diff --git a/src/mainwid.h b/src/mainwid.h index 93737b5..149a53d 100644 --- a/src/mainwid.h +++ b/src/mainwid.h @@ -27,7 +27,7 @@ #include #include "ui_uimainwid.h" -#include "instancesdlg.h" + #include "printdlg.h" class DMM; @@ -36,6 +36,7 @@ class ConfigDlg; class DisplayWid; class TipDlg; class Settings; +class InstancesDlg; class MainWid : public QFrame, private Ui::UIMainWid { @@ -96,7 +97,7 @@ public Q_SLOTS: DisplayWid *m_display; double m_dval; TipDlg *m_tipDlg; - InstancesDlg m_instancesDlg; + InstancesDlg *m_instancesDlg; Settings *m_settings; void readConfig(); diff --git a/src/mainwin.cpp b/src/mainwin.cpp index ff87dd0..3562229 100644 --- a/src/mainwin.cpp +++ b/src/mainwin.cpp @@ -120,7 +120,6 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) connect(m_stateMgr, &SharedStateManager::instanceIdAlreadyInUse, this, [=](){ QMessageBox::critical(this, APP_NAME,tr("Another instance is running.")); - qInfo() << "quit"; qApp->quit(); }); @@ -128,9 +127,9 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) QTimer::singleShot(1000, action_Connect, &QAction::trigger); } -void MainWin::sendRaiseApplicationWindow(const QString & session_id) +void MainWin::sendStateSLOT(const QString & state) { - m_stateMgr->writeState("RAISE_"+session_id); + m_stateMgr->writeState(state); } diff --git a/src/mainwin.h b/src/mainwin.h index 53fcea2..0c78581 100644 --- a/src/mainwin.h +++ b/src/mainwin.h @@ -46,7 +46,7 @@ protected Q_SLOTS: void connectSLOT(bool); void startSLOT(); void stopSLOT(); - void sendRaiseApplicationWindow(const QString &); + void sendStateSLOT(const QString &); void on_action_About_triggered(); void on_action_Menu_triggered(); void setConnectSLOT(bool); diff --git a/src/settings.cpp b/src/settings.cpp index a903abb..321569c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -67,7 +67,7 @@ QStringList Settings::getConfigInstances() QDir dir(m_configPath); if (!dir.exists()) return {}; - qInfo() << m_configPath << m_configBaseFileName << m_configFileNameSuffix; + //qInfo() << m_configPath << m_configBaseFileName << m_configFileNameSuffix; QString pattern = QString("%1*%2") .arg(m_configBaseFileName) .arg(m_configFileNameSuffix.isEmpty() ? "" : "." + m_configFileNameSuffix); @@ -95,8 +95,8 @@ QStringList Settings::getConfigInstances() result.prepend("default"); } - for (auto item : result) - qInfo() << item; + //for (auto item : result) + // qInfo() << item; return result; } @@ -155,3 +155,14 @@ void Settings::clear() { m_tmpConfig->clear(); } + + +void Settings::deleteConfig(QString session_id) +{ + if(session_id.isEmpty()) + return; + + QFile configFile(m_configPath+"/"+m_configBaseFileName+"_"+session_id+"."+m_configFileNameSuffix); + configFile.remove(); +} + diff --git a/src/settings.h b/src/settings.h index b99df5b..9d852b1 100644 --- a/src/settings.h +++ b/src/settings.h @@ -32,6 +32,8 @@ class Settings : public QObject const bool &fileConverted() const { return m_fileConverted; } const QString &fileName() const { return m_filename; } + void deleteConfig(QString session_id); + QStringList getConfigInstances(); void save(); void clear(); diff --git a/src/sharedstatemanager.cpp b/src/sharedstatemanager.cpp index 05f27a3..9b5a6df 100644 --- a/src/sharedstatemanager.cpp +++ b/src/sharedstatemanager.cpp @@ -137,6 +137,8 @@ void SharedStateManager::checkForChanges() { //qInfo() << currentState << QJsonDocument(data).toJson(QJsonDocument::Compact); m_lastState = currentState; + if (currentState.startsWith("UPDATE_INSTANCES")) + Q_EMIT instancesChanged(m_instances); Q_EMIT stateChanged(currentState); } } @@ -170,3 +172,4 @@ void SharedStateManager::unregisterInstance() writeJsonData(data); } } + diff --git a/src/sharedstatemanager.h b/src/sharedstatemanager.h index 05a4fe0..326cbf1 100644 --- a/src/sharedstatemanager.h +++ b/src/sharedstatemanager.h @@ -16,7 +16,6 @@ class SharedStateManager : public QObject bool registerInstance(); void unregisterInstance(); - bool writeState(const QString &newState); void checkForChanges(); QStringList instances() { return m_instances; }; @@ -25,6 +24,9 @@ class SharedStateManager : public QObject void instanceIdAlreadyInUse(); void instancesChanged(QStringList &instances); +public Q_SLOTS: + bool writeState(const QString &newState); + private: QJsonObject readJsonData(); bool writeJsonData(const QJsonObject &obj); diff --git a/src/ui/uiinstancesdlg.ui b/src/ui/uiinstancesdlg.ui index b8af084..d843074 100644 --- a/src/ui/uiinstancesdlg.ui +++ b/src/ui/uiinstancesdlg.ui @@ -25,7 +25,7 @@ - Choose instance + Choose instance to open @@ -51,6 +51,9 @@ + + add new instance + + @@ -62,6 +65,9 @@ + + remove instances + - @@ -69,6 +75,9 @@ .. + + true + From e7753229a13ed69f5ec1255cc65c2ba325c7591b Mon Sep 17 00:00:00 2001 From: Sarah Mischke Date: Sun, 10 Aug 2025 17:27:02 +0200 Subject: [PATCH 4/8] fix instance naming chaos --- QtDMM.spec | 2 +- assets/translations/qtdmm_de.ts | 86 ++++++++++++++++----------------- src/instancesdlg.cpp | 10 ++-- src/instancesdlg.h | 4 +- src/mainwid.cpp | 6 +-- src/mainwid.h | 2 +- src/settings.cpp | 20 ++++---- src/settings.h | 6 +-- src/ui/uidmmprefs.ui | 3 ++ 9 files changed, 71 insertions(+), 68 deletions(-) diff --git a/QtDMM.spec b/QtDMM.spec index 7af30e7..3a5e0c3 100644 --- a/QtDMM.spec +++ b/QtDMM.spec @@ -1,5 +1,5 @@ Name: qtdmm -Version: 1.0.0-alpha.1-7-ge07025e+e07025e +Version: 1.0.0-alpha.1-8-g602d80f+602d80f Release: 1%{?dist} Summary: DMM Readout Software Including a Configurable Recorder. diff --git a/assets/translations/qtdmm_de.ts b/assets/translations/qtdmm_de.ts index 0d395b8..fb8d08e 100644 --- a/assets/translations/qtdmm_de.ts +++ b/assets/translations/qtdmm_de.ts @@ -506,12 +506,12 @@ Ist das DMM angeschlossen und eingeschaltet? MainWin - + QtDMM: Welcome! QtDMM: Willkommen! - + <h1>QtDMM %1</h1><hr><div align=right><i>A simple recorder for DMM's</i></div><p><div align=justify>A simple display software for a variety of digital multimeter. Currently confirmed are:<table>%2</table>Other compatible models may work also.<p>QtDMM features min/max memory and a configurable recorder with import/export and printing function. Sampling may be started manually, at a given time or triggered by a measured threshold. Additionally an external program may be started when given thresholds are reached.</div><div align=justify><b>QtDMM</b> uses the platform independent toolkit <b>Qt</b> version %3 and is licensed under <b>GPL 3</b> (Versions prior to v0.9.0 where licensed under GPL 2)</div><br>&copy; 2001-2014 Matthias Toussaint &nbsp;-&nbsp;&nbsp;<font color=blue><u><a href='mailto:qtdmm@mtoussaint.de'>qtdmm@mtoussaint.de</a></u></font><p><br>The icons (except the DMM icon) have been taken from the KDE project.<p> <h1>QtDMM %1</h1><hr><div align=right><i>Ein einfacher Datenrekorder für DMM</i></div><p><div align=justify>Ein einfaches Anzeigeprogramm für eine Vielzahl von DMM's. Aktuell bestätigt sind:<table>%2</table>Andere kompatible Modelle sollten ebenfalls funktionieren.<p>QtDMM stellt die Funktionen Min/Max Werte halten, ein konfigurierbaren Datenrekorder mit Daten im/export Funktion sowie ein Druckfunktion zur Verfügung. Die Datenaufzeichnung kann manuell, durch einen Grenzwert oder durch eine Zeitfunktion ausgelöst werden. Desweiteren kann ein externes Programm beim erreichen eines Grenzwertes gestartet werden.</div><div align=justify><b>QtDMM</b> wurde mit der Platformunabhängigen <b>Qt</b> Bibliothek in der Version %3 welche unter der <b>GPLv3</b> lizensiert ist erstellt.(Versionen vor 0.9.0 wurden unter der GPLv2 Lizenz veröffentlicht)</div><br>&copy; 2001-2014 Matthias Toussaint &nbsp;-&nbsp;&nbsp;<font color=blue><u><a href='mailto:qtdmm@mtoussaint.de'>qtdmm@mtoussaint.de</a></u></font><p><br>Die Symbole (bis auf das DMM Symbol) stammen von dem KDE Projekt.<p> @@ -675,47 +675,47 @@ Danach müssen Sie sich ab- und wieder anmelden. Hier kann das DMM Modell ausgewählt werden. Wenn Ihr DMM nicht in der Liste ist, können Sie versuchen die Einstellungen per Hand herauszufinden. Und freundlicher weise an <font color=blue><u>qtdmm@mtoussaint.de</u></font> schicken, so das diese in der nächsten Version eingepflegt werden. - + Load Settings Einstellungen laden - + Save Settings Einstellungen speichern - + Port settings Anschlusseinstellungen - + Parit&y &Parität - + Parity for serial communication. May be None, Odd or Even. Parität für die serielle Übertragung. Diese kann Keine, Gerade oder Ungerade sein. - + None Keine - + Even Gerade - + Odd Ungerade - + Number of display digits. <ul><li>3 1/2 - 2000 Counts</li> <li>3 3/4 - 4000 Counts</li> @@ -730,47 +730,47 @@ Danach müssen Sie sich ab- und wieder anmelden. </ul> - + variable bytes ASCII, Sigrok variable bytes ASCII, Sigrok - + <html><head/><body><p>These protocoll settings have not been confirmed by a user yet. If you own this model and can confirm that it works. Please give me a note. <a href="https://github.com/tuxmaster/QtDMM"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/tuxmaster/QtDMM</span></a></p></body></html> <html><head/><body><p>Diese Protokolleinstellungen wurden bisher von keinem Benutzer bestätigt. Wenn Sie dieses Modell besitzen und bestätigen können, das es funkioniert, dann melden Sie es bitte an: <a href="mailto:qtdmm@mtoussaint.de"><span style=" text-decoration: underline; color:#0000ff;">qtdmm@mtoussaint.de</span></a></p></body></html> - + <html><head/><body><p>If you have a DMM not listed above and find manual settings that work, please report to <a href="https://github.com/tuxmaster/QtDMM"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/tuxmaster/QtDMM</span></a>. This way future users of this DMM can benefit from your help.</p></body></html> <html><head/><body><p>Wenn Sie ein DMM verwenden, welches hier nicht aufgeführt ist, aber Sie aber passende Einstellungen gefunden haben, so teilen Sie es bitte <a href="mailto:qtdmm@mtoussaint.de"><span style=" text-decoration: underline; color:#0000ff;">qtdmm@mtoussaint.de</span></a> mit. So können zukümpftige Versionen von Ihrer Hilfe profitieren.</p></body></html> - + 11 bytes binary, continuous (CyrustekES51986) 11 bytes binär, kontinuierlich (CyrustekES51986) - + 23 bytes ASCII, continuous (VC870) 23 bytes ASCII, kontinuierlich (VC870) - + 22 bytes binary, continuous (DO3122) 22 bytes binary, kontinuierlich (DO3122) - + 14 bytes half-ASCII, UNI-T UT61E (CyrustekES51922) 14 bytes halb-ASCII, UNI-T UT61E (CyrustekES51922) - + DTM0660 DTM0660 - + 11 bytes binary, continuous (CyrustekES51962) 11 bytes binär, kontinuierlich(CyrustekES51962) @@ -783,7 +783,7 @@ Danach müssen Sie sich ab- und wieder anmelden. <html><head/><body><p>Wenn Sie ein DMM verwenden, welches hier nicht aufgeführt ist, aber Sie aber passende Einstellungen gefunden haben, so teilen Sie es bitte <a href="mailto:qtdmm@mtoussaint.de"><span style=" text-decoration: underline; color:#0000ff;">qtdmm@mtoussaint.de</span></a> mit. So können zukümpftige Versionen von Ihrer Hilfe profitieren.</p></body></html> - + Number of bits for serial communication. Anzahl der Bits für die Übertragung. @@ -804,12 +804,12 @@ Danach müssen Sie sich ab- und wieder anmelden. 8 Bits - + &Bits: - + Number of stop bits for serial communication. Anzahl der Stoppbits. @@ -822,17 +822,17 @@ Danach müssen Sie sich ab- und wieder anmelden. 2 Stoppbits - + &Port: &Anschluss: - + Choose the serial device here. <i>(Hint for DOS people: /dev/ttyS0 corresponds to COM1. /dev/ttyS1 to COM2 ...)</i> Hier bitte den seriellen Anschluß wählen.<i>(Für Unixumsteiger: /dev/ttyS0 entspricht COM1 und so weiter)</i> - + Select the baud rate for the DMM here. If you encounter problems connecting to your DMM try lowering the baud rate. I had some problems with my <b>Metex ME-32</b>. The Documentation said 1200 baud but it only worked at 600. Hier die Baudrate für das DMM auswählen. Wenn Probleme mit der Verbindung zum DMM auftreten, bitte die Baudrate verringern. Es sind Probleme mit dem <b>Metex ME-32</b> bekannt. Laut Dokumentation soll es mit 1200 Baud laufen, aber tatsächlich geht es nur mit 600 Baud. @@ -865,63 +865,63 @@ Danach müssen Sie sich ab- und wieder anmelden. 19200 Baud - + &Digits S&tellen - + &Stop bits: &Stoppbits: - + Baud &rate: Baud&rate: - + External device setup Externe Steuerung - + Protocol Protokoll - + Here you may select the Communication type. If you have a not "officially" supported multimeter, just try out the existing protocols. If you are lucky it may work. If you find working settings, send the to me. Hier wird das Kommunikationsprotokoll ausgewählt. Wenn Sie kein "offiziell" unterstützes DMM benutzte, versuchen Sie eines der bereits vorhanden Protokolle. Mit etwas etwas Glück passt eines. Wenn Sie eins finden, teilen Sie es bitte dem Autor mit. Here you may select the Communication type. If you have a not "officially" supported multimeter, just try out the existing protocols. If you are lucky it may work. If you find working settings, send the to me. - + 14 bytes ASCII, polling (Metex/Voltcraft) 14 Bytes ASCII, auf Abfrage (Metex/Voltcraft) - + 11 bytes ASCII, continuous (PeakTech 451) 11 Bytes ASCII, kontinuierlich (PeakTech 451) - + 14 bytes ASCII, continuous (Voltcraft) 14 Bytes ASCII, kontinuierlich (Voltcraft) - + 15 bytes ASCII, continuous (Voltcraft) 15 Bytes ASCII, kontinuierlich (Voltcraft) - + 11 bytes binary, continuous (M9803R) 11 Bytes binär, kontinuierlich (M9803R) - + 14 bytes binary, continuous (VC820) 14 Bytes binär, kontinuierlich (VC820) @@ -930,27 +930,27 @@ Danach müssen Sie sich ab- und wieder anmelden. 22 Bytes ASCII, kontinuierlich (IsoTech) - + 11 bytes binary, continuous (VC940) 11 Bytes binär, kontinuierlich (VC940) - + 14 bytes ASCII/binary, continuous (QM1537) 14 Bytes ASCII/Binär, kontinuierlich (QM1537) - + 9 bytes binary, continuous (RS 22-812) 9 Bytes binär, kontinuierlich (RS 22-812) - + &Number of values: &Anzahl der Werte: - + Some multimeter send several lines of data containing different measured values. As QtDMM only shows one variable here you can set the number of lines to be ignored for each measurement (That means that QtDMM only uses the first line). Einige Multimeter senden verschiedenen Zeile mit verschiedenen Messwerten. Hier kann die Anzahl der zu ignorieren Zeilen eingetragen werden.( Das bedeutet, QtDMM verarbeitet nur die erste Zeile). diff --git a/src/instancesdlg.cpp b/src/instancesdlg.cpp index 3a9bfb6..3bce2b6 100644 --- a/src/instancesdlg.cpp +++ b/src/instancesdlg.cpp @@ -4,9 +4,9 @@ #include "instancesdlg.h" -InstancesDlg::InstancesDlg(Settings *settings, QString session_id, QString config_path, QWidget *parent) +InstancesDlg::InstancesDlg(Settings *settings, QString instance_id, QString config_path, QWidget *parent) : QDialog(parent) - , m_sessionId(session_id.isEmpty() ? "default" : session_id) + , m_instanceId(instance_id.isEmpty() ? "default" : instance_id) , m_configPath(config_path) , m_settings(settings) { @@ -38,12 +38,12 @@ void InstancesDlg::updateInstancesListBox() QPushButton *btn = new QPushButton(instanceId, ui_instancesList); btn->setProperty("instanceId", instanceId); QFont font = btn->font(); - if (instanceId != m_sessionId) + if (instanceId != m_instanceId) font.setBold(true); font.setPointSize(font.pointSize() + 2); btn->setFont(font); - if (instanceId == m_sessionId || (m_onDelete && m_instancesOnline.contains(instanceId))) + if (instanceId == m_instanceId || (m_onDelete && m_instancesOnline.contains(instanceId))) btn->setEnabled(false); else if (m_onDelete) { @@ -74,7 +74,7 @@ void InstancesDlg::onInstanceButtonClicked() QString configId = btn->property("instanceId").toString(); QString exePath = QCoreApplication::applicationFilePath(); - if (configId == m_sessionId) + if (configId == m_instanceId) return; if (m_instancesOnline.contains(configId)) diff --git a/src/instancesdlg.h b/src/instancesdlg.h index 2e658b7..77274ce 100644 --- a/src/instancesdlg.h +++ b/src/instancesdlg.h @@ -8,7 +8,7 @@ class InstancesDlg : public QDialog, private Ui::UIInstancesDlg { Q_OBJECT public: - InstancesDlg(Settings *settings, QString session_id, QString config_path, QWidget *parent = Q_NULLPTR); + InstancesDlg(Settings *settings, QString instance_id, QString config_path, QWidget *parent = Q_NULLPTR); void setInstancesOnline(QStringList instances); void updateInstancesListBox(); @@ -17,7 +17,7 @@ class InstancesDlg : public QDialog, private Ui::UIInstancesDlg QStringList m_instancesOnline; QStringList m_instancesConfigured; QString m_configPath; - QString m_sessionId; + QString m_instanceId; Settings *m_settings; bool m_onDelete; diff --git a/src/mainwid.cpp b/src/mainwid.cpp index 1ade6f1..89d0a15 100644 --- a/src/mainwid.cpp +++ b/src/mainwid.cpp @@ -34,7 +34,7 @@ #include "settings.h" #include "instancesdlg.h" -MainWid::MainWid(QString session_id, QString config_path, QWidget *parent) : QFrame(parent), +MainWid::MainWid(QString instance_id, QString config_path, QWidget *parent) : QFrame(parent), m_display(0), m_tipDlg(0) { @@ -44,7 +44,7 @@ MainWid::MainWid(QString session_id, QString config_path, QWidget *parent) : QF m_dmm = new DMM(this); m_external = new QProcess(this); - m_settings = new Settings(session_id, config_path, this); + m_settings = new Settings(instance_id, config_path, this); m_configDlg = new ConfigDlg(m_settings, this); m_configDlg->hide(); m_configDlg->readPrinter(&m_printer); @@ -52,7 +52,7 @@ MainWid::MainWid(QString session_id, QString config_path, QWidget *parent) : QF m_printDlg = new qtdmm::PrintDlg(this); m_printDlg->hide(); - m_instancesDlg = new InstancesDlg(m_settings, session_id, config_path,this); + m_instancesDlg = new InstancesDlg(m_settings, instance_id, config_path,this); connect(m_instancesDlg, SIGNAL(writeState(const QString &)), parent, SLOT(sendStateSLOT(const QString &))); connect(m_dmm, SIGNAL(value(double, const QString &, const QString &, const QString &, const QString &, bool, bool, int)), diff --git a/src/mainwid.h b/src/mainwid.h index 149a53d..29ae397 100644 --- a/src/mainwid.h +++ b/src/mainwid.h @@ -42,7 +42,7 @@ class MainWid : public QFrame, private Ui::UIMainWid { Q_OBJECT public: - MainWid(QString session_id, QString config_path, QWidget *parent = Q_NULLPTR); + MainWid(QString instance_id, QString config_path, QWidget *parent = Q_NULLPTR); bool closeWin(); QRect winRect() const; bool saveWindowPosition() const; diff --git a/src/settings.cpp b/src/settings.cpp index 321569c..c1723ac 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -34,26 +34,26 @@ Settings::~Settings() delete m_tmpConfig; } -Settings::Settings(const QString &session_id, const QString &config_path, QObject *parent) +Settings::Settings(const QString &instance_id, const QString &config_path, QObject *parent) : Settings(parent) { QFileInfo fileInfo(m_qsettings->fileName()); m_configPath = fileInfo.absolutePath(); m_configBaseFileName = fileInfo.baseName(); m_configFileNameSuffix = fileInfo.suffix(); - m_sessionId = session_id.isEmpty() ? "default" : session_id; + m_instanceId = instance_id.isEmpty() ? "default" : instance_id; - if (!session_id.isEmpty() || !config_path.isEmpty()) + if (!instance_id.isEmpty() || !config_path.isEmpty()) { m_configPath = config_path.isEmpty() ? fileInfo.absolutePath() : config_path; m_configBaseFileName = fileInfo.baseName(); m_configFileNameSuffix = fileInfo.suffix(); - QString session_fileName = m_configBaseFileName+(session_id.isEmpty() ? "" : "_"+session_id)+"."+m_configFileNameSuffix; - session_fileName.prepend(m_configPath+"/"); + QString instance_fileName = m_configBaseFileName+(instance_id.isEmpty() ? "" : "_"+instance_id)+"."+m_configFileNameSuffix; + instance_fileName.prepend(m_configPath+"/"); delete m_qsettings; - m_qsettings = new QSettings(session_fileName, QSettings::IniFormat, this); + m_qsettings = new QSettings(instance_fileName, QSettings::IniFormat, this); QFile file(m_qsettings->fileName()); m_fileExists = file.exists(); m_filename = m_qsettings->fileName(); @@ -73,7 +73,7 @@ QStringList Settings::getConfigInstances() .arg(m_configFileNameSuffix.isEmpty() ? "" : "." + m_configFileNameSuffix); QStringList result; - result << m_sessionId; + result << m_instanceId; for (const QString &file : dir.entryList({ pattern }, QDir::Files, QDir::Name)) { QString base = QFileInfo(file).completeBaseName(); @@ -157,12 +157,12 @@ void Settings::clear() } -void Settings::deleteConfig(QString session_id) +void Settings::deleteConfig(QString instance_id) { - if(session_id.isEmpty()) + if(instance_id.isEmpty()) return; - QFile configFile(m_configPath+"/"+m_configBaseFileName+"_"+session_id+"."+m_configFileNameSuffix); + QFile configFile(m_configPath+"/"+m_configBaseFileName+"_"+instance_id+"."+m_configFileNameSuffix); configFile.remove(); } diff --git a/src/settings.h b/src/settings.h index 9d852b1..651f2cc 100644 --- a/src/settings.h +++ b/src/settings.h @@ -25,14 +25,14 @@ class Settings : public QObject Q_OBJECT public: explicit Settings(QObject *parent = Q_NULLPTR); - explicit Settings(const QString &session_id, const QString &config_path, QObject *parent = Q_NULLPTR); + explicit Settings(const QString &instance_id, const QString &config_path, QObject *parent = Q_NULLPTR); ~Settings(); const bool &fileExists() const { return m_fileExists; } const bool &fileConverted() const { return m_fileConverted; } const QString &fileName() const { return m_filename; } - void deleteConfig(QString session_id); + void deleteConfig(QString instance_id); QStringList getConfigInstances(); void save(); @@ -58,6 +58,6 @@ class Settings : public QObject QString m_configPath; QString m_configBaseFileName; QString m_configFileNameSuffix; - QString m_sessionId; + QString m_instanceId; QHash *m_tmpConfig; }; diff --git a/src/ui/uidmmprefs.ui b/src/ui/uidmmprefs.ui index cf617c7..7cf620e 100644 --- a/src/ui/uidmmprefs.ui +++ b/src/ui/uidmmprefs.ui @@ -40,6 +40,9 @@ Here you may select your DMM model. If your DMM is not in the list, try to find working settings and mail them to me (<font color=blue><u>qtdmm@mtoussaint.de</u></font>). So I can add them to the list in the next release. + + false + From 75e3931fabdb1a57e621e300b520f6a7f830f5bd Mon Sep 17 00:00:00 2001 From: Sarah Mischke Date: Sun, 10 Aug 2025 23:35:05 +0200 Subject: [PATCH 5/8] update icons and some multi instance refinement --- QtDMM.spec | 2 +- assets/icons/add.xpm | 465 ++++++++++++++++++++++++++++++++ assets/icons/instances.xpm | 199 ++++++++++++++ assets/icons/menu.xpm | 10 +- assets/icons/remove.xpm | 289 ++++++++++++++++++++ assets/translations/qtdmm_de.ts | 171 +++++++----- compile.sh | 2 +- src/guiprefs.cpp | 4 +- src/mainwid.cpp | 6 +- src/mainwid.h | 1 + src/mainwin.cpp | 2 + src/resources.qrc | 3 + src/sharedstatemanager.cpp | 7 +- src/ui/uiinstancesdlg.ui | 16 +- src/ui/uimainwin.ui | 40 ++- 15 files changed, 1129 insertions(+), 88 deletions(-) create mode 100644 assets/icons/add.xpm create mode 100644 assets/icons/instances.xpm create mode 100644 assets/icons/remove.xpm diff --git a/QtDMM.spec b/QtDMM.spec index 3a5e0c3..d2b4594 100644 --- a/QtDMM.spec +++ b/QtDMM.spec @@ -1,5 +1,5 @@ Name: qtdmm -Version: 1.0.0-alpha.1-8-g602d80f+602d80f +Version: 1.0.0-alpha.1-9-ge775322+e775322 Release: 1%{?dist} Summary: DMM Readout Software Including a Configurable Recorder. diff --git a/assets/icons/add.xpm b/assets/icons/add.xpm new file mode 100644 index 0000000..74c723a --- /dev/null +++ b/assets/icons/add.xpm @@ -0,0 +1,465 @@ +/* XPM */ +static char * add_xpm[] = { +"32 32 430 2", +" c None", +". c #81CB74", +"+ c #57BA43", +"@ c #39AD1E", +"# c #3CB020", +"$ c #52BA37", +"% c #8ED27A", +"& c #ABDAA3", +"* c #DEEFDA", +"= c #8FCE82", +"- c #34A91C", +"; c #38AB1E", +"> c #76C560", +", c #D2EBCB", +"' c #D3EDCC", +") c #3EA92D", +"! c #9AD091", +"~ c #E3EDE2", +"{ c #C2E4B8", +"] c #AADC9B", +"^ c #B3DEA6", +"/ c #F1F5F0", +"( c #B4DDA8", +"_ c #72C55A", +": c #279C17", +"< c #5DB451", +"[ c #BEE2B6", +"} c #B0EC8D", +"| c #ABEB86", +"1 c #AEDBA2", +"2 c #67BC50", +"3 c #46B128", +"4 c #1F9610", +"5 c #229712", +"6 c #91D083", +"7 c #A1E580", +"8 c #A1D893", +"9 c #3BA81F", +"0 c #40AB21", +"a c #1C910F", +"b c #1F9210", +"c c #8BCE7D", +"d c #98E07A", +"e c #9CD58F", +"f c #38A31E", +"g c #3DA720", +"h c #1A8D0D", +"i c #1D8E0F", +"j c #88CB7B", +"k c #8FDC74", +"l c #97D38A", +"m c #359F1B", +"n c #39A31E", +"o c #18890C", +"p c #1A8A0E", +"q c #85C979", +"r c #87D76E", +"s c #87D86E", +"t c #93D087", +"u c #329B1A", +"v c #369F1C", +"w c #15850B", +"x c #18860D", +"y c #81C776", +"z c #7ED268", +"A c #7FD268", +"B c #7FD368", +"C c #8ECE83", +"D c #2F9819", +"E c #339C1B", +"F c #12800A", +"G c #16830C", +"H c #7FC575", +"I c #78CE63", +"J c #78CF63", +"K c #8ACC7F", +"L c #2C9418", +"M c #309819", +"N c #58AE58", +"O c #188D18", +"P c #037E01", +"Q c #057C03", +"R c #077B03", +"S c #097B05", +"T c #0C7A06", +"U c #0E7C07", +"V c #117D09", +"W c #147E0B", +"X c #7DC473", +"Y c #72CB5E", +"Z c #72CC5E", +"` c #73CC5E", +" . c #86C97B", +".. c #2A9016", +"+. c #2D9417", +"@. c #32991A", +"#. c #369E1C", +"$. c #3BA11F", +"%. c #3FA622", +"&. c #44AA24", +"*. c #49B027", +"=. c #5EBA3D", +"-. c #8DD172", +";. c #70BA70", +">. c #74BA74", +",. c #2E942E", +"'. c #017B01", +"). c #037802", +"!. c #067802", +"~. c #077704", +"{. c #0A7705", +"]. c #0C7806", +"^. c #0E7908", +"/. c #127B09", +"(. c #79C070", +"_. c #6CC85A", +":. c #6DC95B", +"<. c #6EC95B", +"[. c #81C675", +"}. c #288E14", +"|. c #2B9116", +"1. c #2F9618", +"2. c #339A1B", +"3. c #389F1E", +"4. c #3DA320", +"5. c #41A923", +"6. c #46AD25", +"7. c #6ABE4C", +"8. c #9CD487", +"9. c #9FD888", +"0. c #1F931F", +"a. c #50A950", +"b. c #89C389", +"c. c #89C486", +"d. c #7ABE75", +"e. c #79BD74", +"f. c #78BE73", +"g. c #77BE72", +"h. c #77BF71", +"i. c #76BE70", +"j. c #75BE6D", +"k. c #76BF6D", +"l. c #80C976", +"m. c #68C656", +"n. c #6AC756", +"o. c #6AC757", +"p. c #6BC857", +"q. c #86CC79", +"r. c #7FC571", +"s. c #82C775", +"t. c #86C97A", +"u. c #8ACB7F", +"v. c #8ECD84", +"w. c #91D088", +"x. c #97D28C", +"y. c #9ED595", +"z. c #A3D499", +"A. c #A6D696", +"B. c #87CE6C", +"C. c #6EC848", +"D. c #028402", +"E. c #1F8E1F", +"F. c #85C283", +"G. c #5BB64F", +"H. c #57B74B", +"I. c #57B94B", +"J. c #57BB4B", +"K. c #57BD4B", +"L. c #59BE4C", +"M. c #5BBF4D", +"N. c #5EC14F", +"O. c #60C250", +"P. c #62C351", +"Q. c #64C452", +"R. c #65C553", +"S. c #66C653", +"T. c #67C653", +"U. c #65C552", +"V. c #63C451", +"W. c #5DC04E", +"X. c #64C257", +"Y. c #6FC368", +"Z. c #4AAD47", +"`. c #038303", +" + c #7FC274", +".+ c #65C044", +"++ c #57C02F", +"@+ c #008200", +"#+ c #007B00", +"$+ c #60AF5C", +"%+ c #50B046", +"&+ c #50B246", +"*+ c #50B546", +"=+ c #50B746", +"-+ c #51B846", +";+ c #54BA48", +">+ c #56BC49", +",+ c #5ABE4B", +"'+ c #5CBF4C", +")+ c #5FC14E", +"!+ c #61C24F", +"~+ c #63C350", +"{+ c #64C451", +"]+ c #64C350", +"^+ c #62C350", +"/+ c #66C454", +"(+ c #7BCB6E", +"_+ c #6CC263", +":+ c #46B040", +"<+ c #058F02", +"[+ c #008900", +"}+ c #008300", +"|+ c #59B04C", +"1+ c #4EB72A", +"2+ c #54BC2C", +"3+ c #008100", +"4+ c #007900", +"5+ c #58A955", +"6+ c #49AC41", +"7+ c #49AE41", +"8+ c #49B041", +"9+ c #49B341", +"0+ c #4BB542", +"a+ c #4EB744", +"b+ c #51B945", +"c+ c #55BB47", +"d+ c #58BD49", +"e+ c #5BBF4B", +"f+ c #5EC14C", +"g+ c #60C24D", +"h+ c #62C34E", +"i+ c #7BCD6B", +"j+ c #7BCD6C", +"k+ c #73C764", +"l+ c #5DBB4E", +"m+ c #27A218", +"n+ c #1A9B0D", +"o+ c #109508", +"p+ c #079004", +"q+ c #008B00", +"r+ c #008400", +"s+ c #55AF48", +"t+ c #4BB428", +"u+ c #52BB2B", +"v+ c #008000", +"w+ c #007700", +"x+ c #479C45", +"y+ c #20911D", +"z+ c #259821", +"A+ c #2A9F25", +"B+ c #31A52C", +"C+ c #3AAC33", +"D+ c #45B33D", +"E+ c #53B947", +"F+ c #57BA47", +"G+ c #5BBC4B", +"H+ c #5FC04E", +"I+ c #67C255", +"J+ c #65C151", +"K+ c #5ABD44", +"L+ c #40B124", +"M+ c #38AD1D", +"N+ c #34AB1B", +"O+ c #2EA818", +"P+ c #27A415", +"Q+ c #1E9E10", +"R+ c #14980A", +"S+ c #0A9205", +"T+ c #008C00", +"U+ c #008500", +"V+ c #5BB34C", +"W+ c #49B327", +"X+ c #4FB929", +"Y+ c #007500", +"Z+ c #0C740C", +"`+ c #378E37", +" @ c #328E32", +".@ c #328F32", +"+@ c #329132", +"@@ c #349234", +"#@ c #389535", +"$@ c #3C9638", +"%@ c #409A39", +"&@ c #449D3C", +"*@ c #4CAB3E", +"=@ c #33AB1B", +"-@ c #3AAF1E", +";@ c #3EB221", +">@ c #41B323", +",@ c #5DB647", +"'@ c #56AD44", +")@ c #55AD44", +"!@ c #53AD43", +"~@ c #50AD41", +"{@ c #4CAC40", +"]@ c #4AAB3E", +"^@ c #47AA3C", +"/@ c #53AE45", +"(@ c #48B02C", +"_@ c #46B226", +":@ c #4DB828", +"<@ c #006B00", +"[@ c #006500", +"}@ c #006000", +"|@ c #005E00", +"1@ c #005D00", +"2@ c #015F00", +"3@ c #036001", +"4@ c #056202", +"5@ c #066503", +"6@ c #449D39", +"7@ c #38AE1E", +"8@ c #40B222", +"9@ c #46B625", +"0@ c #4AB827", +"a@ c #55AB42", +"b@ c #197D0D", +"c@ c #1D810F", +"d@ c #218611", +"e@ c #248B13", +"f@ c #289015", +"g@ c #2C9517", +"h@ c #309A19", +"i@ c #359F1C", +"j@ c #3AA51F", +"k@ c #44B125", +"l@ c #006300", +"m@ c #005B00", +"n@ c #005A00", +"o@ c #005C00", +"p@ c #015D01", +"q@ c #036002", +"r@ c #056203", +"s@ c #409A34", +"t@ c #45B524", +"u@ c #4CBA28", +"v@ c #51BD2B", +"w@ c #54AB3F", +"x@ c #187C0D", +"y@ c #1B810E", +"z@ c #1E8510", +"A@ c #228A12", +"B@ c #268F14", +"C@ c #2A9416", +"D@ c #2E9918", +"E@ c #339E1A", +"F@ c #38A41E", +"G@ c #3DAA20", +"H@ c #035E01", +"I@ c #046102", +"J@ c #3C9730", +"K@ c #3EB121", +"L@ c #49B826", +"M@ c #52BD2B", +"N@ c #59C12F", +"O@ c #52AA3D", +"P@ c #167B0C", +"Q@ c #1A800E", +"R@ c #015B01", +"S@ c #035F01", +"T@ c #37952B", +"U@ c #3DB120", +"V@ c #49B827", +"W@ c #55BF2D", +"X@ c #5FC532", +"Y@ c #52AA39", +"Z@ c #147A0B", +"`@ c #187F0D", +" # c #005900", +".# c #025E01", +"+# c #309026", +"@# c #38AE1D", +"## c #53BE2C", +"$# c #60C633", +"%# c #52AB38", +"&# c #137A0A", +"*# c #177F0C", +"=# c #015C01", +"-# c #278C1F", +";# c #2FA819", +"># c #3BB01F", +",# c #47A531", +"'# c #127A0A", +")# c #157F0B", +"!# c #1D8617", +"~# c #21A011", +"{# c #2BA617", +"]# c #3CB01F", +"^# c #349B24", +"/# c #107B09", +"(# c #14800A", +"_# c #11810F", +":# c #0F9508", +"<# c #16990C", +"[# c #1D9D0F", +"}# c #1F9F10", +"|# c #209016", +"1# c #0F7D07", +"2# c #138209", +"3# c #046003", +"4# c #12690A", +"5# c #268416", +"6# c #028D01", +"7# c #068F03", +"8# c #258A23", +"9# c #1B7B15", +"0# c #13810B", +"a# c #0D6C08", +"b# c #3F821E", +"c# c #719728", +"d# c #2D8613", +"e# c #047A04", +"f# c #057D04", +"g# c #3A9239", +"h# c #4B8948", +"i# c #267B21", +"j# c #147F0D", +"k# c #609925", +"l# c #82A62B", +"m# c #42911E", +"n# c #027701", +"o# c #047B02", +"p# c #69A567", +"q# c #4D904B", +"r# c #278123", +"s# c #65AB2A", +"t# c #2E9218", +"u# c #038301", +"v# c #6CAE6A", +"w# c #549951", +" ", +" . + @ # $ % ", +" & * = - ; > , ' ", +" ) ! ~ { ] ] ^ / ( _ ", +" : < [ } | | | 1 2 3 ", +" 4 5 6 7 7 7 7 8 9 0 ", +" a b c d d d d e f g ", +" h i j k k k k l m n ", +" o p q r s s s t u v ", +" w x y z A B B C D E ", +" F G H I J J J K L M ", +" N O P Q R S T U V W X Y Z ` ` ...+.@.#.$.%.&.*.=.-. ", +" ;.>.,.'.).!.~.{.].^./.(._.:.<.<.[.}.|.1.2.3.4.5.6.7.8.9. ", +" 0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C. ", +" D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.T.S.U.V.O.W.X.Y.Z.`. +.+++ ", +" @+#+$+%+&+*+=+-+;+>+,+'+)+!+~+{+{+{+]+^+/+(+_+:+<+[+}+|+1+2+ ", +" 3+4+5+6+7+8+9+0+a+b+c+d+e+f+g+h+m.i+j+k+l+m+n+o+p+q+r+s+t+u+ ", +" v+w+x+y+z+A+B+C+D+=+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U+V+W+X+ ", +" v+Y+Z+`+ @.@+@@@#@$@%@&@*@=@-@;@>@,@'@)@)@!@~@{@]@^@/@(@_@:@ ", +" Y+<@[@}@|@1@|@2@3@4@5@6@7@8@9@0@a@b@c@d@e@f@g@h@i@j@0 k@ ", +" <@l@1@m@n@n@o@p@q@r@s@# t@u@v@w@x@y@z@A@B@C@D@E@F@G@ ", +" H@I@J@K@L@M@N@O@P@Q@ ", +" R@S@T@U@V@W@X@Y@Z@`@ ", +" #.#+#@#9@##$#%#&#*# ", +" #=#-#;#>#L@W@,#'#)# ", +" #1@!#~#{#N+]#^#/#(# ", +" n@|@_#:#<#[#}#|#1#2# ", +" 3#4#5#q+6#<+7#8#9#0# ", +" a#b#c#d#e#f#g#h#i#j# ", +" k#l#m#n#o#p#q#r# ", +" s#t#v+u#v#w# ", +" "}; diff --git a/assets/icons/instances.xpm b/assets/icons/instances.xpm new file mode 100644 index 0000000..cd49b14 --- /dev/null +++ b/assets/icons/instances.xpm @@ -0,0 +1,199 @@ +/* XPM */ +static char * instances_xpm[] = { +"32 32 164 2", +" c None", +". c #D68504", +"+ c #000000", +"@ c #563D06", +"# c #D38D06", +"$ c #915906", +"% c #7F5309", +"& c #F2BB0E", +"* c #875208", +"= c #DE9506", +"- c #7F7F7F", +"; c #86827D", +"> c #8B867C", +", c #8B887C", +"' c #CA954A", +") c #F5CB35", +"! c #B9774A", +"~ c #FFE840", +"{ c #C18046", +"] c #EABA24", +"^ c #E8AA18", +"/ c #595959", +"( c #84654F", +"_ c #CE922B", +": c #B77E3A", +"< c #AC6738", +"[ c #FFE655", +"} c #F6CE3B", +"| c #FFEA64", +"1 c #F4CD3B", +"2 c #FFEE60", +"3 c #AE6100", +"4 c #DC8C03", +"5 c #E3A115", +"6 c #1C1401", +"7 c #794A03", +"8 c #F7E05F", +"9 c #FADF5E", +"0 c #FAE062", +"a c #FFEA77", +"b c #FFEA76", +"c c #FDE568", +"d c #F7D757", +"e c #FFEC68", +"f c #DB8F0F", +"g c #C0D8C1", +"h c #C1D8C0", +"i c #C3D5BB", +"j c #C8A17C", +"k c #F9E165", +"l c #FFF18C", +"m c #FFF08B", +"n c #FFF08C", +"o c #FDE871", +"p c #CE7200", +"q c #B6CBB5", +"r c #804F00", +"s c #C59C00", +"t c #FDEB45", +"u c #FFFAA4", +"v c #FFF6A9", +"w c #FFF6A5", +"x c #FFF6A3", +"y c #FFF9A8", +"z c #FFF254", +"A c #F7CA00", +"B c #DC9402", +"C c #323232", +"D c #CDE0CE", +"E c #C1D8C1", +"F c #C6D6BD", +"G c #D09838", +"H c #F9CF00", +"I c #FFDF0E", +"J c #FFE329", +"K c #FFE531", +"L c #FFE32A", +"M c #FFDF11", +"N c #FDD600", +"O c #E5A83A", +"P c #A25E05", +"Q c #2D2D2D", +"R c #D0E1D1", +"S c #494949", +"T c #B5A287", +"U c #EEC212", +"V c #FFE700", +"W c #FFDF00", +"X c #FFDE00", +"Y c #FFDD00", +"Z c #FFE600", +"` c #F5CD0D", +" . c #A1620C", +".. c #303030", +"+. c #CEDFCF", +"@. c #A79986", +"#. c #DAB369", +"$. c #E6C25C", +"%. c #DC9D4C", +"&. c #FBD800", +"*. c #FEE100", +"=. c #FFE200", +"-. c #FFE201", +";. c #FFE400", +">. c #CC8A3A", +",. c #E9BA33", +"'. c #E3A700", +"). c #141414", +"!. c #C3D9C4", +"~. c #68645F", +"{. c #534D44", +"]. c #676560", +"^. c #E1C17A", +"/. c #E5CC00", +"(. c #D69A48", +"_. c #FFF000", +":. c #C78A2E", +"<. c #EDD011", +"[. c #DCB043", +"}. c #C1D8C2", +"|. c #C1D9C2", +"1. c #C3D9C3", +"2. c #D7C283", +"3. c #C3D7BD", +"4. c #D2D0B4", +"5. c #E9CA00", +"6. c #8C7C6B", +"7. c #74634B", +"8. c #C79704", +"9. c #C2D9C3", +"0. c #CCDDCA", +"a. c #E1D1A9", +"b. c #C0D4BF", +"c. c #BCC3B1", +"d. c #B68207", +"e. c #5F5F5D", +"f. c #4F504F", +"g. c #B4976F", +"h. c #BBCFBC", +"i. c #C1D6C3", +"j. c #D4DFD5", +"k. c #4C4337", +"l. c #5E5F60", +"m. c #828386", +"n. c #BED4BF", +"o. c #C2D8C3", +"p. c #C4DAC6", +"q. c #C9DBCB", +"r. c #121213", +"s. c #5B5B5B", +"t. c #424242", +"u. c #383939", +"v. c #121212", +"w. c #181919", +"x. c #181819", +"y. c #3A3A3A", +"z. c #0A0A0B", +"A. c #FF0000", +"B. c #FFFFFF", +"C. c #969696", +"D. c #FFEE00", +"E. c #0019FF", +"F. c #C4C4C4", +"G. c #0022FF", +" . ", +" + + + + + + + + + + + + + + + @ # $ % & * = ", +" + - - - - - - - - - - - - - ; > , ' ) ! ~ { ] ^ ", +" + - / / / / / / / / / / / / / ( _ : < [ } | 1 2 3 4 5 ", +" + - / + + + + + + + + + + + + 6 7 8 9 0 a b a c d e f ", +" + - / + g g g g g g g g g g h h i j k l m m m n o p ", +" + - / + g + + + g g g + g + q r s t u v w x w v y z A B ", +" + - / + g g g + g g g + g C D E F G H I J K L M N O P ", +" + - / + g + + + g g g + + Q R S T U V W X X X Y Z ` . ", +" + - / + g g g + g g g g g ..+.@.#.$.%.&.*.=.-.;.>.,.'. ", +" + - / + g + + + g + g g g ).!.~.{.].^./.(._.:.<.[. ", +" + - / + g g g g g g g g g g g }.|.1.2.3.4.5.6.7.8. ", +" + - / + g + g + g + g + g g g g 9.0.a.b.c.d.e.f.g. ", +" + - / + g + g + g + g + g g g g |.9.h.i.j.k./ l.m. ", +" + - / + g g g g g g g g g g g g g n.o.p.q.r.s.t.u. ", +" + - / + + + + + + + + + + + + + + v.w.x.r.r./ y.z. ", +" + - / / / / / / / / / / / / / / / / / / / / / y.+ ", +" + - / A.A./ / / / / / / / / / / / / / / / / / / + ", +" + - A.B.A.A./ / / / / / / + + + + + + + + + + y.+ ", +" + - A.B.B.A./ / / / + + + C.C.C.C.C.C.C.C.C.C.y.+ ", +" + - / A.A./ / + + + C.C.C.C.C.C.D.C.C.C.E.E.C.y.+ ", +" + / / / / + + C.C.C.C.C.C.C.C.D.D.D.C.E.E.E.E.y.+ ", +" + - + + + C.C.C.C.C.F.F.C.C.F.C.C.C.C.E.E.E.E.y.+ ", +" + - C.C.C.C.C.F.C.C.C.C.C.C.C.C.C.C.F.C.E.E.C.y.+ ", +" + - D.C.C.C.C.C.C.D.D.D.F.F.F.F.C.C.F.C.C.C.C.y.+ ", +" + - D.C.F.C.C.F.F.D.D.D.F.F.F.F.F.F.C.C.C.C.C.y.+ ", +" + - D.F.C.C.F.F.F.+ + + + + + + F.F.G.C.C.F.C.y.+ ", +" + - D.C.C.F.F.F.+ + + + + + + + + G.G.G.C.F.C.y.+ ", +" + - D.C.C.F.F.+ B.+ y.y.y.y.y.+ + + G.G.C.C.C.y.+ ", +" + - D.C.A.A.+ + y.B.).y.y.y.y.y.+ + + G.G.C.C.y.+ ", +" + - D.C.A.A.+ + y.).).).y.y.y.y.y.+ + G.G.C.C.y.+ ", +" y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y. "}; diff --git a/assets/icons/menu.xpm b/assets/icons/menu.xpm index 17e0bec..6f08e88 100644 --- a/assets/icons/menu.xpm +++ b/assets/icons/menu.xpm @@ -31,27 +31,27 @@ static char * menu_xpm[] = { " ", " .++++++++++++++++++++++. ", " @#########$%&*=-;>,''''@ ", +" @#########$%&*=-;>,''''@ ", " )#######!~{]^/;(_'''''') ", " :::::::::::::::::::::::: ", " ", " ", " ", +" ", +" ", " ++++++++++++++++++++++++ ", " @#########$%&*=-;>,''''@ ", +" @#########$%&*=-;>,''''@ ", " )#######!~{]^/;(_'''''') ", " :::::::::::::::::::::::: ", " ", " ", " ", -" .++++++++++++++++++++++. ", -" @#########$%&*=-;>,''''@ ", -" )#######!~{]^/;(_'''''') ", -" :::::::::::::::::::::::: ", -" ", " ", " ", " ++++++++++++++++++++++++ ", " @#########$%&*=-;>,''''@ ", +" @#########$%&*=-;>,''''@ ", " )#######!~{]^/;(_'''''') ", " :::::::::::::::::::::::: ", " ", diff --git a/assets/icons/remove.xpm b/assets/icons/remove.xpm new file mode 100644 index 0000000..8add7d5 --- /dev/null +++ b/assets/icons/remove.xpm @@ -0,0 +1,289 @@ +/* XPM */ +static char * remove_xpm[] = { +"32 32 254 2", +" c None", +". c #B85E5E", +"+ c #9B1D1D", +"@ c #8D0000", +"# c #8E0000", +"$ c #8F0000", +"% c #910000", +"& c #930000", +"* c #960000", +"= c #990000", +"- c #9C0000", +"; c #A00000", +"> c #A40000", +", c #A80000", +"' c #AC0000", +") c #B10000", +"! c #B50000", +"~ c #BB0000", +"{ c #C00000", +"] c #C50000", +"^ c #CB0000", +"/ c #D10000", +"( c #D70000", +"_ c #DF1C1C", +": c #EB5C5C", +"< c #BF6E6E", +"[ c #C07373", +"} c #9D2D2D", +"| c #830000", +"1 c #840000", +"2 c #850000", +"3 c #860000", +"4 c #880000", +"5 c #8A0000", +"6 c #900000", +"7 c #970000", +"8 c #9B0000", +"9 c #A50000", +"0 c #AA0000", +"a c #AF0000", +"b c #B40000", +"c c #BA0000", +"d c #C10000", +"e c #C70000", +"f c #CD0000", +"g c #D30000", +"h c #E02C2C", +"i c #EB7070", +"j c #F06C6C", +"k c #9E2323", +"l c #AE4D4D", +"m c #CA8F8F", +"n c #CC8484", +"o c #BF5E5E", +"p c #C26262", +"q c #C36262", +"r c #C46262", +"s c #C56161", +"t c #C76161", +"u c #C86161", +"v c #CA6161", +"w c #CC6161", +"x c #CD6161", +"y c #CF6161", +"z c #D16161", +"A c #D36161", +"B c #D46161", +"C c #D66161", +"D c #D76161", +"E c #D86161", +"F c #D96161", +"G c #DA6060", +"H c #DA5D5D", +"I c #DD5F5F", +"J c #E36D6D", +"K c #DF8383", +"L c #E98484", +"M c #EC4D4D", +"N c #ED2222", +"O c #8F0505", +"P c #931E1E", +"Q c #C97F7F", +"R c #D25B5B", +"S c #D04E4E", +"T c #D45151", +"U c #D75050", +"V c #DA5050", +"W c #DD5050", +"X c #E05050", +"Y c #E25050", +"Z c #E45050", +"` c #E65050", +" . c #E75050", +".. c #E85050", +"+. c #E95050", +"@. c #E95151", +"#. c #E85151", +"$. c #E54F4F", +"%. c #E24D4D", +"&. c #E04C4C", +"*. c #DE5353", +"=. c #DE6161", +"-. c #D46363", +";. c #B43E3E", +">. c #8C1414", +",. c #CD5F5F", +"'. c #E92222", +"). c #E80404", +"!. c #890000", +"~. c #7E0000", +"{. c #B65555", +"]. c #C84848", +"^. c #C74343", +"/. c #CB4444", +"(. c #CF4444", +"_. c #D24444", +":. c #D64444", +"<. c #D94444", +"[. c #DC4444", +"}. c #DE4444", +"|. c #E04444", +"1. c #E24444", +"2. c #E44343", +"3. c #E54242", +"4. c #E54141", +"5. c #E44A4A", +"6. c #E45555", +"7. c #E05D5D", +"8. c #D55454", +"9. c #BE3131", +"0. c #A30808", +"a. c #850101", +"b. c #C03838", +"c. c #E50101", +"d. c #E60000", +"e. c #870000", +"f. c #7C0000", +"g. c #B35353", +"h. c #C84949", +"i. c #C74444", +"j. c #CF4343", +"k. c #D24343", +"l. c #D64242", +"m. c #D94242", +"n. c #DC4242", +"o. c #DF4242", +"p. c #E24242", +"q. c #E44444", +"r. c #E64646", +"s. c #E84A4A", +"t. c #E85454", +"u. c #E55555", +"v. c #DF4B4B", +"w. c #D43434", +"x. c #C51515", +"y. c #AB0000", +"z. c #A30000", +"A. c #9B0101", +"B. c #880101", +"C. c #BE3636", +"D. c #E30202", +"E. c #E40000", +"F. c #790000", +"G. c #A14242", +"H. c #AC2D2D", +"I. c #B22626", +"J. c #BE2E2E", +"K. c #C63333", +"L. c #CE3737", +"M. c #D43939", +"N. c #D93B3B", +"O. c #DD3C3C", +"P. c #E13D3D", +"Q. c #E43E3E", +"R. c #E63D3D", +"S. c #E73939", +"T. c #E63333", +"U. c #E42727", +"V. c #E01818", +"W. c #DA0808", +"X. c #CC0000", +"Y. c #BC0101", +"Z. c #B10303", +"`. c #A40202", +" + c #880A0A", +".+ c #C33535", +"++ c #E00000", +"@+ c #E20000", +"#+ c #7B1111", +"$+ c #8F2F2F", +"%+ c #922B2B", +"&+ c #962D2D", +"*+ c #9B2E2E", +"=+ c #A03030", +"-+ c #A53131", +";+ c #A93232", +">+ c #AD3232", +",+ c #B13131", +"'+ c #B52F2F", +")+ c #B82C2C", +"!+ c #BC2929", +"~+ c #BF2828", +"{+ c #C22727", +"]+ c #C42929", +"^+ c #C62C2C", +"/+ c #C72F2F", +"(+ c #C73030", +"_+ c #C62F2F", +":+ c #C42E2E", +"<+ c #C22E2E", +"[+ c #C02D2D", +"}+ c #BC2D2D", +"|+ c #C13131", +"1+ c #D51212", +"2+ c #DB0000", +"3+ c #E10000", +"4+ c #6D0000", +"5+ c #680000", +"6+ c #660202", +"7+ c #650101", +"8+ c #670000", +"9+ c #6A0000", +"0+ c #710000", +"a+ c #750101", +"b+ c #7A0101", +"c+ c #7E0202", +"d+ c #840202", +"e+ c #890202", +"f+ c #8E0202", +"g+ c #940101", +"h+ c #A20101", +"i+ c #A90101", +"j+ c #B00101", +"k+ c #B70101", +"l+ c #BF0101", +"m+ c #C70101", +"n+ c #CE0000", +"o+ c #D20000", +"p+ c #DA0000", +"q+ c #660000", +"r+ c #630000", +"s+ c #620000", +"t+ c #650000", +"u+ c #6B0000", +"v+ c #6F0000", +"w+ c #730000", +"x+ c #770000", +"y+ c #810000", +"z+ c #8B0000", +"A+ c #9D0000", +"B+ c #A90000", +"C+ c #BC0000", +"D+ c #C30000", +"E+ c #CA0000", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" . + @ @ @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : ", +" < [ } | 1 1 2 3 4 5 @ 6 & 7 8 ; 9 0 a b c d e f g h i j ", +" k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N ", +" O P Q R S T U V W X Y Z ` ...+.@.#. .$.%.&.*.=.-.;.>.,.'.). ", +" !.~.{.].^./.(._.:.<.[.}.|.1.2.2.3.4.2.5.6.7.8.9.0.& a.b.c.d. ", +" e.f.g.h.i./.j.k.l.m.n.o.p.q.r.s...t.u.v.w.x.! y.z.A.B.C.D.E. ", +" 2 F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.g X.] Y.Z.`.7 +.+++@+ ", +" | F.#+$+%+&+*+=+-+;+>+,+'+)+!+~+{+]+^+/+(+_+:+<+[+}+|+1+2+3+ ", +" F.4+5+6+7+7+7+8+9+4+0+a+b+c+d+e+f+g+A.h+i+j+k+l+m+n+o+p+ ", +" 4+q+r+s+r+t+5+u+v+w+x+f.y+3 z+% 7 A+z.B+a ! C+D+E+o+ ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/assets/translations/qtdmm_de.ts b/assets/translations/qtdmm_de.ts index fb8d08e..c58e06c 100644 --- a/assets/translations/qtdmm_de.ts +++ b/assets/translations/qtdmm_de.ts @@ -419,47 +419,47 @@ Ist das DMM angeschlossen und eingeschaltet? MainWid - + QtDMM: Unsaved data QtDMM: Ungesicherte Daten - + <font size=+2><b>Unsaved data</b></font><p>You still have unsaved measured data in memory. If you quit now it will be lost.<p>Do you want to export your unsaved data first? <font size=+2><b>Ungesicherte Daten</b></font><p>Es befinden sich ungesicherte Daten im Speicher. Wenn Sie das Programm beenden gehen diese verloren.<p>Sollen diese vorher exportiert werden? - + Export data first Daten erst exportieren - + Quit without saving Beenden ohne speichern - + Automatic start at %1 Automatisch starten bei %1 - + Raising threshold %1 Grenzwert steigent %1 - + Falling threshold %1 Grenzwert fallend %1 - + <font size=+2><b>Launch error</b></font><p>Application %1 is still running!<p>Do you want to kill it now? <font size=+2><b>Startfehler</b></font><p>Programm %s läuft noch!<p>Wollen sie es jetzt beenden? - + <font size=+2><b>Launch error</b></font><p>Couldn't launch %1 <font size=+2><b>Startfehler</b></font><p>Konnte %1 nicht starten @@ -468,18 +468,18 @@ Ist das DMM angeschlossen und eingeschaltet? <font size=+2><b>Startfehler</b></font><p>Programm %s is still running!<p>Do you want to kill it now - + Launched %1 %1 gestartet - + %1 terminated with exit code %2. %1 mit dem Rückgabecode %2 beendet. - - + + QtDMM: Launch error QtDMM: Startfehler @@ -488,17 +488,17 @@ Ist das DMM angeschlossen und eingeschaltet? <font size=+2><b>Startfehler</b></font><p>Programm %1 läuft noch.<p>Soll es getötet werden - + Yes, kill it! Ja, töten! - + No, keep running Nein, es laufen lassen - + Bummer! Reinfall! @@ -506,17 +506,17 @@ Ist das DMM angeschlossen und eingeschaltet? MainWin - + QtDMM: Welcome! QtDMM: Willkommen! - + <h1>QtDMM %1</h1><hr><div align=right><i>A simple recorder for DMM's</i></div><p><div align=justify>A simple display software for a variety of digital multimeter. Currently confirmed are:<table>%2</table>Other compatible models may work also.<p>QtDMM features min/max memory and a configurable recorder with import/export and printing function. Sampling may be started manually, at a given time or triggered by a measured threshold. Additionally an external program may be started when given thresholds are reached.</div><div align=justify><b>QtDMM</b> uses the platform independent toolkit <b>Qt</b> version %3 and is licensed under <b>GPL 3</b> (Versions prior to v0.9.0 where licensed under GPL 2)</div><br>&copy; 2001-2014 Matthias Toussaint &nbsp;-&nbsp;&nbsp;<font color=blue><u><a href='mailto:qtdmm@mtoussaint.de'>qtdmm@mtoussaint.de</a></u></font><p><br>The icons (except the DMM icon) have been taken from the KDE project.<p> <h1>QtDMM %1</h1><hr><div align=right><i>Ein einfacher Datenrekorder für DMM</i></div><p><div align=justify>Ein einfaches Anzeigeprogramm für eine Vielzahl von DMM's. Aktuell bestätigt sind:<table>%2</table>Andere kompatible Modelle sollten ebenfalls funktionieren.<p>QtDMM stellt die Funktionen Min/Max Werte halten, ein konfigurierbaren Datenrekorder mit Daten im/export Funktion sowie ein Druckfunktion zur Verfügung. Die Datenaufzeichnung kann manuell, durch einen Grenzwert oder durch eine Zeitfunktion ausgelöst werden. Desweiteren kann ein externes Programm beim erreichen eines Grenzwertes gestartet werden.</div><div align=justify><b>QtDMM</b> wurde mit der Platformunabhängigen <b>Qt</b> Bibliothek in der Version %3 welche unter der <b>GPLv3</b> lizensiert ist erstellt.(Versionen vor 0.9.0 wurden unter der GPLv2 Lizenz veröffentlicht)</div><br>&copy; 2001-2014 Matthias Toussaint &nbsp;-&nbsp;&nbsp;<font color=blue><u><a href='mailto:qtdmm@mtoussaint.de'>qtdmm@mtoussaint.de</a></u></font><p><br>Die Symbole (bis auf das DMM Symbol) stammen von dem KDE Projekt.<p> - + Another instance is running. @@ -1327,12 +1327,12 @@ Der Wert kann auch mit einem Suffix wie m, u, n, p, k, M, G oder T angegeben wer UIInstancesDlg - Instances + Instance Manager - Choose instance to open + Choose instance to open, or add/remove instances @@ -1562,54 +1562,99 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar - + Recorder Rekorder - + File Datei - + + Export graph + + + + + Import graph + + + + + Print graph + + + + + Connect/Disconnect DMM + + + + + reset min/max + + + + + Start recording + + + + + Stop recording + + + + + Clear graph + Graphen löschen + + + Help Hilfe - - instances + + Ctrl+M - - open or create an instance + + Instances + + + + + Instance Manager - + Ctrl+N - + Display Anzeige - - - + + + Menu Menü - + &Export &Export - + <html><head/><body><p><span style=" font-weight:600;">Export recorder graph</span></p><p>Here you can export the recorded data as tab separated list. Each line contains the following values (separated by a tab character): date (dd.mm.yyyy) time (hh:mm:ss) value (float) unit.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Rekorder Graphen exportieren</span></p><p>Hier können die aufgezeichneten Daten als eine Liste durch Tabulatoren getrennt exportiert werden. Jede Zeile enthält die folgenden Werte (getrennt durch einen Tabulator): Datum (tt.mm.jjjj) Zeit (ss:mm:SS) Wert (Fließkomma) Einheit.</p></body></html> @@ -1618,22 +1663,22 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+E - + &Import - + <html><head/><body><p><span style=" font-weight:600;">Import data into recorder</span></p><p>Here you can import previously exported data files. QtDMM tries to do an educated guess if the file format is correct and rejects import of files which to not match.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Importiert Daten in den Rekorder</span></p><p>Hier können zuvor exportierte Daten importiert werden. QtDMM versucht das Format zu lesen und verweigert den Import von ungültigen Dateien.</p></body></html> - + &Print &Drucken - + <html><head/><body><p><span style=" font-weight:600;">Print recorder graph</span></p><p>A dialog will open where you can define a title and a comment for your printout. The printer itself can also be configured here. To be able to print you need at least one working postscript printer configured in your system. Printing into a file is also supported.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Rekorder Graphen drucken</span></p><p>Es öffnet sich ein Fenster,indem der Titel und ein Kommentar für den Ausdruck festgelegt werden kann. Der Drucker selbst kann hier auch ausgewält werden. Der Ausdruck in eine Datei(PDF) ist ebenfalls möglich.</p></body></html> @@ -1642,25 +1687,25 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+D - - + + &Configure &Konfigurieren - - - + + + <html><head/><body><p><span style=" font-weight:600;">Configure QtDMM</span></p><p>This will open QtDMM's configuration dialog. Here you can configure it's visual appearance and all options regarding the multimeter hardware and the recorder.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">QtDMM konfigurieren</span></p><p>Dies öffnen das Konfugurationsfenster für QtDMM. Hier kann die visuelle Erscheinung, alle Optionen die die Datenaufzeichnung betreffen sowie die Einstellungen für das DMM festgelegt werden.</p></body></html> - + &Quit &Beenden - + <html><head/><body><p><span style=" font-weight:600;">Quit QtDMM</span></p><p>If the recorder contains unsaved data QtDMM will give you the option to savve your data first.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">QtDMM Beenden</span></p><p>Wenn der Datenrekorder ungespeicherte Daten enthällt, haben Sie die Möglichkeit diese vorher zu speichern.</p></body></html> @@ -1669,12 +1714,12 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+B - + &Connect &Verbinden - + <html><head/><body><p><span style=" font-weight:600;">Connect to the Multimeter</span></p><p>This will establish the serial connection to the dmm. If not connected the serial port is free and can be used by other software.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Verbindung zum DMM herstellen</span></p><p>Die baut die serielle Verbindung zum DMM auf.</p></body></html> @@ -1683,12 +1728,12 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+V - + &Reset &Zurücksetzen - + <html><head/><body><p><span style=" font-weight:600;">Reset min/max values</span></p><p>The min/max values in the display will be reset. You can activate this option at any time. </p></body></html> <html><head/><body><p><span style=" font-weight:600;">Min/Max Werte zurücksetzen</span></p><p>Die Min/Max Werte in der Anzeige werden zurückgesetzt. Diese Option kann jederzeit aktiviert werden. </p></body></html> @@ -1697,12 +1742,12 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+Z - + &Start &Starten - + <html><head/><body><p><span style=" font-weight:600;">Start the recorder</span></p><p>If you are in manual mode this will start the recorder. Press F2 to set the recorder options.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Rekorder starten</span></p><p>Startet den Rekorder wenn sich dieser im manuellen Modus befindet. F2 drücken für die Rekordereinstellungen.</p></body></html> @@ -1711,12 +1756,12 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+S - + S&top &Anhalten - + <html><head/><body><p><span style=" font-weight:600;">Stop the recorder</span></p><p>The recorder will be stopped. This is independent from the start mode of the recorder. </p></body></html> <html><head/><body><p><span style=" font-weight:600;">Hällt den Rekorder an</span></p><p>Der Rekoder wird angehalten. Dies ist unabhängig von dem gewählten Startmodus. </p></body></html> @@ -1725,12 +1770,12 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+A - + &Clear &Löschen - + <html><head/><body><p><span style=" font-weight:600;">Clear the recorder graph</span></p><p>If the recorder is already started it will clear the graph and continue recording.</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Lösche den Graphen</span></p><p>Wenn der Rekorder läuft, wird der Graph gelöscht und es wird weiter aufgezeichnet.</p></body></html> @@ -1739,7 +1784,7 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Enf - + C&onfigure &Konfigurieren @@ -1748,7 +1793,7 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Strg+F2 - + &About Ü&ber @@ -1757,12 +1802,12 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar Ü&ber die Version - + <html><head/><body><p><span style=" font-weight:600;">Copyright information</span></p><p>Show copyright information and some blurb about QtDMM. </p></body></html> <html><head/><body><p><span style=" font-weight:600;">Urheber Information</span></p><p>Zeigt die Information zum Urheber sowie etwas Werbung zu QtDMM an. </p></body></html> - + &Tip of the day &Tipp des Tages @@ -1771,17 +1816,17 @@ Die maximale Auflösung für die Datensammlung liegt bei 1/10 Sekunde, bei Bedar &Tipp des Tages - + <html><head/><body><p>Show tip of the day.</p></body></html> <html><head/><body><p>Zeigt den Tipp des Tages an.</p></body></html> - + &Direct Help &Direkte Hilfe - + <html><head/><body><p><span style=" font-weight:600;">Direct Help</span></p><p>Enter the direct help mode. You have done this already when reading this text :)</p></body></html> <html><head/><body><p><span style=" font-weight:600;">Direkte Hilfe</span></p><p>Schalten in den direkten Hilfemodus um. Dies haben Sie bereits duch lesen des Textes getan :)</p></body></html> diff --git a/compile.sh b/compile.sh index 7a912ab..eb7bd49 100755 --- a/compile.sh +++ b/compile.sh @@ -129,7 +129,7 @@ then ${RUN} && ${QTDMM_EXE} elif ${RUN} then - ./${QTDMM_EXE} --debug + ./${QTDMM_EXE} #--debug fi exit 0 diff --git a/src/guiprefs.cpp b/src/guiprefs.cpp index afc8758..c99ea88 100644 --- a/src/guiprefs.cpp +++ b/src/guiprefs.cpp @@ -103,8 +103,8 @@ void GuiPrefs::setToolbarVisibility(bool disp, bool dmm, bool graph, bool file) void GuiPrefs::applySLOT() { - m_cfg->setInt("QtDMM/version", 0); - m_cfg->setInt("QtDMM/revision", 84); + m_cfg->setInt("QtDMM/version", 0); // TODO set version by cmake + m_cfg->setInt("QtDMM/revision", 84); // TODO set revision by cmake m_cfg->setBool("QtDMM/show-tip", showTip()); m_cfg->setBool("Save/window-pos", saveWindowPosition()); m_cfg->setBool("Save/window-size", saveWindowSize()); diff --git a/src/mainwid.cpp b/src/mainwid.cpp index 89d0a15..d8d8736 100644 --- a/src/mainwid.cpp +++ b/src/mainwid.cpp @@ -34,6 +34,8 @@ #include "settings.h" #include "instancesdlg.h" + + MainWid::MainWid(QString instance_id, QString config_path, QWidget *parent) : QFrame(parent), m_display(0), m_tipDlg(0) @@ -55,6 +57,7 @@ MainWid::MainWid(QString instance_id, QString config_path, QWidget *parent) : Q m_instancesDlg = new InstancesDlg(m_settings, instance_id, config_path,this); connect(m_instancesDlg, SIGNAL(writeState(const QString &)), parent, SLOT(sendStateSLOT(const QString &))); + connect(this, SIGNAL(sendState(const QString &)), parent, SLOT(sendStateSLOT(const QString &))); connect(m_dmm, SIGNAL(value(double, const QString &, const QString &, const QString &, const QString &, bool, bool, int)), this, SLOT(valueSLOT(double, const QString &, const QString &, const QString &, const QString &, bool, bool, int))); connect(m_dmm, SIGNAL(error(const QString &)), this, SIGNAL(error(const QString &))); @@ -82,7 +85,8 @@ MainWid::MainWid(QString instance_id, QString config_path, QWidget *parent) : Q ui_graph->setSettings(m_settings); //resetSLOT(); - + m_settings->save(); + Q_EMIT sendState("UPDATE_INSTANCES_"+QString::number(QDateTime::currentMSecsSinceEpoch())); startTimer(100); if (m_configDlg->showTip()) diff --git a/src/mainwid.h b/src/mainwid.h index 29ae397..d39986c 100644 --- a/src/mainwid.h +++ b/src/mainwid.h @@ -62,6 +62,7 @@ class MainWid : public QFrame, private Ui::UIMainWid void setConnect(bool); void toolbarVisibility(bool, bool, bool, bool); void connectDMM(bool); + void sendState(const QString&); public Q_SLOTS: void valueSLOT(double, const QString &, const QString &, const QString &, const QString &, bool, bool, int); diff --git a/src/mainwin.cpp b/src/mainwin.cpp index 3562229..6b44923 100644 --- a/src/mainwin.cpp +++ b/src/mainwin.cpp @@ -95,7 +95,9 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) if (!winRect.isEmpty()) { if (m_wid->saveWindowPosition()) + { move(winRect.x(), winRect.y()); + } if (m_wid->saveWindowSize()) resize(winRect.width(), winRect.height()); else diff --git a/src/resources.qrc b/src/resources.qrc index a61b464..c7692e6 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -22,6 +22,7 @@ ../assets/icons/W.xpm ../assets/icons/W_small.xpm ../assets/icons/ac.xpm + ../assets/icons/add.xpm ../assets/icons/all_digits.xpm ../assets/icons/auto.xpm ../assets/icons/bar.xpm @@ -61,6 +62,7 @@ ../assets/icons/icon.xpm ../assets/icons/icon_gray.xpm ../assets/icons/import.xpm + ../assets/icons/instances.xpm ../assets/icons/integration.xpm ../assets/icons/integration_old.xpm ../assets/icons/k.xpm @@ -88,6 +90,7 @@ ../assets/icons/print.xpm ../assets/icons/quit.xpm ../assets/icons/recorder.xpm + ../assets/icons/remove.xpm ../assets/icons/reset.xpm ../assets/icons/scale.xpm ../assets/icons/sixty_bar.xpm diff --git a/src/sharedstatemanager.cpp b/src/sharedstatemanager.cpp index 9b5a6df..57e3999 100644 --- a/src/sharedstatemanager.cpp +++ b/src/sharedstatemanager.cpp @@ -15,7 +15,7 @@ SharedStateManager::SharedStateManager(const QString &instanceId, QObject *paren m_registered(false), m_emit_inUse(false) { - m_timer.setInterval(500); + m_timer.setInterval(250); connect(&m_timer, &QTimer::timeout, this, &SharedStateManager::checkForChanges); m_timer.start(); } @@ -111,6 +111,9 @@ bool SharedStateManager::registerInstance() m_registered = writeJsonData(data); if (!m_registered) qInfo() << "reg failed"; + else + qInfo() << "reg" << m_instanceId; + } return m_registered; @@ -135,7 +138,7 @@ void SharedStateManager::checkForChanges() if (currentState != m_lastState) { - //qInfo() << currentState << QJsonDocument(data).toJson(QJsonDocument::Compact); + qInfo() << currentState << QJsonDocument(data).toJson(QJsonDocument::Compact); m_lastState = currentState; if (currentState.startsWith("UPDATE_INSTANCES")) Q_EMIT instancesChanged(m_instances); diff --git a/src/ui/uiinstancesdlg.ui b/src/ui/uiinstancesdlg.ui index d843074..cb8c6a8 100644 --- a/src/ui/uiinstancesdlg.ui +++ b/src/ui/uiinstancesdlg.ui @@ -6,12 +6,12 @@ 0 0 - 400 - 269 + 390 + 397 - Instances + Instance Manager @@ -25,7 +25,7 @@ - Choose instance to open + Choose instance to open, or add/remove instances @@ -58,8 +58,8 @@ + - - .. + + :/Symbols/add.xpm:/Symbols/add.xpm @@ -72,8 +72,8 @@ - - - .. + + :/Symbols/remove.xpm:/Symbols/remove.xpm true diff --git a/src/ui/uimainwin.ui b/src/ui/uimainwin.ui index c67f998..6a9892f 100644 --- a/src/ui/uimainwin.ui +++ b/src/ui/uimainwin.ui @@ -26,6 +26,9 @@ DMM + + + false @@ -50,6 +53,9 @@ Recorder + + + false @@ -150,6 +156,9 @@ &Export + + Export graph + <html><head/><body><p><span style=" font-weight:600;">Export recorder graph</span></p><p>Here you can export the recorded data as tab separated list. Each line contains the following values (separated by a tab character): date (dd.mm.yyyy) time (hh:mm:ss) value (float) unit.</p></body></html> @@ -168,6 +177,9 @@ &Import + + Import graph + <html><head/><body><p><span style=" font-weight:600;">Import data into recorder</span></p><p>Here you can import previously exported data files. QtDMM tries to do an educated guess if the file format is correct and rejects import of files which to not match.</p></body></html> @@ -186,6 +198,9 @@ &Print + + Print graph + <html><head/><body><p><span style=" font-weight:600;">Print recorder graph</span></p><p>A dialog will open where you can define a title and a comment for your printout. The printer itself can also be configured here. To be able to print you need at least one working postscript printer configured in your system. Printing into a file is also supported.</p></body></html> @@ -243,6 +258,9 @@ &Connect + + Connect/Disconnect DMM + <html><head/><body><p><span style=" font-weight:600;">Connect to the Multimeter</span></p><p>This will establish the serial connection to the dmm. If not connected the serial port is free and can be used by other software.</p></body></html> @@ -261,6 +279,9 @@ &Reset + + reset min/max + <html><head/><body><p><span style=" font-weight:600;">Reset min/max values</span></p><p>The min/max values in the display will be reset. You can activate this option at any time. </p></body></html> @@ -296,6 +317,9 @@ &Start + + Start recording + <html><head/><body><p><span style=" font-weight:600;">Start the recorder</span></p><p>If you are in manual mode this will start the recorder. Press F2 to set the recorder options.</p></body></html> @@ -317,6 +341,9 @@ S&top + + Stop recording + <html><head/><body><p><span style=" font-weight:600;">Stop the recorder</span></p><p>The recorder will be stopped. This is independent from the start mode of the recorder. </p></body></html> @@ -335,6 +362,9 @@ &Clear + + Clear graph + <html><head/><body><p><span style=" font-weight:600;">Clear the recorder graph</span></p><p>If the recorder is already started it will clear the graph and continue recording.</p></body></html> @@ -414,7 +444,7 @@ - + :/Symbols/menu.xpm:/Symbols/menu.xpm @@ -424,19 +454,19 @@ Menu - Ctrl+M + Ctrl+M - :/Symbols/dmm_big.xpm:/Symbols/dmm_big.xpm + :/Symbols/instances.xpm:/Symbols/instances.xpm - instances + Instances - open or create an instance + Instance Manager Ctrl+N From c29bb0429a90fa56e6cb2d4fc9a2d3505cbe8823 Mon Sep 17 00:00:00 2001 From: Sarah Mischke Date: Mon, 11 Aug 2025 00:14:32 +0200 Subject: [PATCH 6/8] fix tuxmaster issue #29 --- QtDMM.spec | 2 +- assets/translations/qtdmm_de.ts | 92 ++++++++++++++++----------------- src/dmmprefs.cpp | 41 ++++++++++++--- src/dmmprefs.h | 4 +- src/ui/uidmmprefs.ui | 8 ++- 5 files changed, 90 insertions(+), 57 deletions(-) diff --git a/QtDMM.spec b/QtDMM.spec index d2b4594..1c2cad6 100644 --- a/QtDMM.spec +++ b/QtDMM.spec @@ -1,5 +1,5 @@ Name: qtdmm -Version: 1.0.0-alpha.1-9-ge775322+e775322 +Version: 1.0.0-alpha.1-10-g75e3931+75e3931 Release: 1%{?dist} Summary: DMM Readout Software Including a Configurable Recorder. diff --git a/assets/translations/qtdmm_de.ts b/assets/translations/qtdmm_de.ts index c58e06c..e9f3492 100644 --- a/assets/translations/qtdmm_de.ts +++ b/assets/translations/qtdmm_de.ts @@ -303,18 +303,18 @@ Ist das DMM angeschlossen und eingeschaltet? <b>Hier können Sie den Anschluss und das Protokoll für Ihr DMM einstellen. Es gibt schon eine Reihe vorkonfigurierter Modelle.</b> - + Manual settings Manuelle Einstellung - + Load DMM description DMM Beschreibung laden - - + + DMM description (*.cfg) DMM Beschreibung (*.cfg) @@ -323,7 +323,7 @@ Ist das DMM angeschlossen und eingeschaltet? DMM Beschreibung (*.ini) - + Save DMM description DMM Beschreibung speichern @@ -675,47 +675,47 @@ Danach müssen Sie sich ab- und wieder anmelden. Hier kann das DMM Modell ausgewählt werden. Wenn Ihr DMM nicht in der Liste ist, können Sie versuchen die Einstellungen per Hand herauszufinden. Und freundlicher weise an <font color=blue><u>qtdmm@mtoussaint.de</u></font> schicken, so das diese in der nächsten Version eingepflegt werden. - + Load Settings Einstellungen laden - + Save Settings Einstellungen speichern - + Port settings Anschlusseinstellungen - + Parit&y &Parität - + Parity for serial communication. May be None, Odd or Even. Parität für die serielle Übertragung. Diese kann Keine, Gerade oder Ungerade sein. - + None Keine - + Even Gerade - + Odd Ungerade - + Number of display digits. <ul><li>3 1/2 - 2000 Counts</li> <li>3 3/4 - 4000 Counts</li> @@ -730,47 +730,47 @@ Danach müssen Sie sich ab- und wieder anmelden. </ul> - + variable bytes ASCII, Sigrok variable bytes ASCII, Sigrok - + <html><head/><body><p>These protocoll settings have not been confirmed by a user yet. If you own this model and can confirm that it works. Please give me a note. <a href="https://github.com/tuxmaster/QtDMM"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/tuxmaster/QtDMM</span></a></p></body></html> <html><head/><body><p>Diese Protokolleinstellungen wurden bisher von keinem Benutzer bestätigt. Wenn Sie dieses Modell besitzen und bestätigen können, das es funkioniert, dann melden Sie es bitte an: <a href="mailto:qtdmm@mtoussaint.de"><span style=" text-decoration: underline; color:#0000ff;">qtdmm@mtoussaint.de</span></a></p></body></html> - + <html><head/><body><p>If you have a DMM not listed above and find manual settings that work, please report to <a href="https://github.com/tuxmaster/QtDMM"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/tuxmaster/QtDMM</span></a>. This way future users of this DMM can benefit from your help.</p></body></html> <html><head/><body><p>Wenn Sie ein DMM verwenden, welches hier nicht aufgeführt ist, aber Sie aber passende Einstellungen gefunden haben, so teilen Sie es bitte <a href="mailto:qtdmm@mtoussaint.de"><span style=" text-decoration: underline; color:#0000ff;">qtdmm@mtoussaint.de</span></a> mit. So können zukümpftige Versionen von Ihrer Hilfe profitieren.</p></body></html> - + 11 bytes binary, continuous (CyrustekES51986) 11 bytes binär, kontinuierlich (CyrustekES51986) - + 23 bytes ASCII, continuous (VC870) 23 bytes ASCII, kontinuierlich (VC870) - + 22 bytes binary, continuous (DO3122) 22 bytes binary, kontinuierlich (DO3122) - + 14 bytes half-ASCII, UNI-T UT61E (CyrustekES51922) 14 bytes halb-ASCII, UNI-T UT61E (CyrustekES51922) - + DTM0660 DTM0660 - + 11 bytes binary, continuous (CyrustekES51962) 11 bytes binär, kontinuierlich(CyrustekES51962) @@ -783,7 +783,7 @@ Danach müssen Sie sich ab- und wieder anmelden. <html><head/><body><p>Wenn Sie ein DMM verwenden, welches hier nicht aufgeführt ist, aber Sie aber passende Einstellungen gefunden haben, so teilen Sie es bitte <a href="mailto:qtdmm@mtoussaint.de"><span style=" text-decoration: underline; color:#0000ff;">qtdmm@mtoussaint.de</span></a> mit. So können zukümpftige Versionen von Ihrer Hilfe profitieren.</p></body></html> - + Number of bits for serial communication. Anzahl der Bits für die Übertragung. @@ -804,12 +804,12 @@ Danach müssen Sie sich ab- und wieder anmelden. 8 Bits - + &Bits: - + Number of stop bits for serial communication. Anzahl der Stoppbits. @@ -822,17 +822,17 @@ Danach müssen Sie sich ab- und wieder anmelden. 2 Stoppbits - + &Port: &Anschluss: - + Choose the serial device here. <i>(Hint for DOS people: /dev/ttyS0 corresponds to COM1. /dev/ttyS1 to COM2 ...)</i> Hier bitte den seriellen Anschluß wählen.<i>(Für Unixumsteiger: /dev/ttyS0 entspricht COM1 und so weiter)</i> - + Select the baud rate for the DMM here. If you encounter problems connecting to your DMM try lowering the baud rate. I had some problems with my <b>Metex ME-32</b>. The Documentation said 1200 baud but it only worked at 600. Hier die Baudrate für das DMM auswählen. Wenn Probleme mit der Verbindung zum DMM auftreten, bitte die Baudrate verringern. Es sind Probleme mit dem <b>Metex ME-32</b> bekannt. Laut Dokumentation soll es mit 1200 Baud laufen, aber tatsächlich geht es nur mit 600 Baud. @@ -865,63 +865,63 @@ Danach müssen Sie sich ab- und wieder anmelden. 19200 Baud - + &Digits S&tellen - + &Stop bits: &Stoppbits: - + Baud &rate: Baud&rate: - + External device setup Externe Steuerung - + Protocol Protokoll - + Here you may select the Communication type. If you have a not "officially" supported multimeter, just try out the existing protocols. If you are lucky it may work. If you find working settings, send the to me. Hier wird das Kommunikationsprotokoll ausgewählt. Wenn Sie kein "offiziell" unterstützes DMM benutzte, versuchen Sie eines der bereits vorhanden Protokolle. Mit etwas etwas Glück passt eines. Wenn Sie eins finden, teilen Sie es bitte dem Autor mit. Here you may select the Communication type. If you have a not "officially" supported multimeter, just try out the existing protocols. If you are lucky it may work. If you find working settings, send the to me. - + 14 bytes ASCII, polling (Metex/Voltcraft) 14 Bytes ASCII, auf Abfrage (Metex/Voltcraft) - + 11 bytes ASCII, continuous (PeakTech 451) 11 Bytes ASCII, kontinuierlich (PeakTech 451) - + 14 bytes ASCII, continuous (Voltcraft) 14 Bytes ASCII, kontinuierlich (Voltcraft) - + 15 bytes ASCII, continuous (Voltcraft) 15 Bytes ASCII, kontinuierlich (Voltcraft) - + 11 bytes binary, continuous (M9803R) 11 Bytes binär, kontinuierlich (M9803R) - + 14 bytes binary, continuous (VC820) 14 Bytes binär, kontinuierlich (VC820) @@ -930,27 +930,27 @@ Danach müssen Sie sich ab- und wieder anmelden. 22 Bytes ASCII, kontinuierlich (IsoTech) - + 11 bytes binary, continuous (VC940) 11 Bytes binär, kontinuierlich (VC940) - + 14 bytes ASCII/binary, continuous (QM1537) 14 Bytes ASCII/Binär, kontinuierlich (QM1537) - + 9 bytes binary, continuous (RS 22-812) 9 Bytes binär, kontinuierlich (RS 22-812) - + &Number of values: &Anzahl der Werte: - + Some multimeter send several lines of data containing different measured values. As QtDMM only shows one variable here you can set the number of lines to be ignored for each measurement (That means that QtDMM only uses the first line). Einige Multimeter senden verschiedenen Zeile mit verschiedenen Messwerten. Hier kann die Anzahl der zu ignorieren Zeilen eingetragen werden.( Das bedeutet, QtDMM verarbeitet nur die erste Zeile). diff --git a/src/dmmprefs.cpp b/src/dmmprefs.cpp index fd659fe..7b2e1b3 100644 --- a/src/dmmprefs.cpp +++ b/src/dmmprefs.cpp @@ -45,6 +45,21 @@ DmmPrefs::DmmPrefs(QWidget *parent) : PrefWidget(parent) " also a number of predefined models."); m_pixmap = new QPixmap(":/Symbols/dmm.xpm"); + setupComboBoxModel(); + + message2->hide(); + + m_path = QDir::currentPath(); +} + + +DmmPrefs::~DmmPrefs() +{ + delete m_pixmap; +} + +void DmmPrefs::setupComboBoxModel() +{ ui_model->clear(); ui_model->insertItem(-1, tr("Manual settings")); @@ -61,15 +76,27 @@ DmmPrefs::DmmPrefs(QWidget *parent) : PrefWidget(parent) ui_model->addItem(cfg.name); } - message2->hide(); - - m_path = QDir::currentPath(); -} + QCompleter *completer = new QCompleter(ui_model->model(), this); + completer->setCaseSensitivity(Qt::CaseInsensitive); + completer->setFilterMode(Qt::MatchContains); + completer->setCompletionMode(QCompleter::PopupCompletion); + ui_model->setCompleter(completer); -DmmPrefs::~DmmPrefs() -{ - delete m_pixmap; + connect(ui_model->lineEdit(), &QLineEdit::editingFinished, this, [this]() + { + bool found = false; + for (int i = 0; i < ui_model->count(); ++i) + { + if (ui_model->itemText(i).compare(ui_model->currentText(), Qt::CaseInsensitive) == 0) + { + found = true; + break; + } + } + if (!found) + ui_model->setCurrentIndex(-1); + }); } QString DmmPrefs::deviceListText() const diff --git a/src/dmmprefs.h b/src/dmmprefs.h index c75b93b..1d5d814 100644 --- a/src/dmmprefs.h +++ b/src/dmmprefs.h @@ -64,7 +64,7 @@ protected Q_SLOTS: protected: QString m_path; DmmDecoder::DMMInfo m_dmmInfo; - -private: QStringListModel *m_portlist; + + void setupComboBoxModel(); }; diff --git a/src/ui/uidmmprefs.ui b/src/ui/uidmmprefs.ui index 7cf620e..8115210 100644 --- a/src/ui/uidmmprefs.ui +++ b/src/ui/uidmmprefs.ui @@ -41,11 +41,17 @@ Here you may select your DMM model. If your DMM is not in the list, try to find working settings and mail them to me (<font color=blue><u>qtdmm@mtoussaint.de</u></font>). So I can add them to the list in the next release. - false + true + + QComboBox::NoInsert + + + QComboBox::AdjustToContents + From d0ba31218e4206e4460d2e3c2bc68685b8ca938f Mon Sep 17 00:00:00 2001 From: Sarah Mischke Date: Mon, 11 Aug 2025 15:07:56 +0200 Subject: [PATCH 7/8] instances now fully working! graph: new CSV format. It might be buggy while importing. --- QtDMM.spec | 2 +- assets/translations/qtdmm_de.ts | 57 ++++++-- src/dmmgraph.cpp | 226 ++++++++++++++++++++++++++++++-- src/dmmgraph.h | 2 +- src/mainwin.cpp | 44 ++++++- src/mainwin.h | 1 + src/sharedstatemanager.cpp | 5 +- 7 files changed, 302 insertions(+), 35 deletions(-) diff --git a/QtDMM.spec b/QtDMM.spec index 1c2cad6..90324e3 100644 --- a/QtDMM.spec +++ b/QtDMM.spec @@ -1,5 +1,5 @@ Name: qtdmm -Version: 1.0.0-alpha.1-10-g75e3931+75e3931 +Version: 1.0.0-alpha.1-11-gc29bb04+c29bb04 Release: 1%{?dist} Summary: DMM Readout Software Including a Configurable Recorder. diff --git a/assets/translations/qtdmm_de.ts b/assets/translations/qtdmm_de.ts index e9f3492..682b318 100644 --- a/assets/translations/qtdmm_de.ts +++ b/assets/translations/qtdmm_de.ts @@ -229,41 +229,57 @@ Ist das DMM angeschlossen und eingeschaltet? Daten importieren ... - + Export data Daten exportieren + + + File contains only header + + All files (*.*) Alle Dateien (*.*) - + QtDMM: Unsaved data QtDMM: Ungesicherte Daten - + <font size=+2><b>Unsaved data</b></font><p>Importing data will overwrite your measured data<p>Do you want to export your unsaved data first? <font size=+2><b>Ungesicherte Daten</b></font><p>Beim Importieren werden alle bisherigen Messwerte gelöscht.<p>Möchten Sie zu ersten die bisherigen Daten exportieren? - + Export data first Daten zu erst exportieren - + Import & overwrite data Importieren und Daten löschen - + Import data Daten importieren - + + CSV (*.csv);;All files (*) + + + + + Cannot open file. + + + + + Oops! Seems not to be a valid file Diese Datei scheint nicht gültig zu sein @@ -506,17 +522,38 @@ Ist das DMM angeschlossen und eingeschaltet? MainWin - + + Record DMM data + + + + + Multiple instances of QtDMM have been detected. +Please choose which instance should record. + + + + + This instance + + + + + All instances + + + + QtDMM: Welcome! QtDMM: Willkommen! - + <h1>QtDMM %1</h1><hr><div align=right><i>A simple recorder for DMM's</i></div><p><div align=justify>A simple display software for a variety of digital multimeter. Currently confirmed are:<table>%2</table>Other compatible models may work also.<p>QtDMM features min/max memory and a configurable recorder with import/export and printing function. Sampling may be started manually, at a given time or triggered by a measured threshold. Additionally an external program may be started when given thresholds are reached.</div><div align=justify><b>QtDMM</b> uses the platform independent toolkit <b>Qt</b> version %3 and is licensed under <b>GPL 3</b> (Versions prior to v0.9.0 where licensed under GPL 2)</div><br>&copy; 2001-2014 Matthias Toussaint &nbsp;-&nbsp;&nbsp;<font color=blue><u><a href='mailto:qtdmm@mtoussaint.de'>qtdmm@mtoussaint.de</a></u></font><p><br>The icons (except the DMM icon) have been taken from the KDE project.<p> <h1>QtDMM %1</h1><hr><div align=right><i>Ein einfacher Datenrekorder für DMM</i></div><p><div align=justify>Ein einfaches Anzeigeprogramm für eine Vielzahl von DMM's. Aktuell bestätigt sind:<table>%2</table>Andere kompatible Modelle sollten ebenfalls funktionieren.<p>QtDMM stellt die Funktionen Min/Max Werte halten, ein konfigurierbaren Datenrekorder mit Daten im/export Funktion sowie ein Druckfunktion zur Verfügung. Die Datenaufzeichnung kann manuell, durch einen Grenzwert oder durch eine Zeitfunktion ausgelöst werden. Desweiteren kann ein externes Programm beim erreichen eines Grenzwertes gestartet werden.</div><div align=justify><b>QtDMM</b> wurde mit der Platformunabhängigen <b>Qt</b> Bibliothek in der Version %3 welche unter der <b>GPLv3</b> lizensiert ist erstellt.(Versionen vor 0.9.0 wurden unter der GPLv2 Lizenz veröffentlicht)</div><br>&copy; 2001-2014 Matthias Toussaint &nbsp;-&nbsp;&nbsp;<font color=blue><u><a href='mailto:qtdmm@mtoussaint.de'>qtdmm@mtoussaint.de</a></u></font><p><br>Die Symbole (bis auf das DMM Symbol) stammen von dem KDE Projekt.<p> - + Another instance is running. diff --git a/src/dmmgraph.cpp b/src/dmmgraph.cpp index 8b8e8a8..95e8552 100644 --- a/src/dmmgraph.cpp +++ b/src/dmmgraph.cpp @@ -1152,20 +1152,28 @@ void DMMGraph::fillInfoBox(const QPoint &pos) bool DMMGraph::exportDataSLOT() { QDir path; - QString fn = QFileDialog::getSaveFileName(this, tr("Export data"), m_cfg->getString("QtDMM/LastUsesPath", "")); - if (!fn.isNull()) + QFileInfo fileInfo(m_cfg->getString("QtDMM/LastUsesPath")); + QStringList validSuffixes = { "csv" }; + QString fnSuffix = validSuffixes.contains(fileInfo.suffix()) ? fileInfo.suffix() : "csv"; + QString fn = fileInfo.baseName().isEmpty() ? "untitled.csv" : fileInfo.absolutePath() + "/untitled." + fnSuffix; + fn = QFileDialog::getSaveFileName(this, tr("Export data"), fn, "CSV (*.csv)"); + + if (!fn.isNull() && m_pointer>0) { QFile file(fn); m_cfg->setString("QtDMM/LastUsesPath", path.absoluteFilePath(fn)); file.open(QIODevice::WriteOnly); QTextStream ts(&file); - printf("p %d %d\n", m_pointer, m_sampleTime); + QString line = QString("timestamp;time (s);value;unit\n"); + ts << line; + for (int i = 0; i < m_pointer; i++) { - //QDateTime dt = m_graphStartDateTime.addMSecs(i * static_cast(qRound(m_sampleTime / 10.))); QDateTime dt = m_graphStartDateTime.addMSecs(i * m_sampleTime * 100); - QString line = QString("%1\t%2\t%3\n").arg(dt.toString("dd.MM.yyyy\tHH:mm:ss:zzz")).arg((*m_array)[i], 0, 'f').arg(m_unit); + //timestamp: ISO8601 + double deltaTime = (dt.toMSecsSinceEpoch()-m_graphStartDateTime.toMSecsSinceEpoch())/1000.0f; + line = QString("%1;%2;%3;%4\n").arg(dt.toString("yyyy-MM-ddTHH:mm:ss,zzz")).arg(deltaTime).arg((*m_array)[i], 0, 'f').arg(m_unit); ts << line; } m_dirty = false; @@ -1178,6 +1186,188 @@ bool DMMGraph::exportDataSLOT() return false; } + +void DMMGraph::importDataSLOT() +{ + if (m_dirty && m_alertUnsaved) + { + QMessageBox question; + question.setWindowTitle(tr("QtDMM: Unsaved data")); + question.setText(tr("Unsaved data

" + "Importing data will overwrite your measured data" + "

Do you want to export your unsaved data first?")); + question.setIcon(QMessageBox::Question); + + // Standard-Buttons + question.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + question.setDefaultButton(QMessageBox::Yes); + question.setEscapeButton(QMessageBox::Cancel); + + QAbstractButton *yesButton = question.button(QMessageBox::Yes); + if (yesButton) + yesButton->setText(tr("Export data first")); + + QAbstractButton *noButton = question.button(QMessageBox::No); + if (noButton) + noButton->setText(tr("Import & overwrite data")); + + switch (question.exec()) + { + case QMessageBox::Yes: + exportDataSLOT(); + return; + case QMessageBox::Cancel: + return; + } + } + QDir path; + QString fn = QFileDialog::getOpenFileName(this, tr("Import data"), m_cfg->getString("QtDMM/LastUsesPath", tr("CSV (*.csv);;All files (*)"))); + + int cnt = 0; + int sample = 0; + + QDateTime graphEnd; + + if (!fn.isNull()) + { + m_cfg->setString("QtDMM/LastUsesPath", path.absoluteFilePath(fn)); + // First pass -> figure out size and sample time + QFile file(fn); + if (!file.open(QIODevice::ReadOnly)) + { + Q_EMIT error(tr("Cannot open file.")); + return; + } + + QStringList token; + QStringList dateToken; + QStringList timeToken; + QStringList timeParts; + + QTextStream ts(&file); + + QString line = ts.readLine(); + if (line.isNull()) + { + Q_EMIT error(tr("Oops! Seems not to be a valid file")); + file.close(); + return; + } + + // skip CSV-Header + if (line.startsWith("timestamp")) + { + line = ts.readLine(); + if (line.isNull()) + { + Q_EMIT error(tr("File contains only header")); + file.close(); + return; + } + } + + QRegularExpression reLegacy( + R"(^(?\d{2})\.(?\d{2})\.(?\d{4})\t(?\d{2}):(?\d{2}):(?\d{2}):(?\d{1,3})\t(?-?\d+(?:\.\d+)?|nan)\t(?.*)$)", + QRegularExpression::CaseInsensitiveOption + ); + + QRegularExpression reCSV( + R"(^(?\d{4})-(?\d{2})-(?\d{2})T(?\d{2}):(?\d{2}):(?\d{2})[,\.](?\d{1,3});(?-?\d+(?:\.\d+)?|nan);(?-?\d+(?:\.\d+)?|nan);(?.*)$)", + QRegularExpression::CaseInsensitiveOption + ); + + // detect format + bool isLegacy = reLegacy.match(line).hasMatch(); + + //(*m_array).clear(); + QVector values; + QRegularExpressionMatch match; + do + { + if (!line.trimmed().isEmpty()) + { + match = isLegacy ? reLegacy.match(line) : reCSV.match(line); + + if (!match.hasMatch()) + { + qInfo() << line; + Q_EMIT error(tr("Oops! Seems not to be a valid file")); + file.close(); + return; + } + + QDate valueDate( + match.captured("year").toInt(), + match.captured("month").toInt(), + match.captured("day").toInt() + ); + + QTime valueTime( + match.captured("hour").toInt(), + match.captured("minute").toInt(), + match.captured("second").toInt(), + match.captured("ms").toInt() + ); + + if (values.isEmpty()) + { + setUnit(match.captured("unit")); + m_graphStartDateTime = QDateTime(valueDate, valueTime); + } + + graphEnd = QDateTime(valueDate, valueTime); + sample += m_graphStartDateTime.secsTo(graphEnd); + values << (match.captured("value") == "nan" ? 0.0f : match.captured("value").toDouble()); + } + + line = ts.readLine(); + } + while (!line.isNull()); + file.close(); + + int cnt = values.size(); + m_sampleTime = (sample / (cnt > 1 ? cnt - 1 : 1))/10; + if (m_sampleTime<1) m_sampleTime=1; + qInfo() << m_graphStartDateTime.secsTo( graphEnd ) << m_sampleTime; + //m_sampleTime = m_graphStartDateTime.secsTo( graphEnd ) / (cnt > 1 ? cnt - 1 : 1); + + int size = m_size * m_sampleTime; + + if (cnt > 1) + { + Q_EMIT sampleTime(m_sampleTime); + m_sampleTime = (sample / (cnt - 1))/10; + } + if (m_sampleTime<1) m_sampleTime=1; + qInfo() << sample << cnt << m_sampleTime << m_graphStartDateTime.secsTo( graphEnd ); + + m_scaleMin = 1e40; + m_scaleMax = -1e40; + + // TEST + setGraphSize(size, cnt * m_sampleTime); + + for(int i=0; isetText(tr("Export data first")); @@ -1240,8 +1429,13 @@ void DMMGraph::importDataSLOT() if (!line.isNull()) { - QRegularExpression re(R"(^\d+\.\d+\.\d+\t\d+:\d+:\d+(?:\.\d+)?\t-?\d*\.\d+\t.*$)"); - if (!re.match(line).hasMatch()) + QRegularExpression reLegacy( + R"(^(?\d{2})\.(?\d{2})\.(?\d{4})\t(?\d{2}):(?\d{2}):(?\d{2}):(?\d{1,3})\t(?-?\d+(?:\.\d+)?)\t.*$)" + ); + QRegularExpression reCSV( + R"(^(?\d{4})-(?\d{2})-(?\d{2})T(?\d{2}):(?\d{2}):(?\d{2}),(?\d{1,3});(?-?\d+(?:\.\d+)?);(?-?\d+(?:\.\d+)?);(?.+)$)" + ); + if (!reCSV.match(line).hasMatch()) { Q_EMIT error(tr("Oops! Seems not to be a valid file")); @@ -1321,12 +1515,12 @@ void DMMGraph::importDataSLOT() m_sampleTime = sample / (cnt - 1); } - /* if (cnt*m_sampleTime > length) - { - if (size > cnt*m_sampleTime) size = cnt*m_sampleTime; - emit graphSize( size, cnt*m_sampleTime ); - setGraphSize( size, cnt*m_sampleTime ); - }*/ + // if (cnt*m_sampleTime > length) + // { + // if (size > cnt*m_sampleTime) size = cnt*m_sampleTime; + // emit graphSize( size, cnt*m_sampleTime ); + // setGraphSize( size, cnt*m_sampleTime ); + // } m_scaleMin = 1e40; m_scaleMax = -1e40; @@ -1373,6 +1567,10 @@ void DMMGraph::importDataSLOT() } } +*/ + + + void DMMGraph::setThresholds(double falling, double raising) { m_fallingThreshold = falling; diff --git a/src/dmmgraph.h b/src/dmmgraph.h index ae1878c..426b1da 100644 --- a/src/dmmgraph.h +++ b/src/dmmgraph.h @@ -150,7 +150,7 @@ protected Q_SLOTS: double m_xstep; double m_hUnitFact; double m_maxUnit; - int m_sampleTime; + double m_sampleTime; int m_sampleLength; bool m_running; bool m_connected; diff --git a/src/mainwin.cpp b/src/mainwin.cpp index 6b44923..87503e7 100644 --- a/src/mainwin.cpp +++ b/src/mainwin.cpp @@ -33,6 +33,7 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) : QMainWindow(parent) , m_running(false) , m_menu(Q_NULLPTR) + , m_localRecord(true) { setupUi(this); setupIcons(); @@ -107,11 +108,13 @@ MainWin::MainWin(QCommandLineParser &parser, QWidget *parent) connect(m_stateMgr, &SharedStateManager::stateChanged, this, [=](const QString& state){ if (state == "RECORD") { - action_Start->trigger(); + QMetaObject::invokeMethod(m_wid, "startSLOT", Qt::DirectConnection); + m_localRecord = false; } else if (state == "STOP") { - action_Stop->trigger(); + if (!m_localRecord) + action_Stop->trigger(); } else if (state == "RAISE_"+(m_config_id.isEmpty()?"default":m_config_id)) { @@ -156,7 +159,6 @@ void MainWin::createActions() connect(action_Connect, SIGNAL(triggered(bool)), m_wid, SLOT(connectSLOT(bool))); connect(action_Connect, SIGNAL(triggered(bool)), this, SLOT(connectSLOT(bool))); connect(action_Reset, SIGNAL(triggered()), m_wid, SLOT(resetSLOT())); - connect(action_Start, SIGNAL(triggered()), m_wid, SLOT(startSLOT())); connect(action_Start, SIGNAL(triggered()), this, SLOT(startSLOT())); connect(action_Stop, SIGNAL(triggered()), m_wid, SLOT(stopSLOT())); connect(action_Stop, SIGNAL(triggered()), this, SLOT(stopSLOT())); @@ -189,12 +191,44 @@ void MainWin::createActions() void MainWin::startSLOT() { - m_stateMgr->writeState("RECORD"); + if (m_stateMgr->instances().count()<=1) + { + QMetaObject::invokeMethod(m_wid, "startSLOT", Qt::DirectConnection); + m_localRecord = true; + } + else + { + QMessageBox question( + QMessageBox::Question, + tr("Record DMM data"), + tr("Multiple instances of QtDMM have been detected.\n" + "Please choose which instance should record."), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + question.button(QMessageBox::Yes)->setText(tr("This instance")); + question.button(QMessageBox::No)->setText(tr("All instances")); + question.setEscapeButton(QMessageBox::Cancel); + + switch (question.exec()) + { + case QMessageBox::Yes: + QMetaObject::invokeMethod(m_wid, "startSLOT", Qt::DirectConnection); + m_localRecord = true; + return; + case QMessageBox::No: + m_stateMgr->writeState("RECORD"); + m_localRecord = false; + return; + } + } } void MainWin::stopSLOT() { - m_stateMgr->writeState("STOP"); + qInfo() << "stop" << m_localRecord; + if (! m_localRecord) + m_stateMgr->writeState("STOP"); + m_localRecord = false; + } void MainWin::runningSLOT(bool on) diff --git a/src/mainwin.h b/src/mainwin.h index 0c78581..f5197b0 100644 --- a/src/mainwin.h +++ b/src/mainwin.h @@ -63,6 +63,7 @@ protected Q_SLOTS: QMenu *m_menu; SharedStateManager* m_stateMgr; QString m_config_id; + bool m_localRecord; void setupIcons(); void createToolBars(); diff --git a/src/sharedstatemanager.cpp b/src/sharedstatemanager.cpp index 57e3999..d768faa 100644 --- a/src/sharedstatemanager.cpp +++ b/src/sharedstatemanager.cpp @@ -111,9 +111,6 @@ bool SharedStateManager::registerInstance() m_registered = writeJsonData(data); if (!m_registered) qInfo() << "reg failed"; - else - qInfo() << "reg" << m_instanceId; - } return m_registered; @@ -138,7 +135,7 @@ void SharedStateManager::checkForChanges() if (currentState != m_lastState) { - qInfo() << currentState << QJsonDocument(data).toJson(QJsonDocument::Compact); + //qInfo() << currentState << QJsonDocument(data).toJson(QJsonDocument::Compact); m_lastState = currentState; if (currentState.startsWith("UPDATE_INSTANCES")) Q_EMIT instancesChanged(m_instances); From a371a17b46bb70adca2fe4a4237ec79ace4857f1 Mon Sep 17 00:00:00 2001 From: Sarah Mischke Date: Tue, 12 Aug 2025 06:32:07 +0200 Subject: [PATCH 8/8] add some test files to import into graph --- QtDMM.spec | 2 +- cmake/ctest.cmake | 2 +- tests/data/do3122.json_todo | 17 -- tests/data/dtm0660.json_todo | 17 -- tests/data/es51922.json | 101 ----------- tests/data/es51962.json | 41 ----- tests/data/es51986.json | 29 ---- tests/data/graph/legacy.txt | 42 +++++ tests/data/graph/legacy_nan.txt | 47 ++++++ tests/data/graph/new_dpoint.csv | 43 +++++ tests/data/graph/new_komma_ms.csv | 28 +++ tests/data/graph/new_larger.csv | 272 ++++++++++++++++++++++++++++++ tests/data/m9803r.json | 17 -- tests/data/qm1537.json | 17 -- tests/data/rs22812.json | 17 -- tests/data/vc820.json | 29 ---- tests/data/vc870.json | 19 --- tests/data/vc940.json | 17 -- 18 files changed, 434 insertions(+), 323 deletions(-) delete mode 100644 tests/data/do3122.json_todo delete mode 100644 tests/data/dtm0660.json_todo delete mode 100644 tests/data/es51922.json delete mode 100644 tests/data/es51962.json delete mode 100644 tests/data/es51986.json create mode 100644 tests/data/graph/legacy.txt create mode 100644 tests/data/graph/legacy_nan.txt create mode 100644 tests/data/graph/new_dpoint.csv create mode 100644 tests/data/graph/new_komma_ms.csv create mode 100644 tests/data/graph/new_larger.csv delete mode 100644 tests/data/m9803r.json delete mode 100644 tests/data/qm1537.json delete mode 100644 tests/data/rs22812.json delete mode 100644 tests/data/vc820.json delete mode 100644 tests/data/vc870.json delete mode 100644 tests/data/vc940.json diff --git a/QtDMM.spec b/QtDMM.spec index 90324e3..b6061e8 100644 --- a/QtDMM.spec +++ b/QtDMM.spec @@ -1,5 +1,5 @@ Name: qtdmm -Version: 1.0.0-alpha.1-11-gc29bb04+c29bb04 +Version: 1.0.0-alpha.1-12-gd0ba312+d0ba312 Release: 1%{?dist} Summary: DMM Readout Software Including a Configurable Recorder. diff --git a/cmake/ctest.cmake b/cmake/ctest.cmake index 4e8c46c..351a075 100644 --- a/cmake/ctest.cmake +++ b/cmake/ctest.cmake @@ -6,7 +6,7 @@ if (BUILD_TESTING) add_executable(${TEST_DECODER} MACOSX_BUNDLE tests/test_decoder.cpp src/dmmdecoder.cpp ${DECODER_FILES}) target_link_libraries(${TEST_DECODER} PRIVATE Qt::Core Qt::Test) - file(GLOB TEST_FILES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/tests/data/*.json") + file(GLOB TEST_FILES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/tests/data/decoder/*.json") foreach(test_file ${TEST_FILES}) get_filename_component(name ${test_file} NAME_WE) add_test(NAME ${name} COMMAND ${TEST_DECODER} ${test_file}) diff --git a/tests/data/do3122.json_todo b/tests/data/do3122.json_todo deleted file mode 100644 index 9cacdcb..0000000 --- a/tests/data/do3122.json_todo +++ /dev/null @@ -1,17 +0,0 @@ -{ - "decoder": "DO3122Continuous", - "tests": [ - { - "hex": "AA 55 52 24 00 xx ", - "expected": { - "dval": 0.0, - "val": "0.0000", - "unit": "V", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - } - ] -} diff --git a/tests/data/dtm0660.json_todo b/tests/data/dtm0660.json_todo deleted file mode 100644 index 1d5ed5a..0000000 --- a/tests/data/dtm0660.json_todo +++ /dev/null @@ -1,17 +0,0 @@ -{ - "decoder": "DTM0660", - "tests": [ - { - "hex": "17 27 3D 4F 5D 67 7D 87 9D A0 B0 C0 D4 E0", - "expected": { - "dval": 0.0, - "val": "0.0000", - "unit": "V", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - } - ] -} diff --git a/tests/data/es51922.json b/tests/data/es51922.json deleted file mode 100644 index e1eeccb..0000000 --- a/tests/data/es51922.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "decoder": "CyrustekES51922", - "tests": [ - { - "hex": "30 30 30 30 30 30 3B 30 30 30 3A 30 0D 0A", - "expected": { - "dval": 0.0, - "val": "0.0000", - "unit": "V", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - }, - { - "hex": "30 30 30 30 30 30 3B 30 30 30 38 30 0D 0A", - "expected": { - "dval": 0.0, - "val": "0.0000", - "unit": "V", - "range": "MANU", - "special": "DC", - "hold": false, - "showBar": true - } - }, - { - "hex": "30 30 30 30 30 30 3B 32 30 30 3A 30 0D 0A", - "expected": { - "dval": 0.0, - "val": "0.0000", - "unit": "V", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - }, - { - "hex": "30 30 30 30 30 30 3D 30 30 30 3A 30 0D 0A", - "expected": { - "dval": 0.0, - "val": "000.00", - "unit": "uA", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - }, - { - "hex": "30 30 30 30 30 30 30 30 30 30 34 32 0D 0A", - "expected": { - "dval": 0.0, - "val": "00.000", - "unit": "A", - "range": "MANU", - "special": "AC", - "hold": true, - "showBar": true - } - }, - { - "hex": "30 30 30 30 30 30 3B 30 30 30 3B 30 0D 0A", - "expected": { - "dval": 0.0, - "val": "0.0000", - "unit": "Hz", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - }, - { - "hex": "30 30 30 30 30 37 3F 30 30 30 36 30 0D 0A", - "expected": { - "dval": 0.000007, - "val": "00.007", - "unit": "mA", - "range": "AUTO", - "special": "AC", - "hold": false, - "showBar": true - } - }, - { - "hex": "34 30 31 33 34 34 3B 34 30 30 38 30 0D 0A", - "expected": { - "dval": -0.01344, - "val": "-013.44", - "unit": "mV", - "range": "MANU", - "special": "DC", - "hold": false, - "showBar": true - } - } - ] -} diff --git a/tests/data/es51962.json b/tests/data/es51962.json deleted file mode 100644 index f74eba5..0000000 --- a/tests/data/es51962.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "decoder": "CyrustekES51962", - "tests": [ - { - "hex": "30 30 30 35 38 3B 30 30 3A 0D 0A", - "expected": { - "dval": 0.0058, - "val": "005.8", - "unit": "mV", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - }, - { - "hex": "30 30 30 32 31 3B 34 30 38 0D 0A", - "expected": { - "dval": -0.0021, - "val": "-002.1", - "unit": "mV", - "range": "MANU", - "special": "DC", - "hold": false, - "showBar": true - } - }, - { - "hex": "30 30 31 34 30 33 30 30 30 0D 0A", - "expected": { - "dval": 14.0, - "val": "014.0", - "unit": "Ohm", - "range": "MANU", - "special": "", - "hold": false, - "showBar": true - } - } - ] -} diff --git a/tests/data/es51986.json b/tests/data/es51986.json deleted file mode 100644 index 3c82703..0000000 --- a/tests/data/es51986.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "decoder": "CyrustekES51986", - "tests": [ - { - "hex": "30 30 30 30 30 3B 38 30 3A 0D 0A", - "expected": { - "dval": 0.0, - "val": "0.000", - "unit": "V", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - }, - { - "hex": "30 30 30 30 30 3B 3C 30 38 0D 0A", - "expected": { - "dval": 0.0, - "val": "-0.000", - "unit": "V", - "range": "MANU", - "special": "DC", - "hold": false, - "showBar": true - } - } - ] -} diff --git a/tests/data/graph/legacy.txt b/tests/data/graph/legacy.txt new file mode 100644 index 0000000..350a0be --- /dev/null +++ b/tests/data/graph/legacy.txt @@ -0,0 +1,42 @@ +09.07.2025 13:16:38 0.001200 V +09.07.2025 13:16:39 -0.000080 V +09.07.2025 13:16:40 -0.003340 V +09.07.2025 13:16:41 -0.001470 V +09.07.2025 13:16:42 -0.002050 V +09.07.2025 13:16:43 -0.001940 V +09.07.2025 13:16:44 -0.005850 V +09.07.2025 13:16:45 -0.371410 V +09.07.2025 13:16:46 -1.049560 V +09.07.2025 13:16:47 -1.314830 V +09.07.2025 13:16:48 -1.314900 V +09.07.2025 13:16:49 -1.314900 V +09.07.2025 13:16:50 -1.314900 V +09.07.2025 13:16:51 -1.314930 V +09.07.2025 13:16:52 -1.062350 V +09.07.2025 13:16:53 -0.792770 V +09.07.2025 13:16:54 -1.079020 V +09.07.2025 13:16:55 -0.987650 V +09.07.2025 13:16:56 -0.044250 V +09.07.2025 13:16:57 0.002180 V +09.07.2025 13:16:58 -0.002060 V +09.07.2025 13:16:59 -0.000850 V +09.07.2025 13:17:00 -0.000080 V +09.07.2025 13:17:01 0.411220 V +09.07.2025 13:17:02 1.315010 V +09.07.2025 13:17:03 1.315130 V +09.07.2025 13:17:04 1.315170 V +09.07.2025 13:17:05 1.315130 V +09.07.2025 13:17:06 1.315170 V +09.07.2025 13:17:07 1.315100 V +09.07.2025 13:17:08 0.920540 V +09.07.2025 13:17:09 -0.000190 V +09.07.2025 13:17:10 -0.000640 V +09.07.2025 13:17:11 -0.000380 V +09.07.2025 13:17:12 -0.020760 V +09.07.2025 13:17:13 -1.055930 V +09.07.2025 13:17:14 -0.911510 V +09.07.2025 13:17:15 0.005540 V +09.07.2025 13:17:16 0.000000 V +09.07.2025 13:17:17 0.000000 V +09.07.2025 13:17:18 -0.000030 V +09.07.2025 13:17:19 -0.000160 V diff --git a/tests/data/graph/legacy_nan.txt b/tests/data/graph/legacy_nan.txt new file mode 100644 index 0000000..23995b6 --- /dev/null +++ b/tests/data/graph/legacy_nan.txt @@ -0,0 +1,47 @@ +15.07.2025 10:14:53:775 nan Ohm +15.07.2025 10:14:54:275 nan Ohm +15.07.2025 10:14:54:775 nan Ohm +15.07.2025 10:14:55:275 nan Ohm +15.07.2025 10:14:55:775 nan Ohm +15.07.2025 10:14:56:275 nan Ohm +15.07.2025 10:14:56:775 0.011452 Ohm +15.07.2025 10:14:57:275 0.037174 Ohm +15.07.2025 10:14:57:775 0.075652 Ohm +15.07.2025 10:14:58:275 0.032896 Ohm +15.07.2025 10:14:58:775 -0.004520 Ohm +15.07.2025 10:14:59:275 0.044218 Ohm +15.07.2025 10:14:59:775 -0.030110 Ohm +15.07.2025 10:15:00:275 -0.064386 Ohm +15.07.2025 10:15:00:775 -0.007114 Ohm +15.07.2025 10:15:01:275 -0.020008 Ohm +15.07.2025 10:15:01:775 -0.022212 Ohm +15.07.2025 10:15:02:275 -0.022284 Ohm +15.07.2025 10:15:02:775 -0.021094 Ohm +15.07.2025 10:15:03:275 -0.019696 Ohm +15.07.2025 10:15:03:775 -0.020166 Ohm +15.07.2025 10:15:04:275 -0.020674 Ohm +15.07.2025 10:15:04:775 nan Ohm +15.07.2025 10:15:05:275 nan Ohm +15.07.2025 10:15:05:775 nan Ohm +15.07.2025 10:15:06:275 nan Ohm +15.07.2025 10:15:06:775 nan Ohm +15.07.2025 10:15:07:275 nan Ohm +15.07.2025 10:15:07:775 nan Ohm +15.07.2025 10:15:08:275 nan Ohm +15.07.2025 10:15:08:775 nan Ohm +15.07.2025 10:15:09:275 nan Ohm +15.07.2025 10:15:09:775 nan Ohm +15.07.2025 10:15:10:275 2117800.000000 Ohm +15.07.2025 10:15:10:775 2543000.000000 Ohm +15.07.2025 10:15:11:275 2460800.000000 Ohm +15.07.2025 10:15:11:775 2610000.000000 Ohm +15.07.2025 10:15:12:275 2716800.000000 Ohm +15.07.2025 10:15:12:775 2777600.000000 Ohm +15.07.2025 10:15:13:275 2730800.000000 Ohm +15.07.2025 10:15:13:775 2675000.000000 Ohm +15.07.2025 10:15:14:275 2811200.000000 Ohm +15.07.2025 10:15:14:775 2890800.000000 Ohm +15.07.2025 10:15:15:275 2966800.000000 Ohm +15.07.2025 10:15:15:775 5567600.000000 Ohm +15.07.2025 10:15:16:275 31088200.000000 Ohm +15.07.2025 10:15:16:775 63226000.000000 Ohm diff --git a/tests/data/graph/new_dpoint.csv b/tests/data/graph/new_dpoint.csv new file mode 100644 index 0000000..84480a6 --- /dev/null +++ b/tests/data/graph/new_dpoint.csv @@ -0,0 +1,43 @@ +12.07.2025 23:38:02:997 0.007020 V +12.07.2025 23:38:03:497 0.002960 V +12.07.2025 23:38:03:997 0.003720 V +12.07.2025 23:38:04:497 0.015560 V +12.07.2025 23:38:04:997 -0.005920 V +12.07.2025 23:38:05:497 -0.008000 V +12.07.2025 23:38:05:997 0.003000 V +12.07.2025 23:38:06:497 0.008060 V +12.07.2025 23:38:06:997 0.003660 V +12.07.2025 23:38:07:497 0.004400 V +12.07.2025 23:38:07:997 -0.003740 V +12.07.2025 23:38:08:497 0.006900 V +12.07.2025 23:38:08:997 0.004340 V +12.07.2025 23:38:09:497 0.010820 V +12.07.2025 23:38:09:997 0.012800 V +12.07.2025 23:38:10:497 0.001280 V +12.07.2025 23:38:10:997 0.002960 V +12.07.2025 23:38:11:497 0.027380 V +12.07.2025 23:38:11:997 0.034560 V +12.07.2025 23:38:12:497 0.027940 V +12.07.2025 23:38:12:997 0.026200 V +12.07.2025 23:38:13:497 0.027480 V +12.07.2025 23:38:13:997 0.019960 V +12.07.2025 23:38:14:497 0.010080 V +12.07.2025 23:38:14:997 0.015940 V +12.07.2025 23:38:15:497 0.027260 V +12.07.2025 23:38:15:997 0.031040 V +12.07.2025 23:38:16:497 0.032680 V +12.07.2025 23:38:16:997 0.032040 V +12.07.2025 23:38:17:497 0.008040 V +12.07.2025 23:38:17:997 -0.016300 V +12.07.2025 23:38:18:497 0.048620 V +12.07.2025 23:38:18:997 0.016080 V +12.07.2025 23:38:19:497 -0.000800 V +12.07.2025 23:38:19:997 0.040260 V +12.07.2025 23:38:20:497 0.005200 V +12.07.2025 23:38:20:997 -0.002120 V +12.07.2025 23:38:21:497 0.009780 V +12.07.2025 23:38:21:997 0.001220 V +12.07.2025 23:38:22:497 -0.001840 V +12.07.2025 23:38:22:997 -0.002940 V +12.07.2025 23:38:23:497 0.002880 V +12.07.2025 23:38:23:997 0.000880 V diff --git a/tests/data/graph/new_komma_ms.csv b/tests/data/graph/new_komma_ms.csv new file mode 100644 index 0000000..f13176d --- /dev/null +++ b/tests/data/graph/new_komma_ms.csv @@ -0,0 +1,28 @@ +timestamp;time (ms);value;unit +2025-08-11T05:41:54,551;0;0.000000;V +2025-08-11T05:41:54,751;0.2;0.000000;V +2025-08-11T05:41:54,951;0.4;0.000000;V +2025-08-11T05:41:55,151;0.6;0.000000;V +2025-08-11T05:41:55,351;0.8;0.000000;V +2025-08-11T05:41:55,551;1;0.000000;V +2025-08-11T05:41:55,751;1.2;0.000000;V +2025-08-11T05:41:55,951;1.4;-0.003600;V +2025-08-11T05:41:56,151;1.6;-0.003600;V +2025-08-11T05:41:56,351;1.8;-0.001900;V +2025-08-11T05:41:56,551;2;-0.000200;V +2025-08-11T05:41:56,751;2.2;-0.000200;V +2025-08-11T05:41:56,951;2.4;-0.000400;V +2025-08-11T05:41:57,151;2.6;-0.000400;V +2025-08-11T05:41:57,351;2.8;-0.000400;V +2025-08-11T05:41:57,551;3;-0.000400;V +2025-08-11T05:41:57,751;3.2;-0.000400;V +2025-08-11T05:41:57,951;3.4;0.000000;V +2025-08-11T05:41:58,151;3.6;0.000000;V +2025-08-11T05:41:58,351;3.8;0.000000;V +2025-08-11T05:41:58,551;4;0.000000;V +2025-08-11T05:41:58,751;4.2;0.000000;V +2025-08-11T05:41:58,951;4.4;0.000000;V +2025-08-11T05:41:59,151;4.6;0.000000;V +2025-08-11T05:41:59,351;4.8;0.000000;V +2025-08-11T05:41:59,551;5;0.000000;V +2025-08-11T05:41:59,751;5.2;0.000000;V diff --git a/tests/data/graph/new_larger.csv b/tests/data/graph/new_larger.csv new file mode 100644 index 0000000..9907ae2 --- /dev/null +++ b/tests/data/graph/new_larger.csv @@ -0,0 +1,272 @@ +timestamp;time (s);value;unit +2025-08-11T10:25:22,289;0;0.032700;V +2025-08-11T10:25:22,489;0.2;0.036000;V +2025-08-11T10:25:22,689;0.4;0.036000;V +2025-08-11T10:25:22,889;0.6;0.032400;V +2025-08-11T10:25:23,089;0.8;0.028800;V +2025-08-11T10:25:23,289;1;0.028800;V +2025-08-11T10:25:23,489;1.2;0.024700;V +2025-08-11T10:25:23,689;1.4;0.024700;V +2025-08-11T10:25:23,889;1.6;0.027950;V +2025-08-11T10:25:24,089;1.8;0.031200;V +2025-08-11T10:25:24,289;2;0.031200;V +2025-08-11T10:25:24,489;2.2;0.032100;V +2025-08-11T10:25:24,689;2.4;0.032100;V +2025-08-11T10:25:24,889;2.6;0.034250;V +2025-08-11T10:25:25,089;2.8;0.036400;V +2025-08-11T10:25:25,289;3;0.036400;V +2025-08-11T10:25:25,489;3.2;0.033600;V +2025-08-11T10:25:25,689;3.4;0.033600;V +2025-08-11T10:25:25,889;3.6;0.045300;V +2025-08-11T10:25:26,089;3.8;0.057000;V +2025-08-11T10:25:26,289;4;0.057000;V +2025-08-11T10:25:26,489;4.2;0.053900;V +2025-08-11T10:25:26,689;4.4;0.053900;V +2025-08-11T10:25:26,889;4.6;0.049350;V +2025-08-11T10:25:27,089;4.8;0.044800;V +2025-08-11T10:25:27,289;5;0.044800;V +2025-08-11T10:25:27,489;5.2;0.043000;V +2025-08-11T10:25:27,689;5.4;0.043000;V +2025-08-11T10:25:27,889;5.6;0.038850;V +2025-08-11T10:25:28,089;5.8;0.034700;V +2025-08-11T10:25:28,289;6;0.034700;V +2025-08-11T10:25:28,489;6.2;0.029500;V +2025-08-11T10:25:28,689;6.4;0.029500;V +2025-08-11T10:25:28,889;6.6;0.026150;V +2025-08-11T10:25:29,089;6.8;0.022800;V +2025-08-11T10:25:29,289;7;0.022800;V +2025-08-11T10:25:29,489;7.2;0.025200;V +2025-08-11T10:25:29,689;7.4;0.025200;V +2025-08-11T10:25:29,889;7.6;0.024200;V +2025-08-11T10:25:30,089;7.8;0.023200;V +2025-08-11T10:25:30,289;8;0.023200;V +2025-08-11T10:25:30,489;8.2;0.035500;V +2025-08-11T10:25:30,689;8.4;0.035500;V +2025-08-11T10:25:30,889;8.6;0.036850;V +2025-08-11T10:25:31,089;8.8;0.038200;V +2025-08-11T10:25:31,289;9;0.038200;V +2025-08-11T10:25:31,489;9.2;0.036000;V +2025-08-11T10:25:31,689;9.4;0.036000;V +2025-08-11T10:25:31,889;9.6;0.036000;V +2025-08-11T10:25:32,089;9.8;0.036000;V +2025-08-11T10:25:32,289;10;0.036000;V +2025-08-11T10:25:32,489;10.2;0.032800;V +2025-08-11T10:25:32,689;10.4;0.032800;V +2025-08-11T10:25:32,889;10.6;0.034050;V +2025-08-11T10:25:33,089;10.8;0.035300;V +2025-08-11T10:25:33,289;11;0.035300;V +2025-08-11T10:25:33,489;11.2;0.033100;V +2025-08-11T10:25:33,689;11.4;0.033100;V +2025-08-11T10:25:33,889;11.6;0.030500;V +2025-08-11T10:25:34,089;11.8;0.027900;V +2025-08-11T10:25:34,289;12;0.027900;V +2025-08-11T10:25:34,489;12.2;0.053300;V +2025-08-11T10:25:34,689;12.4;0.053300;V +2025-08-11T10:25:34,889;12.6;0.041200;V +2025-08-11T10:25:35,089;12.8;0.029100;V +2025-08-11T10:25:35,289;13;0.029100;V +2025-08-11T10:25:35,489;13.2;0.023000;V +2025-08-11T10:25:35,689;13.4;0.023000;V +2025-08-11T10:25:35,889;13.6;0.020800;V +2025-08-11T10:25:36,089;13.8;0.018600;V +2025-08-11T10:25:36,289;14;0.018600;V +2025-08-11T10:25:36,489;14.2;0.007700;V +2025-08-11T10:25:36,689;14.4;0.007700;V +2025-08-11T10:25:36,889;14.6;0.006100;V +2025-08-11T10:25:37,089;14.8;0.004500;V +2025-08-11T10:25:37,289;15;0.004500;V +2025-08-11T10:25:37,489;15.2;0.080400;V +2025-08-11T10:25:37,689;15.4;0.080400;V +2025-08-11T10:25:37,889;15.6;0.118350;V +2025-08-11T10:25:38,089;15.8;0.156300;V +2025-08-11T10:25:38,289;16;0.156300;V +2025-08-11T10:25:38,489;16.2;-0.011100;V +2025-08-11T10:25:38,689;16.4;-0.011100;V +2025-08-11T10:25:38,889;16.6;0.001150;V +2025-08-11T10:25:39,089;16.8;0.013400;V +2025-08-11T10:25:39,289;17;0.013400;V +2025-08-11T10:25:39,489;17.2;-0.051650;V +2025-08-11T10:25:39,689;17.4;-0.116700;V +2025-08-11T10:25:39,889;17.6;-0.116700;V +2025-08-11T10:25:40,089;17.8;-0.004700;V +2025-08-11T10:25:40,289;18;-0.004700;V +2025-08-11T10:25:40,489;18.2;-0.022100;V +2025-08-11T10:25:40,689;18.4;-0.039500;V +2025-08-11T10:25:40,889;18.6;-0.039500;V +2025-08-11T10:25:41,089;18.8;0.017900;V +2025-08-11T10:25:41,289;19;0.017900;V +2025-08-11T10:25:41,489;19.2;0.008900;V +2025-08-11T10:25:41,689;19.4;-0.000100;V +2025-08-11T10:25:41,889;19.6;-0.000100;V +2025-08-11T10:25:42,089;19.8;-0.042000;V +2025-08-11T10:25:42,289;20;-0.042000;V +2025-08-11T10:25:42,489;20.2;-0.005550;V +2025-08-11T10:25:42,689;20.4;0.030900;V +2025-08-11T10:25:42,889;20.6;0.030900;V +2025-08-11T10:25:43,089;20.8;0.006100;V +2025-08-11T10:25:43,289;21;0.006100;V +2025-08-11T10:25:43,489;21.2;-0.006100;V +2025-08-11T10:25:43,689;21.4;-0.018300;V +2025-08-11T10:25:43,889;21.6;-0.018300;V +2025-08-11T10:25:44,089;21.8;0.000700;V +2025-08-11T10:25:44,289;22;0.000700;V +2025-08-11T10:25:44,489;22.2;0.009400;V +2025-08-11T10:25:44,689;22.4;0.018100;V +2025-08-11T10:25:44,889;22.6;0.018100;V +2025-08-11T10:25:45,089;22.8;0.032300;V +2025-08-11T10:25:45,289;23;0.032300;V +2025-08-11T10:25:45,489;23.2;0.032600;V +2025-08-11T10:25:45,689;23.4;0.032900;V +2025-08-11T10:25:45,889;23.6;0.032900;V +2025-08-11T10:25:46,089;23.8;0.029600;V +2025-08-11T10:25:46,289;24;0.029600;V +2025-08-11T10:25:46,489;24.2;0.006350;V +2025-08-11T10:25:46,689;24.4;-0.016900;V +2025-08-11T10:25:46,889;24.6;-0.016900;V +2025-08-11T10:25:47,089;24.8;-0.001000;V +2025-08-11T10:25:47,289;25;-0.001000;V +2025-08-11T10:25:47,489;25.2;0.004100;V +2025-08-11T10:25:47,689;25.4;0.009200;V +2025-08-11T10:25:47,889;25.6;0.009200;V +2025-08-11T10:25:48,089;25.8;0.008100;V +2025-08-11T10:25:48,289;26;0.008100;V +2025-08-11T10:25:48,489;26.2;0.002950;V +2025-08-11T10:25:48,689;26.4;-0.002200;V +2025-08-11T10:25:48,889;26.6;-0.002200;V +2025-08-11T10:25:49,089;26.8;0.015600;V +2025-08-11T10:25:49,289;27;0.015600;V +2025-08-11T10:25:49,489;27.2;0.007800;V +2025-08-11T10:25:49,689;27.4;0.000000;V +2025-08-11T10:25:49,889;27.6;0.000000;V +2025-08-11T10:25:50,089;27.8;0.014200;V +2025-08-11T10:25:50,289;28;0.014200;V +2025-08-11T10:25:50,489;28.2;0.040000;V +2025-08-11T10:25:50,689;28.4;0.065800;V +2025-08-11T10:25:50,889;28.6;0.065800;V +2025-08-11T10:25:51,089;28.8;0.015300;V +2025-08-11T10:25:51,289;29;0.015300;V +2025-08-11T10:25:51,489;29.2;0.018650;V +2025-08-11T10:25:51,689;29.4;0.022000;V +2025-08-11T10:25:51,889;29.6;0.022000;V +2025-08-11T10:25:52,089;29.8;0.007600;V +2025-08-11T10:25:52,289;30;0.007600;V +2025-08-11T10:25:52,489;30.2;0.000800;V +2025-08-11T10:25:52,689;30.4;-0.006000;V +2025-08-11T10:25:52,889;30.6;-0.006000;V +2025-08-11T10:25:53,089;30.8;0.002400;V +2025-08-11T10:25:53,289;31;0.002400;V +2025-08-11T10:25:53,489;31.2;0.002700;V +2025-08-11T10:25:53,689;31.4;0.003000;V +2025-08-11T10:25:53,889;31.6;0.003000;V +2025-08-11T10:25:54,089;31.8;0.549700;V +2025-08-11T10:25:54,289;32;0.549700;V +2025-08-11T10:25:54,489;32.2;0.292850;V +2025-08-11T10:25:54,689;32.4;0.036000;V +2025-08-11T10:25:54,889;32.6;0.036000;V +2025-08-11T10:25:55,089;32.8;0.000000;V +2025-08-11T10:25:55,289;33;0.000000;V +2025-08-11T10:25:55,489;33.2;-0.006500;V +2025-08-11T10:25:55,689;33.4;-0.013000;V +2025-08-11T10:25:55,889;33.6;-0.013000;V +2025-08-11T10:25:56,089;33.8;0.000000;V +2025-08-11T10:25:56,289;34;0.000000;V +2025-08-11T10:25:56,489;34.2;-0.003500;V +2025-08-11T10:25:56,689;34.4;-0.007000;V +2025-08-11T10:25:56,889;34.6;-0.007000;V +2025-08-11T10:25:57,089;34.8;-0.007000;V +2025-08-11T10:25:57,289;35;-0.007000;V +2025-08-11T10:25:57,489;35.2;-0.004000;V +2025-08-11T10:25:57,689;35.4;-0.001000;V +2025-08-11T10:25:57,889;35.6;-0.001000;V +2025-08-11T10:25:58,089;35.8;0.322000;V +2025-08-11T10:25:58,289;36;0.322000;V +2025-08-11T10:25:58,489;36.2;0.075000;V +2025-08-11T10:25:58,689;36.4;-0.172000;V +2025-08-11T10:25:58,889;36.6;-0.172000;V +2025-08-11T10:25:59,089;36.8;0.123000;V +2025-08-11T10:25:59,289;37;0.123000;V +2025-08-11T10:25:59,489;37.2;-0.551500;V +2025-08-11T10:25:59,689;37.4;-1.226000;V +2025-08-11T10:25:59,889;37.6;-1.226000;V +2025-08-11T10:26:00,089;37.8;-0.059000;V +2025-08-11T10:26:00,289;38;-0.059000;V +2025-08-11T10:26:00,489;38.2;0.345500;V +2025-08-11T10:26:00,689;38.4;0.750000;V +2025-08-11T10:26:00,889;38.6;0.750000;V +2025-08-11T10:26:01,089;38.8;1.205000;V +2025-08-11T10:26:01,289;39;1.205000;V +2025-08-11T10:26:01,489;39.2;1.241500;V +2025-08-11T10:26:01,689;39.4;1.278000;V +2025-08-11T10:26:01,889;39.6;1.278000;V +2025-08-11T10:26:02,089;39.8;0.704000;V +2025-08-11T10:26:02,289;40;0.704000;V +2025-08-11T10:26:02,489;40.2;0.718500;V +2025-08-11T10:26:02,689;40.4;0.733000;V +2025-08-11T10:26:02,889;40.6;0.733000;V +2025-08-11T10:26:03,089;40.8;0.153000;V +2025-08-11T10:26:03,289;41;0.153000;V +2025-08-11T10:26:03,489;41.2;0.198500;V +2025-08-11T10:26:03,689;41.4;0.244000;V +2025-08-11T10:26:03,889;41.6;0.244000;V +2025-08-11T10:26:04,089;41.8;-0.013000;V +2025-08-11T10:26:04,289;42;-0.013000;V +2025-08-11T10:26:04,489;42.2;-0.344500;V +2025-08-11T10:26:04,689;42.4;-0.676000;V +2025-08-11T10:26:04,889;42.6;-0.676000;V +2025-08-11T10:26:05,089;42.8;-0.820000;V +2025-08-11T10:26:05,289;43;-0.820000;V +2025-08-11T10:26:05,489;43.2;-0.059500;V +2025-08-11T10:26:05,689;43.4;0.701000;V +2025-08-11T10:26:05,889;43.6;0.701000;V +2025-08-11T10:26:06,089;43.8;1.168000;V +2025-08-11T10:26:06,289;44;1.168000;V +2025-08-11T10:26:06,489;44.2;0.625500;V +2025-08-11T10:26:06,689;44.4;0.083000;V +2025-08-11T10:26:06,889;44.6;0.083000;V +2025-08-11T10:26:07,089;44.8;-0.237000;V +2025-08-11T10:26:07,289;45;-0.237000;V +2025-08-11T10:26:07,489;45.2;-0.232000;V +2025-08-11T10:26:07,689;45.4;-0.227000;V +2025-08-11T10:26:07,889;45.6;-0.227000;V +2025-08-11T10:26:08,089;45.8;0.432000;V +2025-08-11T10:26:08,289;46;0.432000;V +2025-08-11T10:26:08,489;46.2;0.348500;V +2025-08-11T10:26:08,689;46.4;0.265000;V +2025-08-11T10:26:08,889;46.6;0.265000;V +2025-08-11T10:26:09,089;46.8;-0.043000;V +2025-08-11T10:26:09,289;47;-0.043000;V +2025-08-11T10:26:09,489;47.2;-0.021500;V +2025-08-11T10:26:09,689;47.4;0.000000;V +2025-08-11T10:26:09,889;47.6;0.000000;V +2025-08-11T10:26:10,089;47.8;1.144200;V +2025-08-11T10:26:10,289;48;1.144200;V +2025-08-11T10:26:10,489;48.2;0.712500;V +2025-08-11T10:26:10,689;48.4;0.280800;V +2025-08-11T10:26:10,889;48.6;0.280800;V +2025-08-11T10:26:11,089;48.8;0.835900;V +2025-08-11T10:26:11,289;49;0.835900;V +2025-08-11T10:26:11,489;49.2;0.046150;V +2025-08-11T10:26:11,689;49.4;-0.743600;V +2025-08-11T10:26:11,889;49.6;-0.743600;V +2025-08-11T10:26:12,089;49.8;0.002900;V +2025-08-11T10:26:12,289;50;0.002900;V +2025-08-11T10:26:12,489;50.2;0.003250;V +2025-08-11T10:26:12,689;50.4;0.003600;V +2025-08-11T10:26:12,889;50.6;0.003600;V +2025-08-11T10:26:13,089;50.8;-0.049300;V +2025-08-11T10:26:13,289;51;-0.049300;V +2025-08-11T10:26:13,489;51.2;-0.024250;V +2025-08-11T10:26:13,689;51.4;0.000800;V +2025-08-11T10:26:13,889;51.6;0.000800;V +2025-08-11T10:26:14,089;51.8;-0.009800;V +2025-08-11T10:26:14,289;52;-0.009800;V +2025-08-11T10:26:14,489;52.2;-0.016300;V +2025-08-11T10:26:14,689;52.4;-0.022800;V +2025-08-11T10:26:14,889;52.6;-0.022800;V +2025-08-11T10:26:15,089;52.8;-0.003100;V +2025-08-11T10:26:15,289;53;-0.003100;V +2025-08-11T10:26:15,489;53.2;-0.006600;V +2025-08-11T10:26:15,689;53.4;-0.010100;V +2025-08-11T10:26:15,889;53.6;-0.010100;V +2025-08-11T10:26:16,089;53.8;0.001600;V +2025-08-11T10:26:16,289;54;0.001600;V diff --git a/tests/data/m9803r.json b/tests/data/m9803r.json deleted file mode 100644 index cbec126..0000000 --- a/tests/data/m9803r.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "decoder": "M9803RContinuous", - "tests": [ - { - "hex": "00 04 03 02 01 00 00 00 04 00 0D 0A", - "expected": { - "dval": 123.4, - "val": "123.4", - "unit": "mV", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - } - ] -} diff --git a/tests/data/qm1537.json b/tests/data/qm1537.json deleted file mode 100644 index a0cda73..0000000 --- a/tests/data/qm1537.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "decoder": "QM1537Continuous", - "tests": [ - { - "hex": "2B 33 34 38 32 20 34 31 00 40 80 22 0D 0A", - "expected": { - "dval": 348.2, - "val": "348.2", - "unit": "mV", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - } - ] -} diff --git a/tests/data/rs22812.json b/tests/data/rs22812.json deleted file mode 100644 index 55701b0..0000000 --- a/tests/data/rs22812.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "decoder": "RS22812Continuous", - "tests": [ - { - "hex": "00 03 00 D7 D7 DF 50 0B 24", - "expected": { - "dval": -0.001, - "val": " -1.000", - "unit": "mV", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - } - ] -} diff --git a/tests/data/vc820.json b/tests/data/vc820.json deleted file mode 100644 index 7d72a17..0000000 --- a/tests/data/vc820.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "decoder": "VC820Continuous", - "tests": [ - { - "hex": "17 2F 3D 47 5D 67 7D 8A 97 A0 B8 C0 D4 E8", - "expected": { - "dval": -0.4, - "val": " -000.4", - "unit": "mV", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - }, - { - "hex": "15 25 3B 40 55 67 7D 8F 9E A0 B0 C0 D1 E1", - "expected": { - "dval": 210.6, - "val": " 210.6", - "unit": "C", - "range": "MANU", - "special": "TE", - "hold": false, - "showBar": true - } - } - ] -} diff --git a/tests/data/vc870.json b/tests/data/vc870.json deleted file mode 100644 index 6bb6fc9..0000000 --- a/tests/data/vc870.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "decoder": "VC870Continuous", - "tests": [ - { - "hex": "30 30 30 34 30 30 30 30 34 30 30 30 30 00 00 30 30 30 30 30 31 0D 0A", - "expected": { - "dval": 4.0, - "val": " 4.0000", - "unit": "V", - "special": "DC", - "dval2": 4.0, - "val2": " 4.0000", - "unit2": "V", - "hold": false, - "showBar": true - } - } - ] -} diff --git a/tests/data/vc940.json b/tests/data/vc940.json deleted file mode 100644 index e4c9372..0000000 --- a/tests/data/vc940.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "decoder": "VC940Continuous", - "tests": [ - { - "hex": "30 30 30 30 30 31 31 30 31 0D 0A", - "expected": { - "dval": 0.0, - "val": "0.0000", - "unit": "V", - "range": "AUTO", - "special": "DC", - "hold": false, - "showBar": true - } - } - ] -}