... #include "cMainWindow.h" #include <QApplication> int main(int argc, char **argv) { QApplication app(argc, argv); cMainWindow *oMainWindow = new cMainWindow; oMainWindow->resize(400, 200); oMainWindow->show(); return app.exec(); } ...
... #pragma once #include <QMainWindow> #include "cActions.h" class QLabel; namespace Ui { class cMainWindow; } class cMainWindow : public QMainWindow { Q_OBJECT public: using sAction = cActions::sAction; public: explicit cMainWindow(QWidget *parent = 0); ~cMainWindow(); private slots: void on_actionHomePage_triggered(); void on_actionThemePage_triggered(); void onAction(const sAction &_action); private: Ui::cMainWindow *ui; QLabel *m_themeStatus; }; ...
... #include "cMainWindow.h" #include "ui_cMainWindow.h" #include <QStyleFactory> #include <QMessageBox> #include <QLabel> const QString ACTION_APPLY_STYLE = "ACTION_APPLY_STYLE"; cMainWindow::cMainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::cMainWindow) { ui->setupUi(this); ui->stackedWidget->setCurrentWidget(ui->pageHome); ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); QStringList oThemes = QStyleFactory::keys(); for (const auto &oTheme : oThemes) { qDebug() << "La detection du style d'apparence a reussi." << "|theme=" << oTheme; ui->tableWidget->insertRow(ui->tableWidget->rowCount()); QTableWidgetItem *oTableWidgetItem = new QTableWidgetItem(oTheme); ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 0, oTableWidgetItem); cActions *oActions = new cActions; oActions->addAction(oTheme, ACTION_APPLY_STYLE, "Appliquer le style"); oActions->initActions(); connect(oActions, &cActions::emitAction, this, &cMainWindow::onAction); ui->tableWidget->setCellWidget(ui->tableWidget->rowCount() - 1, 1, oActions); } qDebug() << "La detection du style en cours est termine." << "|style=" << qApp->style()->name(); m_themeStatus = new QLabel; statusBar()->addWidget(m_themeStatus); m_themeStatus->setText(tr("Thème : %1").arg(qApp->style()->name())); } cMainWindow::~cMainWindow() { delete ui; } void cMainWindow::on_actionHomePage_triggered() { ui->stackedWidget->setCurrentWidget(ui->pageHome); } void cMainWindow::on_actionThemePage_triggered() { ui->stackedWidget->setCurrentWidget(ui->pageTheme); } void cMainWindow::onAction(const sAction &_action) { qDebug() << "L'action est en cours d'application." << "|data=" << _action.data << "|key=" << _action.key << "|text=" << _action.text; if (_action.key == ACTION_APPLY_STYLE) { qApp->setStyle(_action.data); m_themeStatus->setText(tr("Thème : %1").arg(qApp->style()->name())); } } ...
... #pragma once #include <QWidget> #include <QVector> #include <QMap> namespace Ui { class cActions; } class cActions : public QWidget { Q_OBJECT public: struct sAction { QString data; QString key; QString text; }; public: explicit cActions(QWidget *parent = 0); ~cActions(); void addAction(const QString &_data, const QString &_key, const QString &_text); void initActions(); private: bool isActive(const QString &_key) const; bool loadAction(const QString &_key, sAction &_action) const; private slots: void onAction(); signals: void emitAction(sAction); private: Ui::cActions *ui; QVector<sAction> m_actions; QMap<QAction *, QString> m_keys; }; ...
... #include "cActions.h" #include "ui_cActions.h" #include <QMenu> cActions::cActions(QWidget *parent) : QWidget(parent), ui(new Ui::cActions) { ui->setupUi(this); ui->layActions->setAlignment(Qt::AlignCenter); } cActions::~cActions() { delete ui; } void cActions::addAction(const QString &_data, const QString &_key, const QString &_text) { if (!isActive(_key)) { sAction oAction{_data, _key, _text}; m_actions.push_back(oAction); } else { qDebug() << "L'action a ete deja ajoutee a la liste." << "|data=" << _data << "|key=" << _key << "|text=" << _text; } } void cActions::initActions() { if (m_actions.isEmpty()) { qDebug() << "Aucune action n'a ete ajoutee à liste"; return; } QMenu *oMenu = new QMenu(this); for (const auto &oAction : m_actions) { QAction *iAction = new QAction(oAction.text); iAction->setData(oAction.data); connect(iAction, &QAction::triggered, this, &cActions::onAction); m_keys[iAction] = oAction.key; oMenu->addAction(iAction); } ui->btnActions->setMenu(oMenu); } bool cActions::isActive(const QString &_key) const { for (const auto &oAction : m_actions) { if (oAction.key == _key) { return true; } } return false; } bool cActions::loadAction(const QString &_key, sAction &_action) const { for (const auto &oAction : m_actions) { if (oAction.key == _key) { _action = oAction; return true; } } return false; } void cActions::onAction() { QAction *oAction = qobject_cast<QAction *>(sender()); QString oKey = m_keys[oAction]; sAction iAction; if (loadAction(oKey, iAction)) { emit emitAction(iAction); } } ...
... cmake_minimum_required(VERSION 3.10.0) project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_PREFIX_PATH "C:/Qt/6.5.2/msvc2019_64/lib/cmake") find_package(Qt6 REQUIRED COMPONENTS Widgets ) qt_wrap_ui(UI_FILES cMainWindow.ui cActions.ui ) add_executable(rdvcpp main.cpp cMainWindow.cpp cActions.cpp resources.qrc ${UI_FILES} ) target_link_libraries (rdvcpp Qt6::Widgets ) ...
... <RCC> <qresource prefix="/img"> <file alias="logo.png">data/img/logo.png</file> </qresource> </RCC> ...
... rdvcpp.exe ...
... #include "cMainWindow.h" #include <QApplication> #include <QFontDatabase> int main(int argc, char **argv) { QApplication app(argc, argv); QString oFontFile(":/font/fontawesome-webfont.ttf"); int id = QFontDatabase::addApplicationFont(oFontFile); if (id == -1) { qDebug() << "Le chargement de la police a echoue." << "|fontFile=" << oFontFile; } else { QStringList oFontFamilies = QFontDatabase::applicationFontFamilies(id); qDebug() << "Le chargement de la police a reussi." << "|fontFile=" << oFontFile << "|fontFamilies=" << oFontFamilies; } cMainWindow *oMainWindow = new cMainWindow; oMainWindow->resize(400, 200); oMainWindow->show(); return app.exec(); } ...
... #pragma once #include <QMainWindow> class cHelpWindow; namespace Ui { class cMainWindow; } class cMainWindow : public QMainWindow { Q_OBJECT public: explicit cMainWindow(QWidget *parent = 0); ~cMainWindow(); private slots: void on_actionHelpApp_triggered(); void on_actionAboutApp_triggered(); void on_actionAboutQt_triggered(); private: Ui::cMainWindow *ui; cHelpWindow *m_helpWindow; }; ...
... #include "cMainWindow.h" #include "ui_cMainWindow.h" #include "cHelpWindow.h" #include <QMessageBox> #include <QFile> #include <QFontDatabase> #include <QDebug> cMainWindow::cMainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::cMainWindow) { ui->setupUi(this); QFile oFile(":/help/fr.html"); if (!oFile.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Le fichier d'aide est introuvable." << "filename=" << oFile.fileName(); return; } QByteArray oFileData = oFile.readAll(); m_helpWindow = new cHelpWindow(QString(oFileData), this); } cMainWindow::~cMainWindow() { delete ui; } void cMainWindow::on_actionHelpApp_triggered() { m_helpWindow->exec(); } void cMainWindow::on_actionAboutApp_triggered() { QMessageBox::about(this, "A propos de l'application ", "<b>ReadySCOPE - v1.0</b><br>" "Oscilloscope numérique<br><br>" "Produit par <a href='https://readydev.ovh/home'>ReadyDEV</a><br>" "Plateforme de Développement Continu"); } void cMainWindow::on_actionAboutQt_triggered() { QMessageBox::aboutQt(this); } ...
... #pragma once #include <QDialog> class cFloatButton; namespace Ui { class cHelpWindow; } class cHelpWindow : public QDialog { Q_OBJECT public: explicit cHelpWindow(const QString &_message, QWidget *parent = 0); ~cHelpWindow(); protected: void resizeEvent(QResizeEvent *event); private slots: void onOpenTopLink(); void onOpenBottomLink(); private: Ui::cHelpWindow *ui; QString m_message; cFloatButton *m_topLink; cFloatButton *m_bottomLink; }; ...
... #include "cHelpWindow.h" #include "ui_cHelpWindow.h" #include "cFloatButton.h" #include <QLabel> #include <QResizeEvent> #include <QScrollBar> using namespace std::chrono_literals; cHelpWindow::cHelpWindow(const QString &_message, QWidget *parent) : QDialog(parent), ui(new Ui::cHelpWindow), m_message(_message) { ui->setupUi(this); ui->txtHelp->setHtml(m_message); resize(600, 300); m_bottomLink = new cFloatButton(ICON_FA_CHEVRON_DOWN, this); connect(m_bottomLink, &cFloatButton::emitClicked, this, &cHelpWindow::onOpenBottomLink); m_topLink = new cFloatButton(ICON_FA_CHEVRON_UP, this); connect(m_topLink, &cFloatButton::emitClicked, this, &cHelpWindow::onOpenTopLink); } cHelpWindow::~cHelpWindow() { delete ui; } void cHelpWindow::resizeEvent(QResizeEvent *event) { m_bottomLink->move(width() - 75 - 50, height() - 85); m_topLink->move(width() - 75, height() - 85); } void cHelpWindow::onOpenTopLink() { QScrollBar *oScrollBar = ui->txtHelp->verticalScrollBar(); oScrollBar->setValue(0); } void cHelpWindow::onOpenBottomLink() { QScrollBar *oScrollBar = ui->txtHelp->verticalScrollBar(); oScrollBar->setValue(oScrollBar->maximum()); } ...
... #pragma once #include <QWidget> #include "IconsFontAwesome4.h" namespace Ui { class cFloatButton; } class cFloatButton : public QWidget { Q_OBJECT public: explicit cFloatButton(const QString &_iconLabel, QWidget *parent = 0); ~cFloatButton(); protected: bool eventFilter(QObject *object, QEvent *event); signals: void emitClicked(); private: Ui::cFloatButton *ui; QString m_iconLabel; }; ...
... #include "cFloatButton.h" #include "ui_cFloatButton.h" #include <QMouseEvent> using namespace std::chrono_literals; cFloatButton::cFloatButton(const QString &_iconLabel, QWidget *parent) : QWidget(parent), ui(new Ui::cFloatButton), m_iconLabel(_iconLabel) { ui->setupUi(this); adjustSize(); QFont font; font.setFamily("FontAwesome"); font.setPixelSize(20); ui->lblButton->setFont(font); ui->lblButton->setText(m_iconLabel); ui->lblButton->installEventFilter(this); } cFloatButton::~cFloatButton() { delete ui; } bool cFloatButton::eventFilter(QObject *object, QEvent *event) { if (object == ui->lblButton && event->type() == QEvent::MouseButtonRelease) { QMouseEvent *oMouseEvent = static_cast<QMouseEvent *>(event); if (oMouseEvent->button() == Qt::LeftButton) { emit emitClicked(); return true; } } return false; } ...
... cmake_minimum_required(VERSION 3.10.0) project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_PREFIX_PATH "C:/Qt/6.5.2/msvc2019_64/lib/cmake") find_package(Qt6 REQUIRED COMPONENTS Widgets ) qt_wrap_ui(UI_FILES cMainWindow.ui cHelpWindow.ui cFloatButton.ui ) add_executable(rdvcpp main.cpp cMainWindow.cpp cHelpWindow.cpp cFloatButton.cpp resources.qrc ${UI_FILES} ) target_link_libraries (rdvcpp Qt6::Widgets ) ...
... <RCC> <qresource prefix="/img"> <file alias="logo.png">data/img/logo.png</file> </qresource> <qresource prefix="/help"> <file alias="fr.html">data/help/fr.html</file> </qresource> <qresource prefix="/font"> <file alias="fontawesome-webfont.ttf">data/font/fontawesome-webfont.ttf</file> </qresource> </RCC> ...
... rdvcpp.exe ...
... #include "cMainWindow.h" #include <QApplication> int main(int argc, char **argv) { QApplication app(argc, argv); cMainWindow *oMainWindow = new cMainWindow; oMainWindow->resize(600, 400); oMainWindow->show(); return app.exec(); } ...
... #pragma once #include <QMainWindow> #include <QtSerialPort/QSerialPort> #include <QVector> #include <QMap> namespace Ui { class cMainWindow; } class cMainWindow : public QMainWindow { Q_OBJECT public: explicit cMainWindow(QWidget *parent = 0); ~cMainWindow(); private: bool isActive(const QString &_portName) const; void addConnection(const QString &_portName); void addPortToTab(const QString &_portName); bool loadConnection(const QString &_portName, QSerialPort **_serialPort) const; bool loadPortToTab(const QString &_portName, QWidget **_tabWidget) const; bool loadPortToTab(QWidget *_oTabWidget, QString &_portName) const; bool loadPortToTab(const QString &_portName, QLayout **_layout) const; void showSendMessageTab(const QString &_portName) const; void clearOpenConnection(); void clearSendMessagePort1(); void clearSendMessagePort2(); private slots: void on_actionOpenConnection_triggered(); void on_actionDisplayConnection_triggered(); void on_btnOpenConnection_clicked(); void on_btnSendMessagePort1_clicked(); void on_btnSendMessagePort2_clicked(); void onReadyData(); void onErrorOccurred(QSerialPort::SerialPortError error); void onSendMessage(QAction *_action); private: Ui::cMainWindow *ui; QVector<QSerialPort *> m_connections; QMap<QString, QWidget *> m_portToTab; }; ...
... #include "cMainWindow.h" #include "ui_cMainWindow.h" #include "cPortAction.h" #include "cMessageSend.h" #include "cMessageRecv.h" #include <QMessageBox> #include <QScrollBar> cMainWindow::cMainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::cMainWindow) { ui->setupUi(this); ui->stackedWidget->setCurrentWidget(ui->pageHome); ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->tabWidget->setCurrentWidget(ui->tabSendMessagePort1); ui->messageLayoutPort1->setAlignment(Qt::AlignTop); ui->messageLayoutPort2->setAlignment(Qt::AlignTop); } cMainWindow::~cMainWindow() { delete ui; } bool cMainWindow::isActive(const QString &_portName) const { for (QSerialPort *oSerialPort : m_connections) { if (oSerialPort->portName() == _portName) { if (oSerialPort->isOpen()) return true; } } return false; } void cMainWindow::addConnection(const QString &_portName) { ui->tableWidget->insertRow(ui->tableWidget->rowCount()); QTableWidgetItem *oTableWidgetItem = new QTableWidgetItem(_portName); ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 0, oTableWidgetItem); cPortAction *oPortAction = new cPortAction(_portName); connect(oPortAction, &cPortAction::emitSendMessage, this, &cMainWindow::onSendMessage); ui->tableWidget->setCellWidget(ui->tableWidget->rowCount() - 1, 1, oPortAction); } void cMainWindow::addPortToTab(const QString &_portName) { switch (m_portToTab.size()) { case 0: m_portToTab[_portName] = ui->tabSendMessagePort1; ui->tabWidget->setTabText(ui->tabWidget->indexOf(ui->tabSendMessagePort1), _portName); break; case 1: m_portToTab[_portName] = ui->tabSendMessagePort2; ui->tabWidget->setTabText(ui->tabWidget->indexOf(ui->tabSendMessagePort2), _portName); break; default: break; } } bool cMainWindow::loadConnection(const QString &_portName, QSerialPort **_serialPort) const { for (QSerialPort *oSerialPort : m_connections) { if (oSerialPort->portName() == _portName) { if (oSerialPort->isOpen()) { (*_serialPort) = oSerialPort; return true; } } } return false; } bool cMainWindow::loadPortToTab(const QString &_portName, QWidget **_tabWidget) const { QMap<QString, QWidget *>::const_iterator it; for (it = m_portToTab.begin(); it != m_portToTab.end(); ++it) { if (it.key() == _portName) { (*_tabWidget) = it.value(); return true; } } return false; } bool cMainWindow::loadPortToTab(QWidget *_oTabWidget, QString &_portName) const { QMap<QString, QWidget *>::const_iterator it; for (it = m_portToTab.begin(); it != m_portToTab.end(); ++it) { if (it.value() == _oTabWidget) { _portName = it.key(); return true; } } return false; } bool cMainWindow::loadPortToTab(const QString &_portName, QLayout **_layout) const { QWidget *oTabWidget; if (!loadPortToTab(_portName, &oTabWidget)) return false; if (oTabWidget == ui->tabSendMessagePort1) { (*_layout) = ui->messageLayoutPort1; return true; } if (oTabWidget == ui->tabSendMessagePort2) { (*_layout) = ui->messageLayoutPort2; return true; } return false; } void cMainWindow::showSendMessageTab(const QString &_portName) const { QWidget *oTabWidget; if (!loadPortToTab(_portName, &oTabWidget)) return; ui->tabWidget->setTabVisible(ui->tabWidget->indexOf(ui->tabSendMessagePort1), (oTabWidget == ui->tabSendMessagePort1)); ui->tabWidget->setTabVisible(ui->tabWidget->indexOf(ui->tabSendMessagePort2), (oTabWidget == ui->tabSendMessagePort2)); } void cMainWindow::clearOpenConnection() { ui->edtPortName->clear(); } void cMainWindow::clearSendMessagePort1() { ui->edtSendMessagePort1->clear(); } void cMainWindow::clearSendMessagePort2() { ui->edtSendMessagePort2->clear(); } void cMainWindow::on_actionOpenConnection_triggered() { if (m_connections.size() == 2) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("Le nombre maximal de connexions est atteint.")); return; } ui->stackedWidget->setCurrentWidget(ui->pageOpenConnection); } void cMainWindow::on_actionDisplayConnection_triggered() { ui->stackedWidget->setCurrentWidget(ui->pageDisplayConnection); } void cMainWindow::on_btnOpenConnection_clicked() { QString oPortName = ui->edtPortName->text(); if (oPortName.isEmpty()) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("Le nom du port est obligatoire.")); return; } if (isActive(oPortName)) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("Le port série est déjà ouvert.")); return; } QSerialPort *oSerialPort = new QSerialPort(this); connect(oSerialPort, &QSerialPort::readyRead, this, &cMainWindow::onReadyData); connect(oSerialPort, &QSerialPort::errorOccurred, this, &cMainWindow::onErrorOccurred); oSerialPort->setPortName(oPortName); oSerialPort->setBaudRate(QSerialPort::Baud9600); oSerialPort->setDataBits(QSerialPort::Data8); oSerialPort->setFlowControl(QSerialPort::NoFlowControl); oSerialPort->setParity(QSerialPort::NoParity); oSerialPort->setStopBits(QSerialPort::OneStop); oSerialPort->open(QIODevice::ReadWrite); if (!oSerialPort->isOpen()) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("La connexion au port série a échoué.")); return; } QMessageBox::information(this, tr("Messages d'informations"), tr("La connexion au port série a réussi.")); m_connections.push_back(oSerialPort); addConnection(oPortName); addPortToTab(oPortName); clearOpenConnection(); ui->stackedWidget->setCurrentWidget(ui->pageHome); } void cMainWindow::on_btnSendMessagePort1_clicked() { QString oMessage = ui->edtSendMessagePort1->toPlainText(); if (oMessage.isEmpty()) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("Le message est obligatoire.")); return; } QString oPortName; if (!loadPortToTab(ui->tabSendMessagePort1, oPortName)) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("Le nom du port est inconnu.")); return; } QSerialPort *oSerialPort; if (!loadConnection(oPortName, &oSerialPort)) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("La connexion port série est introuvable.")); return; } cMessageSend *oMessageSend = new cMessageSend(oMessage); ui->messageLayoutPort1->addWidget(oMessageSend); ui->scrollAreaPort1->widget()->adjustSize(); qApp->processEvents(); ui->scrollAreaPort1->verticalScrollBar()->setValue(ui->scrollAreaPort1->verticalScrollBar()->maximum()); oSerialPort->write(oMessage.toUtf8()); clearSendMessagePort1(); qDebug() << "L'envoi de message est termine." << "|portName=" << oSerialPort->portName() << "|message=" << oMessage.left(50); } void cMainWindow::on_btnSendMessagePort2_clicked() { QString oMessage = ui->edtSendMessagePort2->toPlainText(); if (oMessage.isEmpty()) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("Le message est obligatoire.")); return; } QString oPortName; if (!loadPortToTab(ui->tabSendMessagePort2, oPortName)) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("Le nom du port est inconnu.")); return; } QSerialPort *oSerialPort; if (!loadConnection(oPortName, &oSerialPort)) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("La connexion port série est introuvable.")); return; } cMessageSend *oMessageSend = new cMessageSend(oMessage); ui->messageLayoutPort2->addWidget(oMessageSend); ui->scrollAreaPort2->widget()->adjustSize(); qApp->processEvents(); ui->scrollAreaPort2->verticalScrollBar()->setValue(ui->scrollAreaPort2->verticalScrollBar()->maximum()); oSerialPort->write(oMessage.toUtf8()); clearSendMessagePort2(); qDebug() << "L'envoi de message est termine." << "|portName=" << oSerialPort->portName() << "|message=" << oMessage.left(50); } void cMainWindow::onReadyData() { QSerialPort *oSerialPort = qobject_cast<QSerialPort *>(sender()); QByteArray oMessage = oSerialPort->readAll(); QString oPortName = oSerialPort->portName(); QLayout *oMessageLayout; if (!loadPortToTab(oSerialPort->portName(), &oMessageLayout)) return; cMessageRecv *oMessageRecv = new cMessageRecv(oMessage); oMessageLayout->addWidget(oMessageRecv); qDebug() << "La reception de message est termine." << "|portName=" << oSerialPort->portName() << "|message=" << oMessage.left(50); } void cMainWindow::onErrorOccurred(QSerialPort::SerialPortError error) { if (error != QSerialPort::NoError) { QSerialPort *oSerialPort = qobject_cast<QSerialPort *>(sender()); qDebug() << "La connexion au port serie a echoue." << "|errorCode=" << error << "|portName=" << oSerialPort->portName(); } } void cMainWindow::onSendMessage(QAction *_action) { QString oPortName = _action->data().toString(); QSerialPort *oSerialPort; if (loadConnection(oPortName, &oSerialPort)) { ui->stackedWidget->setCurrentWidget(ui->pageSendMessage); showSendMessageTab(oPortName); qDebug() << "L'envoi de message a demarre." << "|portName=" << oSerialPort->portName(); } } ...
... #pragma once #include <QWidget> namespace Ui { class cPortAction; } class cPortAction : public QWidget { Q_OBJECT public: explicit cPortAction(const QString &_portName, QWidget *parent = 0); ~cPortAction(); private: void initActions(); private slots: void onSendMessage(); signals: void emitSendMessage(QAction *); private: Ui::cPortAction *ui; QString m_portName; }; ...
... #include "cPortAction.h" #include "ui_cPortAction.h" #include <QMenu> cPortAction::cPortAction(const QString &_portName, QWidget *parent) : QWidget(parent), ui(new Ui::cPortAction), m_portName(_portName) { ui->setupUi(this); ui->layActions->setAlignment(Qt::AlignCenter); initActions(); } cPortAction::~cPortAction() { delete ui; } void cPortAction::initActions() { QMenu *oMenu = new QMenu(this); QAction *oActions = new QAction("Envoyer un message"); oActions->setData(m_portName); oMenu->addAction(oActions); connect(oActions, &QAction::triggered, this, &cPortAction::onSendMessage); ui->btnActions->setMenu(oMenu); } void cPortAction::onSendMessage() { QAction *oActions = qobject_cast<QAction *>(sender()); emit emitSendMessage(oActions); } ...
... #pragma once #include <QWidget> namespace Ui { class cMessageSend; } class cMessageSend : public QWidget { Q_OBJECT public: explicit cMessageSend(const QString &_message, QWidget *parent = 0); ~cMessageSend(); private: Ui::cMessageSend *ui; QString m_message; }; ...
... #include "cMessageSend.h" #include "ui_cMessageSend.h" using namespace std::chrono_literals; cMessageSend::cMessageSend(const QString &_message, QWidget *parent) : QWidget(parent), ui(new Ui::cMessageSend), m_message(_message) { ui->setupUi(this); ui->layLogo->setAlignment(Qt::AlignTop); ui->lblMessage->setText(m_message); } cMessageSend::~cMessageSend() { delete ui; } ...
... #pragma once #include <QWidget> namespace Ui { class cMessageRecv; } class cMessageRecv : public QWidget { Q_OBJECT public: explicit cMessageRecv(const QString &_message, QWidget *parent = 0); ~cMessageRecv(); private: Ui::cMessageRecv *ui; QString m_message; }; ...
... #include "cMessageRecv.h" #include "ui_cMessageRecv.h" using namespace std::chrono_literals; cMessageRecv::cMessageRecv(const QString &_message, QWidget *parent) : QWidget(parent), ui(new Ui::cMessageRecv), m_message(_message) { ui->setupUi(this); ui->layLogo->setAlignment(Qt::AlignTop); ui->lblMessage->setText(m_message); } cMessageRecv::~cMessageRecv() { delete ui; } ...
... cmake_minimum_required(VERSION 3.10.0) project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_PREFIX_PATH "C:/Qt/6.5.2/msvc2019_64/lib/cmake") find_package(Qt6 REQUIRED COMPONENTS Widgets SerialPort ) qt_wrap_ui(UI_FILES cMainWindow.ui cPortAction.ui cMessageSend.ui cMessageRecv.ui ) add_executable(rdvcpp main.cpp cMainWindow.cpp cPortAction.cpp cMessageSend.cpp cMessageRecv.cpp resources.qrc ${UI_FILES} ) target_link_libraries (rdvcpp Qt6::Widgets Qt6::SerialPort ) ...
... <RCC> <qresource prefix="/img"> <file alias="logo.png">data/img/logo.png</file> </qresource> </RCC> ...
... rdvcpp.exe ...
... #include "cMainWindow.h" #include <QApplication> int main(int argc, char **argv) { QApplication app(argc, argv); cMainWindow *oMainWindow = new cMainWindow; oMainWindow->resize(400, 500); oMainWindow->show(); return app.exec(); } ...
... #pragma once #include <QMainWindow> class QLabel; class QSettings; namespace Ui { class cMainWindow; } class cMainWindow : public QMainWindow { Q_OBJECT public: struct sSettingsDTO { // General QString inputDevice; int bufferSize; int nanValue; bool isAfterGlow; int refreshRate; QString settingsPath; // Format QString displayFormat; QString binaryFormat; // Sacling double scalingA; double scalingB; bool isScalingEnabled; }; public: explicit cMainWindow(QWidget *parent = 0); ~cMainWindow(); private: void loadDefaultValue(sSettingsDTO &_settingsDTO); void readSettings(sSettingsDTO &_settingsDTO); void writeSettings(const sSettingsDTO &_settingsDTO); void saveSettings(QSettings &_settings, const sSettingsDTO &_settingsDTO); void loadSettings(QSettings &_settings, sSettingsDTO &_settingsDTO); protected: void closeEvent(QCloseEvent *event); private slots: void on_actionSaveSettings_triggered(); void on_actionLoadSettings_triggered(); void on_actionSettingsPage_triggered(); void on_btnSettingsOK_clicked(); private: Ui::cMainWindow *ui; QString m_settingsPath; }; ...
... #include "cMainWindow.h" #include "ui_cMainWindow.h" #include <QFileDialog> #include <QSettings> #include <QDir> #include <QFileInfo> #include <QMessageBox> #include <QCloseEvent> // Organization static const QString DEF_ORGANIZATION_NAME = "ReadyDEV"; static const QString DEF_APP_NAME = "ReadySCOPE"; // Settings : General static const QString DEF_INPUT_DEVICE = "InputDevice"; static const QString DEF_BUFFER_SIZE = "BufferSize"; static const QString DEF_NAN_VALUE = "NanValue"; static const QString DEF_AFTER_GLOW = "AfterGlow"; static const QString DEF_REFRESH_RATE = "RefreshRate"; static const QString DEF_SETTINGS_PATH = "SettingsPath"; // Settings : Format static const QString DEF_SETTINGS_FORMAT = "Format"; static const QString DEF_DISPLAY_FORMAT = "DisplayFormat"; static const QString DEF_BINARY_FORMAT = "BinaryFormat"; // Settings : Scaling static const QString DEF_SETTINGS_SCALING = "Scaling"; static const QString DEF_SCALING_A = "ScalingA"; static const QString DEF_SCALING_B = "ScalingB"; static const QString DEF_SCALING_ENABLED = "ScalingEnabled"; cMainWindow::cMainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::cMainWindow) { ui->setupUi(this); ui->stackedWidget->setCurrentWidget(ui->pageHome); QSettings oSettings(DEF_ORGANIZATION_NAME, DEF_APP_NAME); sSettingsDTO oSettingsDTO; loadSettings(oSettings, oSettingsDTO); writeSettings(oSettingsDTO); } cMainWindow::~cMainWindow() { delete ui; } void cMainWindow::loadDefaultValue(sSettingsDTO &_settingsDTO) { // General _settingsDTO.inputDevice = "[input-device]"; _settingsDTO.bufferSize = 100000; _settingsDTO.nanValue = 0; _settingsDTO.isAfterGlow = false; _settingsDTO.refreshRate = 10; _settingsDTO.settingsPath = QDir::homePath(); // Format _settingsDTO.displayFormat = "[display-format]"; _settingsDTO.binaryFormat = "[binary-format]"; // Scaling _settingsDTO.scalingA = 1.0; _settingsDTO.scalingB = 0.0; _settingsDTO.isScalingEnabled = false; } void cMainWindow::readSettings(sSettingsDTO &_settingsDTO) { // General _settingsDTO.inputDevice = ui->edtInputDevice->text(); _settingsDTO.bufferSize = ui->edtBufferSize->value(); _settingsDTO.nanValue = ui->edtNanValue->value(); _settingsDTO.isAfterGlow = ui->radAfterGlowYes->isChecked(); _settingsDTO.refreshRate = ui->edtRefreshRate->value(); _settingsDTO.settingsPath = m_settingsPath; // Format _settingsDTO.displayFormat = ui->edtDisplayFormat->text(); _settingsDTO.binaryFormat = ui->edtBinaryFormat->text(); // Scaling _settingsDTO.scalingA = ui->edtScalingA->value(); _settingsDTO.scalingB = ui->edtScalingB->value(); _settingsDTO.isScalingEnabled = ui->chbScalingEnabled->isChecked(); } void cMainWindow::writeSettings(const sSettingsDTO &_settingsDTO) { // General ui->edtInputDevice->setText(_settingsDTO.inputDevice); ui->edtBufferSize->setValue(_settingsDTO.bufferSize); ui->edtNanValue->setValue(_settingsDTO.nanValue); ui->radAfterGlowYes->setChecked(_settingsDTO.isAfterGlow); ui->radAfterGlowNo->setChecked(!_settingsDTO.isAfterGlow); ui->edtRefreshRate->setValue(_settingsDTO.refreshRate); m_settingsPath = _settingsDTO.settingsPath; // Format ui->edtDisplayFormat->setText(_settingsDTO.displayFormat); ui->edtBinaryFormat->setText(_settingsDTO.binaryFormat); // Scaling ui->edtScalingA->setValue(_settingsDTO.scalingA); ui->edtScalingB->setValue(_settingsDTO.scalingB); ui->chbScalingEnabled->setChecked(_settingsDTO.isScalingEnabled); } void cMainWindow::saveSettings(QSettings &_settings, const sSettingsDTO &_settingsDTO) { // General _settings.setValue(DEF_INPUT_DEVICE, _settingsDTO.inputDevice); _settings.setValue(DEF_BUFFER_SIZE, _settingsDTO.bufferSize); _settings.setValue(DEF_NAN_VALUE, _settingsDTO.nanValue); _settings.setValue(DEF_AFTER_GLOW, _settingsDTO.isAfterGlow); _settings.setValue(DEF_REFRESH_RATE, _settingsDTO.refreshRate); _settings.setValue(DEF_SETTINGS_PATH, _settingsDTO.settingsPath); // Format _settings.beginGroup(DEF_SETTINGS_FORMAT); _settings.setValue(DEF_DISPLAY_FORMAT, _settingsDTO.displayFormat); _settings.setValue(DEF_BINARY_FORMAT, _settingsDTO.binaryFormat); _settings.endGroup(); // Scaling _settings.beginGroup(DEF_SETTINGS_SCALING); _settings.setValue(DEF_SCALING_A, _settingsDTO.scalingA); _settings.setValue(DEF_SCALING_B, _settingsDTO.scalingB); _settings.setValue(DEF_SCALING_ENABLED, _settingsDTO.isScalingEnabled); _settings.endGroup(); } void cMainWindow::loadSettings(QSettings &_settings, sSettingsDTO &_settingsDTO) { sSettingsDTO oSettingsDTO; loadDefaultValue(oSettingsDTO); // General _settingsDTO.inputDevice = _settings.value(DEF_INPUT_DEVICE, oSettingsDTO.inputDevice).toString(); _settingsDTO.bufferSize = _settings.value(DEF_BUFFER_SIZE, oSettingsDTO.bufferSize).toInt(); _settingsDTO.nanValue = _settings.value(DEF_NAN_VALUE, oSettingsDTO.nanValue).toInt(); _settingsDTO.isAfterGlow = _settings.value(DEF_AFTER_GLOW, oSettingsDTO.isAfterGlow).toBool(); _settingsDTO.refreshRate = _settings.value(DEF_REFRESH_RATE, oSettingsDTO.refreshRate).toInt(); _settingsDTO.settingsPath = _settings.value(DEF_SETTINGS_PATH, oSettingsDTO.settingsPath).toString(); // Format _settings.beginGroup(DEF_SETTINGS_FORMAT); _settingsDTO.displayFormat = _settings.value(DEF_DISPLAY_FORMAT, oSettingsDTO.displayFormat).toString(); _settingsDTO.binaryFormat = _settings.value(DEF_BINARY_FORMAT, oSettingsDTO.binaryFormat).toString(); _settings.endGroup(); // Scaling _settings.beginGroup(DEF_SETTINGS_SCALING); _settingsDTO.scalingA = _settings.value(DEF_SCALING_A, oSettingsDTO.scalingA).toDouble(); _settingsDTO.scalingB = _settings.value(DEF_SCALING_B, oSettingsDTO.scalingB).toDouble(); _settingsDTO.isScalingEnabled = _settings.value(DEF_SCALING_ENABLED, oSettingsDTO.isScalingEnabled).toBool(); _settings.endGroup(); } void cMainWindow::closeEvent(QCloseEvent *event) { sSettingsDTO oSettingsDTO; readSettings(oSettingsDTO); QSettings oSettings(DEF_ORGANIZATION_NAME, DEF_APP_NAME); saveSettings(oSettings, oSettingsDTO); } void cMainWindow::on_actionSaveSettings_triggered() { QString oFilename = QFileDialog::getSaveFileName(this, tr("Sauvegarder les configurations"), m_settingsPath, tr("Settings (*.ini)")); if (oFilename.isEmpty()) { qDebug() << "L'enregistrement des configurations a ete annule."; return; } m_settingsPath = QFileInfo(oFilename).absolutePath(); sSettingsDTO oSettingsDTO; readSettings(oSettingsDTO); QSettings oSettings(oFilename, QSettings::IniFormat); saveSettings(oSettings, oSettingsDTO); qDebug() << "L'enregistrement des configurations s'est bien deroule." << "|filename=" << oFilename; } void cMainWindow::on_actionLoadSettings_triggered() { QString oFilename = QFileDialog::getOpenFileName(this, tr("Charger les configurations"), m_settingsPath, tr("Settings (*.ini)")); if (oFilename.isEmpty()) { qDebug() << "Le chargement des configurations a ete annule."; return; } m_settingsPath = QFileInfo(oFilename).absolutePath(); sSettingsDTO oSettingsDTO; QSettings oSettings(oFilename, QSettings::IniFormat); loadSettings(oSettings, oSettingsDTO); writeSettings(oSettingsDTO); qDebug() << "Le chargement des configurations s'est bien deroule." << "|filename=" << oFilename; } void cMainWindow::on_actionSettingsPage_triggered() { ui->stackedWidget->setCurrentWidget(ui->pageSettings); } void cMainWindow::on_btnSettingsOK_clicked() { ui->stackedWidget->setCurrentWidget(ui->pageHome); } ...
... cmake_minimum_required(VERSION 3.10.0) project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_PREFIX_PATH "C:/Qt/6.5.2/msvc2019_64/lib/cmake") find_package(Qt6 REQUIRED COMPONENTS Widgets ) qt_wrap_ui(UI_FILES cMainWindow.ui ) add_executable(rdvcpp main.cpp cMainWindow.cpp resources.qrc ${UI_FILES} ) target_link_libraries (rdvcpp Qt6::Widgets ) ...
... <RCC> <qresource prefix="/img"> <file alias="logo.png">data/img/logo.png</file> </qresource> </RCC> ...
... rdvcpp.exe ...
... #include "cMainWindow.h" #include <QApplication> int main(int argc, char **argv) { QApplication app(argc, argv); cMainWindow *oMainWindow = new cMainWindow; oMainWindow->resize(640, 480); oMainWindow->show(); return app.exec(); } ...
... #pragma once #include <QMainWindow> #include "cPlot.h" namespace Ui { class cMainWindow; } class cMainWindow : public QMainWindow { Q_OBJECT public: using sPlot = cPlot::sPlot; using sPlots = cPlot::sPlots; public: explicit cMainWindow(QWidget *parent = 0); ~cMainWindow(); private: void addManagePlot(const sPlot &_plot); void updateManagePlot(); private slots: void on_actionChangeBackgroundColor_triggered(); void on_actionAddPlot_triggered(); void on_actionPlotPage_triggered(); void on_actionManagePlotPage_triggered(); void on_plot_emitResizePlot(); protected: void resizeEvent(QResizeEvent *event); void timerEvent(QTimerEvent *event); private: Ui::cMainWindow *ui; QVector<QImage> m_images; int m_refreshTime; int m_refreshTimerId; }; ...
... #include "cMainWindow.h" #include "ui_cMainWindow.h" #include <QColorDialog> #include <QResizeEvent> #include <QMessageBox> static const int DEF_REFRESH_TIME = 100; // 100ms : 10 Hz cMainWindow::cMainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::cMainWindow), m_refreshTime(DEF_REFRESH_TIME) { ui->setupUi(this); ui->stackedWidget->setCurrentWidget(ui->pagePlot); ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); m_refreshTimerId = startTimer(m_refreshTime); } cMainWindow::~cMainWindow() { delete ui; } void cMainWindow::addManagePlot(const sPlot &_plot) { ui->tableWidget->insertRow(ui->tableWidget->rowCount()); int iCol = 0; QTableWidgetItem *oId = new QTableWidgetItem(QString("%1").arg(_plot.id)); QTableWidgetItem *oX = new QTableWidgetItem(QString("%1").arg(_plot.x)); QTableWidgetItem *oY = new QTableWidgetItem(QString("%1").arg(_plot.y)); QTableWidgetItem *oWidth = new QTableWidgetItem(QString("%1").arg(_plot.width)); QTableWidgetItem *oHeight = new QTableWidgetItem(QString("%1").arg(_plot.height)); QTableWidgetItem *oDivision = new QTableWidgetItem(QString("%1").arg(_plot.nDivision)); ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, iCol++, oId); ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, iCol++, oX); ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, iCol++, oY); ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, iCol++, oWidth); ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, iCol++, oHeight); ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, iCol++, oDivision); } void cMainWindow::updateManagePlot() { if (ui->plot->getSize()) { ui->tableWidget->setRowCount(0); for (const auto &oPlot : ui->plot->getPlots()) { addManagePlot(oPlot); } } } void cMainWindow::on_actionChangeBackgroundColor_triggered() { QColor oldColor = ui->plot->getBackgroundColor(); QColor newColor = QColorDialog::getColor(oldColor, this, tr("Sélectionner une couleur")); if (!newColor.isValid()) { qDebug() << "Aucune couleur n'a ete selectionne."; return; } if (newColor != oldColor) { ui->plot->setBackgroundColor(newColor); } } void cMainWindow::on_actionAddPlot_triggered() { if (ui->plot->isMax()) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("Le nombre maximal d'oscilloscopes est atteint.")); return; } ui->plot->addPlot(); updateManagePlot(); } void cMainWindow::on_actionPlotPage_triggered() { ui->stackedWidget->setCurrentWidget(ui->pagePlot); } void cMainWindow::on_actionManagePlotPage_triggered() { ui->stackedWidget->setCurrentWidget(ui->pageManagePlot); } void cMainWindow::on_plot_emitResizePlot() { updateManagePlot(); } void cMainWindow::resizeEvent(QResizeEvent *event) { QWidget *oCurrentWidget = ui->stackedWidget->currentWidget(); if (oCurrentWidget != ui->pagePlot) { ui->stackedWidget->setCurrentWidget(ui->pagePlot); ui->stackedWidget->setCurrentWidget(oCurrentWidget); } } void cMainWindow::timerEvent(QTimerEvent *event) { ui->plot->render(); ui->plot->repaint(); } ...
... #pragma once #include <QWidget> #include <QImage> #include <QVector> #include <QMap> class QMenu; class cPlot : public QWidget { Q_OBJECT public: struct sPlot { int id; int x; int y; int width; int height; int nDivision; }; using sPlots = QVector<sPlot>; using sData = QVector<QPointF>; using sImages = QMap<int, QImage>; using sDatas = QMap<int, sData>; using sXShiftValues = QMap<int, double>; using sAnimatePlots = QMap<int, bool>; using sOffsets = QMap<int, QPointF>; public: explicit cPlot(QWidget *parent = nullptr); ~cPlot(); void render(); void setBackgroundColor(const QColor _color); void addPlot(); bool isMax() const; const QColor &getBackgroundColor() const { return m_backgroundColor; } sPlots &getPlots() { return m_plots; } const sPlots &getPlots() const { return m_plots; } int getSize() const { return m_plots.size(); } private: void addPlotImage(int _plotId, int _width, int _height); void addPlotXShiftValue(int _plotId); void addPlotOffset(int _plotId); // void initScreenSize(); void createPlotMenu(); bool loadAllPlots(sPlots &_plots) const; bool loadPlot(int _x, int _y, sPlot &_plot) const; bool isActivePlot(const QPoint &_pos) const; bool isActivePlot(const QPoint &_pos, int &_plotId) const; bool hasPlotImage(int _plotId) const; bool hasPlotData(int _plotId) const; bool hasPlotXShiftValue(int _plotId) const; bool hasPlotOffset(int _plotId) const; bool isAnimatePlot(int _plotId) const; void generatePlotData(sData &_datas, double _xShiftValue); QPointF pointToPlot(const QPointF &_point) const; void drawText(QPaintDevice *_image, int _x, int _y, int _width, int _height, int _fontSize, bool _isBold, const QColor &_color, int _align, const QString &_text); // void drawPlotBackgroundColor(); void drawPlotsBackgroundColor(); void drawPlotsDefaultBorder(); void drawPlotsBorder(); void drawTextNoPlots(); void drawActivePlots(); void drawPlotsGrids(); void drawPlotsGridsDivs(); void drawPlotsGridsTicks(); void drawPlotsGridsTicksDivs(); void drawPlotsGridsDivsValues(); void drawAnimatePlots(); void drawPlotsDatas(); void drawPlots(); protected: void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *event); void mousePressEvent(QMouseEvent *event); void wheelEvent(QWheelEvent *event); private: void onResizePlot(const QSize &_size); void onPlotMenu(const QPoint &_pos); void onAddPlotData(); void onAnimatePlotData(); void onPlotClick(const QPoint &_pos); signals: void emitResizePlot(QSize _size); void emitPlotMenu(QPoint _pos); void emitPlotClick(QPoint _pos); private: sPlots m_plots; sImages m_images; sDatas m_datas; sXShiftValues m_xShiftValues; sAnimatePlots m_isAnimatePlots; sOffsets m_offsets; // QSize m_screenSize; QImage m_image; QMenu *m_plotMenu; QColor m_backgroundColor; // double m_scaleFactor; }; ...
... #include "cPlot.h" #include "cMainWindow.h" #include <QPainter> #include <QPaintEvent> #include <QMenu> #include <QApplication> #include <QScreen> #include <QMessageBox> // debug static const bool DEF_DEBUG_ON = false; // plot static const int DEF_PLOT_MAX = 9; static const int DEF_PLOT_MARGIN_LEFT = 70; static const int DEF_PLOT_MARGIN_BOTTOM = 50; static const int DEF_PLOT_MARGIN_TOP = 30; static const int DEF_PLOT_MARGIN_RIGHT = 10; static const int DEF_PLOT_PIXEL_PER_DIV = 40; static const int DEF_PLOT_TEXT_FONT_SIZE = 10; static const int DEF_PLOT_DATA_NUMBER = 1024; static const double DEF_PLOT_X_MIN = -45; static const double DEF_PLOT_X_MAX = 2000; static const double DEF_PLOT_X_SHIT_VALUE = 45; static const double DEF_PLOT_X_SHIT_PER_TIME = 5; static const QPointF DEF_PLOT_OFFSET = QPointF(-5, -3); static const double DEF_PLOT_X_PER_DIV = 90.0 / 2.0; static const double DEF_PLOT_Y_PER_DIV = 1.0 / 2.0; static const int DEF_PLOT_DEFAULT_BORDER_THICKNESS = 1; static const int DEF_PLOT_BORDER_THICKNESS = 2; static const int DEF_PLOT_DATA_THICKNESS = 2; static const QColor DEF_PLOT_BACKGROUND_COLOR = "#FF000000"; static const QColor DEF_PLOT_DEFAULT_BORDER_COLOR = "#FF404040"; static const QColor DEF_PLOT_BORDER_COLOR = "#FFAA0000"; static const QColor DEF_PLOT_TEXT_COLOR = "#FFAA0000"; static const QColor DEF_NO_PLOT_TEXT_COLOR = "#FF808080"; static const QColor DEF_NO_PLOT_BACKGROUND_COLOR = "#80808080"; static const QColor DEF_PLOT_DATA_COLOR = "#FFAA00AA"; static const QString DEF_PLOT_FONT_FAMILY = "Arial"; static const QString DEF_NO_PLOT_TEXT = "[NO-PLOT]"; static const QString DEF_NO_PLOT_ITEM_TEXT = "NO-PLOT-[%1]"; static const QString DEF_PLOT_ITEM_TEXT = "PLOT-[%1]"; // axis static const int DEF_AXIS_DIV_PER_GRID = 2; static const int DEF_AXIS_THICKNESS = 2; static const int DEF_AXIS_GRID_THICKNESS = 1; static const int DEF_AXIS_TICK_THICKNESS = 1; static const int DEF_AXIS_TICK_DIV_THICKNESS = 2; static const int DEF_AXIS_DIV_PER_GRID_THICKNESS = 2; static const int DEF_AXIS_TICK_SIZE = 5; static const int DEF_AXIS_TICK_GRID_SIZE = 10; static const int DEF_AXIS_DIV_VALUE_FONT_SIZE = 10; static const double DEF_AXIS_TICK_PER_DIV = 5.0; static const double DEF_AXIS_TICK_DIV_PER_GRID = 2.0; static const QColor DEF_AXIS_COLOR = "#FF808080"; static const QColor DEF_AXIS_TICK_COLOR = "#FFAA0000"; static const QColor DEF_AXIS_TICK_VALUE_COLOR = "#FFAA0000"; static const QColor DEF_AXIS_GRID_COLOR = "#FF333333"; static const QColor DEF_AXIS_DIV_PER_GRID_COLOR = "#FF222222"; cPlot::cPlot(QWidget *parent) : QWidget(parent), m_image(parent->width(), parent->height(), QImage::Format_ARGB32), m_scaleFactor(1.0), m_backgroundColor(DEF_PLOT_BACKGROUND_COLOR) { initScreenSize(); createPlotMenu(); connect(this, &cPlot::emitResizePlot, this, &cPlot::onResizePlot); connect(this, &cPlot::emitPlotMenu, this, &cPlot::onPlotMenu); connect(this, &cPlot::emitPlotClick, this, &cPlot::onPlotClick); } cPlot::~cPlot() { } void cPlot::render() { drawPlotBackgroundColor(); drawPlotsBackgroundColor(); drawPlotsDefaultBorder(); drawTextNoPlots(); drawActivePlots(); drawPlotsGrids(); drawPlotsGridsDivs(); drawPlotsGridsTicks(); drawPlotsGridsTicksDivs(); drawPlotsGridsDivsValues(); drawAnimatePlots(); drawPlotsDatas(); drawPlotsBorder(); drawPlots(); } void cPlot::setBackgroundColor(const QColor _color) { if (m_backgroundColor != _color) { m_backgroundColor = _color; } } void cPlot::addPlot() { if (isMax()) return; m_plots.push_back(sPlot()); int oSzie = m_plots.size(); double oSqrt = sqrt((double)oSzie); int oCeil = (int)ceil(oSqrt); int oDivision = oCeil; int oWidth = width() / oDivision; int oHeight = height() / oDivision; for (int iCount = 0; iCount < m_plots.size(); iCount++) { int oId = iCount; int iX = iCount % oDivision; int iY = iCount / oDivision; int oX = iX * oWidth; int oY = iY * oHeight; sPlot &oPlot = m_plots[iCount]; oPlot.id = oId; oPlot.x = oX; oPlot.y = oY; oPlot.width = oWidth; oPlot.height = oHeight; oPlot.nDivision = oDivision; addPlotImage(oPlot.id, oWidth, oHeight); addPlotXShiftValue(oPlot.id); addPlotOffset(oPlot.id); } if (m_plots.size() && DEF_DEBUG_ON) { qDebug() << "\nLe calcul des parametres de l'oscillosocpe."; for (const auto &oPlot : m_plots) { qDebug() << "|id=" << oPlot.id << "|x=" << oPlot.x << "|y=" << oPlot.y << "|width=" << oPlot.width << "|height=" << oPlot.height << "|WIDTH=" << width() << "|HEIGHT=" << height() << "|nSCOPE=" << oPlot.nDivision * oPlot.nDivision; } } } bool cPlot::isMax() const { return (m_plots.size() >= DEF_PLOT_MAX); } void cPlot::addPlotImage(int _plotId, int _width, int _height) { if (hasPlotImage(_plotId)) { QImage &oImage = m_images[_plotId]; oImage = oImage.scaled(QSize(_width, _height) * m_scaleFactor); } else { m_images[_plotId] = QImage(QSize(_width, _height) * m_scaleFactor, QImage::Format_ARGB32); } } void cPlot::addPlotXShiftValue(int _plotId) { if (!hasPlotXShiftValue(_plotId)) { m_xShiftValues[_plotId] = _plotId * DEF_PLOT_X_SHIT_VALUE; } } void cPlot::addPlotOffset(int _plotId) { if (!hasPlotOffset(_plotId)) { m_offsets[_plotId] = DEF_PLOT_OFFSET; } } void cPlot::initScreenSize() { m_screenSize = QApplication::primaryScreen()->geometry().size(); qDebug() << Q_FUNC_INFO << "|screenSize=" << m_screenSize; } void cPlot::createPlotMenu() { m_plotMenu = new QMenu(this); QAction *oAction; oAction = new QAction("Ajouter des données"); connect(oAction, &QAction::triggered, this, &cPlot::onAddPlotData); m_plotMenu->addAction(oAction); oAction = new QAction("Animer les données"); connect(oAction, &QAction::triggered, this, &cPlot::onAnimatePlotData); m_plotMenu->addAction(oAction); } bool cPlot::loadAllPlots(sPlots &_plots) const { if (m_plots.isEmpty()) return false; const sPlot &oPlot = m_plots[0]; int oDivision = oPlot.nDivision; int oWidth = oPlot.width; int oHeight = oPlot.height; int oSize = oDivision * oDivision; for (int iCount = 0; iCount < oSize; iCount++) { int oId = iCount; int iX = iCount % oDivision; int iY = iCount / oDivision; int oX = iX * oWidth; int oY = iY * oHeight; sPlot iPlot; iPlot.id = oId; iPlot.x = oX; iPlot.y = oY; iPlot.width = oWidth; iPlot.height = oHeight; iPlot.nDivision = oDivision; _plots.push_back(iPlot); } if (_plots.size() && DEF_DEBUG_ON) { qDebug() << "\nLe calcul des parametres de l'oscillosocpe [par défaut]."; for (const auto &iPlot : _plots) { qDebug() << "|id=" << iPlot.id << "|x=" << iPlot.x << "|y=" << iPlot.y << "|width=" << iPlot.width << "|height=" << iPlot.height << "|WIDTH=" << width() << "|HEIGHT=" << height() << "|nSCOPE=" << iPlot.nDivision * iPlot.nDivision; } } return true; } bool cPlot::loadPlot(int _x, int _y, sPlot &_plot) const { if (m_plots.size()) { sPlots oPlots; if (loadAllPlots(oPlots)) { for (const auto &oPlot : oPlots) { QRegion oRegion(oPlot.x, oPlot.y, oPlot.width, oPlot.height); if (oRegion.contains(QPoint(_x, _y))) { _plot = oPlot; return true; } } } } return false; } bool cPlot::isActivePlot(const QPoint &_pos) const { for (const auto &oPlot : m_plots) { QRegion oRegion(oPlot.x, oPlot.y, oPlot.width, oPlot.height); if (oRegion.contains(_pos)) { return true; } } return false; } bool cPlot::isActivePlot(const QPoint &_pos, int &_plotId) const { for (const auto &oPlot : m_plots) { QRegion oRegion(oPlot.x, oPlot.y, oPlot.width, oPlot.height); if (oRegion.contains(_pos)) { _plotId = oPlot.id; return true; } } return false; } bool cPlot::hasPlotImage(int _plotId) const { for (const auto &oPlotId : m_images.keys()) { if (oPlotId == _plotId) { return true; } } return false; } bool cPlot::hasPlotData(int _plotId) const { for (const auto &oPlotId : m_datas.keys()) { if (oPlotId == _plotId) { return true; } } return false; } bool cPlot::hasPlotXShiftValue(int _plotId) const { for (const auto &oPlotId : m_xShiftValues.keys()) { if (oPlotId == _plotId) { return true; } } return false; } bool cPlot::hasPlotOffset(int _plotId) const { for (const auto &oPlotId : m_offsets.keys()) { if (oPlotId == _plotId) { return true; } } return false; } bool cPlot::isAnimatePlot(int _plotId) const { for (const auto &oPlotId : m_isAnimatePlots.keys()) { if (oPlotId == _plotId) { return true; } } return false; } void cPlot::generatePlotData(sData &_datas, double _xShiftValue) { for (int iX = 0; iX < DEF_PLOT_DATA_NUMBER; iX++) { double oX = DEF_PLOT_X_MIN + ((DEF_PLOT_X_MAX - DEF_PLOT_X_MIN) * iX) / DEF_PLOT_DATA_NUMBER; double oY = 2 + qSin(qDegreesToRadians(oX)); oX = oX - _xShiftValue; QPointF oData(oX, oY); _datas.push_back(oData); } } QPointF cPlot::pointToPlot(const QPointF &_point) const { double oX = _point.x() * DEF_PLOT_PIXEL_PER_DIV / DEF_PLOT_X_PER_DIV; double oY = _point.y() * DEF_PLOT_PIXEL_PER_DIV / DEF_PLOT_Y_PER_DIV; return QPointF(oX, oY); } void cPlot::drawText(QPaintDevice *_image, int _x, int _y, int _width, int _height, int _fontSize, bool _isBold, const QColor &_color, int _align, const QString &_text) { QPainter oPainter; oPainter.begin(_image); oPainter.setRenderHint(QPainter::TextAntialiasing); oPainter.setPen(_color); QFont oFont = oPainter.font(); oFont.setPointSize(_fontSize); oFont.setStyleHint(QFont::Helvetica, QFont::PreferAntialias); oFont.setBold(_isBold); oFont.setFamily(DEF_PLOT_FONT_FAMILY); oPainter.setFont(oFont); oPainter.drawText(QRect(_x, _y, _width, _height), _align, _text); oPainter.end(); } void cPlot::drawPlotBackgroundColor() { QPainter oPainter; oPainter.begin(&m_image); oPainter.fillRect(0, 0, m_image.width(), m_image.height(), m_backgroundColor); oPainter.end(); } void cPlot::drawPlotsBackgroundColor() { for (sPlot &oPlot : m_plots) { if (hasPlotImage(oPlot.id)) { QImage &oImage = m_images[oPlot.id]; QPainter oPainter; oPainter.begin(&oImage); oPainter.fillRect(0, 0, oPlot.width, oPlot.height, m_backgroundColor); oPainter.end(); } } } void cPlot::drawPlotsDefaultBorder() { sPlots oPlots; if (loadAllPlots(oPlots)) { for (int iCount = 0; iCount < oPlots.size(); iCount++) { if (iCount < m_plots.size()) { sPlot &oPlot = m_plots[iCount]; if (hasPlotImage(oPlot.id)) { QImage &oImage = m_images[oPlot.id]; QPainter oPainter; oPainter.begin(&oImage); oPainter.setPen(QPen(DEF_PLOT_DEFAULT_BORDER_COLOR, DEF_PLOT_DEFAULT_BORDER_THICKNESS, Qt::DashLine)); oPainter.drawRect(0, 0, oPlot.width, oPlot.height); oPainter.end(); } } else { sPlot &oPlot = oPlots[iCount]; QPainter oPainter; oPainter.begin(&m_image); oPainter.setPen(QPen(DEF_PLOT_DEFAULT_BORDER_COLOR, DEF_PLOT_DEFAULT_BORDER_THICKNESS, Qt::DashLine)); oPainter.drawRect(oPlot.x, oPlot.y, oPlot.width, oPlot.height); oPainter.end(); } } } } void cPlot::drawPlotsBorder() { for (auto &oPlot : m_plots) { if (hasPlotImage(oPlot.id)) { QImage &oImage = m_images[oPlot.id]; int oX = DEF_PLOT_MARGIN_LEFT; int oY = DEF_PLOT_MARGIN_TOP; int oWidth = oPlot.width - (DEF_PLOT_MARGIN_LEFT + DEF_PLOT_MARGIN_RIGHT); int oHeight = oPlot.height - (DEF_PLOT_MARGIN_TOP + DEF_PLOT_MARGIN_BOTTOM); QPainter oPainter; oPainter.begin(&oImage); oPainter.setPen(QPen(DEF_PLOT_BORDER_COLOR, DEF_PLOT_BORDER_THICKNESS)); oPainter.drawRect(oX, oY, oWidth, oHeight); oPainter.end(); } } } void cPlot::drawTextNoPlots() { if (m_plots.isEmpty()) { drawText(&m_image, 0, 0, width(), height(), DEF_PLOT_TEXT_FONT_SIZE, false, DEF_NO_PLOT_TEXT_COLOR, Qt::AlignCenter, DEF_NO_PLOT_TEXT); return; } sPlots oPlots; if (loadAllPlots(oPlots)) { for (int iCount = 0; iCount < oPlots.size(); iCount++) { QString oText; if (iCount < m_plots.size()) { sPlot &oPlot = m_plots[iCount]; if (hasPlotImage(oPlot.id)) { QImage &oImage = m_images[oPlot.id]; oText = QString(DEF_PLOT_ITEM_TEXT).arg(oPlot.id); drawText(&oImage, 0, 0, oPlot.width, DEF_PLOT_MARGIN_TOP, DEF_PLOT_TEXT_FONT_SIZE, false, DEF_PLOT_TEXT_COLOR, Qt::AlignCenter, oText); } } else { sPlot &oPlot = oPlots[iCount]; oText = QString(DEF_NO_PLOT_ITEM_TEXT).arg(oPlot.id); drawText(&m_image, oPlot.x, oPlot.y, oPlot.width, oPlot.height, DEF_PLOT_TEXT_FONT_SIZE, false, DEF_NO_PLOT_TEXT_COLOR, Qt::AlignCenter, oText); } } } } void cPlot::drawActivePlots() { if (m_plots.size()) { QRegion oRegion(0, 0, width(), height()); for (const auto &oPlot : m_plots) { QRegion iRegion(oPlot.x, oPlot.y, oPlot.width, oPlot.height); oRegion = oRegion.subtracted(iRegion); } QPainter oPainter; oPainter.begin(&m_image); oPainter.setClipRegion(oRegion); oPainter.fillRect(0, 0, width(), height(), DEF_NO_PLOT_BACKGROUND_COLOR); oPainter.end(); } } void cPlot::drawPlotsGrids() { for (auto &oPlot : m_plots) { if (hasPlotImage(oPlot.id)) { QImage &oImage = m_images[oPlot.id]; const double &xShiftValue = m_xShiftValues[oPlot.id]; int oXmax = oPlot.width - (DEF_PLOT_MARGIN_LEFT + DEF_PLOT_MARGIN_RIGHT); int oYmax = oPlot.height - (DEF_PLOT_MARGIN_TOP + DEF_PLOT_MARGIN_BOTTOM); QRect oRect(DEF_PLOT_MARGIN_LEFT, DEF_PLOT_MARGIN_TOP, oXmax, oYmax); for (int iX = 0; iX < 3 * oXmax; iX += DEF_PLOT_PIXEL_PER_DIV) { QPainter oPainter; oPainter.begin(&oImage); oPainter.setClipRect(oRect); oPainter.translate(oRect.bottomLeft()); oPainter.scale(1.0, -1.0); int oDx = iX - xShiftValue; oPainter.setPen(QPen(DEF_AXIS_GRID_COLOR, DEF_AXIS_GRID_THICKNESS, Qt::DotLine)); oPainter.drawLine(oDx, 0, oDx, oYmax); oPainter.end(); } for (int iY = 0; iY < oYmax; iY += DEF_PLOT_PIXEL_PER_DIV) { QPainter oPainter; oPainter.begin(&oImage); oPainter.setClipRect(oRect); oPainter.translate(oRect.bottomLeft()); oPainter.scale(1.0, -1.0); oPainter.setPen(QPen(DEF_AXIS_GRID_COLOR, DEF_AXIS_GRID_THICKNESS, Qt::DotLine)); oPainter.drawLine(0, iY, oXmax, iY); oPainter.end(); } } } } void cPlot::drawPlotsGridsDivs() { for (auto &oPlot : m_plots) { if (hasPlotImage(oPlot.id)) { QImage &oImage = m_images[oPlot.id]; const double &xShiftValue = m_xShiftValues[oPlot.id]; int oXmax = oPlot.width - (DEF_PLOT_MARGIN_LEFT + DEF_PLOT_MARGIN_RIGHT); int oYmax = oPlot.height - (DEF_PLOT_MARGIN_TOP + DEF_PLOT_MARGIN_BOTTOM); QRect oRect(DEF_PLOT_MARGIN_LEFT, DEF_PLOT_MARGIN_TOP, oXmax, oYmax); int oDiv = DEF_AXIS_DIV_PER_GRID * DEF_PLOT_PIXEL_PER_DIV; for (int iX = 0; iX < 3 * oXmax; iX += oDiv) { QPainter oPainter; oPainter.begin(&oImage); oPainter.setClipRect(oRect); oPainter.translate(oRect.bottomLeft()); oPainter.scale(1.0, -1.0); int oDx = iX - xShiftValue; oPainter.setPen(QPen(DEF_AXIS_DIV_PER_GRID_COLOR, DEF_AXIS_DIV_PER_GRID_THICKNESS)); oPainter.drawLine(oDx, 0, oDx, oYmax); oPainter.end(); } for (int iY = 0; iY < oYmax; iY += oDiv) { QPainter oPainter; oPainter.begin(&oImage); oPainter.setClipRect(oRect); oPainter.translate(oRect.bottomLeft()); oPainter.scale(1.0, -1.0); oPainter.setPen(QPen(DEF_AXIS_DIV_PER_GRID_COLOR, DEF_AXIS_DIV_PER_GRID_THICKNESS)); oPainter.drawLine(0, iY, oXmax, iY); oPainter.end(); } } } } void cPlot::drawPlotsGridsTicks() { for (auto &oPlot : m_plots) { if (hasPlotImage(oPlot.id)) { QImage &oImage = m_images[oPlot.id]; const double &xShiftValue = m_xShiftValues[oPlot.id]; int oXmax = oPlot.width - (DEF_PLOT_MARGIN_LEFT + DEF_PLOT_MARGIN_RIGHT); int oYmax = oPlot.height - (DEF_PLOT_MARGIN_TOP + DEF_PLOT_MARGIN_BOTTOM); QRect oRect(DEF_PLOT_MARGIN_LEFT, DEF_PLOT_MARGIN_TOP, oXmax, oYmax); int oTick = DEF_PLOT_PIXEL_PER_DIV / DEF_AXIS_TICK_PER_DIV; for (int iX = 0; iX < 3 * oXmax; iX += oTick) { QPainter oPainter; oPainter.begin(&oImage); oPainter.setClipRect(oRect); oPainter.translate(oRect.bottomLeft()); oPainter.scale(1.0, -1.0); int oDx = iX - xShiftValue; oPainter.setPen(QPen(DEF_AXIS_TICK_COLOR, DEF_AXIS_TICK_THICKNESS, Qt::SolidLine)); oPainter.drawLine(oDx, -DEF_AXIS_TICK_SIZE, oDx, DEF_AXIS_TICK_SIZE); oPainter.end(); } for (int iY = 0; iY < oYmax; iY += oTick) { QPainter oPainter; oPainter.begin(&oImage); oPainter.setClipRect(oRect); oPainter.translate(oRect.bottomLeft()); oPainter.scale(1.0, -1.0); oPainter.setPen(QPen(DEF_AXIS_TICK_COLOR, DEF_AXIS_TICK_THICKNESS, Qt::SolidLine)); oPainter.drawLine(-DEF_AXIS_TICK_SIZE, iY, DEF_AXIS_TICK_SIZE, iY); oPainter.end(); } } } } void cPlot::drawPlotsGridsTicksDivs() { for (auto &oPlot : m_plots) { if (hasPlotImage(oPlot.id)) { QImage &oImage = m_images[oPlot.id]; const double &xShiftValue = m_xShiftValues[oPlot.id]; int oXmax = oPlot.width - (DEF_PLOT_MARGIN_LEFT + DEF_PLOT_MARGIN_RIGHT); int oYmax = oPlot.height - (DEF_PLOT_MARGIN_TOP + DEF_PLOT_MARGIN_BOTTOM); QRect oRect(DEF_PLOT_MARGIN_LEFT, DEF_PLOT_MARGIN_TOP, oXmax, oYmax); int oDiv = DEF_PLOT_PIXEL_PER_DIV * DEF_AXIS_TICK_DIV_PER_GRID; for (int iX = 0; iX < 3 * oXmax; iX += oDiv) { QPainter oPainter; oPainter.begin(&oImage); oPainter.setClipRect(oRect); oPainter.translate(oRect.bottomLeft()); oPainter.scale(1.0, -1.0); int oDx = iX - xShiftValue; oPainter.setPen(QPen(DEF_AXIS_TICK_COLOR, DEF_AXIS_TICK_DIV_THICKNESS, Qt::SolidLine)); oPainter.drawLine(oDx, -DEF_AXIS_TICK_GRID_SIZE, oDx, DEF_AXIS_TICK_GRID_SIZE); oPainter.end(); } oDiv = DEF_PLOT_PIXEL_PER_DIV; for (int iY = 0; iY < oYmax; iY += oDiv) { QPainter oPainter; oPainter.begin(&oImage); oPainter.setClipRect(oRect); oPainter.translate(oRect.bottomLeft()); oPainter.scale(1.0, -1.0); oPainter.setPen(QPen(DEF_AXIS_TICK_COLOR, DEF_AXIS_TICK_DIV_THICKNESS, Qt::SolidLine)); oPainter.drawLine(-DEF_AXIS_TICK_GRID_SIZE, iY, DEF_AXIS_TICK_GRID_SIZE, iY); oPainter.end(); } } } } void cPlot::drawPlotsGridsDivsValues() { for (auto &oPlot : m_plots) { if (hasPlotImage(oPlot.id)) { QImage &oImage = m_images[oPlot.id]; const double &xShiftValue = m_xShiftValues[oPlot.id]; int oXmax = oPlot.width - (DEF_PLOT_MARGIN_LEFT + DEF_PLOT_MARGIN_RIGHT); int oYmax = oPlot.height - (DEF_PLOT_MARGIN_TOP + DEF_PLOT_MARGIN_BOTTOM); QRect oRect(DEF_PLOT_MARGIN_LEFT, DEF_PLOT_MARGIN_TOP, oXmax, oYmax); QRect oRect2(DEF_PLOT_MARGIN_LEFT - 10, DEF_PLOT_MARGIN_TOP, oXmax + DEF_PLOT_MARGIN_RIGHT, oYmax + DEF_PLOT_MARGIN_BOTTOM); int oDiv = DEF_PLOT_PIXEL_PER_DIV * DEF_AXIS_TICK_DIV_PER_GRID; for (int iX = 0; iX < 3 * oXmax; iX += oDiv) { double oX = iX * DEF_PLOT_X_PER_DIV / DEF_PLOT_PIXEL_PER_DIV; QString oValue = QString("%1").arg(oX); QPainter oPainter; oPainter.begin(&oImage); oPainter.setClipRect(oRect2); oPainter.translate(oRect.bottomLeft()); oPainter.scale(1.0, 1.0); oPainter.setPen(DEF_AXIS_TICK_VALUE_COLOR); int oDx = iX - xShiftValue; QFont oFont = oPainter.font(); oFont.setPointSize(DEF_AXIS_DIV_VALUE_FONT_SIZE); oFont.setStyleHint(QFont::Helvetica, QFont::PreferAntialias); oFont.setFamily(DEF_PLOT_FONT_FAMILY); oPainter.setFont(oFont); oPainter.drawText(oDx - 40, 10, 80, 25, Qt::AlignHCenter | Qt::AlignTop, oValue); oPainter.end(); } oDiv = DEF_PLOT_PIXEL_PER_DIV; for (int iY = 0; iY < oYmax; iY += oDiv) { double oY = iY * DEF_PLOT_Y_PER_DIV / DEF_PLOT_PIXEL_PER_DIV; QString oValue = QString("%1").arg(oY); QPainter oPainter; oPainter.begin(&oImage); oPainter.translate(oRect.bottomLeft()); oPainter.scale(1.0, 1.0); oPainter.setPen(DEF_AXIS_TICK_VALUE_COLOR); QFont oFont = oPainter.font(); oFont.setPointSize(DEF_AXIS_DIV_VALUE_FONT_SIZE); oFont.setStyleHint(QFont::Helvetica, QFont::PreferAntialias); oFont.setFamily(DEF_PLOT_FONT_FAMILY); oPainter.setFont(oFont); oPainter.drawText(-80 - 15, -iY - 20, 80, 40, Qt::AlignVCenter | Qt::AlignRight, oValue); oPainter.end(); } } } } void cPlot::drawAnimatePlots() { for (const auto &oPlotId : m_isAnimatePlots.keys()) { const bool &isAnimatePlot = m_isAnimatePlots[oPlotId]; if (hasPlotXShiftValue(oPlotId) && isAnimatePlot) { sData oData; double &xShiftValues = m_xShiftValues[oPlotId]; xShiftValues += DEF_PLOT_X_SHIT_PER_TIME; generatePlotData(oData, xShiftValues); m_datas[oPlotId] = oData; } } } void cPlot::drawPlotsDatas() { for (const auto &oPlotId : m_datas.keys()) { const sData &oDatas = m_datas[oPlotId]; const sPlot &oPlot = m_plots[oPlotId]; QImage &oImage = m_images[oPlot.id]; int oXmax = oPlot.width - (DEF_PLOT_MARGIN_LEFT + DEF_PLOT_MARGIN_RIGHT); int oYmax = oPlot.height - (DEF_PLOT_MARGIN_TOP + DEF_PLOT_MARGIN_BOTTOM); QRect oRect(DEF_PLOT_MARGIN_LEFT, DEF_PLOT_MARGIN_TOP, oXmax, oYmax); for (int iX = 0; iX < oDatas.size() - 1; iX++) { QPointF oPoint1 = pointToPlot(oDatas[iX]); QPointF oPoint2 = pointToPlot(oDatas[iX + 1]); QPainter oPainter; oPainter.begin(&oImage); oPainter.setClipRect(oRect); oPainter.translate(oRect.bottomLeft()); oPainter.scale(1.0, -1.0); oPainter.setPen(QPen(DEF_PLOT_DATA_COLOR, DEF_PLOT_DATA_THICKNESS, Qt::SolidLine)); oPainter.drawLine(oPoint1, oPoint2); oPainter.end(); } } } void cPlot::drawPlots() { for (auto &oPlot : m_plots) { if (hasPlotImage(oPlot.id)) { QImage &oImage = m_images[oPlot.id]; QPainter oPainter; oPainter.begin(&m_image); oPainter.drawImage(oPlot.x, oPlot.y, oImage.scaled(QSize(oPlot.width, oPlot.height) * m_scaleFactor)); oPainter.end(); } } } void cPlot::paintEvent(QPaintEvent *event) { QPainter oPainter(this); QRect oRect = rect() & event->rect(); oPainter.setClipRect(oRect); oPainter.drawImage(0, 0, m_image.scaled(size() * m_scaleFactor)); } void cPlot::resizeEvent(QResizeEvent *event) { m_image = m_image.scaled(event->size() * m_scaleFactor); emit emitResizePlot(event->size()); } void cPlot::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { emit emitPlotClick(event->pos()); } else if (event->button() == Qt::RightButton) { emit emitPlotMenu(event->pos()); } } void cPlot::wheelEvent(QWheelEvent *event) { qDebug() << "cPlot::wheelEvent()..."; } void cPlot::onResizePlot(const QSize &_size) { if (m_plots.size()) { const sPlot &oPlot = m_plots[0]; int oDivision = oPlot.nDivision; int oWidth = _size.width() / oDivision; int oHeight = _size.height() / oDivision; for (int iCount = 0; iCount < m_plots.size(); iCount++) { sPlot &iPlot = m_plots[iCount]; int oId = iCount; int iX = iCount % oDivision; int iY = iCount / oDivision; int oX = iX * oWidth; int oY = iY * oHeight; iPlot.id = oId; iPlot.x = oX; iPlot.y = oY; iPlot.width = oWidth; iPlot.height = oHeight; iPlot.nDivision = oDivision; if (hasPlotImage(iPlot.id)) { QImage &oImage = m_images[iPlot.id]; oImage = oImage.scaled(QSize(oWidth, oHeight) * m_scaleFactor); } } } if (m_plots.size() && DEF_DEBUG_ON) { qDebug() << "\nLe calcul des parametres de l'oscillosocpe."; for (const auto &oPlot : m_plots) { qDebug() << "|id=" << oPlot.id << "|x=" << oPlot.x << "|y=" << oPlot.y << "|width=" << oPlot.width << "|height=" << oPlot.height << "|WIDTH=" << _size.width() << "|HEIGHT=" << _size.height() << "|nSCOPE=" << oPlot.nDivision * oPlot.nDivision; } } } void cPlot::onPlotMenu(const QPoint &_pos) { if (isActivePlot(_pos)) { m_plotMenu->exec(mapToGlobal(_pos)); } } void cPlot::onAddPlotData() { QPoint oPos = mapFromGlobal(m_plotMenu->pos()); int oPlotId; if (isActivePlot(oPos, oPlotId)) { if (hasPlotData(oPlotId)) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("L'oscilloscope [%1] contient déjà des données.").arg(oPlotId)); return; } if (hasPlotXShiftValue(oPlotId)) { sData oData; const double &oXShiftValues = m_xShiftValues[oPlotId]; generatePlotData(oData, oXShiftValues); m_datas[oPlotId] = oData; } } } void cPlot::onAnimatePlotData() { QPoint oPos = mapFromGlobal(m_plotMenu->pos()); int oPlotId; if (isActivePlot(oPos, oPlotId)) { if (!hasPlotData(oPlotId)) { QMessageBox::critical(this, tr("Messages d'erreurs"), tr("L'oscilloscope [%1] doit contenir des données.").arg(oPlotId)); return; } if (isAnimatePlot(oPlotId)) { bool &isAnimatePlot = m_isAnimatePlots[oPlotId]; isAnimatePlot = !isAnimatePlot; } else { m_isAnimatePlots[oPlotId] = true; } } } void cPlot::onPlotClick(const QPoint &_pos) { sPlot oPlot; if (loadPlot(_pos.x(), _pos.y(), oPlot)) { qDebug() << "cPlot::mousePressEvent()...\n" << "|x=" << _pos.x() << "|y=" << _pos.y() << "|oPlot.id=" << oPlot.id << "|oPlot.x=" << oPlot.x << "|oPlot.y=" << oPlot.y << "|oPlot.width=" << oPlot.width << "|oPlot.height=" << oPlot.height << "|m_image.bytesPerLine=" << m_image.bytesPerLine() << "|m_image.width=" << m_image.width() << "|m_image.bits=" << m_image.bits() << "|m_image.bits=" << m_image.depth(); } } ...
... cmake_minimum_required(VERSION 3.10.0) project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_PREFIX_PATH "C:/Qt/6.5.2/msvc2019_64/lib/cmake") find_package(Qt6 REQUIRED COMPONENTS Widgets ) qt_wrap_ui(UI_FILES cMainWindow.ui ) add_executable(rdvcpp main.cpp cMainWindow.cpp cPlot.cpp resources.qrc ${UI_FILES} ) target_link_libraries (rdvcpp Qt6::Widgets ) ...
... <RCC> <qresource prefix="/img"> <file alias="logo.png">data/img/logo.png</file> </qresource> </RCC> ...
... rdvcpp.exe ...