diff --git a/src/atcore.h b/src/atcore.h --- a/src/atcore.h +++ b/src/atcore.h @@ -59,6 +59,8 @@ Q_PROPERTY(QStringList portSpeeds READ portSpeeds) Q_PROPERTY(QString connectedPort READ connectedPort) Q_PROPERTY(AtCore::STATES state READ state WRITE setState NOTIFY stateChanged) + Q_PROPERTY(bool sdMount READ isSdMounted WRITE setSdMounted NOTIFY sdMountChanged) + Q_PROPERTY(QStringList sdFileList READ sdFileList NOTIFY sdCardFileListChanged) public: /** * @brief STATES enum Possible states the printer can be in @@ -200,6 +202,59 @@ */ quint16 serialTimerInterval() const; + /** + * @brief Attempt to Mount an sd card + * @param slot: Sd card Slot on machine (0 is default) + */ + void mountSd(uint slot = 0); + + /** + * @brief Attempt to Unmount an sd card + * @param slot: Sd card Slot on machine (0 is default) + */ + void umountSd(uint slot = 0); + + /** + * @brief sdFileList + * @return List of files on the sd card. + */ + QStringList sdFileList(); + + /** + * @brief Append a file to AtCorePrivate::sdCardFileList. + * @param fileName: new FileName + */ + void appendSdCardFileList(const QString &fileName); + + /** + * @brief Clear AtCorePrivate::sdCardFileList. + */ + void clearSdCardFileList(); + + /** + * @brief Check if an sd card is mounted on the printer + * @return True if card mounted + */ + bool isSdMounted() const; + + /** + * @brief Set if the sd card is mounted by the printer + * @param mounted: True is mounted + */ + void setSdMounted(const bool mounted); + + /** + * @brief returns AtCorePrivate::sdCardReadingFileList + * @return True if printer is returning sd card file list + */ + bool isReadingSdCardList() const; + + /** + * @brief set AtCorePrivate::sdCardReadingFileList + * @param readingList set true if reading file list + */ + void setReadingSdCardList(bool readingList); + signals: /** @@ -225,7 +280,17 @@ /** * @brief Available serialports Changed */ - void portsChanged(QStringList); + void portsChanged(const QStringList &portList); + + /** + * @brief Sd Card Mount Changed + */ + void sdMountChanged(bool newState); + + /** + * @brief The files on the sd card have changed. + */ + void sdCardFileListChanged(const QStringList &fileList); public slots: @@ -246,8 +311,9 @@ /** * @brief Public Interface for printing a file * @param fileName: the gcode file to print. + * @param sdPrint: set true to print fileName from Sd card */ - void print(const QString &fileName); + void print(const QString &fileName, bool sdPrint); /** * @brief Stop the Printer by empting the queue and aborting the print job (if running) @@ -378,6 +444,16 @@ */ void setSerialTimerInterval(const quint16 &newTime); + /** + * @brief delete file from sd card + */ + void sdDelete(const QString &fileName); + + /** + * @brief Queue the Printer for status of sd card print + */ + void sdCardPrintStatus(); + private slots: /** * @brief processQueue send commands from the queue. @@ -407,6 +483,11 @@ */ void locateSerialPort(); + /** + * @brief Send request to the printer for the sd card file list. + */ + void getSDFileList(); + private: /** * @brief True if a firmware plugin is loaded @@ -428,6 +509,12 @@ */ void findFirmwarePlugins(); + /** + * @brief stops print just for sd prints used internally + * @sa stop(),emergencyStop() + */ + void stopSdPrint(); + /** * @brief Hold private data of AtCore. */ diff --git a/src/atcore.cpp b/src/atcore.cpp --- a/src/atcore.cpp +++ b/src/atcore.cpp @@ -61,6 +61,11 @@ AtCore::STATES printerState; //!< @param printerState: State of the Printer QStringList serialPorts; //!< @param seralPorts: Detected serial Ports QTimer *serialTimer = nullptr; //!< @param serialTimer: Timer connected to locateSerialPorts + bool sdCardMounted = false; //!< @param sdCardMounted: True if Sd Card is mounted. + bool sdCardReadingFileList = false; //!< @param sdCardReadingFileList: True while getting file names from sd card + bool sdCardPrinting = false; //!< @param sdCardPrinting: True if currently printing from sd card. + QString sdCardFileName; //!< @param sdCardFileName: name of file being used from sd card. + QStringList sdCardFileList; //!< @param sdCardFileList: List of files on sd card. }; AtCore::AtCore(QObject *parent) : @@ -325,14 +330,23 @@ return d->percentage; } -void AtCore::print(const QString &fileName) +void AtCore::print(const QString &fileName, bool sdPrint) { if (state() == AtCore::CONNECTING) { qCDebug(ATCORE_CORE) << "Load a firmware plugin to print."; return; } - //START A THREAD AND CONNECT TO IT setState(AtCore::STARTPRINT); + if (sdPrint) { + pushCommand(GCode::toCommand(GCode::M23, fileName)); + d->sdCardFileName = fileName; + pushCommand(GCode::toCommand(GCode::M24)); + setState(AtCore::BUSY); + d->sdCardPrinting = true; + connect(d->tempTimer, &QTimer::timeout, this, &AtCore::sdCardPrintStatus); + return; + } + //START A THREAD AND CONNECT TO IT QThread *thread = new QThread(); PrintThread *printThread = new PrintThread(this, fileName); printThread->moveToThread(thread); @@ -357,8 +371,9 @@ void AtCore::closeConnection() { if (serialInitialized()) { - if (state() == AtCore::BUSY) { - //we have to clean print if printing. + if (AtCore::state() == AtCore::BUSY && !d->sdCardPrinting) { + //we have to clean print if printing from the host. + //disconnecting from a printer printing via sd card should not affect its print. setState(AtCore::STOP); } if (firmwarePluginLoaded()) { @@ -373,6 +388,7 @@ QString msg = d->pluginLoader.unload() ? QStringLiteral("success") : QStringLiteral("FAIL"); qCDebug(ATCORE_PLUGIN) << QStringLiteral("Firmware plugin %1 unload: %2").arg(name, msg); serial()->close(); + clearSdCardFileList(); setState(AtCore::DISCONNECTED); } } @@ -388,28 +404,47 @@ qCDebug(ATCORE_CORE) << "Atcore state changed from [" \ << d->printerState << "] to [" << state << "]"; d->printerState = state; + if (state == AtCore::FINISHEDPRINT && d->sdCardPrinting) { + d->sdCardPrinting = false; + disconnect(d->tempTimer, &QTimer::timeout, this, &AtCore::sdCardPrintStatus); + } emit(stateChanged(d->printerState)); } } void AtCore::stop() { setState(AtCore::STOP); d->commandQueue.clear(); + if (d->sdCardPrinting) { + stopSdPrint(); + } setExtruderTemp(0, 0); setBedTemp(0); home(AtCore::X); } void AtCore::emergencyStop() { - if (state() == AtCore::BUSY) { - setState(AtCore::STOP); - } d->commandQueue.clear(); + if (AtCore::state() == AtCore::BUSY) { + if (!d->sdCardPrinting) { + //Stop our running print thread + setState(AtCore::STOP); + } + } serial()->pushCommand(GCode::toCommand(GCode::M112).toLocal8Bit()); } +void AtCore::stopSdPrint() +{ + pushCommand(GCode::toCommand(GCode::M25)); + d->sdCardFileName = QString(); + pushCommand(GCode::toCommand(GCode::M23, d->sdCardFileName)); + AtCore::setState(AtCore::FINISHEDPRINT); + AtCore::setState(AtCore::IDLE); +} + void AtCore::requestFirmware() { if (serialInitialized()) { @@ -472,19 +507,26 @@ void AtCore::pause(const QString &pauseActions) { + if (d->sdCardPrinting) { + pushCommand(GCode::toCommand(GCode::M25)); + } pushCommand(GCode::toCommand(GCode::M114)); - setState(AtCore::PAUSE); if (!pauseActions.isEmpty()) { QStringList temp = pauseActions.split(QChar::fromLatin1(',')); for (int i = 0; i < temp.length(); i++) { pushCommand(temp.at(i)); } } + setState(AtCore::PAUSE); } void AtCore::resume() { - pushCommand(GCode::toCommand(GCode::G0, QString::fromLatin1(d->posString))); + if (d->sdCardPrinting) { + pushCommand(GCode::toCommand(GCode::M24)); + } else { + pushCommand(GCode::toCommand(GCode::G0, QString::fromLatin1(d->posString))); + } setState(AtCore::BUSY); } @@ -628,3 +670,74 @@ pushCommand(GCode::toCommand(GCode::M84)); } } + +bool AtCore::isSdMounted() const +{ + return d->sdCardMounted; +} + +void AtCore::setSdMounted(bool mounted) +{ + if (mounted != isSdMounted()) { + d->sdCardMounted = mounted; + emit(sdMountChanged(d->sdCardMounted)); + } +} + +void AtCore::getSDFileList() +{ + pushCommand(GCode::toCommand(GCode::M20)); +} + +QStringList AtCore::sdFileList() +{ + if (!d->sdCardReadingFileList) { + getSDFileList(); + } + return d->sdCardFileList; +} + +void AtCore::appendSdCardFileList(const QString &fileName) +{ + d->sdCardFileList.append(fileName); + emit(sdCardFileListChanged(d->sdCardFileList)); +} + +void AtCore::clearSdCardFileList() +{ + d->sdCardFileList.clear(); + emit(sdCardFileListChanged(d->sdCardFileList)); +} + +void AtCore::sdDelete(const QString &fileName) +{ + if (d->sdCardFileList.contains(fileName)) { + pushCommand(GCode::toCommand(GCode::M30, fileName)); + getSDFileList(); + } +} + +void AtCore::mountSd(uint slot) +{ + pushCommand(GCode::toCommand(GCode::M21, QString::number(slot))); +} + +void AtCore::umountSd(uint slot) +{ + pushCommand(GCode::toCommand(GCode::M22, QString::number(slot))); +} + +bool AtCore::isReadingSdCardList() const +{ + return d->sdCardReadingFileList; +} + +void AtCore::setReadingSdCardList(bool readingList) +{ + d->sdCardReadingFileList = readingList; +} + +void AtCore::sdCardPrintStatus() +{ + pushCommand(GCode::toCommand(GCode::M27)); +} diff --git a/src/gcodecommands.cpp b/src/gcodecommands.cpp --- a/src/gcodecommands.cpp +++ b/src/gcodecommands.cpp @@ -96,13 +96,15 @@ case G90: case G91: return code; + case G32: return code.append(QStringLiteral(" S1")); case G0: case G1: case G28: code = value1.isEmpty() ? code : code.append(QStringLiteral(" %1").arg(value1.toUpper())); return code; + default: return commandNotSupported; } @@ -129,7 +131,7 @@ return QObject::tr("M21: Initialize SDCard"); case M22://Teacup - Sprinter - Marlin - Repetier - RepRap Firmware return QObject::tr("M22: Release SDCard"); - case M23:////Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware + case M23://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M23: Select SD file"); case M24://Teacup - Sprinter - Marlin - Repetier - Smoothie - RepRap Firmware return QObject::tr("M24: Start/resume SD print"); @@ -289,7 +291,7 @@ return QObject::tr("M231: Set OPS parameter"); case M232://Repetier return QObject::tr("M232: Read and reset max. advance values"); - case M240: //Marlin + case M240://Marlin return QObject::tr("M240: Trigger camera"); case M250://Marlin return QObject::tr("M250: Set LCD contrast"); @@ -494,35 +496,68 @@ { QString code = QStringLiteral("M%1").arg(QString::number(gcode)); switch (gcode) { + case M20: + case M24: + case M25: + case M27: case M105: case M107: case M112: case M114: case M115: case M116: case M119: return code; + + case M21: + case M22: + code = value1.isEmpty() ? code : code.append(QStringLiteral(" P%1").arg(value1)); + return code; + + case M23: + case M28: + case M29: + case M30: case M117: - code = value1.isEmpty() ? GCode::commandRequiresArgument.arg(QStringLiteral("M"), QString::number(gcode)) : QStringLiteral("M117 %1").arg(value1); + code = value1.isEmpty() ? GCode::commandRequiresArgument.arg(QStringLiteral("M"), QString::number(gcode)) : code.append(QStringLiteral(" %1").arg(value1)); return code; + case M109: case M140: case M190: case M220: case M221: code = value1.isEmpty() ? GCode::commandRequiresArgument.arg(QStringLiteral("M"), QString::number(gcode)) : code.append(QStringLiteral(" S%1").arg(value1)); return code; + case M84: code = value1.isEmpty() ? code : code.append(QStringLiteral(" S%1").arg(value1)); return code; + case M104: code = value2.isEmpty() ? code.append(QStringLiteral(" S%1").arg(value1)) : code.append(QStringLiteral(" P%1 S%2").arg(value1).arg(value2)); code = value1.isEmpty() ? GCode::commandRequiresArgument.arg(QStringLiteral("M"), QString::number(gcode)) : code ; return code; + case M106: code = value2.isEmpty() ? code.append(QStringLiteral(" S%1").arg(value1)) : code.append(QStringLiteral(" P%1 S%2").arg(value1).arg(value2)); code = value1.isEmpty() ? QStringLiteral("M106") : code ; return code; + + /// For M26 values that end with %. AtCore will send the percentage verison of the command (optional in firmwares) + /// For all values not ending in % it will start on that byte. This is the standard Sd resume supported by all reprap based firmware. + case M26: { + if (!value1.isEmpty()) { + if (value1.endsWith(QStringLiteral("%"))) { + QString temp = value1; + temp.replace(QStringLiteral("%"), QStringLiteral("")); + return code.append(QStringLiteral(" P%1").arg(temp.toDouble() / 100)); + } + return code.append(QStringLiteral(" S%1").arg(value1)); + } + return GCode::commandRequiresArgument.arg(QStringLiteral("M"), QString::number(gcode)); + } + default: return commandNotSupported; } diff --git a/src/plugins/marlinplugin.h b/src/plugins/marlinplugin.h --- a/src/plugins/marlinplugin.h +++ b/src/plugins/marlinplugin.h @@ -48,4 +48,10 @@ * @return Marlin */ QString name() const override; + + /** + * @brief validateCommand to filter commands from messages + * @param lastMessage: last Message from printer + */ + void validateCommand(const QString &lastMessage) override; }; diff --git a/src/plugins/marlinplugin.cpp b/src/plugins/marlinplugin.cpp --- a/src/plugins/marlinplugin.cpp +++ b/src/plugins/marlinplugin.cpp @@ -39,3 +39,47 @@ { qCDebug(MARLIN_PLUGIN) << name() << " plugin loaded!"; } + +void MarlinPlugin::validateCommand(const QString &lastMessage) +{ + if (lastMessage.contains(QStringLiteral("End file list"))) { + core()->setReadingSdCardList(false); + } else if (core()->isReadingSdCardList()) { + // Below is to not add directories + if (!lastMessage.endsWith(QChar::fromLatin1('/'))) { + QString fileName = lastMessage; + fileName.chop(fileName.length() - fileName.lastIndexOf(QChar::fromLatin1(' '))); + core()->appendSdCardFileList(fileName); + } + } else { + if (lastMessage.contains(QStringLiteral("SD card ok"))) { + core()->setSdMounted(true); + } else if (lastMessage.contains(QStringLiteral("SD init fail"))) { + core()->setSdMounted(false); + } else if (lastMessage.contains(QStringLiteral("Begin file list"))) { + core()->setSdMounted(true); + core()->clearSdCardFileList(); + core()->setReadingSdCardList(true); + } else if (lastMessage.contains(QStringLiteral("SD printing byte"))) { + QString temp = lastMessage; + temp.replace(QStringLiteral("SD printing byte"), QString()); + qlonglong total = temp.mid(temp.lastIndexOf(QChar::fromLatin1('/')) + 1, temp.length() - temp.lastIndexOf(QChar::fromLatin1('/'))).toLongLong(); + if (total != 0) { + temp.chop(temp.length() - temp.lastIndexOf(QChar::fromLatin1('/'))); + qlonglong remaining = total - temp.toLongLong(); + float progress = float(total - remaining) * 100 / float(total); + core()->printProgressChanged(progress); + if (progress >= 100) { + core()->setState(AtCore::FINISHEDPRINT); + core()->setState(AtCore::IDLE); + } + } else { + core()->setState(AtCore::FINISHEDPRINT); + core()->setState(AtCore::IDLE); + } + } + if (lastMessage.contains(QStringLiteral("ok"))) { + emit readyForCommand(); + } + } +} diff --git a/src/plugins/repetierplugin.h b/src/plugins/repetierplugin.h --- a/src/plugins/repetierplugin.h +++ b/src/plugins/repetierplugin.h @@ -48,4 +48,10 @@ * @return Repetier */ QString name() const override; + + /** + * @brief validateCommand to filter commands from messages + * @param lastMessage: last Message from printer + */ + void validateCommand(const QString &lastMessage) override; }; diff --git a/src/plugins/repetierplugin.cpp b/src/plugins/repetierplugin.cpp --- a/src/plugins/repetierplugin.cpp +++ b/src/plugins/repetierplugin.cpp @@ -39,3 +39,49 @@ { qCDebug(REPETIER_PLUGIN) << name() << " plugin loaded!"; } + +void RepetierPlugin::validateCommand(const QString &lastMessage) +{ + if (lastMessage.contains(QStringLiteral("End file list"))) { + core()->setReadingSdCardList(false); + } else if (core()->isReadingSdCardList()) { + // Below is to not add directories + if (!lastMessage.endsWith(QChar::fromLatin1('/'))) { + QString fileName = lastMessage; + fileName.chop(fileName.length() - fileName.lastIndexOf(QChar::fromLatin1(' '))); + core()->appendSdCardFileList(fileName); + } + } else { + if (lastMessage.contains(QStringLiteral("SD card"))) { + if (lastMessage.contains(QStringLiteral("inserted"))) { + core()->setSdMounted(true); + } else if (lastMessage.contains(QStringLiteral("removed"))) { + core()->setSdMounted(false); + } + } else if (lastMessage.contains(QStringLiteral("Begin file list"))) { + core()->setSdMounted(true); + core()->setReadingSdCardList(true); + core()->clearSdCardFileList(); + } else if (lastMessage.contains(QStringLiteral("SD printing byte"))) { + QString temp = lastMessage; + temp.replace(QStringLiteral("SD printing byte"), QString()); + qlonglong total = temp.mid(temp.lastIndexOf(QChar::fromLatin1('/')) + 1, temp.length() - temp.lastIndexOf(QChar::fromLatin1('/'))).toLongLong(); + if (total != 0) { + temp.chop(temp.length() - temp.lastIndexOf(QChar::fromLatin1('/'))); + qlonglong remaining = total - temp.toLongLong(); + float progress = float(total - remaining) * 100 / float(total); + core()->printProgressChanged(progress); + if (progress >= 100) { + core()->setState(AtCore::FINISHEDPRINT); + core()->setState(AtCore::IDLE); + } + } else { + core()->setState(AtCore::FINISHEDPRINT); + core()->setState(AtCore::IDLE); + } + } + if (lastMessage.contains(QStringLiteral("ok"))) { + emit readyForCommand(); + } + } +} diff --git a/testclient/mainwindow.h b/testclient/mainwindow.h --- a/testclient/mainwindow.h +++ b/testclient/mainwindow.h @@ -131,6 +131,10 @@ */ void printPBClicked(); + /** + * @brief Print Button for Sd Prints clicked. + */ + void sdPrintPBClicked(); /** * @brief Save the log file. */ @@ -176,12 +180,24 @@ * @brief Show the about dialog */ void about(); + + /** + * @brief List Files on the sd card. + */ + void getSdList(); + + /** + * @brief Sd Card Delete file clicked + */ + void sdDelPBClicked(); + signals: /** * @brief printFile emit ready to print a file to atcore * @param fileName : the file to print + * @param sdPrint : True if file is on printers Sd Card */ - void printFile(const QString &fileName); + void printFile(const QString &fileName, bool sdPrint = false); private: Ui::MainWindow *ui; @@ -269,4 +285,9 @@ * @brief Populate comboboxes */ void populateCBs(); + + /** + * @brief Gui Changes for when sd card mount status has changed. + */ + void sdChanged(bool mounted); }; diff --git a/testclient/mainwindow.cpp b/testclient/mainwindow.cpp --- a/testclient/mainwindow.cpp +++ b/testclient/mainwindow.cpp @@ -90,18 +90,27 @@ connect(ui->mvAxisPB, &QPushButton::clicked, this, &MainWindow::mvAxisPBClicked); connect(ui->fanSpeedPB, &QPushButton::clicked, this, &MainWindow::fanSpeedPBClicked); connect(ui->printPB, &QPushButton::clicked, this, &MainWindow::printPBClicked); + connect(ui->sdPrintPB, &QPushButton::clicked, this, &MainWindow::sdPrintPBClicked); + connect(ui->sdDelPB, &QPushButton::clicked, this, &MainWindow::sdDelPBClicked); connect(ui->printerSpeedPB, &QPushButton::clicked, this, &MainWindow::printerSpeedPBClicked); connect(ui->flowRatePB, &QPushButton::clicked, this, &MainWindow::flowRatePBClicked); connect(ui->showMessagePB, &QPushButton::clicked, this, &MainWindow::showMessage); connect(ui->pluginCB, &QComboBox::currentTextChanged, this, &MainWindow::pluginCBChanged); connect(ui->disableMotorsPB, &QPushButton::clicked, this, &MainWindow::disableMotorsPBClicked); + connect(ui->sdListPB, &QPushButton::clicked, this, &MainWindow::getSdList); connect(core, &AtCore::stateChanged, this, &MainWindow::printerStateChanged); connect(this, &MainWindow::printFile, core, &AtCore::print); connect(ui->stopPB, &QPushButton::clicked, core, &AtCore::stop); connect(ui->emergencyStopPB, &QPushButton::clicked, core, &AtCore::emergencyStop); connect(axisControl, &AxisControl::clicked, this, &MainWindow::axisControlClicked); connect(core, &AtCore::portsChanged, this, &MainWindow::locateSerialPort); connect(core, &AtCore::printProgressChanged, this, &MainWindow::printProgressChanged); + connect(core, &AtCore::sdMountChanged, this, &MainWindow::sdChanged); + + connect(core, &AtCore::sdCardFileListChanged, [this](QStringList fileList) { + ui->sdFileListView->clear(); + ui->sdFileListView->addItems(fileList); + }); connect(&core->temperature(), &Temperature::bedTemperatureChanged, [ this ](float temp) { checkTemperature(0x00, 0, temp); @@ -135,11 +144,13 @@ ui->menuView->insertAction(nullptr, ui->moveDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->tempTimelineDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->logDock->toggleViewAction()); + ui->menuView->insertAction(nullptr, ui->sdDock->toggleViewAction()); //more dock stuff. setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North); setTabPosition(Qt::RightDockWidgetArea, QTabWidget::North); tabifyDockWidget(ui->moveDock, ui->tempControlsDock); + tabifyDockWidget(ui->moveDock, ui->sdDock); ui->moveDock->raise(); tabifyDockWidget(ui->connectDock, ui->printDock); @@ -488,14 +499,16 @@ ui->moveDock->setDisabled(true); ui->tempControlsDock->setDisabled(true); ui->printDock->setDisabled(true); + ui->sdDock->setDisabled(true); break; case AtCore::CONNECTING: stateString = QStringLiteral("Connecting"); ui->commandDock->setDisabled(false); ui->moveDock->setDisabled(false); ui->tempControlsDock->setDisabled(false); ui->printDock->setDisabled(false); + ui->sdDock->setDisabled(false); break; case AtCore::STOP: @@ -553,14 +566,16 @@ delete ui->moveDock->titleBarWidget(); delete ui->tempControlsDock->titleBarWidget(); delete ui->printDock->titleBarWidget(); + delete ui->sdDock->titleBarWidget(); } else { ui->connectDock->setTitleBarWidget(new QWidget()); ui->logDock->setTitleBarWidget(new QWidget()); ui->tempTimelineDock->setTitleBarWidget(new QWidget()); ui->commandDock->setTitleBarWidget(new QWidget()); ui->moveDock->setTitleBarWidget(new QWidget()); ui->tempControlsDock->setTitleBarWidget(new QWidget()); ui->printDock->setTitleBarWidget(new QWidget()); + ui->sdDock->setTitleBarWidget(new QWidget()); } } @@ -581,3 +596,33 @@ { core->setIdleHold(0); } + +void MainWindow::sdChanged(bool mounted) +{ + QString labelText = mounted ? QStringLiteral("SD") : QString(); + ui->lbl_sd->setText(labelText); +} + +void MainWindow::getSdList() +{ + core->sdFileList(); +} + +void MainWindow::sdPrintPBClicked() +{ + if (ui->sdFileListView->currentRow() < 0) { + QMessageBox::information(this, QStringLiteral("Print Error"), QStringLiteral("You must Select a file from the list")); + } else { + core->print(ui->sdFileListView->currentItem()->text(), true); + } +} + +void MainWindow::sdDelPBClicked() +{ + if (ui->sdFileListView->currentRow() < 0) { + QMessageBox::information(this, QStringLiteral("Delete Error"), QStringLiteral("You must Select a file from the list")); + } else { + core->sdDelete(ui->sdFileListView->currentItem()->text()); + ui->sdFileListView->setCurrentRow(-1); + } +} diff --git a/testclient/mainwindow.ui b/testclient/mainwindow.ui --- a/testclient/mainwindow.ui +++ b/testclient/mainwindow.ui @@ -56,6 +56,41 @@ + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + + @@ -380,6 +415,71 @@ + + + false + + + + 0 + 42 + 515 + 317 + + + + S&d Card + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Get List + + + + + + + Print Selected + + + + + + + Delete Selected + + + + + + + + + + Files On Sd Card. + + + + + + + + + + + diff --git a/unittests/gcodetests.h b/unittests/gcodetests.h --- a/unittests/gcodetests.h +++ b/unittests/gcodetests.h @@ -35,6 +35,17 @@ void command_unsupportedG(); bool testMCodeNeedsArg(GCode::MCommands code); + void command_M20(); + void command_M21(); + void command_M22(); + void command_M23(); + void command_M24(); + void command_M25(); + void command_M26(); + void command_M27(); + void command_M28(); + void command_M29(); + void command_M30(); void command_M84(); void command_M104(); void command_M105(); diff --git a/unittests/gcodetests.cpp b/unittests/gcodetests.cpp --- a/unittests/gcodetests.cpp +++ b/unittests/gcodetests.cpp @@ -68,6 +68,70 @@ return GCode::toCommand(code) == GCode::commandRequiresArgument.arg(QStringLiteral("M"), QString::number(code)); } +void GCodeTests::command_M20() +{ + QVERIFY(GCode::toCommand(GCode::M20) == QStringLiteral("M20")); +} + +void GCodeTests::command_M21() +{ + QVERIFY(GCode::toCommand(GCode::M21) == QStringLiteral("M21")); + QVERIFY(GCode::toCommand(GCode::M21, QStringLiteral("2")) == QStringLiteral("M21 P2")); +} + +void GCodeTests::command_M22() +{ + QVERIFY(GCode::toCommand(GCode::M22) == QStringLiteral("M22")); + QVERIFY(GCode::toCommand(GCode::M22, QStringLiteral("5")) == QStringLiteral("M22 P5")); +} + +void GCodeTests::command_M23() +{ + QVERIFY(testMCodeNeedsArg(GCode::M23)); + QVERIFY(GCode::toCommand(GCode::M23, QStringLiteral("FileName")) == QStringLiteral("M23 FileName")); +} + +void GCodeTests::command_M24() +{ + QVERIFY(GCode::toCommand(GCode::M24) == QStringLiteral("M24")); +} + +void GCodeTests::command_M25() +{ + QVERIFY(GCode::toCommand(GCode::M25) == QStringLiteral("M25")); +} + +void GCodeTests::command_M26() +{ + QVERIFY(testMCodeNeedsArg(GCode::M26)); + QVERIFY(GCode::toCommand(GCode::M26, QStringLiteral("15%")) == QStringLiteral("M26 P0.15")); + QVERIFY(GCode::toCommand(GCode::M26, QStringLiteral("15")) == QStringLiteral("M26 S15")); + +} + +void GCodeTests::command_M27() +{ + QVERIFY(GCode::toCommand(GCode::M27) == QStringLiteral("M27")); +} + +void GCodeTests::command_M28() +{ + QVERIFY(testMCodeNeedsArg(GCode::M28)); + QVERIFY(GCode::toCommand(GCode::M28, QStringLiteral("FileName")) == QStringLiteral("M28 FileName")); +} + +void GCodeTests::command_M29() +{ + QVERIFY(testMCodeNeedsArg(GCode::M29)); + QVERIFY(GCode::toCommand(GCode::M29, QStringLiteral("FileName")) == QStringLiteral("M29 FileName")); +} + +void GCodeTests::command_M30() +{ + QVERIFY(testMCodeNeedsArg(GCode::M30)); + QVERIFY(GCode::toCommand(GCode::M30, QStringLiteral("FileName")) == QStringLiteral("M30 FileName")); +} + void GCodeTests::command_M84() { QVERIFY(GCode::toCommand(GCode::M84) == QStringLiteral("M84"));