diff --git a/src/dialogs/profilesdialog.cpp b/src/dialogs/profilesdialog.cpp index d9add15..db65c3a 100644 --- a/src/dialogs/profilesdialog.cpp +++ b/src/dialogs/profilesdialog.cpp @@ -1,289 +1,292 @@ /* Atelier KDE Printer Host for 3D Printing Copyright (C) <2016> Author: Lays Rodrigues - lays.rodrigues@kde.org 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 #include #include #include #include "profilesdialog.h" #include "ui_profilesdialog.h" ProfilesDialog::ProfilesDialog(QWidget *parent) : QDialog(parent) , ui(new Ui::ProfilesDialog) , m_modified(false) { ui->setupUi(this); ui->firmwareCB->addItem(QStringLiteral("Auto-Detect")); ui->firmwareCB->addItems(detectFWPlugins()); ui->baudCB->addItems(SERIAL::BAUDS); ui->baudCB->setCurrentText(QLatin1String("115200")); ui->profileCB->setAutoCompletion(true); - connect(ui->profileCB, static_cast(&QComboBox::currentIndexChanged), this, [this](const int newIndex) { + connect(ui->profileCB, QOverload::of(&QComboBox::currentIndexChanged), this, [this](const int newIndex) { blockSignals(true); ui->profileCB->setCurrentIndex(m_prevIndex); blockSignals(false); askToSave(); blockSignals(true); m_prevIndex = newIndex; ui->profileCB->setCurrentIndex(m_prevIndex); blockSignals(false); loadSettings(); }); updateCBProfiles(); connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &ProfilesDialog::buttonBoxClicked); connect(ui->heatedBedCK, &QCheckBox::clicked, this, [this](const bool & status) { ui->bedTempSB->setEnabled(status); }); connect(ui->cartesianRB, &QRadioButton::clicked, this, [this] { ui->printerTypeStack->setCurrentIndex(1); }); connect(ui->deltaRB, &QRadioButton::clicked, this, [this] { ui->printerTypeStack->setCurrentIndex(0); }); connect(ui->removeProfilePB, &QPushButton::clicked, this, &ProfilesDialog::removeProfile); ui->removeProfilePB->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"), style()->standardIcon(QStyle::SP_TrashIcon))); //if any control is modified and no load / save has happened contents are not saved. auto modify = [this] {setModified(true);}; connect(ui->baudCB, &QComboBox::currentTextChanged, modify); connect(ui->radiusSB, &QSpinBox::editingFinished, modify); connect(ui->z_delta_dimensionSB, &QSpinBox::editingFinished, modify); connect(ui->x_dimensionSB, &QSpinBox::editingFinished, modify); connect(ui->y_dimensionSB, &QSpinBox::editingFinished, modify); connect(ui->z_dimensionSB, &QSpinBox::editingFinished, modify); connect(ui->heatedBedCK, &QCheckBox::stateChanged, modify); connect(ui->bedTempSB, &QSpinBox::editingFinished, modify); connect(ui->extruderTempSB, &QSpinBox::editingFinished, modify); connect(ui->postPauseLE, &QLineEdit::editingFinished, modify); connect(ui->firmwareCB, &QComboBox::currentTextChanged, modify); + connect(ui->autoReportTempCK, &QCheckBox::stateChanged, modify); } ProfilesDialog::~ProfilesDialog() { delete ui; } void ProfilesDialog::buttonBoxClicked(QAbstractButton *btn) { switch (ui->buttonBox->buttonRole(btn)) { case QDialogButtonBox::ResetRole: askToSave(); loadSettings(); break; case QDialogButtonBox::RejectRole: askToSave(); close(); break; case QDialogButtonBox::AcceptRole: saveSettings(); break; default: break; } } void ProfilesDialog::saveSettings() { m_settings.beginGroup(QStringLiteral("Profiles")); QStringList groups = m_settings.childGroups(); m_settings.endGroup(); if (groups.contains(ui->profileCB->currentText())) { int ret = QMessageBox::warning( this , i18n("Overwrite Profile?") , i18n("A profile with this name already exists. \n Are you sure you want to overwrite it?") , QMessageBox::Save , QMessageBox::Cancel ); if (ret == QMessageBox::Cancel) { return; } } save(); } void ProfilesDialog::save() { QString currentProfile = ui->profileCB->currentText(); //Add indent to better view of the data m_settings.beginGroup(QStringLiteral("Profiles")); m_settings.beginGroup(currentProfile); //BED if (ui->cartesianRB->isChecked()) { m_settings.setValue(QStringLiteral("isCartesian"), true); m_settings.setValue(QStringLiteral("dimensionX"), ui->x_dimensionSB->value()); m_settings.setValue(QStringLiteral("dimensionY"), ui->y_dimensionSB->value()); m_settings.setValue(QStringLiteral("dimensionZ"), ui->z_dimensionSB->value()); } else { m_settings.setValue(QStringLiteral("isCartesian"), false); m_settings.setValue(QStringLiteral("radius"), ui->radiusSB->value()); m_settings.setValue(QStringLiteral("z_delta_dimension"), ui->z_delta_dimensionSB->value()); } m_settings.setValue(QStringLiteral("heatedBed"), ui->heatedBedCK->isChecked()); m_settings.setValue(QStringLiteral("maximumTemperatureBed"), ui->bedTempSB->value()); //HOTEND m_settings.setValue(QStringLiteral("maximumTemperatureExtruder"), ui->extruderTempSB->value()); + m_settings.setValue(QStringLiteral("autoReportTemp"), ui->autoReportTempCK->isChecked()); //Baud m_settings.setValue(QStringLiteral("bps"), ui->baudCB->currentText()); m_settings.setValue(QStringLiteral("firmware"), ui->firmwareCB->currentText()); m_settings.setValue(QStringLiteral("postPause"), ui->postPauseLE->text()); m_settings.endGroup(); m_settings.endGroup(); //Load new profile setModified(false); updateCBProfiles(); loadSettings(currentProfile); emit updateProfiles(); } void ProfilesDialog::loadSettings(const QString ¤tProfile) { m_settings.beginGroup(QStringLiteral("Profiles")); const QString profileName = currentProfile.isEmpty() ? ui->profileCB ->currentText() : currentProfile; ui->profileCB->setCurrentText(profileName); m_settings.beginGroup(profileName); //BED if (m_settings.value(QStringLiteral("isCartesian")).toBool()) { ui->printerTypeStack->setCurrentIndex(1); ui->cartesianRB->setChecked(true); ui->deltaRB->setChecked(false); ui->x_dimensionSB->setValue(m_settings.value(QStringLiteral("dimensionX"), QStringLiteral("0")).toInt()); ui->y_dimensionSB->setValue(m_settings.value(QStringLiteral("dimensionY"), QStringLiteral("0")).toInt()); ui->z_dimensionSB->setValue(m_settings.value(QStringLiteral("dimensionZ"), QStringLiteral("0")).toInt()); } else { ui->printerTypeStack->setCurrentIndex(0); ui->deltaRB->setChecked(true); ui->cartesianRB->setChecked(false); ui->radiusSB->setValue(m_settings.value(QStringLiteral("radius"), QStringLiteral("0")).toInt()); ui->z_delta_dimensionSB->setValue(m_settings.value(QStringLiteral("z_delta_dimension"), QStringLiteral("0")).toInt()); } ui->heatedBedCK->setChecked(m_settings.value(QStringLiteral("heatedBed"), QStringLiteral("true")).toBool()); ui->bedTempSB->setEnabled(ui->heatedBedCK->isChecked()); ui->bedTempSB->setValue(m_settings.value(QStringLiteral("maximumTemperatureBed"), QStringLiteral("0")).toInt()); + ui->autoReportTempCK->setChecked(m_settings.value(QStringLiteral("autoReportTemp"), QStringLiteral("false")).toBool()); //HOTEND ui->extruderTempSB->setValue(m_settings.value(QStringLiteral("maximumTemperatureExtruder"), QStringLiteral("0")).toInt()); //Baud ui->baudCB->setCurrentText(m_settings.value(QStringLiteral("bps"), QStringLiteral("115200")).toString()); ui->firmwareCB->setCurrentText(m_settings.value(QStringLiteral("firmware"), QStringLiteral("Auto-Detect")).toString()); ui->postPauseLE->setText(m_settings.value(QStringLiteral("postPause"), QString()).toString()); m_settings.endGroup(); m_settings.endGroup(); setModified(false); } void ProfilesDialog::updateCBProfiles() { m_settings.beginGroup(QStringLiteral("Profiles")); QStringList groups = m_settings.childGroups(); m_settings.endGroup(); if (groups.isEmpty()) { ui->printerTypeStack->setCurrentIndex(1); } ui->profileCB->clear(); ui->profileCB->addItems(groups); } void ProfilesDialog::removeProfile() { QString currentProfile = ui->profileCB->currentText(); m_settings.beginGroup(QStringLiteral("Profiles")); m_settings.beginGroup(currentProfile); m_settings.remove(""); m_settings.endGroup(); m_settings.remove(currentProfile); m_settings.endGroup(); updateCBProfiles(); } QStringList ProfilesDialog::detectFWPlugins() { QStringList firmwares; QStringList paths = AtCoreDirectories::pluginDir; //Add our runtime paths const QString &path(qApp->applicationDirPath()); paths.prepend(path + QStringLiteral("/../Plugins/AtCore")); paths.prepend(path + QStringLiteral("/AtCore")); paths.prepend(path + QStringLiteral("/plugins")); for (const QString &path : qAsConst(paths)) { firmwares = firmwaresInPath(path); if (!firmwares.isEmpty()) { //use path where plugins were detected. break; } } return firmwares; } QStringList ProfilesDialog::firmwaresInPath(const QString &path) { QStringList firmwares; QStringList files = QDir(path).entryList(QDir::Files); for (const QString &f : files) { QString file = f; #if defined(Q_OS_WIN) if (file.endsWith(QStringLiteral(".dll"))) #elif defined(Q_OS_MAC) if (file.endsWith(QStringLiteral(".dylib"))) #else if (file.endsWith(QStringLiteral(".so"))) #endif file = file.split(QChar::fromLatin1('.')).at(0); else { continue; } if (file.startsWith(QStringLiteral("lib"))) { file = file.remove(QStringLiteral("lib")); } file = file.toLower().simplified(); firmwares.append(file); } return firmwares; } void ProfilesDialog::setModified(bool modified) { m_modified = modified; } void ProfilesDialog::askToSave() { if (m_modified) { int ret = QMessageBox::question( this , i18n("Save?") , i18n("This Profile has been modified, Would you like to Save it?") , QMessageBox::Save , QMessageBox::No ); if (ret == QMessageBox::Save) { save(); } } } diff --git a/src/dialogs/profilesdialog.ui b/src/dialogs/profilesdialog.ui index b570fd1..340d7c0 100644 --- a/src/dialogs/profilesdialog.ui +++ b/src/dialogs/profilesdialog.ui @@ -1,388 +1,405 @@ ProfilesDialog 0 0 0 0 Profiles Profile profileCB 0 0 true Remove Profile 2 Mechanics Printer Type &Cartesian true &Delta 1 Radi&us radiusSB mm 999999999 Dimension &Z z_delta_dimensionSB mm 999999999 Dimension &X x_dimensionSB mm 999999999 Dimension &Y y_dimensionSB mm 999999999 Dimension &Z z_dimensionSB mm 999999999 Temperatures - - + + - Hea&ted bed? + Maxim&um Bed - heatedBedCK + bedTempSB - - + + + + ºC + + + 999 + + + + + + + <html><head/><body><p>Temperature reporting using M155 command. When enabled the printer will return temperature data automaticly at a set interval.</p></body></html> + - + Auto Temperature Report - - true + + + + + + - - + + - Maxim&um Bed + Ma&ximum Hotend - bedTempSB + extruderTempSB ºC 999 - - + + - Ma&ximum Hotend + Hea&ted bed? - extruderTempSB + heatedBedCK - - - - ºC + + + + - - 999 + + true Advanced Bi&ts per second baudCB Firmware firmwareCB PostPa&use postPauseLE Qt::Horizontal QDialogButtonBox::Close|QDialogButtonBox::Reset|QDialogButtonBox::Save profileCB removeProfilePB cartesianRB baudCB deltaRB radiusSB z_delta_dimensionSB x_dimensionSB y_dimensionSB z_dimensionSB heatedBedCK bedTempSB extruderTempSB buttonBox diff --git a/src/widgets/atcoreinstancewidget.cpp b/src/widgets/atcoreinstancewidget.cpp index 494ed1f..a47bdaf 100644 --- a/src/widgets/atcoreinstancewidget.cpp +++ b/src/widgets/atcoreinstancewidget.cpp @@ -1,671 +1,681 @@ /* Atelier KDE Printer Host for 3D Printing Copyright (C) <2017> Author: Lays Rodrigues - lays.rodrigues@kde.org 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 #include #include #include #include "atcoreinstancewidget.h" AtCoreInstanceWidget::AtCoreInstanceWidget(QWidget *parent): QWidget(parent) , m_bedSize(200, 200) { m_theme = palette().text().color().value() >= QColor(Qt::lightGray).value() ? QString("dark") : QString("light") ; m_iconSize = QSize(fontMetrics().lineSpacing(), fontMetrics().lineSpacing()); auto HLayout = new QHBoxLayout; m_bedExtWidget = new BedExtruderWidget(this); HLayout->addWidget(m_bedExtWidget); m_movementWidget = new MovementWidget(false, this); m_movementWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); HLayout->addWidget(m_movementWidget); auto VLayout = new QVBoxLayout; VLayout->addLayout(HLayout); m_plotWidget = new PlotWidget(this); VLayout->addWidget(m_plotWidget, 80); auto controlTab = new QWidget(this); controlTab->setLayout(VLayout); //AdvancedTab VLayout = new QVBoxLayout; m_printWidget = new PrintWidget(false, this); VLayout->addWidget(m_printWidget); m_commandWidget = new CommandWidget(this); VLayout->addWidget(m_commandWidget); m_logWidget = new LogWidget(new QTemporaryFile(QDir::tempPath() + QStringLiteral("/Atelier_")), this); VLayout->addWidget(m_logWidget); m_advancedTab = new QWidget(this); m_advancedTab->setLayout(VLayout); m_sdWidget = new SdWidget(this); VLayout = new QVBoxLayout(); buildToolbar(); buildConnectionToolbar(); HLayout = new QHBoxLayout; HLayout->addWidget(m_toolBar); HLayout->addWidget(m_connectToolBar); HLayout->addWidget(m_connectButton); VLayout->addLayout(HLayout); m_toolBar->setHidden(true); m_tabWidget = new QTabWidget(this); m_tabWidget->addTab(controlTab, i18n("Controls")); m_tabWidget->addTab(m_advancedTab, i18n("Advanced")); m_tabWidget->addTab(m_sdWidget, i18n("Sd Card")); VLayout->addWidget(m_tabWidget); m_statusWidget = new StatusWidget(false, this); m_statusWidget->showPrintArea(false); VLayout->addWidget(m_statusWidget); setLayout(VLayout); enableControls(false); updateProfileData(); initConnectsToAtCore(); } AtCoreInstanceWidget::~AtCoreInstanceWidget() { m_core.closeConnection(); } void AtCoreInstanceWidget::buildToolbar() { m_toolBar = new QToolBar(this); m_toolBar->setIconSize(m_iconSize); m_toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); auto lb = new QLabel(this); QIcon icon = QIcon::fromTheme("go-home", QIcon(QString(":/%1/home").arg(m_theme))); lb->setPixmap(icon.pixmap(m_iconSize)); m_toolBar->addWidget(lb); lb = new QLabel(i18n("Home:"), this); m_toolBar->addWidget(lb); auto homeAll = new QAction(i18n("All")); connect(homeAll, &QAction::triggered, this, [this] { m_core.home(); }); m_toolBar->addAction(homeAll); for (const auto &homes : std::map {{"X", AtCore::X}, {"Y", AtCore::Y}, {"Z", AtCore::Z}}) { auto home = new QAction(homes.first, this); connect(home, &QAction::triggered, this, [this, homes] { m_core.home(uchar(homes.second)); }); m_toolBar->addAction(home); } m_toolBar->addSeparator(); m_printAction = new QAction(QIcon::fromTheme("media-playback-start", style()->standardIcon(QStyle::SP_MediaPlay)), i18n("Print"), this); connect(m_printAction, &QAction::triggered, this, [this] { if (m_core.state() == AtCore::BUSY) { m_logWidget->appendLog(i18n("Pause Print")); pausePrint(); return; } if (m_core.state() == AtCore::IDLE) { print(); } else if (m_core.state() == AtCore::PAUSE) { m_logWidget->appendLog(i18n("Resume Print")); m_core.resume(); } }); m_toolBar->addAction(m_printAction); m_stopAction = new QAction(QIcon::fromTheme("media-playback-stop", QIcon(QStringLiteral(":/%1/stop").arg(m_theme))), i18n("Stop"), this); connect(m_stopAction, &QAction::triggered, this, &AtCoreInstanceWidget::stopPrint); connect(m_stopAction, &QAction::triggered, this, [this] { m_printAction->setText(i18n("Print")); m_printAction->setIcon(QIcon::fromTheme("media-playback-start", QIcon(QStringLiteral(":/%1/start").arg(m_theme)))); }); m_toolBar->addAction(m_stopAction); auto disableMotorsAction = new QAction(style()->standardIcon(QStyle::SP_MediaStop), i18n("Disable Motors"), this); connect(disableMotorsAction, &QAction::triggered, this, &AtCoreInstanceWidget::disableMotors); m_toolBar->addAction(disableMotorsAction); togglePrintButtons(m_fileCount); } void AtCoreInstanceWidget::buildConnectionToolbar() { m_connectToolBar = new QToolBar(this); m_comboPort = new QComboBox(this); m_comboPort->setEditable(true); auto deviceLabel = new QLabel(i18n("Device"), this); auto deviceLayout = new QHBoxLayout; deviceLayout->addWidget(deviceLabel); deviceLayout->addWidget(m_comboPort, 100); m_comboProfile = new QComboBox(this); m_comboProfile->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); auto profileLayout = new QHBoxLayout; auto profileLabel = new QLabel(i18n("Profile"), this); profileLayout->addWidget(profileLabel); profileLayout->addWidget(m_comboProfile, 100); auto connectLayout = new QHBoxLayout; connectLayout->addLayout(deviceLayout, 50); connectLayout->addLayout(profileLayout, 50); m_connectWidget = new QWidget(this); m_connectWidget->setLayout(connectLayout); m_connectToolBar->addWidget(m_connectWidget); m_connectButton = new QPushButton(QIcon::fromTheme("network-connect", QIcon(QString(":/%1/connect").arg(m_theme))), i18n("Connect"), this); m_connectButton->setIconSize(m_iconSize); m_connectButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(this, &AtCoreInstanceWidget::disableDisconnect, m_connectButton, &QPushButton::setDisabled); connect(m_connectButton, &QPushButton::clicked, this, &AtCoreInstanceWidget::connectButtonClicked); m_connectionTimer = new QTimer(this); m_connectionTimer->setInterval(20000); m_connectionTimer->setSingleShot(true); connect(m_connectionTimer, &QTimer::timeout, this, [this] { m_connectButton->clicked(); QMessageBox::critical(this, tr("Connection Error"), tr("Your machine did not respond after 20 seconds.\n\nBefore connecting again check that your printer is on and your are connecting using the correct BAUD Rate for your device.")); }); } void AtCoreInstanceWidget::connectButtonClicked() { if (m_core.state() == AtCore::DISCONNECTED) { if (m_comboProfile->currentText().isEmpty()) { QMessageBox::information( this , i18n("No Profiles!") , i18n("Connecting Requires creating a profile for your printer. Create a profile in the next dialog then try again.") ); emit(requestProfileDialog()); return; } if (m_comboPort->currentText().isEmpty()) { QMessageBox::critical( this , i18n("Error") , i18n("Please, connect a serial device to continue!") ); return; } //Get profile data before connecting. m_profileData = readProfile(); //then connect if (m_core.newConnection(m_comboPort->currentText(), m_profileData["bps"].toInt(), m_profileData["firmware"].toString())) { emit(connectionChanged(m_profileData["name"].toString())); m_profileData["heatedBed"].toBool() ? m_bedExtWidget->setBedMaxTemperature(m_profileData["bedTemp"].toInt()) : m_bedExtWidget->setBedThermoHidden(true); m_bedExtWidget->setExtruderMaxTemperature(m_profileData["hotendTemp"].toInt()); //AddFan Support to profile m_printWidget->updateFanCount(2); //Adjust bed size QSize newSize; if (m_profileData["isCartesian"].toBool()) { newSize = QSize(m_profileData["dimensionX"].toInt(), m_profileData["dimensionY"].toInt()); } else { newSize = QSize(m_profileData["radius"].toInt(), 0); } if (newSize != m_bedSize) { m_bedSize = newSize; emit bedSizeChanged(m_bedSize); } } } else { m_core.closeConnection(); emit(connectionChanged(i18n("Connect a Printer"))); } } void AtCoreInstanceWidget::initConnectsToAtCore() { //connect log to atcoreMessages connect(&m_core, &AtCore::atcoreMessage, m_logWidget, &LogWidget::appendLog); m_core.setSerialTimerInterval(100); // Handle device changes connect(&m_core, &AtCore::portsChanged, this, &AtCoreInstanceWidget::updateSerialPort); + + connect(&m_core, &AtCore::autoTemperatureReportChanged, this, [this](const bool autoReport) { + if (m_profileData["autoReportTemp"].toBool() != autoReport) { + m_profileData["autoReportTemp"] = autoReport; + saveProfile(); + } + }); // 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, m_bedExtWidget, &BedExtruderWidget::setExtruderCount); // Bed and Extruder temperatures management connect(m_bedExtWidget, &BedExtruderWidget::bedTemperatureChanged, &m_core, &AtCore::setBedTemp); connect(m_bedExtWidget, &BedExtruderWidget::extTemperatureChanged, &m_core, &AtCore::setExtruderTemp); //command Widget connect(m_commandWidget, &CommandWidget::commandPressed, this, [this](const QString & command) { m_logWidget->appendLog(i18n("Push: %1", command)); m_core.pushCommand(command); }); connect(m_commandWidget, &CommandWidget::messagePressed, [this](const QString & message) { m_logWidget->appendLog(i18n("Display: %1", message)); m_core.showMessage(message); }); // Fan, Flow and Speed management connect(m_printWidget, &PrintWidget::fanSpeedChanged, &m_core, &AtCore::setFanSpeed); connect(m_printWidget, &PrintWidget::flowRateChanged, &m_core, &AtCore::setFlowRate); connect(m_printWidget, &PrintWidget::printSpeedChanged, &m_core, &AtCore::setPrinterSpeed); //Movement Widget connect(m_movementWidget, &MovementWidget::absoluteMove, this, [this](const QLatin1Char & axis, const double value) { m_logWidget->appendLog(GCode::description(GCode::G1)); m_core.move(axis, value); }); connect(m_movementWidget, &MovementWidget::unitsChanged, this, [this](int units) { auto selection = static_cast(units); m_core.setUnits(selection); }); connect(m_movementWidget, &MovementWidget::relativeMove, this, [this](const QLatin1Char & axis, const double value) { m_logWidget->appendLog(i18n("Relative Move: %1, %2", axis, QString::number(value))); m_core.setRelativePosition(); m_core.move(axis, value); m_core.setAbsolutePosition(); }); //Sd Card Stuff connect(&m_core, &AtCore::sdCardFileListChanged, m_sdWidget, &SdWidget::updateFilelist); connect(m_sdWidget, &SdWidget::requestSdList, &m_core, &AtCore::sdFileList); connect(&m_core, &AtCore::sdMountChanged, m_statusWidget, &StatusWidget::setSD); connect(m_sdWidget, &SdWidget::printSdFile, this, [this](const QString & fileName) { if (fileName.isEmpty()) { QMessageBox::information( this , i18n("Print Error") , i18n("You must Select a file from the list") ); } else { m_core.print(fileName, true); togglePrintButtons(true); } }); connect(m_sdWidget, &SdWidget::deleteSdFile, this, [this](const QString & fileName) { if (fileName.isEmpty()) { QMessageBox::information( this , i18n("Delete Error") , i18n("You must Select a file from the list") ); } else { m_core.sdDelete(fileName); } }); } void AtCoreInstanceWidget::printFile(const QUrl &fileName) { if (fileName.isEmpty()) { QMessageBox::critical( this , i18n("Filename Empty") , i18n("No filename sent from calling method, please check and try again.") ); return; } if (!QFileInfo(fileName.toLocalFile()).isReadable()) { QMessageBox::critical( this , i18n("File not found") , i18n("%1 \nIs not readable, please check and try again.", fileName.toLocalFile()) ); return; } if (m_core.state() == AtCore::IDLE) { m_logWidget->appendLog(i18n("Printing:%1", fileName.toLocalFile())); m_core.print(fileName.toLocalFile()); } } void AtCoreInstanceWidget::print() { emit(requestFileChooser()); } void AtCoreInstanceWidget::pausePrint() { if (m_core.state() == AtCore::BUSY) { m_core.pause(m_profileData["postPause"].toString()); } else if (m_core.state() == AtCore::PAUSE) { m_core.resume(); } } void AtCoreInstanceWidget::stopPrint() { m_core.stop(); } void AtCoreInstanceWidget::disableMotors() { m_core.disableMotors(0); } void AtCoreInstanceWidget::handlePrinterStatusChanged(AtCore::STATES newState) { static QString stateString; switch (newState) { case AtCore::CONNECTING: { m_connectionTimer->start(); m_core.setSerialTimerInterval(0); m_connectButton->setText(i18n("Disconnect")); m_connectButton->setIcon(QIcon::fromTheme("network-disconnect", QIcon(QString(":/%1/disconnect").arg(m_theme)))); m_connectToolBar->setHidden(true); m_toolBar->setHidden(false); stateString = i18n("Connecting..."); m_logWidget->appendLog(i18n("Attempting to Connect")); connect(&m_core, &AtCore::receivedMessage, m_logWidget, &LogWidget::appendRLog); connect(&m_core, &AtCore::pushedCommand, m_logWidget, &LogWidget::appendSLog); } break; case AtCore::IDLE: { if (m_connectionTimer->isActive()) { + m_core.setAutoTemperatureReport(m_profileData["autoReportTemp"].toBool()); m_connectionTimer->stop(); } stateString = i18n("Connected to %1", m_core.connectedPort()); emit extruderCountChanged(m_core.extruderCount()); m_logWidget->appendLog(stateString); emit disableDisconnect(false); enableControls(true); connectExtruderTemperatureData(true); if (m_profileData["heatedBed"].toBool()) { connectBedTemperatureData(true); } if (!m_core.availableFirmwarePlugins().contains(m_profileData["firmware"].toString())) { m_profileData["firmware"] = m_core.firmwarePlugin()->name().toLower(); saveProfile(); } } break; case AtCore::DISCONNECTED: { if (m_connectionTimer->isActive()) { m_connectionTimer->stop(); } stateString = i18n("Not Connected"); disconnect(&m_core, &AtCore::receivedMessage, m_logWidget, &LogWidget::appendRLog); disconnect(&m_core, &AtCore::pushedCommand, m_logWidget, &LogWidget::appendSLog); m_logWidget->appendLog(i18n("Serial disconnected")); m_core.setSerialTimerInterval(100); m_connectButton->setText(i18n("Connect")); m_connectButton->setIcon(QIcon::fromTheme("network-connect", QIcon(QString(":/%1/connect").arg(m_theme)))); m_connectToolBar->setHidden(false); m_toolBar->setHidden(true); enableControls(false); connectExtruderTemperatureData(false); if (m_profileData["heatedBed"].toBool()) { connectBedTemperatureData(false); } } break; case AtCore::STARTPRINT: { stateString = i18n("Starting Print"); m_statusWidget->showPrintArea(true); connect(&m_core, &AtCore::printProgressChanged, m_statusWidget, &StatusWidget::updatePrintProgress); } break; case AtCore::FINISHEDPRINT: { stateString = i18n("Finished Print"); m_statusWidget->showPrintArea(false); disconnect(&m_core, &AtCore::printProgressChanged, m_statusWidget, &StatusWidget::updatePrintProgress); m_printAction->setText(i18n("Print")); m_printAction->setIcon(QIcon::fromTheme("media-playback-start", QIcon(QString(":/%1/start").arg(m_theme)))); m_logWidget->appendLog(i18n("Finished Print Job")); } break; case AtCore::BUSY: { stateString = i18n("Printing"); emit disableDisconnect(true); m_printAction->setText(i18n("Pause")); m_printAction->setIcon(QIcon::fromTheme("media-playback-pause", QIcon(QString(":/%1/pause").arg(m_theme)))); } break; case AtCore::PAUSE: { stateString = i18n("Paused"); m_printAction->setText(i18n("Resume")); m_printAction->setIcon(QIcon::fromTheme("media-playback-start", QIcon(QString(":/%1/start").arg(m_theme)))); } break; case AtCore::STOP: { stateString = i18n("Stoping Print"); m_logWidget->appendLog(stateString); } break; case AtCore::ERRORSTATE: { stateString = i18n("Error"); } break; default: m_logWidget->appendLog(i18n("Unknown AtCore State, %1", newState)); break; } m_statusWidget->setState(stateString); } void AtCoreInstanceWidget::checkTemperature(uint sensorType, uint number, float temp) { static 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[%1] Temperature").arg(QString::number(number)); break; case 0x03: // extruder target msg = QString::fromLatin1("Extruder[%1] Target Temperature").arg(QString::number(number)); 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").arg(QString::number(double(temp), 'f', 2))); m_logWidget->appendLog(msg); } void AtCoreInstanceWidget::enableControls(bool b) { if (b) { layout()->removeWidget(m_logWidget); layout()->removeWidget(m_statusWidget); layout()->addWidget(m_statusWidget); m_advancedTab->layout()->addWidget(m_logWidget); } else { m_advancedTab->layout()->removeWidget(m_logWidget); layout()->addWidget(m_logWidget); layout()->removeWidget(m_statusWidget); layout()->addWidget(m_statusWidget); } m_tabWidget->setHidden(!b); m_toolBar->setEnabled(b); } bool AtCoreInstanceWidget::connected() { return (m_core.state() != AtCore::DISCONNECTED); } void AtCoreInstanceWidget::setFileCount(int count) { m_fileCount = count; togglePrintButtons(m_fileCount); } void AtCoreInstanceWidget::updateSerialPort(QStringList ports) { m_comboPort->clear(); //Remove any strings that match ttyS## from the port list. ports = ports.filter(QRegularExpression("^((?!ttyS\\d+).)*$")); if (!ports.isEmpty()) { m_comboPort->addItems(ports); m_logWidget->appendLog(i18n("Found %1 Ports", QString::number(ports.count()))); } else { QString portError(i18n("No available ports! Please connect a serial device to continue!")); if (!m_logWidget->endsWith(portError)) { m_logWidget->appendLog(portError); } } } void AtCoreInstanceWidget::updateProfileData() { m_settings.beginGroup("Profiles"); QStringList profiles = m_settings.childGroups(); m_settings.endGroup(); m_comboProfile->clear(); m_comboProfile->addItems(profiles); if (m_core.state() != AtCore::DISCONNECTED) { m_profileData = readProfile(); bool hBed = m_profileData["heatedBed"].toBool(); m_bedExtWidget->setBedThermoHidden(!hBed); connectBedTemperatureData(hBed); m_bedExtWidget->setBedMaxTemperature(m_profileData["bedTemp"].toInt()); m_bedExtWidget->setExtruderMaxTemperature(m_profileData["hotendTemp"].toInt()); } } void AtCoreInstanceWidget::togglePrintButtons(bool shown) { m_printAction->setVisible(shown); m_stopAction->setVisible(shown); } bool AtCoreInstanceWidget::isPrinting() { return (m_core.state() == AtCore::BUSY); } QMap AtCoreInstanceWidget::readProfile() { QString profile = m_comboProfile->currentText(); m_settings.beginGroup("Profiles"); m_settings.beginGroup(profile); QMap data{ {"bps", m_settings.value(QStringLiteral("bps"), QStringLiteral("115200"))} , {"bedTemp", m_settings.value(QStringLiteral("maximumTemperatureBed"), QStringLiteral("0"))} , {"hotendTemp", m_settings.value(QStringLiteral("maximumTemperatureExtruder"), QStringLiteral("0"))} , {"firmware", m_settings.value(QStringLiteral("firmware"), QStringLiteral("Auto-Detect"))} , {"postPause", m_settings.value(QStringLiteral("postPause"), QString())} , {"heatedBed", m_settings.value(QStringLiteral("heatedBed"), true)} , {"name", profile} , {"isCartesian", m_settings.value(QStringLiteral("isCartesian"), true)} , {"dimensionX", m_settings.value(QStringLiteral("dimensionX"), QStringLiteral("200"))} , {"dimensionY", m_settings.value(QStringLiteral("dimensionY"), QStringLiteral("200"))} , {"dimensionZ", m_settings.value(QStringLiteral("dimensionZ"), QStringLiteral("180"))} , {"radius", m_settings.value(QStringLiteral("radius"), QStringLiteral("200"))} , {"z_delta_dimension", m_settings.value(QStringLiteral("z_delta_dimension"), QStringLiteral("180"))} + , {"autoReportTemp", m_settings.value(QStringLiteral("autoReportTemp"), false)} }; m_settings.endGroup(); m_settings.endGroup(); return data; } void AtCoreInstanceWidget::saveProfile() { QString profile = m_comboProfile->currentText(); m_settings.beginGroup("Profiles"); m_settings.beginGroup(m_profileData["name"].toString()); m_settings.setValue(QStringLiteral("firmware"), m_profileData["firmware"]); + m_settings.setValue(QStringLiteral("autoReportTemp"), m_profileData["autoReportTemp"]); m_settings.endGroup(); m_settings.endGroup(); } void AtCoreInstanceWidget::connectBedTemperatureData(bool connected) { if (connected) { if (m_plotWidget->plots().contains((i18n("Actual Bed")))) { return; } m_plotWidget->addPlot(i18n("Actual Bed")); connect(m_core.temperature().get(), &Temperature::bedTemperatureChanged, [this] { const float temp = m_core.temperature().get()->bedTemperature(); checkTemperature(0x00, 0, temp); m_plotWidget->appendPoint(i18n("Actual Bed"), temp); m_bedExtWidget->updateBedTemp(temp); }); m_plotWidget->addPlot(i18n("Target Bed")); connect(m_core.temperature().get(), &Temperature::bedTargetTemperatureChanged, [this] { const float temp = m_core.temperature().get()->bedTargetTemperature(); checkTemperature(0x01, 0, temp); m_plotWidget->appendPoint(i18n("Target Bed"), temp); m_bedExtWidget->updateBedTargetTemp(int(temp)); }); } else { if (m_plotWidget->plots().contains(i18n("Actual Bed"))) { m_plotWidget->removePlot(i18n("Actual Bed")); disconnect(m_core.temperature().get(), &Temperature::bedTemperatureChanged, this, nullptr); m_plotWidget->removePlot(i18n("Target Bed")); disconnect(m_core.temperature().get(), &Temperature::bedTargetTemperatureChanged, this, nullptr); } } } void AtCoreInstanceWidget::connectExtruderTemperatureData(bool connected) { if (connected) { if (m_plotWidget->plots().contains((i18n("Actual Ext.1")))) { return; } //Add Extruder. m_plotWidget->addPlot(i18n("Actual Ext.1")); connect(m_core.temperature().get(), &Temperature::extruderTemperatureChanged, this, [this] { const float temp = m_core.temperature().get()->extruderTemperature(); checkTemperature(0x02, 0, temp); m_plotWidget->appendPoint(i18n("Actual Ext.1"), temp); m_bedExtWidget->updateExtTemp(temp); }); m_plotWidget->addPlot(i18n("Target Ext.1")); connect(m_core.temperature().get(), &Temperature::extruderTargetTemperatureChanged, this, [this] { const float temp = m_core.temperature().get()->extruderTargetTemperature(); checkTemperature(0x03, 0, temp); m_plotWidget->appendPoint(i18n("Target Ext.1"), temp); m_bedExtWidget->updateExtTargetTemp(int(temp)); }); } else { if (m_plotWidget->plots().contains(i18n("Actual Ext.1"))) { m_plotWidget->removePlot(i18n("Actual Ext.1")); disconnect(m_core.temperature().get(), &Temperature::extruderTemperatureChanged, this, nullptr); m_plotWidget->removePlot(i18n("Target Ext.1")); disconnect(m_core.temperature().get(), &Temperature::extruderTargetTemperatureChanged, this, nullptr); } } } QSize AtCoreInstanceWidget::bedSize() { return m_bedSize; }