File indexing completed on 2024-05-19 05:51:03
0001 /* Atelier KDE Printer Host for 3D Printing 0002 Copyright (C) <2017> 0003 Author: Lays Rodrigues - lays.rodrigues@kde.org 0004 Chris Rizzitello - rizzitello@kde.org 0005 0006 This program is free software: you can redistribute it and/or modify 0007 it under the terms of the GNU General Public License as published by 0008 the Free Software Foundation, either version 3 of the License, or 0009 (at your option) any later version. 0010 0011 This program is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 GNU General Public License for more details. 0015 0016 You should have received a copy of the GNU General Public License 0017 along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "atcoreinstancewidget.h" 0021 #include "machineinfo.h" 0022 #include <GCodeCommands> 0023 #include <KLocalizedString> 0024 #include <QToolBar> 0025 #include <SerialLayer> 0026 0027 const QMap<MachineInfo::KEY, QString> AtCoreInstanceWidget::keyString = {{MachineInfo::KEY::NAME, QStringLiteral("Name")}, 0028 {MachineInfo::KEY::BAUDRATE, QStringLiteral("bps")}, 0029 {MachineInfo::KEY::FIRMWARE, QStringLiteral("firmware")}, 0030 {MachineInfo::KEY::MAXBEDTEMP, QStringLiteral("maximumTemperatureBed")}, 0031 {MachineInfo::KEY::MAXEXTTEMP, QStringLiteral("maximumTemperatureExtruder")}, 0032 {MachineInfo::KEY::POSTPAUSE, QStringLiteral("postPause")}, 0033 {MachineInfo::KEY::ISCARTESIAN, QStringLiteral("isCartesian")}, 0034 {MachineInfo::KEY::XMAX, QStringLiteral("dimensionX")}, 0035 {MachineInfo::KEY::YMAX, QStringLiteral("dimensionY")}, 0036 {MachineInfo::KEY::ZMAX, QStringLiteral("dimensionZ")}, 0037 {MachineInfo::KEY::AUTOTEMPREPORT, QStringLiteral("autoReportTemp")}}; 0038 0039 AtCoreInstanceWidget::AtCoreInstanceWidget(QWidget *parent) 0040 : QWidget(parent) 0041 , m_bedSize(200, 200) 0042 { 0043 m_theme = palette().text().color().value() >= QColor(Qt::lightGray).value() ? QString("dark") : QString("light"); 0044 m_iconSize = QSize(fontMetrics().lineSpacing(), fontMetrics().lineSpacing()); 0045 auto HLayout = new QHBoxLayout; 0046 m_bedExtWidget = new BedExtruderWidget(this); 0047 HLayout->addWidget(m_bedExtWidget); 0048 0049 m_movementWidget = new MovementWidget(this); 0050 m_movementWidget->setDisableMotorsButtonVisible(false); 0051 m_movementWidget->setHomeButtonsVisible(false); 0052 m_movementWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); 0053 HLayout->addWidget(m_movementWidget); 0054 0055 auto VLayout = new QVBoxLayout; 0056 VLayout->addLayout(HLayout); 0057 0058 m_plotWidget = new PlotWidget(this); 0059 VLayout->addWidget(m_plotWidget, 80); 0060 0061 auto controlTab = new QWidget(this); 0062 controlTab->setLayout(VLayout); 0063 0064 // AdvancedTab 0065 VLayout = new QVBoxLayout; 0066 m_printWidget = new PrintWidget(false, this); 0067 VLayout->addWidget(m_printWidget); 0068 0069 m_commandWidget = new CommandWidget(this); 0070 VLayout->addWidget(m_commandWidget); 0071 0072 m_logWidget = new LogWidget(new QTemporaryFile(QDir::tempPath() + QStringLiteral("/Atelier_")), this); 0073 VLayout->addWidget(m_logWidget); 0074 0075 m_advancedTab = new QWidget(this); 0076 m_advancedTab->setLayout(VLayout); 0077 0078 m_sdWidget = new SdWidget(this); 0079 0080 VLayout = new QVBoxLayout(); 0081 buildToolbar(); 0082 buildConnectionToolbar(); 0083 HLayout = new QHBoxLayout; 0084 HLayout->addWidget(m_toolBar); 0085 HLayout->addWidget(m_connectToolBar); 0086 HLayout->addWidget(m_connectButton); 0087 VLayout->addLayout(HLayout); 0088 m_toolBar->setHidden(true); 0089 0090 m_tabWidget = new QTabWidget(this); 0091 m_tabWidget->addTab(controlTab, i18n("Controls")); 0092 m_tabWidget->addTab(m_advancedTab, i18n("Advanced")); 0093 m_tabWidget->addTab(m_sdWidget, i18n("Sd Card")); 0094 VLayout->addWidget(m_tabWidget); 0095 0096 m_statusWidget = new StatusWidget(false, this); 0097 m_statusWidget->showPrintArea(false); 0098 VLayout->addWidget(m_statusWidget); 0099 setLayout(VLayout); 0100 0101 enableControls(false); 0102 updateProfileData(); 0103 initConnectsToAtCore(); 0104 } 0105 AtCoreInstanceWidget::~AtCoreInstanceWidget() 0106 { 0107 m_core.close(); 0108 } 0109 0110 void AtCoreInstanceWidget::buildToolbar() 0111 { 0112 m_toolBar = new QToolBar(this); 0113 m_toolBar->setIconSize(m_iconSize); 0114 m_toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 0115 0116 auto lb = new QLabel(this); 0117 QIcon icon = QIcon::fromTheme("go-home", QIcon(QString(":/%1/home").arg(m_theme))); 0118 lb->setPixmap(icon.pixmap(m_iconSize)); 0119 m_toolBar->addWidget(lb); 0120 lb = new QLabel(i18n("Home:"), this); 0121 m_toolBar->addWidget(lb); 0122 0123 auto homeAll = new QAction(i18n("All")); 0124 connect(homeAll, &QAction::triggered, this, [this] { m_core.home(); }); 0125 m_toolBar->addAction(homeAll); 0126 0127 for (const auto &homes : std::map<QString, int> {{"X", AtCore::X}, {"Y", AtCore::Y}, {"Z", AtCore::Z}}) { 0128 auto home = new QAction(homes.first, this); 0129 connect(home, &QAction::triggered, this, [this, homes] { m_core.home(uchar(homes.second)); }); 0130 m_toolBar->addAction(home); 0131 } 0132 0133 m_toolBar->addSeparator(); 0134 0135 m_printAction = new QAction(QIcon::fromTheme("media-playback-start", style()->standardIcon(QStyle::SP_MediaPlay)), i18n("Print"), this); 0136 connect(m_printAction, &QAction::triggered, this, [this] { 0137 if (m_core.state() == AtCore::BUSY) { 0138 m_logWidget->appendLog(i18n("Pause Print")); 0139 pausePrint(); 0140 return; 0141 } 0142 if (m_core.state() == AtCore::IDLE) { 0143 print(); 0144 } else if (m_core.state() == AtCore::PAUSE) { 0145 m_logWidget->appendLog(i18n("Resume Print")); 0146 m_core.resume(); 0147 } 0148 }); 0149 m_toolBar->addAction(m_printAction); 0150 0151 m_stopAction = new QAction(QIcon::fromTheme("media-playback-stop", QIcon(QStringLiteral(":/%1/stop").arg(m_theme))), i18n("Stop"), this); 0152 connect(m_stopAction, &QAction::triggered, this, &AtCoreInstanceWidget::stopPrint); 0153 connect(m_stopAction, &QAction::triggered, this, [this] { 0154 m_printAction->setText(i18n("Print")); 0155 m_printAction->setIcon(QIcon::fromTheme("media-playback-start", QIcon(QStringLiteral(":/%1/start").arg(m_theme)))); 0156 }); 0157 m_toolBar->addAction(m_stopAction); 0158 0159 auto disableMotorsAction = new QAction(style()->standardIcon(QStyle::SP_MediaStop), i18n("Disable Motors"), this); 0160 connect(disableMotorsAction, &QAction::triggered, this, &AtCoreInstanceWidget::disableMotors); 0161 m_toolBar->addAction(disableMotorsAction); 0162 0163 togglePrintButtons(m_fileCount); 0164 } 0165 0166 void AtCoreInstanceWidget::buildConnectionToolbar() 0167 { 0168 m_connectToolBar = new QToolBar(this); 0169 m_comboPort = new QComboBox(this); 0170 m_comboPort->setEditable(true); 0171 auto deviceLabel = new QLabel(i18n("Device"), this); 0172 auto deviceLayout = new QHBoxLayout; 0173 deviceLayout->addWidget(deviceLabel); 0174 deviceLayout->addWidget(m_comboPort, 100); 0175 0176 m_comboProfile = new QComboBox(this); 0177 m_comboProfile->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); 0178 auto profileLayout = new QHBoxLayout; 0179 auto profileLabel = new QLabel(i18n("Profile"), this); 0180 profileLayout->addWidget(profileLabel); 0181 profileLayout->addWidget(m_comboProfile, 100); 0182 0183 auto connectLayout = new QHBoxLayout; 0184 connectLayout->addLayout(deviceLayout, 50); 0185 connectLayout->addLayout(profileLayout, 50); 0186 0187 m_connectWidget = new QWidget(this); 0188 m_connectWidget->setLayout(connectLayout); 0189 m_connectToolBar->addWidget(m_connectWidget); 0190 0191 m_connectButton = new QPushButton(QIcon::fromTheme("network-connect", QIcon(QString(":/%1/connect").arg(m_theme))), i18n("Connect"), this); 0192 m_connectButton->setIconSize(m_iconSize); 0193 m_connectButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0194 connect(this, &AtCoreInstanceWidget::disableDisconnect, m_connectButton, &QPushButton::setDisabled); 0195 connect(m_connectButton, &QPushButton::clicked, this, &AtCoreInstanceWidget::connectButtonClicked); 0196 0197 m_connectionTimer = new QTimer(this); 0198 m_connectionTimer->setInterval(20000); 0199 m_connectionTimer->setSingleShot(true); 0200 connect(m_connectionTimer, &QTimer::timeout, this, [this] { 0201 m_connectButton->clicked(); 0202 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.")); 0203 }); 0204 } 0205 0206 void AtCoreInstanceWidget::connectButtonClicked() 0207 { 0208 if (m_core.state() == AtCore::DISCONNECTED) { 0209 if (m_comboProfile->currentText().isEmpty()) { 0210 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.")); 0211 emit(requestProfileDialog()); 0212 return; 0213 } 0214 0215 if (m_comboPort->currentText().isEmpty()) { 0216 QMessageBox::critical(this, i18n("Error"), i18n("Please, connect a serial device to continue!")); 0217 return; 0218 } 0219 // Get profile data before connecting. 0220 m_profileData = MachineInfo::instance()->readProfile(m_comboProfile->currentText()); 0221 // then connect 0222 if (m_core.newConnection(m_comboPort->currentText(), m_profileData[keyString[MachineInfo::KEY::BAUDRATE]].toInt(), m_profileData[keyString[MachineInfo::KEY::FIRMWARE]].toString())) { 0223 emit(connectionChanged(QStringLiteral("%1 @ %2").arg(m_profileData[keyString[MachineInfo::KEY::NAME]].toString(), m_comboPort->currentText()))); 0224 m_profileData[keyString[MachineInfo::KEY::MAXBEDTEMP]].toBool() ? m_bedExtWidget->setBedMaxTemperature(m_profileData[keyString[MachineInfo::KEY::MAXBEDTEMP]].toInt()) : m_bedExtWidget->setBedThermoHidden(true); 0225 0226 m_bedExtWidget->setExtruderMaxTemperature(m_profileData[keyString[MachineInfo::KEY::MAXEXTTEMP]].toInt()); 0227 0228 int xMax = m_profileData[keyString[MachineInfo::KEY::XMAX]].toInt(); 0229 int yMax = m_profileData[keyString[MachineInfo::KEY::YMAX]].toInt(); 0230 int zMax = m_profileData[keyString[MachineInfo::KEY::ZMAX]].toInt(); 0231 m_movementWidget->setAxisMax(xMax, yMax, zMax); 0232 // AddFan Support to profile 0233 m_printWidget->updateFanCount(2); 0234 // Adjust bed size 0235 QSize newSize; 0236 if (m_profileData[keyString[MachineInfo::KEY::ISCARTESIAN]].toBool()) { 0237 newSize = QSize(xMax, yMax); 0238 } else { 0239 newSize = QSize(xMax, 0); 0240 } 0241 if (newSize != m_bedSize) { 0242 m_bedSize = newSize; 0243 emit bedSizeChanged(m_bedSize); 0244 } 0245 } 0246 } else { 0247 m_core.closeConnection(); 0248 emit(connectionChanged(i18n("Connect a Printer"))); 0249 } 0250 } 0251 0252 void AtCoreInstanceWidget::initConnectsToAtCore() 0253 { 0254 // connect log to atcoreMessages 0255 connect(&m_core, &AtCore::atcoreMessage, m_logWidget, &LogWidget::appendLog); 0256 m_core.setSerialTimerInterval(100); 0257 // Handle device changes 0258 connect(&m_core, &AtCore::portsChanged, this, &AtCoreInstanceWidget::updateSerialPort); 0259 0260 connect(&m_core, &AtCore::autoTemperatureReportChanged, this, [this](const bool autoReport) { 0261 if (m_profileData[keyString[MachineInfo::KEY::AUTOTEMPREPORT]].toBool() != autoReport) { 0262 m_profileData[keyString[MachineInfo::KEY::AUTOTEMPREPORT]] = autoReport; 0263 saveProfile(); 0264 } 0265 }); 0266 // Handle AtCore status change 0267 connect(&m_core, &AtCore::stateChanged, this, &AtCoreInstanceWidget::handlePrinterStatusChanged); 0268 // If the number of extruders from the printer change, we need to update the radiobuttons on the widget 0269 connect(this, &AtCoreInstanceWidget::extruderCountChanged, m_bedExtWidget, &BedExtruderWidget::setExtruderCount); 0270 // Bed and Extruder temperatures management 0271 connect(m_bedExtWidget, &BedExtruderWidget::bedTemperatureChanged, &m_core, &AtCore::setBedTemp); 0272 connect(m_bedExtWidget, &BedExtruderWidget::extTemperatureChanged, &m_core, &AtCore::setExtruderTemp); 0273 // command Widget 0274 connect(m_commandWidget, &CommandWidget::commandPressed, this, [this](const QString &command) { 0275 m_logWidget->appendLog(i18n("Push: %1", command)); 0276 m_core.pushCommand(command); 0277 }); 0278 0279 connect(m_commandWidget, &CommandWidget::messagePressed, [this](const QString &message) { 0280 m_logWidget->appendLog(i18n("Display: %1", message)); 0281 m_core.showMessage(message); 0282 }); 0283 0284 // Fan, Flow and Speed management 0285 connect(m_printWidget, &PrintWidget::fanSpeedChanged, &m_core, &AtCore::setFanSpeed); 0286 connect(m_printWidget, &PrintWidget::flowRateChanged, &m_core, &AtCore::setFlowRate); 0287 connect(m_printWidget, &PrintWidget::printSpeedChanged, &m_core, &AtCore::setPrinterSpeed); 0288 // Movement Widget 0289 connect(m_movementWidget, &MovementWidget::absoluteMove, this, [this](const QLatin1Char &axis, const double value) { 0290 m_logWidget->appendLog(GCode::description(GCode::G1)); 0291 m_core.move(axis, value); 0292 }); 0293 0294 connect(m_movementWidget, &MovementWidget::unitsChanged, this, [this](int units) { 0295 auto selection = static_cast<AtCore::UNITS>(units); 0296 m_core.setUnits(selection); 0297 }); 0298 0299 connect(m_movementWidget, &MovementWidget::relativeMove, this, [this](const QLatin1Char &axis, const double value) { 0300 m_logWidget->appendLog(i18n("Relative Move: %1, %2", axis, QString::number(value))); 0301 m_core.setRelativePosition(); 0302 m_core.move(axis, value); 0303 m_core.setAbsolutePosition(); 0304 }); 0305 0306 // Sd Card Stuff 0307 connect(&m_core, &AtCore::sdCardFileListChanged, m_sdWidget, &SdWidget::updateFilelist); 0308 connect(m_sdWidget, &SdWidget::requestSdList, &m_core, &AtCore::sdFileList); 0309 connect(&m_core, &AtCore::sdMountChanged, m_statusWidget, &StatusWidget::setSD); 0310 0311 connect(m_sdWidget, &SdWidget::printSdFile, this, [this](const QString &fileName) { 0312 if (fileName.isEmpty()) { 0313 QMessageBox::information(this, i18n("Print Error"), i18n("You must select a file from the list")); 0314 } else { 0315 m_core.print(fileName, true); 0316 togglePrintButtons(true); 0317 } 0318 }); 0319 0320 connect(m_sdWidget, &SdWidget::deleteSdFile, this, [this](const QString &fileName) { 0321 if (fileName.isEmpty()) { 0322 QMessageBox::information(this, i18n("Delete Error"), i18n("You must select a file from the list")); 0323 } else { 0324 m_core.sdDelete(fileName); 0325 } 0326 }); 0327 } 0328 0329 void AtCoreInstanceWidget::printFile(const QUrl &fileName) 0330 { 0331 if (fileName.isEmpty()) { 0332 QMessageBox::critical(this, i18n("Filename Empty"), i18n("No filename sent from calling method, please check and try again.")); 0333 return; 0334 } 0335 if (!QFileInfo(fileName.toLocalFile()).isReadable()) { 0336 QMessageBox::critical(this, i18n("File not found"), i18n("%1 \nIs not readable, please check and try again.", fileName.toLocalFile())); 0337 return; 0338 } 0339 if (m_core.state() == AtCore::IDLE) { 0340 m_logWidget->appendLog(i18n("Printing: %1", fileName.toLocalFile())); 0341 m_core.print(fileName.toLocalFile()); 0342 } 0343 } 0344 0345 void AtCoreInstanceWidget::print() 0346 { 0347 emit(requestFileChooser()); 0348 } 0349 0350 void AtCoreInstanceWidget::pausePrint() 0351 { 0352 if (m_core.state() == AtCore::BUSY) { 0353 m_core.pause(m_profileData[keyString[MachineInfo::KEY::POSTPAUSE]].toString()); 0354 } else if (m_core.state() == AtCore::PAUSE) { 0355 m_core.resume(); 0356 } 0357 } 0358 0359 void AtCoreInstanceWidget::stopPrint() 0360 { 0361 m_core.stop(); 0362 } 0363 0364 void AtCoreInstanceWidget::disableMotors() 0365 { 0366 m_core.disableMotors(0); 0367 } 0368 0369 void AtCoreInstanceWidget::handlePrinterStatusChanged(AtCore::STATES newState) 0370 { 0371 static QString stateString; 0372 switch (newState) { 0373 case AtCore::CONNECTING: { 0374 m_connectionTimer->start(); 0375 m_core.setSerialTimerInterval(0); 0376 m_connectButton->setText(i18n("Disconnect")); 0377 m_connectButton->setIcon(QIcon::fromTheme("network-disconnect", QIcon(QString(":/%1/disconnect").arg(m_theme)))); 0378 m_connectToolBar->setHidden(true); 0379 m_toolBar->setHidden(false); 0380 stateString = i18n("Connecting..."); 0381 m_logWidget->appendLog(i18n("Attempting to Connect")); 0382 connect(&m_core, &AtCore::receivedMessage, m_logWidget, &LogWidget::appendRLog); 0383 connect(&m_core, &AtCore::pushedCommand, m_logWidget, &LogWidget::appendSLog); 0384 } break; 0385 case AtCore::IDLE: { 0386 if (m_connectionTimer->isActive()) { 0387 m_core.setAutoTemperatureReport(m_profileData[keyString[MachineInfo::KEY::AUTOTEMPREPORT]].toBool()); 0388 m_connectionTimer->stop(); 0389 } 0390 stateString = i18n("Connected to %1", m_core.connectedPort()); 0391 emit extruderCountChanged(m_core.extruderCount()); 0392 m_logWidget->appendLog(stateString); 0393 emit disableDisconnect(false); 0394 enableControls(true); 0395 connectExtruderTemperatureData(true); 0396 if (m_profileData[keyString[MachineInfo::KEY::MAXBEDTEMP]].toBool()) { 0397 connectBedTemperatureData(true); 0398 } 0399 if (!m_core.availableFirmwarePlugins().contains(m_profileData[keyString[MachineInfo::KEY::FIRMWARE]].toString())) { 0400 m_profileData[keyString[MachineInfo::KEY::FIRMWARE]] = m_core.firmwarePlugin()->name().toLower(); 0401 saveProfile(); 0402 } 0403 } break; 0404 case AtCore::DISCONNECTED: { 0405 if (m_connectionTimer->isActive()) { 0406 m_connectionTimer->stop(); 0407 } 0408 stateString = i18n("Not Connected"); 0409 disconnect(&m_core, &AtCore::receivedMessage, m_logWidget, &LogWidget::appendRLog); 0410 disconnect(&m_core, &AtCore::pushedCommand, m_logWidget, &LogWidget::appendSLog); 0411 m_logWidget->appendLog(i18n("Serial disconnected")); 0412 m_core.setSerialTimerInterval(100); 0413 m_connectButton->setText(i18n("Connect")); 0414 m_connectButton->setIcon(QIcon::fromTheme("network-connect", QIcon(QString(":/%1/connect").arg(m_theme)))); 0415 m_connectToolBar->setHidden(false); 0416 m_toolBar->setHidden(true); 0417 enableControls(false); 0418 connectExtruderTemperatureData(false); 0419 connectBedTemperatureData(false); 0420 } break; 0421 case AtCore::STARTPRINT: { 0422 stateString = i18n("Starting Print"); 0423 m_statusWidget->showPrintArea(true); 0424 connect(&m_core, &AtCore::printProgressChanged, m_statusWidget, &StatusWidget::updatePrintProgress); 0425 } break; 0426 case AtCore::FINISHEDPRINT: { 0427 stateString = i18n("Finished Print"); 0428 m_statusWidget->showPrintArea(false); 0429 disconnect(&m_core, &AtCore::printProgressChanged, m_statusWidget, &StatusWidget::updatePrintProgress); 0430 m_printAction->setText(i18n("Print")); 0431 m_printAction->setIcon(QIcon::fromTheme("media-playback-start", QIcon(QString(":/%1/start").arg(m_theme)))); 0432 m_logWidget->appendLog(i18n("Finished Print Job")); 0433 } break; 0434 case AtCore::BUSY: { 0435 stateString = i18n("Printing"); 0436 emit disableDisconnect(true); 0437 m_printAction->setText(i18n("Pause")); 0438 m_printAction->setIcon(QIcon::fromTheme("media-playback-pause", QIcon(QString(":/%1/pause").arg(m_theme)))); 0439 } break; 0440 case AtCore::PAUSE: { 0441 stateString = i18n("Paused"); 0442 m_printAction->setText(i18n("Resume")); 0443 m_printAction->setIcon(QIcon::fromTheme("media-playback-start", QIcon(QString(":/%1/start").arg(m_theme)))); 0444 } break; 0445 case AtCore::STOP: { 0446 stateString = i18n("Stopping Print"); 0447 m_logWidget->appendLog(stateString); 0448 } break; 0449 case AtCore::ERRORSTATE: { 0450 stateString = i18n("Error"); 0451 } break; 0452 default: 0453 m_logWidget->appendLog(i18n("Unknown AtCore State, %1", newState)); 0454 break; 0455 } 0456 m_statusWidget->setState(stateString); 0457 } 0458 0459 void AtCoreInstanceWidget::checkTemperature(uint sensorType, uint number, float temp) 0460 { 0461 static QString msg; 0462 switch (sensorType) { 0463 case 0x00: // bed 0464 msg = QString::fromLatin1("Bed Temperature"); 0465 break; 0466 0467 case 0x01: // bed target 0468 msg = QString::fromLatin1("Bed Target Temperature"); 0469 break; 0470 0471 case 0x02: // extruder 0472 msg = QString::fromLatin1("Extruder[%1] Temperature").arg(QString::number(number)); 0473 break; 0474 0475 case 0x03: // extruder target 0476 msg = QString::fromLatin1("Extruder[%1] Target Temperature").arg(QString::number(number)); 0477 break; 0478 0479 case 0x04: // enclosure 0480 msg = QString::fromLatin1("Enclosure Temperature"); 0481 break; 0482 0483 case 0x05: // enclosure target 0484 msg = QString::fromLatin1("Enclosure Target Temperature"); 0485 break; 0486 } 0487 0488 msg.append(QString::fromLatin1(": %1").arg(QString::number(double(temp), 'f', 2))); 0489 m_logWidget->appendLog(msg); 0490 } 0491 0492 void AtCoreInstanceWidget::enableControls(bool b) 0493 { 0494 if (b) { 0495 layout()->removeWidget(m_logWidget); 0496 layout()->removeWidget(m_statusWidget); 0497 layout()->addWidget(m_statusWidget); 0498 m_advancedTab->layout()->addWidget(m_logWidget); 0499 } else { 0500 m_advancedTab->layout()->removeWidget(m_logWidget); 0501 layout()->addWidget(m_logWidget); 0502 layout()->removeWidget(m_statusWidget); 0503 layout()->addWidget(m_statusWidget); 0504 } 0505 m_tabWidget->setHidden(!b); 0506 m_toolBar->setEnabled(b); 0507 } 0508 0509 bool AtCoreInstanceWidget::connected() 0510 { 0511 return (m_core.state() != AtCore::DISCONNECTED); 0512 } 0513 0514 void AtCoreInstanceWidget::setFileCount(int count) 0515 { 0516 m_fileCount = count; 0517 togglePrintButtons(m_fileCount); 0518 } 0519 0520 void AtCoreInstanceWidget::updateSerialPort(QStringList ports) 0521 { 0522 m_comboPort->clear(); 0523 // Remove any strings that match ttyS## from the port list. 0524 ports = ports.filter(QRegularExpression("^((?!ttyS\\d+).)*$")); 0525 if (!ports.isEmpty()) { 0526 m_comboPort->addItems(ports); 0527 m_logWidget->appendLog(i18n("Found %1 Ports", QString::number(ports.count()))); 0528 } else { 0529 QString portError(i18n("No available ports! Please connect a serial device to continue!")); 0530 if (!m_logWidget->endsWith(portError)) { 0531 m_logWidget->appendLog(portError); 0532 } 0533 } 0534 } 0535 0536 void AtCoreInstanceWidget::updateProfileData() 0537 { 0538 m_comboProfile->clear(); 0539 m_comboProfile->addItems(MachineInfo::instance()->profileNames()); 0540 0541 if (m_core.state() != AtCore::DISCONNECTED) { 0542 m_profileData = MachineInfo::instance()->readProfile(m_comboProfile->currentText()); 0543 bool hBed = MachineInfo::instance()->readKey(m_comboProfile->currentText(), MachineInfo::KEY::MAXBEDTEMP).toInt() > 0; 0544 m_bedExtWidget->setBedThermoHidden(!hBed); 0545 connectBedTemperatureData(hBed); 0546 m_bedExtWidget->setBedMaxTemperature(MachineInfo::instance()->readKey(m_comboProfile->currentText(), MachineInfo::KEY::MAXBEDTEMP).toInt()); 0547 m_bedExtWidget->setExtruderMaxTemperature(MachineInfo::instance()->readKey(m_comboProfile->currentText(), MachineInfo::KEY::MAXEXTTEMP).toInt()); 0548 } 0549 } 0550 0551 void AtCoreInstanceWidget::togglePrintButtons(bool shown) 0552 { 0553 m_printAction->setVisible(shown); 0554 m_stopAction->setVisible(shown); 0555 } 0556 0557 bool AtCoreInstanceWidget::isPrinting() 0558 { 0559 return (m_core.state() == AtCore::BUSY); 0560 } 0561 0562 void AtCoreInstanceWidget::saveProfile() 0563 { 0564 QString profile = m_comboProfile->currentText(); 0565 MachineInfo::instance()->storeKey(profile, MachineInfo::KEY::FIRMWARE, m_profileData[keyString[MachineInfo::KEY::FIRMWARE]]); 0566 MachineInfo::instance()->storeKey(profile, MachineInfo::KEY::AUTOTEMPREPORT, m_profileData[keyString[MachineInfo::KEY::AUTOTEMPREPORT]]); 0567 } 0568 0569 void AtCoreInstanceWidget::connectBedTemperatureData(bool connected) 0570 { 0571 if (connected) { 0572 if (m_plotWidget->plots().contains(i18n("Actual Bed"))) { 0573 return; 0574 } 0575 m_plotWidget->addPlot(i18n("Actual Bed")); 0576 connect(m_core.temperature(), &Temperature::bedTemperatureChanged, [this] { 0577 const float temp = m_core.temperature()->bedTemperature(); 0578 checkTemperature(0x00, 0, temp); 0579 m_plotWidget->appendPoint(i18n("Actual Bed"), temp); 0580 m_bedExtWidget->updateBedTemp(temp); 0581 }); 0582 m_plotWidget->addPlot(i18n("Target Bed")); 0583 connect(m_core.temperature(), &Temperature::bedTargetTemperatureChanged, [this] { 0584 const float temp = m_core.temperature()->bedTargetTemperature(); 0585 checkTemperature(0x01, 0, temp); 0586 m_plotWidget->appendPoint(i18n("Target Bed"), temp); 0587 m_bedExtWidget->updateBedTargetTemp(int(temp)); 0588 }); 0589 } else { 0590 if (m_plotWidget->plots().contains(i18n("Actual Bed"))) { 0591 m_plotWidget->removePlot(i18n("Actual Bed")); 0592 disconnect(m_core.temperature(), &Temperature::bedTemperatureChanged, nullptr, nullptr); 0593 m_plotWidget->removePlot(i18n("Target Bed")); 0594 disconnect(m_core.temperature(), &Temperature::bedTargetTemperatureChanged, nullptr, nullptr); 0595 } 0596 } 0597 } 0598 0599 void AtCoreInstanceWidget::connectExtruderTemperatureData(bool connected) 0600 { 0601 if (connected) { 0602 if (m_plotWidget->plots().contains((i18n("Actual Ext.1")))) { 0603 return; 0604 } 0605 // Add Extruder. 0606 m_plotWidget->addPlot(i18n("Actual Ext.1")); 0607 connect(m_core.temperature(), &Temperature::extruderTemperatureChanged, this, [this] { 0608 const float temp = m_core.temperature()->extruderTemperature(); 0609 checkTemperature(0x02, 0, temp); 0610 m_plotWidget->appendPoint(i18n("Actual Ext.1"), temp); 0611 m_bedExtWidget->updateExtTemp(temp); 0612 }); 0613 m_plotWidget->addPlot(i18n("Target Ext.1")); 0614 connect(m_core.temperature(), &Temperature::extruderTargetTemperatureChanged, this, [this] { 0615 const float temp = m_core.temperature()->extruderTargetTemperature(); 0616 checkTemperature(0x03, 0, temp); 0617 m_plotWidget->appendPoint(i18n("Target Ext.1"), temp); 0618 m_bedExtWidget->updateExtTargetTemp(int(temp)); 0619 }); 0620 } else { 0621 if (m_plotWidget->plots().contains(i18n("Actual Ext.1"))) { 0622 m_plotWidget->removePlot(i18n("Actual Ext.1")); 0623 disconnect(m_core.temperature(), &Temperature::extruderTemperatureChanged, nullptr, nullptr); 0624 m_plotWidget->removePlot(i18n("Target Ext.1")); 0625 disconnect(m_core.temperature(), &Temperature::extruderTargetTemperatureChanged, nullptr, nullptr); 0626 } 0627 } 0628 } 0629 0630 QSize AtCoreInstanceWidget::bedSize() 0631 { 0632 return m_bedSize; 0633 }