diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -13,6 +13,7 @@ ifirmware.cpp temperature.cpp printthread.cpp + machineinfo.cpp ) add_library(AtCore SHARED ${AtCoreLib_SRCS}) @@ -40,6 +41,7 @@ IFirmware SerialLayer Temperature + MachineInfo REQUIRED_HEADERS ATCORE_HEADERS ) diff --git a/src/core/machineinfo.h b/src/core/machineinfo.h new file mode 100644 --- /dev/null +++ b/src/core/machineinfo.h @@ -0,0 +1,87 @@ +/* AtCore + Copyright (C) <2019> + + Authors: + Chris Rizzitello + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#pragma once +#include "atcore_export.h" + +#include +#include + +class ATCORE_EXPORT MachineInfo : public QObject +{ + Q_OBJECT +public: + /** + * @brief KEYS enum Possible keys for the printer settings + */ + enum KEY { + NAME, //!< Profile Name + BAUDRATE, //!< Machine BAUD Rate + FIRMWARE, //! &profile) const; + Q_INVOKABLE void storeKey(const QString &profileName, const MachineInfo::KEY key, const QVariant &value) const; + Q_INVOKABLE bool removeProfile(const QString &profileName) const; + Q_INVOKABLE QStringList profileNames() const; + +signals: + /** + * @brief A profile has changed + * @param changedProfileName: name of changed profile. + */ + void profilesChanged() const; + +private: + explicit MachineInfo(QObject *parent = nullptr); + /** + * @brief Map of MachineInfo::KEY -> QString + */ + static const QMap nameMap; + + /** + * @brief m_settings our settings object. + */ + QSettings *m_settings = nullptr; + +}; diff --git a/src/core/machineinfo.cpp b/src/core/machineinfo.cpp new file mode 100644 --- /dev/null +++ b/src/core/machineinfo.cpp @@ -0,0 +1,132 @@ +/* AtCore + Copyright (C) <2019> + + Authors: + Chris Rizzitello + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include "machineinfo.h" + +#include +#include +#include +#include + +const QMap MachineInfo::nameMap = { + {NAME, QStringLiteral("Name")} + , {BAUDRATE, QStringLiteral("bps")} + , {FIRMWARE, QStringLiteral("firmware")} + , {MAXBEDTEMP, QStringLiteral("maximumTemperatureBed")} + , {MAXEXTTEMP, QStringLiteral("maximumTemperatureExtruder")} + , {POSTPAUSE, QStringLiteral("postPause")} + , {ISCARTESIAN, QStringLiteral("isCartesian")} + , {XMAX, QStringLiteral("dimensionX")} + , {YMAX, QStringLiteral("dimensionY")} + , {ZMAX, QStringLiteral("dimensionZ")} + , {AUTOTEMPREPORT, QStringLiteral("autoReportTemp")} +}; + +const MachineInfo &MachineInfo::getInstance() +{ + static MachineInfo m; + return m; +} + +MachineInfo::MachineInfo(QObject *parent) : QObject(parent) +{ + if (QFile(QString(QCoreApplication::applicationDirPath() + QDir::separator() + QStringLiteral("profiles.ini"))).exists()) { + m_settings = new QSettings(QCoreApplication::applicationDirPath() + QDir::separator() + QStringLiteral("profiles"), QSettings::IniFormat, this); + } else { + m_settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, QStringLiteral("atcore"), QStringLiteral("profiles"), this); + } +} + +QVariantMap MachineInfo::readProfile(const QString &profileName) const +{ + m_settings->beginGroup(profileName); + QVariantMap data{ + {nameMap[BAUDRATE], m_settings->value(nameMap[BAUDRATE], QStringLiteral("115200"))} + , {nameMap[MAXBEDTEMP], m_settings->value(nameMap[MAXBEDTEMP], QStringLiteral("0"))} + , {nameMap[MAXEXTTEMP], m_settings->value(nameMap[MAXEXTTEMP], QStringLiteral("0"))} + , {nameMap[FIRMWARE], m_settings->value(nameMap[FIRMWARE], QStringLiteral("Auto-Detect"))} + , {nameMap[POSTPAUSE], m_settings->value(nameMap[POSTPAUSE], QString())} + , {nameMap[NAME], m_settings->group()} + , {nameMap[ISCARTESIAN], m_settings->value(nameMap[ISCARTESIAN], true)} + , {nameMap[XMAX], m_settings->value(nameMap[XMAX], QStringLiteral("200"))} + , {nameMap[YMAX], m_settings->value(nameMap[YMAX], QStringLiteral("200"))} + , {nameMap[ZMAX], m_settings->value(nameMap[ZMAX], QStringLiteral("180"))} + , {nameMap[AUTOTEMPREPORT], m_settings->value(nameMap[AUTOTEMPREPORT], false)} + }; + m_settings->endGroup(); + return data; +} + +QVariant MachineInfo::readKey(const QString &profileName, MachineInfo::KEY key) const +{ + m_settings->beginGroup(profileName); + QVariant data = m_settings->value(nameMap[key]); + m_settings->endGroup(); + return data; +} + +void MachineInfo::storeKey(const QString &profileName, const MachineInfo::KEY key, const QVariant &value) const +{ + m_settings->beginGroup(profileName); + if (key != MachineInfo::NAME) { + m_settings->setValue(nameMap[key], value); + } + m_settings->endGroup(); + emit profilesChanged(); +} + +bool MachineInfo::removeProfile(const QString &profileName) const +{ + if (m_settings->childGroups().contains(profileName)) { + m_settings->beginGroup(profileName); + m_settings->remove(QString()); + m_settings->endGroup(); + emit profilesChanged(); + return true; + } + return false; +} + +void MachineInfo::storeProfile(const QMap &profile) const +{ + m_settings->beginGroup(profile[NAME].toString()); + m_settings->setValue(nameMap[FIRMWARE], profile[FIRMWARE]); + m_settings->setValue(nameMap[BAUDRATE], profile[BAUDRATE]); + m_settings->setValue(nameMap[MAXBEDTEMP], profile[MAXBEDTEMP]); + m_settings->setValue(nameMap[MAXEXTTEMP], profile[MAXEXTTEMP]); + m_settings->setValue(nameMap[POSTPAUSE], profile[POSTPAUSE]); + m_settings->setValue(nameMap[ISCARTESIAN], profile[ISCARTESIAN]); + m_settings->setValue(nameMap[XMAX], profile[XMAX]); + m_settings->setValue(nameMap[YMAX], profile[YMAX]); + m_settings->setValue(nameMap[ZMAX], profile[ZMAX]); + m_settings->setValue(nameMap[AUTOTEMPREPORT], profile[AUTOTEMPREPORT]); + m_settings->endGroup(); + emit profilesChanged(); +} + +QStringList MachineInfo::profileNames() const +{ + QStringList groups = m_settings->childGroups(); + return groups; +} + diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -10,6 +10,7 @@ sdwidget.cpp statuswidget.cpp temperaturewidget.cpp + profilemanager.cpp ) add_library(AtCoreWidgets ${widgetsLIB_SRCS}) @@ -50,6 +51,7 @@ SdWidget StatusWidget TemperatureWidget + ProfileManager REQUIRED_HEADERS ATCOREWIDGETS_HEADERS ) diff --git a/src/widgets/profilemanager.h b/src/widgets/profilemanager.h new file mode 100644 --- /dev/null +++ b/src/widgets/profilemanager.h @@ -0,0 +1,75 @@ +/* AtCore - Widgets + Copyright (C) <2019> + Author: 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 . +*/ +#pragma once + +#include +#include +#include +#include +#include +#include +#include "atcorewidgets_export.h" + +class ATCOREWIDGETS_EXPORT ProfileManager : public QWidget +{ + Q_OBJECT +public: + ProfileManager(QWidget *parent = nullptr); + +private: + QStringList detectFWPlugins() ; + QStringList firmwaresInPath(const QString &path); + void loadSelectedProfile(); + + QRadioButton *radioCartesian = nullptr; + QRadioButton *radioDelta = nullptr; + QLabel *lblX = nullptr; + QLabel *lblZ = nullptr; + QWidget *axisY = nullptr; + QSpinBox *sbMaxX = nullptr; + QSpinBox *sbMaxY = nullptr; + QSpinBox *sbMaxZ = nullptr; + + QCheckBox *checkAutoTempReport = nullptr; + QSpinBox *sbMaxBedTemp = nullptr; + QSpinBox *sbMaxExtTemp = nullptr; + + QComboBox *cbProfile = nullptr; + QComboBox *cbFirmware = nullptr; + QComboBox *cbBaud = nullptr; + QLineEdit *linePostPause = nullptr; +}; + +namespace SERIAL +{ +static const QStringList BAUDS = { + QStringList() << + QStringLiteral("9600") << + QStringLiteral("14400") << + QStringLiteral("19200") << + QStringLiteral("28800") << + QStringLiteral("38400") << + QStringLiteral("57600") << + QStringLiteral("76800") << + QStringLiteral("115200") << + QStringLiteral("230400") << + QStringLiteral("250000") << + QStringLiteral("500000") << + QStringLiteral("1000000") +}; +} diff --git a/src/widgets/profilemanager.cpp b/src/widgets/profilemanager.cpp new file mode 100644 --- /dev/null +++ b/src/widgets/profilemanager.cpp @@ -0,0 +1,333 @@ +/* AtCore - Widgets + Copyright (C) <2019> + Author: 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 "profilemanager.h" +#include "atcore_default_folders.h" +#include "machineinfo.h" + +#include +#include +#include +#include +#include +#include + +ProfileManager::ProfileManager(QWidget *parent) : + QWidget(parent) +{ + auto newLabel = new QLabel(tr("Profile:")); + cbProfile = new QComboBox(); + cbProfile->setEditable(true); + cbProfile->setAutoCompletion(true); + cbProfile->addItems(MachineInfo::getInstance().profileNames()); + connect(&MachineInfo::getInstance(), &MachineInfo::profilesChanged, this, [this] { + int index = cbProfile->currentIndex(); + cbProfile->clear(); + cbProfile->addItems(MachineInfo::getInstance().profileNames()); + cbProfile->setCurrentIndex(std::min(index, cbProfile->count() - 1)); + }); + + connect(cbProfile, QOverload::of(&QComboBox::currentIndexChanged), this, [this] { + if (MachineInfo::getInstance().profileNames().contains(cbProfile->currentText())) + { + loadSelectedProfile(); + } + }); + + connect(cbProfile->lineEdit(), &QLineEdit::editingFinished, this, [this] { + if (MachineInfo::getInstance().profileNames().contains(cbProfile->currentText())) + { + loadSelectedProfile(); + } else + { + QMap newProfile = { + {MachineInfo::NAME, cbProfile->currentText()} + , {MachineInfo::FIRMWARE, cbFirmware->currentText()} + , {MachineInfo::BAUDRATE, cbBaud->currentText()} + , {MachineInfo::POSTPAUSE, linePostPause->text()} + , {MachineInfo::ISCARTESIAN, radioCartesian->isChecked()} + , {MachineInfo::XMAX, sbMaxX->value()} + , {MachineInfo::YMAX, sbMaxY->value()} + , {MachineInfo::ZMAX, sbMaxZ->value()} + , {MachineInfo::AUTOTEMPREPORT, checkAutoTempReport->isChecked()} + , {MachineInfo::MAXBEDTEMP, sbMaxBedTemp->value()} + , {MachineInfo::MAXEXTTEMP, sbMaxExtTemp->value()} + }; + MachineInfo::getInstance().storeProfile(newProfile); + cbProfile->setCurrentIndex(cbProfile->count() - 1); + } + }); + + auto newHLayout = new QHBoxLayout(); + newHLayout->addWidget(newLabel); + newHLayout->addWidget(cbProfile, 75); + + auto newButton = new QToolButton(); + newButton->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"), style()->standardIcon(QStyle::SP_DialogDiscardButton))); + newButton->setToolTip(tr("Delete Current Profile")); + newButton->setIconSize(QSize(fontMetrics().height(), fontMetrics().height())); + connect(newButton, &QToolButton::clicked, this, [this] { + if (!cbProfile->currentText().isEmpty()) + { + MachineInfo::getInstance().removeProfile(cbProfile->currentText()); + } + }); + + auto mainLayout = new QVBoxLayout(); + newHLayout->addWidget(newButton); + mainLayout->addLayout(newHLayout); + auto boxLayout = new QVBoxLayout(); + + newLabel = new QLabel(tr("Printer Type:")); + radioDelta = new QRadioButton(tr("Delta")); + radioCartesian = new QRadioButton(tr("Cartesian")); + radioCartesian->setChecked(true); + connect(radioCartesian, &QRadioButton::toggled, this, [this](bool checked) { + axisY->setVisible(checked); + if (checked) { + lblX->setText(tr("Maximum X")); + lblZ->setText(tr("Maximum Z")); + } else { + lblX->setText(tr("Radius")); + lblZ->setText(tr("Height")); + } + if (MachineInfo::getInstance().profileNames().contains(cbProfile->currentText())) { + if (checked != MachineInfo::getInstance().readKey(cbProfile->currentText(), MachineInfo::ISCARTESIAN).toBool()) { + MachineInfo::getInstance().storeKey(cbProfile->currentText(), MachineInfo::ISCARTESIAN, checked); + } + } + }); + + newHLayout = new QHBoxLayout; + newHLayout->addWidget(newLabel); + newHLayout->addWidget(radioCartesian); + newHLayout->addWidget(radioDelta); + boxLayout->addLayout(newHLayout); + + lblX = new QLabel(tr("Maximum X")); + sbMaxX = new QSpinBox(); + sbMaxX->setMaximum(999999999); + sbMaxX->setSuffix(QStringLiteral("mm")); + connect(sbMaxX, QOverload::of(&QSpinBox::valueChanged), this, [this](int value) { + if (value != MachineInfo::getInstance().readKey(cbProfile->currentText(), MachineInfo::XMAX).toInt()) { + MachineInfo::getInstance().storeKey(cbProfile->currentText(), MachineInfo::XMAX, value); + } + }); + newHLayout = new QHBoxLayout; + newHLayout->addWidget(lblX); + newHLayout->addWidget(sbMaxX); + boxLayout->addLayout(newHLayout); + + newLabel = new QLabel(tr("Maximum Y")); + sbMaxY = new QSpinBox(); + sbMaxY->setMaximum(999999999); + sbMaxY->setSuffix(QStringLiteral("mm")); + connect(sbMaxY, QOverload::of(&QSpinBox::valueChanged), this, [this](int value) { + if (value != MachineInfo::getInstance().readKey(cbProfile->currentText(), MachineInfo::YMAX).toInt()) { + MachineInfo::getInstance().storeKey(cbProfile->currentText(), MachineInfo::YMAX, value); + } + }); + newHLayout = new QHBoxLayout; + newHLayout->setContentsMargins(0, 0, 0, 0); + newHLayout->addWidget(newLabel); + newHLayout->addWidget(sbMaxY); + axisY = new QWidget(this); + axisY->setLayout(newHLayout); + boxLayout->addWidget(axisY); + + lblZ = new QLabel(tr("Maximum Z")); + sbMaxZ = new QSpinBox(); + sbMaxZ->setMaximum(999999999); + sbMaxZ->setSuffix(QStringLiteral("mm")); + connect(sbMaxZ, QOverload::of(&QSpinBox::valueChanged), this, [this](int value) { + if (value != MachineInfo::getInstance().readKey(cbProfile->currentText(), MachineInfo::ZMAX).toInt()) { + MachineInfo::getInstance().storeKey(cbProfile->currentText(), MachineInfo::ZMAX, value); + } + }); + newHLayout = new QHBoxLayout; + newHLayout->addWidget(lblZ); + newHLayout->addWidget(sbMaxZ); + boxLayout->addLayout(newHLayout); + + auto groupBox = new QGroupBox(tr("Mechanics")); + groupBox->setLayout(boxLayout); + mainLayout->addWidget(groupBox); + + boxLayout = new QVBoxLayout; + newLabel = new QLabel(tr("Bed Maximum")); + sbMaxBedTemp = new QSpinBox(); + sbMaxBedTemp->setMaximum(999); + sbMaxBedTemp->setSuffix(QStringLiteral(" ºC")); + connect(sbMaxBedTemp, QOverload::of(&QSpinBox::valueChanged), this, [this](int value) { + if (value != MachineInfo::getInstance().readKey(cbProfile->currentText(), MachineInfo::MAXBEDTEMP).toInt()) { + MachineInfo::getInstance().storeKey(cbProfile->currentText(), MachineInfo::MAXBEDTEMP, value); + } + }); + newHLayout = new QHBoxLayout; + newHLayout->addWidget(newLabel); + newHLayout->addWidget(sbMaxBedTemp); + boxLayout->addLayout(newHLayout); + + sbMaxExtTemp = new QSpinBox(); + sbMaxExtTemp->setMaximum(999); + newLabel = new QLabel(tr("Extruder Maximum")); + sbMaxExtTemp->setSuffix(QStringLiteral(" ºC")); + connect(sbMaxExtTemp, QOverload::of(&QSpinBox::valueChanged), this, [this](int value) { + if (value != MachineInfo::getInstance().readKey(cbProfile->currentText(), MachineInfo::MAXEXTTEMP).toInt()) { + MachineInfo::getInstance().storeKey(cbProfile->currentText(), MachineInfo::MAXEXTTEMP, value); + } + }); + newHLayout = new QHBoxLayout(); + newHLayout->addWidget(newLabel); + newHLayout->addWidget(sbMaxExtTemp); + boxLayout->addLayout(newHLayout); + + checkAutoTempReport = new QCheckBox(tr("Auto Temperature Report")); + checkAutoTempReport->setLayoutDirection(Qt::RightToLeft); + connect(checkAutoTempReport, &QCheckBox::toggled, this, [this](bool checked) { + if (checked != MachineInfo::getInstance().readKey(cbProfile->currentText(), MachineInfo::AUTOTEMPREPORT).toBool()) { + MachineInfo::getInstance().storeKey(cbProfile->currentText(), MachineInfo::AUTOTEMPREPORT, checked); + } + }); + boxLayout->addWidget(checkAutoTempReport, 0, Qt::AlignRight); + + groupBox = new QGroupBox(tr("Temperature")); + groupBox->setLayout(boxLayout); + mainLayout->addWidget(groupBox); + + boxLayout = new QVBoxLayout(); + cbBaud = new QComboBox(); + cbBaud->addItems(SERIAL::BAUDS); + cbBaud->setCurrentText(QStringLiteral("115200")); + connect(cbBaud, &QComboBox::currentTextChanged, this, [this](const QString & newText) { + if (newText != MachineInfo::getInstance().readKey(cbProfile->currentText(), MachineInfo::BAUDRATE).toString()) { + MachineInfo::getInstance().storeKey(cbProfile->currentText(), MachineInfo::BAUDRATE, newText); + } + }); + + newLabel = new QLabel(tr("Bit Rate")); + newHLayout = new QHBoxLayout(); + newHLayout->addWidget(newLabel); + newHLayout->addWidget(cbBaud); + boxLayout->addLayout(newHLayout); + + newLabel = new QLabel(tr("Firmware")); + cbFirmware = new QComboBox(); + cbFirmware->addItem(QStringLiteral("Auto-Detect")); + cbFirmware->addItems(detectFWPlugins()); + connect(cbFirmware, &QComboBox::currentTextChanged, this, [this](const QString & newText) { + if (newText != MachineInfo::getInstance().readKey(cbProfile->currentText(), MachineInfo::FIRMWARE).toString()) { + MachineInfo::getInstance().storeKey(cbProfile->currentText(), MachineInfo::FIRMWARE, newText); + } + }); + + newHLayout = new QHBoxLayout(); + newHLayout->addWidget(newLabel); + newHLayout->addWidget(cbFirmware); + boxLayout->addLayout(newHLayout); + + linePostPause = new QLineEdit(); + connect(linePostPause, &QLineEdit::editingFinished, this, [this] { + if (linePostPause->text() != MachineInfo::getInstance().readKey(cbProfile->currentText(), MachineInfo::POSTPAUSE).toString()) + { + MachineInfo::getInstance().storeKey(cbProfile->currentText(), MachineInfo::POSTPAUSE, linePostPause->text()); + } + }); + newLabel = new QLabel(tr("PostPause")); + newHLayout = new QHBoxLayout(); + newHLayout->addWidget(newLabel); + newHLayout->addWidget(linePostPause); + boxLayout->addLayout(newHLayout); + + groupBox = new QGroupBox(tr("Advanced")); + groupBox->setLayout(boxLayout); + mainLayout->addWidget(groupBox); + setLayout(mainLayout); + loadSelectedProfile(); +} + +void ProfileManager::loadSelectedProfile() +{ + if (!cbProfile->currentText().isEmpty()) { + blockSignals(true); + QString profile = cbProfile->currentText(); + + if (MachineInfo::getInstance().readKey(profile, MachineInfo::ISCARTESIAN).toBool()) { + radioCartesian->setChecked(true); + radioDelta->setChecked(false); + } else { + radioCartesian->setChecked(false); + radioDelta->setChecked(true); + } + sbMaxX->setValue(MachineInfo::getInstance().readKey(profile, MachineInfo::XMAX).toInt()); + sbMaxY->setValue(MachineInfo::getInstance().readKey(profile, MachineInfo::YMAX).toInt()); + sbMaxZ->setValue(MachineInfo::getInstance().readKey(profile, MachineInfo::ZMAX).toInt()); + checkAutoTempReport->setChecked(MachineInfo::getInstance().readKey(profile, MachineInfo::AUTOTEMPREPORT).toBool()); + sbMaxBedTemp->setValue(MachineInfo::getInstance().readKey(profile, MachineInfo::MAXBEDTEMP).toInt()); + sbMaxExtTemp->setValue(MachineInfo::getInstance().readKey(profile, MachineInfo::MAXEXTTEMP).toInt()); + cbFirmware->setCurrentText(MachineInfo::getInstance().readKey(profile, MachineInfo::FIRMWARE).toString()); + cbBaud->setCurrentText(MachineInfo::getInstance().readKey(profile, MachineInfo::BAUDRATE).toString()); + linePostPause->setText(MachineInfo::getInstance().readKey(profile, MachineInfo::POSTPAUSE).toString()); + blockSignals(false); + } +} + +QStringList ProfileManager::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 ProfileManager::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; +}