CANdevStudio
Development tool for CAN bus simulation
Loading...
Searching...
No Matches
qmlexecutorguiimpl.h
Go to the documentation of this file.
1#ifndef QMLEXECUTORGUIIMPL_H
2#define QMLEXECUTORGUIIMPL_H
3
4#include <chrono>
5#include <cassert>
6
7#include <QList>
8#include <QWidget>
9#include <QDesktopServices>
10#include <QPushButton>
11#include <QUrl>
12#include <QFileDialog>
13#include <QDesktopServices>
14#include <QMessageBox>
15#include <QDateTime>
16#include <QTimer>
17#include <QtQml/QQmlError>
18#include <QtQml/QQmlEngine>
19#include <QtQml/QQmlContext>
20
21#include "ui_qmlexecutor.h"
22#include "qmlexecutorguiint.h"
23#include "canbusmodel.hpp"
24
29{
30 Q_OBJECT
31
32public:
37 explicit QMLExecutorGuiImpl(QObject* parent)
38 : QMLExecutorGuiInt(parent)
39 , _ui(new Ui::QMLExecutorPrivate)
40 , _widget(new QWidget)
41 , _qmlUpdateCheckTimer(this)
42 , _CANBusModel(nullptr)
43 {
44 _ui->setupUi(_widget);
45 _ui->logWindow->setVisible(false);
46
47 _ui->splitter->setCollapsible(1, true);
48
49 constexpr int size = 1234;
50 _ui->splitter->setSizes(QList<int>({size,size}));
51
52 _ui->fileName->setReadOnly(true);
53
54 QObject::connect(_ui->editQMLButton, SIGNAL(clicked()), this, SLOT(editQML()));
55 QObject::connect(_ui->loadQMLButton, SIGNAL(clicked()), this, SLOT(browseAndOpenQML()));
56 QObject::connect(&_qmlUpdateCheckTimer, SIGNAL(timeout()), this, SLOT(checkQMLModification()));
57 QObject::connect(_ui->pbDockUndock, &QPushButton::clicked, this, &QMLExecutorGuiImpl::dockUndock);
58 QObject::connect(_ui->showLog, &QPushButton::clicked, [this] {
59 _ui->logWindow->setVisible(!_ui->logWindow->isVisible());
60 });
61 QObject::connect(_ui->pbClean, &QPushButton::clicked, [this] {
62 _ui->logWindow->clear();
63 });
64 }
65
66 virtual QWidget* mainWidget() override
67 {
68 // Using this in constructor is too early (no CSS colors set yet)
69 // Background color of QQuickWidget cannot be set via CSS
71
72 return _widget;
73 }
74
75 void updateUIColor() override
76 {
77 auto color = _widget->palette().color(_widget->backgroundRole());
78 _ui->quickWidget->setClearColor(color);
79 }
80
81public slots:
86 {
87 QUrl url = QFileDialog::getOpenFileUrl(mainWidget(), "Open QML");
88
89 if(!url.isEmpty() && url.isValid())
90 {
91 loadQML(url);
92 }
93 }
94
99 virtual void loadQML(const QUrl& url) override
100 {
101 if(url.isValid() && !url.isEmpty())
102 {
103 // The easiest way to reload QML seems to be creating new QQuickWidget
104 auto splitter = static_cast<QSplitter*>(_ui->quickWidget->parentWidget());
105 auto splitState = splitter->saveState();
106
107 delete _ui->quickWidget;
108 _ui->quickWidget = new QQuickWidget();
110 splitter->insertWidget(0, _ui->quickWidget);
111 splitter->restoreState(splitState);
112
113 QObject::connect(_ui->quickWidget, &QQuickWidget::statusChanged, this, &QMLExecutorGuiImpl::handleStatusChange);
114
115 _qmlUrl = url;
116
117 log("Loading qml file: " + url.toLocalFile());
118
119 assert(_CANBusModel != nullptr);
120
121 _ui->quickWidget->rootContext()->setContextProperty("CANBusModel", _CANBusModel);
122 _ui->quickWidget->rootContext()->setContextProperty("LogWindow", _ui->logWindow);
123
124 _ui->quickWidget->setSource(url);
125
126 _ui->fileName->setText(url.toLocalFile());
127
128 emit QMLLoaded(_qmlUrl);
129
131
132 _ui->editQMLButton->setEnabled(true);
133 }
134
135 }
136
141 virtual void setModel(CANBusModel* model) override
142 {
143 _CANBusModel = model;
144 }
145
150 {
151 _qmlLoadTime = QDateTime::currentDateTime();
152 _qmlUpdateCheckTimer.start(std::chrono::milliseconds(1000).count());
153 }
154
159 {
160 _qmlUpdateCheckTimer.stop();
161 }
162
167 {
168 QDateTime modifycationTime = QFileInfo(_qmlUrl.toLocalFile()).lastModified();
169
170 if(modifycationTime > _qmlLoadTime)
171 {
173
174 if(askForQMLReload())
175 {
176 loadQML(_qmlUrl);
177 }
178
180 }
181 }
182
188 {
189 QMessageBox::StandardButton reply;
190
191 reply = QMessageBox::question(mainWidget(), "QML was updated", _qmlUrl.toLocalFile() + " was changed.\nDo you want to reload it?", QMessageBox::Yes|QMessageBox::No);
192
193 if (reply == QMessageBox::Yes)
194 {
195 return true;
196 }
197
198 return false;
199 }
200
205 void log(const QString& text)
206 {
207 _ui->logWindow->appendPlainText(text);
208 }
209
213 void editQML()
214 {
215 if(_qmlUrl.isValid() && !_qmlUrl.isEmpty())
216 {
217 bool status = QDesktopServices::openUrl(_qmlUrl);
218
219 if(!status)
220 {
221 log(QString("Failed to launch external editor for file: ") + _qmlUrl.toString());
222 }
223 else
224 {
225 log(QString("System editor for QML launched!"));
226 }
227 }
228 }
229
230
231public slots:
236 void handleStatusChange(QQuickWidget::Status status)
237 {
238 switch (status)
239 {
240 case QQuickWidget::Status::Error:
241 {
242 auto errors = _ui->quickWidget->errors();
243
244 for (auto error : errors)
245 {
246 QString errorString = error.toString();
247
248 log(QString("QML status: error - ") + errorString);
249 }
250 }
251 break;
252
253 case QQuickWidget::Status::Null:
254 log(QString("QML status: Null"));
255 break;
256
257 case QQuickWidget::Status::Loading:
258 log(QString("QML status: Loading"));
259 break;
260
261 case QQuickWidget::Status::Ready:
262 log(QString("QML status: Ready"));
263 break;
264 }
265 }
266
267private:
269 Ui::QMLExecutorPrivate* _ui;
270
272 QWidget* _widget;
273
275 QUrl _qmlUrl;
276
278 QDateTime _qmlLoadTime;
279
281 QTimer _qmlUpdateCheckTimer;
282
283 CANBusModel* _CANBusModel;
284};
285
286#endif // QMLEXECUTORGUIIMPL_H
The CANBusModel class is used to interface CAN operations with QML stack.
Definition canbusmodel.hpp:11
QMLExecutor plugin gui implementation.
Definition qmlexecutorguiimpl.h:29
bool askForQMLReload()
ask if qml reload should be done
Definition qmlexecutorguiimpl.h:187
void stopFileModificationChecks()
stops checking for qml file modification
Definition qmlexecutorguiimpl.h:158
virtual void setModel(CANBusModel *model) override
remembers can bus model for qml
Definition qmlexecutorguiimpl.h:141
virtual void loadQML(const QUrl &url) override
loads qml into a quick widget
Definition qmlexecutorguiimpl.h:99
void log(const QString &text)
log message to log area
Definition qmlexecutorguiimpl.h:205
void handleStatusChange(QQuickWidget::Status status)
handle status change of qml, just log it
Definition qmlexecutorguiimpl.h:236
void checkQMLModification()
checks if qml file was modified, ask the user and reloads it if needed
Definition qmlexecutorguiimpl.h:166
void updateUIColor() override
used to align empty QQuickWidget color with current color scheme
Definition qmlexecutorguiimpl.h:75
void browseAndOpenQML()
Slot to do browsing for QML file, calls qml load.
Definition qmlexecutorguiimpl.h:85
void startQMLFileModificationChecks()
starts checking for qml file modification
Definition qmlexecutorguiimpl.h:149
virtual QWidget * mainWidget() override
not used, return main widget for ui
Definition qmlexecutorguiimpl.h:66
QMLExecutorGuiImpl(QObject *parent)
explicit constructor
Definition qmlexecutorguiimpl.h:37
void editQML()
tries to launch system editor for .qml file
Definition qmlexecutorguiimpl.h:213
Interface of gui for QMLExecutor plugin.
Definition qmlexecutorguiint.h:16
void QMLLoaded(const QUrl &url)
this signal is emitted when qml was loaded
QMLExecutor plugin private implementation.
Definition qmlexecutor_p.h:18
Definition canrawsender_p.h:13