Changeset View
Standalone View
src/mainwindow.cpp
Show All 17 Lines | |||||
18 | */ | 18 | */ | ||
19 | #include "mainwindow.h" | 19 | #include "mainwindow.h" | ||
20 | #include "ui_mainwindow.h" | 20 | #include "ui_mainwindow.h" | ||
21 | #include <QFileDialog> | 21 | #include <QFileDialog> | ||
22 | #include <KLocalizedString> | 22 | #include <KLocalizedString> | ||
23 | #include <KStandardAction> | 23 | #include <KStandardAction> | ||
24 | #include <KActionCollection> | 24 | #include <KActionCollection> | ||
25 | #include <KXMLGUIFactory> | 25 | #include <KXMLGUIFactory> | ||
26 | #include <AtCore/SerialLayer> | | |||
27 | #include <AtCore/GCodeCommands> | | |||
28 | #include <dialogs/connectsettingsdialog.h> | 26 | #include <dialogs/connectsettingsdialog.h> | ||
29 | #include <dialogs/profilesdialog.h> | 27 | #include <dialogs/profilesdialog.h> | ||
30 | 28 | #include <memory> | |||
31 | MainWindow::MainWindow(QWidget *parent) : | 29 | MainWindow::MainWindow(QWidget *parent) : | ||
32 | KXmlGuiWindow(parent), | 30 | KXmlGuiWindow(parent), | ||
33 | ui(new Ui::MainWindow) | 31 | ui(new Ui::MainWindow) | ||
34 | { | 32 | { | ||
35 | ui->setupUi(this); | 33 | ui->setupUi(this); | ||
36 | logWidget = new LogWidget; | | |||
37 | setupActions(); | 34 | setupActions(); | ||
38 | initConnectsToAtCore(); | | |||
39 | initWidgets(); | | |||
40 | setCentralWidget(nullptr); | | |||
41 | } | 35 | } | ||
42 | 36 | | |||
43 | MainWindow::~MainWindow() | 37 | MainWindow::~MainWindow() | ||
44 | { | 38 | { | ||
45 | delete ui; | 39 | delete ui; | ||
46 | } | 40 | } | ||
47 | 41 | | |||
48 | void MainWindow::initConnectsToAtCore() | | |||
49 | { | | |||
50 | // Handle AtCore status change | | |||
51 | connect(&core, &AtCore::stateChanged, this, &MainWindow::handlePrinterStatusChanged); | | |||
52 | | ||||
53 | // If the number of extruders from the printer change, we need to update the radiobuttons on the widget | | |||
54 | connect(this, &MainWindow::extruderCountChanged, ui->bedExtWidget, &BedExtruderWidget::setExtruderCount); | | |||
55 | | ||||
56 | // Bed and Extruder temperatures management | | |||
57 | connect(ui->bedExtWidget, &BedExtruderWidget::bedTemperatureChanged, &core, &AtCore::setBedTemp); | | |||
58 | connect(ui->bedExtWidget, &BedExtruderWidget::extTemperatureChanged, &core, &AtCore::setExtruderTemp); | | |||
59 | | ||||
60 | // Connect AtCore temperatures changes on Atelier Plot | | |||
61 | connect(&core.temperature(), &Temperature::bedTemperatureChanged, [ = ](float temp) { | | |||
62 | checkTemperature(0x00, 0, temp); | | |||
63 | ui->plotWidget->appendPoint(i18n("Actual Bed"), temp); | | |||
64 | ui->plotWidget->update(); | | |||
65 | ui->bedExtWidget->updateBedTemp(temp); | | |||
66 | }); | | |||
67 | connect(&core.temperature(), &Temperature::bedTargetTemperatureChanged, [ = ](float temp) { | | |||
68 | checkTemperature(0x01, 0, temp); | | |||
69 | ui->plotWidget->appendPoint(i18n("Target Bed"), temp); | | |||
70 | ui->plotWidget->update(); | | |||
71 | ui->bedExtWidget->updateBedTargetTemp(temp); | | |||
72 | }); | | |||
73 | connect(&core.temperature(), &Temperature::extruderTemperatureChanged, [ = ](float temp) { | | |||
74 | checkTemperature(0x02, 0, temp); | | |||
75 | ui->plotWidget->appendPoint(i18n("Actual Ext.1"), temp); | | |||
76 | ui->plotWidget->update(); | | |||
77 | ui->bedExtWidget->updateExtTemp(temp); | | |||
78 | }); | | |||
79 | connect(&core.temperature(), &Temperature::extruderTargetTemperatureChanged, [ = ](float temp) { | | |||
80 | checkTemperature(0x03, 0, temp); | | |||
81 | ui->plotWidget->appendPoint(i18n("Target Ext.1"), temp); | | |||
82 | ui->plotWidget->update(); | | |||
83 | ui->bedExtWidget->updateExtTargetTemp(temp); | | |||
84 | }); | | |||
85 | | ||||
86 | connect(ui->pushGCodeWidget, &PushGCodeWidget::push, [ = ](QString command) { | | |||
87 | logWidget->addLog("Push " + command); | | |||
88 | core.pushCommand(command); | | |||
89 | }); | | |||
90 | | ||||
91 | // Fan, Flow and Speed management | | |||
92 | connect(ui->ratesControlWidget, &RatesControlWidget::fanSpeedChanged, &core, &AtCore::setFanSpeed); | | |||
93 | connect(ui->ratesControlWidget, &RatesControlWidget::flowRateChanged, &core, &AtCore::setFlowRate); | | |||
94 | connect(ui->ratesControlWidget, &RatesControlWidget::printSpeedChanged, &core, &AtCore::setPrinterSpeed); | | |||
95 | connect(ui->axisViewWidget, &AxisControl::clicked, this, &MainWindow::axisControlClicked); | | |||
96 | | ||||
97 | } | | |||
98 | | ||||
99 | void MainWindow::initWidgets() | | |||
100 | { | | |||
101 | // Disable Toolbox to prevent the user to mess up without a printer being connected | | |||
102 | ui->controlDockWidget->setDisabled(true); | | |||
103 | ui->axisDockWidget->setDisabled(true); | | |||
104 | | ||||
105 | // This dock is of Printing Progress. It only need to be show while printing | | |||
106 | ui->printProgressDockWidget->setVisible(false); | | |||
107 | | ||||
108 | ui->logDockWidget->setWidget(logWidget); | | |||
109 | ui->statusBar->addWidget(ui->statusBarWidget); | | |||
110 | | ||||
111 | ui->homeAllPB->setIcon(style()->standardIcon(QStyle::SP_DirHomeIcon)); | | |||
112 | ui->homeXPB->setIcon(style()->standardIcon(QStyle::SP_DirHomeIcon)); | | |||
113 | ui->homeYPB->setIcon(style()->standardIcon(QStyle::SP_DirHomeIcon)); | | |||
114 | ui->homeZPB->setIcon(style()->standardIcon(QStyle::SP_DirHomeIcon)); | | |||
115 | | ||||
116 | tabifyDockWidget(ui->axisDockWidget, ui->controlDockWidget); | | |||
117 | tabifyDockWidget(ui->view3DdockWidget, ui->gcodeDockWidget); | | |||
118 | tabifyDockWidget(ui->view3DdockWidget, ui->videoDockWidget); | | |||
119 | } | | |||
120 | | ||||
121 | void MainWindow::setupActions() | 42 | void MainWindow::setupActions() | ||
rizzitello: Empty Function | |||||
122 | { | 43 | { | ||
123 | // Actions for the Toolbar | 44 | // Actions for the Toolbar | ||
124 | QAction *action; | 45 | QAction *action; | ||
125 | action = actionCollection()->addAction(QStringLiteral("open_gcode")); | 46 | action = actionCollection()->addAction(QStringLiteral("open_gcode")); | ||
126 | action->setText(i18n("&Open GCode")); | 47 | action->setText(i18n("&Open GCode")); | ||
127 | connect(action, &QAction::triggered, this, &MainWindow::openFile); | 48 | connect(action, &QAction::triggered, this, &MainWindow::openFile); | ||
128 | 49 | | |||
129 | _connect = actionCollection()->addAction(QStringLiteral("connect")); | 50 | action = actionCollection()->addAction(QStringLiteral("connect")); | ||
130 | _connect->setText(i18n("&Connect")); | 51 | action->setText(i18n("&Connect")); | ||
131 | _connect->setCheckable(true); | 52 | connect(action, &QAction::triggered, [ = ]{ | ||
patrickelectric: reference | |||||
132 | connect(_connect, &QAction::toggled, [ = ](bool checked) { | | |||
133 | if (checked) { | | |||
134 | std::unique_ptr<ConnectSettingsDialog> csd(new ConnectSettingsDialog); | 53 | std::unique_ptr<ConnectSettingsDialog> csd(new ConnectSettingsDialog); | ||
135 | connect(csd.get(), &ConnectSettingsDialog::startConnection, [ & ](QString port, QMap<QString, QVariant> data) { | 54 | connect(csd.get(), &ConnectSettingsDialog::startConnection, [ & ](QString port, QMap<QString, QVariant> data) { | ||
patrickelectric: const ref | |||||
136 | core.initSerial(port, data["bps"].toInt()); | | |||
137 | }); | 55 | }); | ||
138 | csd->exec(); | 56 | csd->exec(); | ||
139 | } else { | | |||
140 | core.closeConnection(); | | |||
141 | _connect->setText(i18n("&Connect")); | | |||
142 | ui->bedExtWidget->stopHeating(); | | |||
143 | core.setState(AtCore::DISCONNECTED); | | |||
144 | } | | |||
145 | }); | | |||
146 | | ||||
147 | connect(ui->homeAllPB, &QPushButton::clicked, [=]{ | | |||
148 | core.home(); | | |||
149 | }); | | |||
150 | | ||||
151 | connect(ui->homeXPB, &QPushButton::clicked, [=]{ | | |||
152 | core.home(AtCore::X); | | |||
153 | }); | | |||
154 | | ||||
155 | connect(ui->homeYPB, &QPushButton::clicked, [=]{ | | |||
156 | core.home(AtCore::Y); | | |||
157 | }); | | |||
158 | | ||||
159 | connect(ui->homeZPB, &QPushButton::clicked, [=]{ | | |||
160 | core.home(AtCore::Z); | | |||
161 | }); | 57 | }); | ||
162 | 58 | | |||
163 | action = actionCollection()->addAction(QStringLiteral("profiles")); | 59 | action = actionCollection()->addAction(QStringLiteral("profiles")); | ||
164 | action->setText(i18n("&Profiles")); | 60 | action->setText(i18n("&Profiles")); | ||
165 | connect(action, &QAction::triggered, [ & ] { | 61 | connect(action, &QAction::triggered, [ & ] { | ||
166 | std::unique_ptr<ProfilesDialog> pd(new ProfilesDialog); | 62 | std::unique_ptr<ProfilesDialog> pd(new ProfilesDialog); | ||
rizzitello: why are we now giving the dialog two empty string lists? | |||||
Those data get from AtCore, and since I'm cleaning up this and moving all the management to AtCoreInstanceWidget, for now, I choose to pass empty strings. laysrodrigues: Those data get from AtCore, and since I'm cleaning up this and moving all the management to… | |||||
These are problems that need to be solved before we go removing atcore from the main window.. rizzitello: > I think that we need a better way to get that info without using an instance of AtCore to get… | |||||
D10846 to solve the above issue rizzitello: D10846 to solve the above issue | |||||
If this case exist, should be the default variables value for this constructor. patrickelectric: If this case exist, should be the default variables value for this constructor. | |||||
This will be resolved by D10846. This diff is planed to be based upon that. rizzitello: This will be resolved by D10846. This diff is planed to be based upon that. | |||||
167 | pd->exec(); | 63 | pd->exec(); | ||
168 | }); | 64 | }); | ||
169 | 65 | | |||
170 | action = actionCollection()->addAction(QStringLiteral("print")); | | |||
171 | action->setText(i18n("&Print")); | | |||
172 | connect(action, &QAction::triggered, this, &MainWindow::printFile); | | |||
173 | | ||||
174 | action = actionCollection()->addAction(QStringLiteral("pause")); | | |||
175 | action->setText(i18n("&Pause")); | | |||
176 | connect(action, &QAction::triggered, this, &MainWindow::pausePrint); | | |||
177 | | ||||
178 | action = actionCollection()->addAction(QStringLiteral("stop")); | | |||
179 | action->setText(i18n("&Stop")); | | |||
180 | connect(action, &QAction::triggered, this, &MainWindow::stopPrint); | | |||
181 | | ||||
182 | #ifdef Q_OS_LINUX | 66 | #ifdef Q_OS_LINUX | ||
183 | //only set icons from theme on linux | 67 | //only set icons from theme on linux | ||
184 | actionCollection()->action(QStringLiteral("profiles"))->setIcon(QIcon::fromTheme("emblem-favorite")); | 68 | actionCollection()->action(QStringLiteral("profiles"))->setIcon(QIcon::fromTheme("emblem-favorite")); | ||
185 | #endif | 69 | #endif | ||
186 | //use style's standardIcon for the icons we can. | 70 | //use style's standardIcon for the icons we can. | ||
187 | actionCollection()->action(QStringLiteral("open_gcode"))->setIcon(style()->standardIcon(QStyle::SP_DirOpenIcon)); | 71 | actionCollection()->action(QStringLiteral("open_gcode"))->setIcon(style()->standardIcon(QStyle::SP_DirOpenIcon)); | ||
188 | actionCollection()->action(QStringLiteral("print"))->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); | | |||
189 | actionCollection()->action(QStringLiteral("pause"))->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); | | |||
190 | actionCollection()->action(QStringLiteral("stop"))->setIcon(style()->standardIcon(QStyle::SP_MediaStop)); | | |||
191 | | ||||
192 | // Actions for the Docks | | |||
193 | action = actionCollection()->addAction(QStringLiteral("dock_labels")); | | |||
194 | action->setText(i18n("&Show Dock Labels")); | | |||
195 | action->setCheckable(true); | | |||
196 | action->setChecked(true); | | |||
197 | connect(action, &QAction::triggered, [=](bool checked){ | | |||
198 | toggleDockTitles(checked); | | |||
199 | }); | | |||
200 | | ||||
201 | action = actionCollection()->addAction(QStringLiteral("3d"), ui->view3DdockWidget->toggleViewAction()); | | |||
202 | action->setText(i18n("&3DView")); | | |||
203 | | ||||
204 | action = actionCollection()->addAction(QStringLiteral("gcode"), ui->gcodeDockWidget->toggleViewAction()); | | |||
205 | action->setText(i18n("&GCode")); | | |||
206 | 72 | | |||
207 | action = KStandardAction::quit(qApp, SLOT(quit()), actionCollection()); | 73 | action = KStandardAction::quit(qApp, SLOT(quit()), actionCollection()); | ||
208 | 74 | | |||
209 | // Plot | | |||
210 | action = actionCollection()->addAction(QStringLiteral("plot"), ui->plotDockWidget->toggleViewAction()); | | |||
211 | action->setText(i18n("Temperature Timeline")); | | |||
212 | | ||||
213 | action = actionCollection()->addAction(QStringLiteral("controller"), ui->controlDockWidget->toggleViewAction()); | | |||
214 | action->setText(i18n("Controller")); | | |||
215 | | ||||
216 | action = actionCollection()->addAction(QStringLiteral("axis"), ui->axisDockWidget->toggleViewAction()); | | |||
217 | action->setText(i18n("Axis")); | | |||
218 | | ||||
219 | action = actionCollection()->addAction(QStringLiteral("video"), ui->videoDockWidget->toggleViewAction()); | | |||
220 | action->setText(i18n("Video Monitor")); | | |||
221 | | ||||
222 | action = actionCollection()->addAction(QStringLiteral("log"), ui->logDockWidget->toggleViewAction()); | | |||
223 | action->setText(i18n("Log")); | | |||
224 | | ||||
225 | setupGUI(Default, ":/atelierui"); | 75 | setupGUI(Default, ":/atelierui"); | ||
226 | } | 76 | } | ||
227 | 77 | | |||
228 | void MainWindow::openFile() | 78 | void MainWindow::openFile() | ||
229 | { | 79 | { | ||
230 | QUrl fileNameFromDialog = QFileDialog::getOpenFileUrl(this, i18n("Open GCode"), | 80 | QUrl fileNameFromDialog = QFileDialog::getOpenFileUrl(this, i18n("Open GCode"), | ||
231 | QDir::homePath(), i18n("GCode (*.gco *.gcode)")); | 81 | QDir::homePath(), i18n("GCode (*.gco *.gcode)")); | ||
232 | if (!fileNameFromDialog.isEmpty()) { | 82 | if (!fileNameFromDialog.isEmpty()) { | ||
233 | fileName = fileNameFromDialog; | 83 | m_fileName = fileNameFromDialog; | ||
234 | ui->gcodeEditorWidget->loadFile(fileName); | 84 | ui->gcodeEditorWidget->loadFile(m_fileName); | ||
235 | guiFactory()->addClient(ui->gcodeEditorWidget->gcodeView()); | 85 | guiFactory()->addClient(ui->gcodeEditorWidget->gcodeView()); | ||
236 | ui->view3DWidget->drawModel(fileName.toString()); | 86 | ui->view3DWidget->drawModel(m_fileName.toString()); | ||
237 | } | | |||
238 | } | | |||
239 | | ||||
240 | void MainWindow::printFile() | | |||
241 | { | | |||
242 | if (!fileName.isEmpty() && (core.state() == AtCore::IDLE)) { | | |||
243 | QString f = fileName.toLocalFile(); | | |||
244 | core.print(f); | | |||
245 | } | | |||
246 | } | | |||
247 | | ||||
248 | void MainWindow::pausePrint() | | |||
249 | { | | |||
250 | core.pause(QString()); | | |||
251 | } | | |||
252 | | ||||
253 | void MainWindow::stopPrint() | | |||
254 | { | | |||
255 | core.stop(); | | |||
256 | } | | |||
257 | | ||||
258 | void MainWindow::handlePrinterStatusChanged(AtCore::STATES newState) | | |||
259 | { | | |||
260 | QString stateString; | | |||
261 | switch (newState) { | | |||
262 | case AtCore::CONNECTING: { | | |||
263 | stateString = i18n("Connecting..."); | | |||
264 | connect(&core, &AtCore::receivedMessage, this, &MainWindow::checkReceivedCommand); | | |||
265 | connect(core.serial(), &SerialLayer::pushedCommand, this, &MainWindow::checkPushedCommands); | | |||
266 | } break; | | |||
267 | case AtCore::IDLE: { | | |||
268 | stateString = i18n("Connected to ") + core.serial()->portName(); | | |||
269 | ui->controlDockWidget->setEnabled(true); | | |||
270 | ui->axisDockWidget->setEnabled(true); | | |||
271 | emit extruderCountChanged(core.extruderCount()); | | |||
272 | logWidget->addLog(i18n("Serial connected")); | | |||
273 | _connect->setText(i18n("&Disconnect")); | | |||
274 | } break; | | |||
275 | case AtCore::DISCONNECTED: { | | |||
276 | stateString = i18n("Not Connected"); | | |||
277 | ui->controlDockWidget->setEnabled(false); | | |||
278 | ui->axisDockWidget->setEnabled(false); | | |||
279 | disconnect(&core, &AtCore::receivedMessage, this, &MainWindow::checkReceivedCommand); | | |||
280 | disconnect(core.serial(), &SerialLayer::pushedCommand, this, &MainWindow::checkPushedCommands); | | |||
281 | logWidget->addLog(i18n("Serial disconnected")); | | |||
282 | | ||||
283 | } break; | | |||
284 | case AtCore::STARTPRINT: { | | |||
285 | stateString = i18n("Starting Print"); | | |||
286 | ui->printProgressDockWidget->setVisible(true); | | |||
287 | connect(&core, &AtCore::printProgressChanged, ui->printProgressWidget, &PrintProgressWidget::updateProgressBar); | | |||
288 | } break; | | |||
289 | case AtCore::FINISHEDPRINT: { | | |||
290 | stateString = i18n("Finished Print"); | | |||
291 | ui->printProgressDockWidget->setVisible(false); | | |||
292 | disconnect(&core, &AtCore::printProgressChanged, ui->printProgressWidget, &PrintProgressWidget::updateProgressBar); | | |||
293 | } break; | | |||
294 | case AtCore::BUSY: { | | |||
295 | stateString = i18n("Printing"); | | |||
296 | } break; | | |||
297 | case AtCore::PAUSE: { | | |||
298 | stateString = i18n("Paused"); | | |||
299 | } break; | | |||
300 | case AtCore::STOP: { | | |||
301 | stateString = i18n("Stoping Print"); | | |||
302 | } break; | | |||
303 | case AtCore::ERRORSTATE: { | | |||
304 | stateString = i18n("Error"); | | |||
305 | } break; | | |||
306 | } | | |||
307 | ui->lblState->setText(stateString); | | |||
308 | } | | |||
309 | | ||||
310 | void MainWindow::checkTemperature(uint sensorType, uint number, uint temp) | | |||
311 | { | | |||
312 | QString msg; | | |||
313 | switch (sensorType) { | | |||
314 | case 0x00: // bed | | |||
315 | msg = QString::fromLatin1("Bed Temperature "); | | |||
316 | break; | | |||
317 | | ||||
318 | case 0x01: // bed target | | |||
319 | msg = QString::fromLatin1("Bed Target Temperature "); | | |||
320 | break; | | |||
321 | | ||||
322 | case 0x02: // extruder | | |||
323 | msg = QString::fromLatin1("Extruder Temperature "); | | |||
324 | break; | | |||
325 | | ||||
326 | case 0x03: // extruder target | | |||
327 | msg = QString::fromLatin1("Extruder Target Temperature "); | | |||
328 | break; | | |||
329 | | ||||
330 | case 0x04: // enclosure | | |||
331 | msg = QString::fromLatin1("Enclosure Temperature "); | | |||
332 | break; | | |||
333 | | ||||
334 | case 0x05: // enclosure target | | |||
335 | msg = QString::fromLatin1("Enclosure Target Temperature "); | | |||
336 | break; | | |||
337 | } | | |||
338 | | ||||
339 | msg.append(QString::fromLatin1("[%1] : %2")); | | |||
340 | msg = msg.arg(QString::number(number)) | | |||
341 | .arg(QString::number(temp)); | | |||
342 | | ||||
343 | logWidget->addRLog(msg); | | |||
344 | } | | |||
345 | | ||||
346 | void MainWindow::checkReceivedCommand(const QByteArray &message) | | |||
347 | { | | |||
348 | logWidget->addRLog(QString::fromUtf8(message)); | | |||
349 | } | | |||
350 | | ||||
351 | void MainWindow::checkPushedCommands(QByteArray bmsg) | | |||
352 | { | | |||
353 | QString msg = QString::fromUtf8(bmsg); | | |||
354 | QRegExp _newLine(QChar::fromLatin1('\n')); | | |||
355 | QRegExp _return(QChar::fromLatin1('\r')); | | |||
356 | msg.replace(_newLine, QStringLiteral("\\n")); | | |||
357 | msg.replace(_return, QStringLiteral("\\r")); | | |||
358 | logWidget->addSLog(msg); | | |||
359 | } | | |||
360 | | ||||
361 | void MainWindow::axisControlClicked(QChar axis, int value) | | |||
362 | { | | |||
363 | core.setRelativePosition(); | | |||
364 | core.pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("%1%2").arg(axis, QString::number(value)))); | | |||
365 | core.setAbsolutePosition(); | | |||
366 | } | | |||
367 | | ||||
368 | void MainWindow::toggleDockTitles(bool checked) | | |||
369 | { | | |||
370 | if(checked){ | | |||
371 | delete ui->axisDockWidget->titleBarWidget(); | | |||
372 | delete ui->view3DdockWidget->titleBarWidget(); | | |||
373 | delete ui->plotDockWidget->titleBarWidget(); | | |||
374 | delete ui->logDockWidget->titleBarWidget(); | | |||
375 | delete ui->controlDockWidget->titleBarWidget(); | | |||
376 | delete ui->gcodeDockWidget->titleBarWidget(); | | |||
377 | }else{ | | |||
378 | ui->axisDockWidget->setTitleBarWidget(new QWidget()); | | |||
379 | ui->view3DdockWidget->setTitleBarWidget(new QWidget()); | | |||
380 | ui->plotDockWidget->setTitleBarWidget(new QWidget()); | | |||
381 | ui->logDockWidget->setTitleBarWidget(new QWidget()); | | |||
382 | ui->controlDockWidget->setTitleBarWidget(new QWidget()); | | |||
383 | ui->gcodeDockWidget->setTitleBarWidget(new QWidget()); | | |||
384 | } | 87 | } | ||
385 | } | 88 | } | ||
can we just do AtCoreInstanceWidget *instance = ui->tabWidget->currentWidget()); ? its less to read and auto is doing this anyway. rizzitello: can we just do `AtCoreInstanceWidget *instance = ui->tabWidget->currentWidget());` ? its less… | |||||
Should this be done with a smart pointer @patrickelectric ? rizzitello: Should this be done with a smart pointer @patrickelectric ? |
Empty Function