diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e282ebf..3feefa6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,151 +1,152 @@ /* Atelier KDE Printer Host for 3D Printing Copyright (C) <2016> Author: Lays Rodrigues - laysrodrigues@gmail.com Chris Rizzitello - rizzitello@kde.org This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include #include #include #include "widgets/gcodeeditorwidget.h" MainWindow::MainWindow(QWidget *parent) : KXmlGuiWindow(parent), ui(new Ui::MainWindow), leftToolbar(new QToolBar()), profilesDialog(new ProfilesDialog(this)), connectSettingsDialog(new ConnectSettingsDialog(this)), m_curr_editor_view(nullptr) { ui->setupUi(this); setupActions(); initWidgets(); // Use this if trying to fix the bug with the connection // m_curr_editor_view = ui->gcodeEditorWidget->gcodeView(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::initWidgets() { // When a new profile is added on the Profile Dialog it needs to update the profiles on connection dialog connect(profilesDialog, &ProfilesDialog::updateProfiles, connectSettingsDialog, &ConnectSettingsDialog::updateProfiles); connect(connectSettingsDialog, &ConnectSettingsDialog::startConnection, this, &MainWindow::newConnection); connect(ui->gcodeEditorWidget, &GCodeEditorWidget::updateClientFactory, this, [=](KTextEditor::View* view){ guiFactory()->removeClient(m_curr_editor_view); guiFactory()->addClient(view); m_curr_editor_view = view; }); ui->gcodeDockWidget->setHidden(true); ui->videoDockWidget->setHidden(true); buildToolbar(); -// connectSettingsDialog->setFirmwareList(core.availableFirmwarePlugins()); -// profilesDialog->setBaudRates(core.serial()->validBaudRates()); + auto instance = qobject_cast(ui->tabWidget->currentWidget()); + connectSettingsDialog->setFirmwareList(instance->firmwares()); + profilesDialog->setBaudRates(instance->baudRates()); } void MainWindow::buildToolbar() { leftToolbar->setOrientation(Qt::Vertical); leftToolbar->setMovable(true); leftToolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); addToolBar(Qt::LeftToolBarArea, leftToolbar); } void MainWindow::setupActions() { // Actions for the Toolbar QAction *action; action = actionCollection()->addAction(QStringLiteral("open_gcode")); action->setText(i18n("&Open GCode")); connect(action, &QAction::triggered, this, &MainWindow::openFile); action = actionCollection()->addAction(QStringLiteral("connect")); action->setText(i18n("&Connect")); connect(action, &QAction::triggered, connectSettingsDialog, &ConnectSettingsDialog::show); action = actionCollection()->addAction(QStringLiteral("profiles")); action->setText(i18n("&Profiles")); connect(action, &QAction::triggered, profilesDialog, &ProfilesDialog::show); action = actionCollection()->addAction(QStringLiteral("3d"), ui->view3DdockWidget->toggleViewAction()); action->setText(i18n("&3D")); leftToolbar->addAction(action); action = actionCollection()->addAction(QStringLiteral("gcode"), ui->gcodeDockWidget->toggleViewAction()); action->setText(i18n("&GCode")); leftToolbar->addAction(action); // This causes the program to crash when opening a second file, why? Apparently conflicts with // the connect that also works with the guiFactory // connect(action, &QAction::toggled, [=](bool b){ // b ? guiFactory()->addClient(m_curr_editor_view) : guiFactory()->removeClient(m_curr_editor_view); // }); action = actionCollection()->addAction(QStringLiteral("video"), ui->videoDockWidget->toggleViewAction()); action->setText(i18n("&Video")); leftToolbar->addAction(action); #ifdef Q_OS_LINUX //only set icons from theme on linux actionCollection()->action(QStringLiteral("profiles"))->setIcon(QIcon::fromTheme("emblem-favorite")); #endif //use style's standardIcon for the icons we can. actionCollection()->action(QStringLiteral("open_gcode"))->setIcon(style()->standardIcon(QStyle::SP_DirOpenIcon)); action = KStandardAction::quit(qApp, SLOT(quit()), actionCollection()); setupGUI(Default, ":/atelierui"); } void MainWindow::openFile() { QUrl fileNameFromDialog = QFileDialog::getOpenFileUrl(this, i18n("Open GCode"), QDir::homePath(), i18n("GCode (*.gco *.gcode)")); if (!fileNameFromDialog.isEmpty()) { ui->gcodeEditorWidget->loadFile(fileNameFromDialog); ui->view3DWidget->drawModel(fileNameFromDialog.toString()); const int tabs = ui->tabWidget->count(); m_openFiles.append(fileNameFromDialog); for(int i=0; i < tabs; ++i){ auto instance = qobject_cast(ui->tabWidget->widget(i)); instance->setOpenFiles(m_openFiles); } } } void MainWindow::newConnection(const QString& port, const QMap& profile) { const int tabs = ui->tabWidget->count(); if(ui->tabWidget->count() == 1){ auto instance = qobject_cast(ui->tabWidget->currentWidget()); if(!instance->connected()){ instance->startConnection(port, profile); return; } } auto newInstanceWidget = new AtCoreInstanceWidget(); ui->tabWidget->addTab(newInstanceWidget, QString::number(tabs+1)); newInstanceWidget->startConnection(port, profile); } diff --git a/src/widgets/atcoreinstancewidget.cpp b/src/widgets/atcoreinstancewidget.cpp index 3aac982..3ce9b4b 100644 --- a/src/widgets/atcoreinstancewidget.cpp +++ b/src/widgets/atcoreinstancewidget.cpp @@ -1,308 +1,320 @@ /* Atelier KDE Printer Host for 3D Printing Copyright (C) <2017> Author: Lays Rodrigues - laysrodriguessilva@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "atcoreinstancewidget.h" #include "ui_atcoreinstancewidget.h" #include #include #include #include #include "../dialogs/choosefiledialog.h" AtCoreInstanceWidget::AtCoreInstanceWidget(QWidget *parent): QWidget(parent), m_connected(false) { ui = new Ui::AtCoreInstanceWidget; ui->setupUi(this); ui->printPB->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); ui->pausePB->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); ui->stopPB->setIcon(style()->standardIcon(QStyle::SP_MediaStop)); ui->disableMotorsPB->setIcon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton)); ui->printProgressWidget->setVisible(false); setupConnections(); initConnectsToAtCore(); enableControls(false); } AtCoreInstanceWidget::~AtCoreInstanceWidget() { delete ui; } void AtCoreInstanceWidget::setupConnections(){ connect(ui->pausePB, &QPushButton::clicked, this, &AtCoreInstanceWidget::pausePrint); connect(ui->stopPB, &QPushButton::clicked, this, &AtCoreInstanceWidget::stopPrint); connect(ui->disableMotorsPB, &QPushButton::clicked, this, &AtCoreInstanceWidget::disableMotors); buildToolbar(); connect(ui->disconnectPB, &QPushButton::clicked, [=]{ m_core.setState(AtCore::DISCONNECTED); }); connect(ui->printPB, &QPushButton::clicked, this, &AtCoreInstanceWidget::print); } void AtCoreInstanceWidget::buildToolbar() { toolBar = new QToolBar(); //toolBar->setOrientation(Qt::Vertical); auto *axis = new QAction("Axis"); axis->setCheckable(true); axis->setChecked(true); connect(axis, &QAction::toggled, ui->axisViewWidget, &AxisControl::setVisible); auto *controls = new QAction("Controls"); controls->setCheckable(true); controls->setChecked(true); connect(controls, &QAction::toggled, ui->bedExtWidget, &BedExtruderWidget::setVisible); auto *plot = new QAction("Temperature Plot"); plot->setCheckable(true); plot->setChecked(true); connect(plot, &QAction::toggled, ui->plotWidget, &PlotWidget::setVisible); toolBar->addAction(axis); toolBar->addAction(controls); toolBar->addAction(plot); ui->toolBarLayout->addWidget(new QLabel(i18n("Show/Hide: "))); ui->toolBarLayout->addWidget(toolBar); ui->toolBarLayout->addStretch(); } void AtCoreInstanceWidget::startConnection(QString serialPort, QMap profiles){ m_core.initSerial(serialPort, profiles["bps"].toInt()); } void AtCoreInstanceWidget::initConnectsToAtCore() { // Handle AtCore status change connect(&m_core, &AtCore::stateChanged, this, &AtCoreInstanceWidget::handlePrinterStatusChanged); // If the number of extruders from the printer change, we need to update the radiobuttons on the widget connect(this, &AtCoreInstanceWidget::extruderCountChanged, ui->bedExtWidget, &BedExtruderWidget::setExtruderCount); // Bed and Extruder temperatures management connect(ui->bedExtWidget, &BedExtruderWidget::bedTemperatureChanged, &m_core, &AtCore::setBedTemp); connect(ui->bedExtWidget, &BedExtruderWidget::extTemperatureChanged, &m_core, &AtCore::setExtruderTemp); // Connect AtCore temperatures changes on Atelier Plot connect(&m_core.temperature(), &Temperature::bedTemperatureChanged, [ = ](float temp) { checkTemperature(0x00, 0, temp); ui->plotWidget->appendPoint(i18n("Actual Bed"), temp); ui->plotWidget->update(); ui->bedExtWidget->updateBedTemp(temp); }); connect(&m_core.temperature(), &Temperature::bedTargetTemperatureChanged, [ = ](float temp) { checkTemperature(0x01, 0, temp); ui->plotWidget->appendPoint(i18n("Target Bed"), temp); ui->plotWidget->update(); ui->bedExtWidget->updateBedTargetTemp(temp); }); connect(&m_core.temperature(), &Temperature::extruderTemperatureChanged, [ = ](float temp) { checkTemperature(0x02, 0, temp); ui->plotWidget->appendPoint(i18n("Actual Ext.1"), temp); ui->plotWidget->update(); ui->bedExtWidget->updateExtTemp(temp); }); connect(&m_core.temperature(), &Temperature::extruderTargetTemperatureChanged, [ = ](float temp) { checkTemperature(0x03, 0, temp); ui->plotWidget->appendPoint(i18n("Target Ext.1"), temp); ui->plotWidget->update(); ui->bedExtWidget->updateExtTargetTemp(temp); }); connect(ui->pushGCodeWidget, &PushGCodeWidget::push, [ = ](QString command) { ui->logWidget->addLog("Push " + command); m_core.pushCommand(command); }); // Fan, Flow and Speed management connect(ui->ratesControlWidget, &RatesControlWidget::fanSpeedChanged, &m_core, &AtCore::setFanSpeed); connect(ui->ratesControlWidget, &RatesControlWidget::flowRateChanged, &m_core, &AtCore::setFlowRate); connect(ui->ratesControlWidget, &RatesControlWidget::printSpeedChanged, &m_core, &AtCore::setPrinterSpeed); connect(ui->axisViewWidget, &AxisControl::clicked, this, &AtCoreInstanceWidget::axisControlClicked); } void AtCoreInstanceWidget::printFile(const QString& fileName) { if (!fileName.isEmpty() && (m_core.state() == AtCore::IDLE)) { m_core.print(fileName); } } void AtCoreInstanceWidget::print(){ auto dialog = new ChooseFileDialog(this, m_files); if(dialog->exec() == QDialog::Accepted){ printFile(dialog->choosenFile()); } } void AtCoreInstanceWidget::pausePrint() { m_core.pause(QString()); } void AtCoreInstanceWidget::stopPrint() { m_core.stop(); } void AtCoreInstanceWidget::disableMotors() { m_core.pushCommand(GCode::toCommand(GCode::M18)); } void AtCoreInstanceWidget::handlePrinterStatusChanged(AtCore::STATES newState) { QString stateString; switch (newState) { case AtCore::CONNECTING: { stateString = i18n("Connecting..."); connect(&m_core, &AtCore::receivedMessage, this, &AtCoreInstanceWidget::checkReceivedCommand); connect(m_core.serial(), &SerialLayer::pushedCommand, this, &AtCoreInstanceWidget::checkPushedCommands); } break; case AtCore::IDLE: { stateString = i18n("Connected to ") + m_core.serial()->portName(); emit extruderCountChanged(m_core.extruderCount()); ui->logWidget->addLog(i18n("Serial connected")); ui->disconnectPB->setEnabled(true); setConnectedStatus(true); } break; case AtCore::DISCONNECTED: { stateString = i18n("Not Connected"); disconnect(&m_core, &AtCore::receivedMessage, this, &AtCoreInstanceWidget::checkReceivedCommand); disconnect(m_core.serial(), &SerialLayer::pushedCommand, this, &AtCoreInstanceWidget::checkPushedCommands); ui->logWidget->addLog(i18n("Serial disconnected")); setConnectedStatus(false); } break; case AtCore::STARTPRINT: { stateString = i18n("Starting Print"); ui->printProgressWidget->setVisible(true); connect(&m_core, &AtCore::printProgressChanged, ui->printProgressWidget, &PrintProgressWidget::updateProgressBar); } break; case AtCore::FINISHEDPRINT: { stateString = i18n("Finished Print"); ui->printProgressWidget->setVisible(false); disconnect(&m_core, &AtCore::printProgressChanged, ui->printProgressWidget, &PrintProgressWidget::updateProgressBar); } break; case AtCore::BUSY: { stateString = i18n("Printing"); ui->disconnectPB->setDisabled(true); } break; case AtCore::PAUSE: { stateString = i18n("Paused"); } break; case AtCore::STOP: { stateString = i18n("Stoping Print"); } break; case AtCore::ERRORSTATE: { stateString = i18n("Error"); } break; } ui->lblState->setText(stateString); } void AtCoreInstanceWidget::checkTemperature(uint sensorType, uint number, uint temp) { QString msg; switch (sensorType) { case 0x00: // bed msg = QString::fromLatin1("Bed Temperature "); break; case 0x01: // bed target msg = QString::fromLatin1("Bed Target Temperature "); break; case 0x02: // extruder msg = QString::fromLatin1("Extruder Temperature "); break; case 0x03: // extruder target msg = QString::fromLatin1("Extruder Target Temperature "); break; case 0x04: // enclosure msg = QString::fromLatin1("Enclosure Temperature "); break; case 0x05: // enclosure target msg = QString::fromLatin1("Enclosure Target Temperature "); break; } msg.append(QString::fromLatin1("[%1] : %2")); msg = msg.arg(QString::number(number)) .arg(QString::number(temp)); ui->logWidget->addRLog(msg); } void AtCoreInstanceWidget::checkReceivedCommand(const QByteArray &message) { ui->logWidget->addRLog(QString::fromUtf8(message)); } void AtCoreInstanceWidget::checkPushedCommands(QByteArray bmsg) { QString msg = QString::fromUtf8(bmsg); QRegExp _newLine(QChar::fromLatin1('\n')); QRegExp _return(QChar::fromLatin1('\r')); msg.replace(_newLine, QStringLiteral("\\n")); msg.replace(_return, QStringLiteral("\\r")); ui->logWidget->addSLog(msg); } void AtCoreInstanceWidget::axisControlClicked(QChar axis, int value) { m_core.setRelativePosition(); m_core.pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("%1%2").arg(axis, QString::number(value)))); m_core.setAbsolutePosition(); } void AtCoreInstanceWidget::enableControls(bool b) { ui->mainTab->setEnabled(b); ui->printPB->setEnabled(b); ui->pausePB->setEnabled(b); ui->stopPB->setEnabled(b); ui->disconnectPB->setEnabled(b); ui->disableMotorsPB->setEnabled(b); toolBar->setEnabled(b); } bool AtCoreInstanceWidget::connected() { return m_connected; } void AtCoreInstanceWidget::setConnectedStatus(bool b) { m_connected = b; enableControls(b); } void AtCoreInstanceWidget::setOpenFiles(QList files) { m_files = files; } +const QStringList AtCoreInstanceWidget::baudRates() +{ + return m_core.portSpeeds(); +} + +const QStringList AtCoreInstanceWidget::firmwares() +{ + return m_core.availableFirmwarePlugins(); +} + + + diff --git a/src/widgets/atcoreinstancewidget.h b/src/widgets/atcoreinstancewidget.h index 6a846af..d3fce38 100644 --- a/src/widgets/atcoreinstancewidget.h +++ b/src/widgets/atcoreinstancewidget.h @@ -1,76 +1,78 @@ /* Atelier KDE Printer Host for 3D Printing Copyright (C) <2017> Author: Lays Rodrigues - laysrodriguessilva@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #pragma once #include #include #include #include namespace Ui { class AtCoreInstanceWidget; } /** * @todo write docs */ class AtCoreInstanceWidget : public QWidget { Q_OBJECT public: /** * Default constructor */ AtCoreInstanceWidget(QWidget* parent = nullptr); /** * Destructor */ ~AtCoreInstanceWidget(); void startConnection(QString serialPort, QMap profiles); bool connected(); void setOpenFiles(QList files); + const QStringList baudRates(); + const QStringList firmwares(); private: Ui::AtCoreInstanceWidget* ui; AtCore m_core; QToolBar *toolBar; QList m_files; bool m_connected; void setupConnections(); void initConnectsToAtCore(); void printFile(const QString& fileName); void pausePrint(); void stopPrint(); void disableMotors(); void checkReceivedCommand(const QByteArray &message); void checkPushedCommands(QByteArray bmsg); void handlePrinterStatusChanged(AtCore::STATES newState); void checkTemperature(uint sensorType, uint number, uint temp); void axisControlClicked(QChar axis, int value); void enableControls(bool b); void buildToolbar(); void setConnectedStatus(bool b); void print(); signals: void extruderCountChanged(int count); };