diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ project(atelier) find_package(ECM REQUIRED NO_MODULE) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) include(KDECompilerSettings) include(KDEInstallDirs) include(KDECMakeSettings) @@ -27,6 +27,8 @@ AtCore ) +find_package(Qwt6 REQUIRED) + find_package(KF5 ${KF5_DEP_VERSION} REQUIRED COMPONENTS I18n XmlGui @@ -48,7 +50,7 @@ Multimedia MultimediaWidgets ) - + if(BUILD_TESTING) find_package(Qt5Test ${QT_MIN_VERSION} CONFIG REQUIRED) endif() diff --git a/cmake/FindQwt6.cmake b/cmake/FindQwt6.cmake new file mode 100644 --- /dev/null +++ b/cmake/FindQwt6.cmake @@ -0,0 +1,112 @@ +# Qt Widgets for Technical Applications +# available at http://www.http://qwt.sourceforge.net/ +# +# The module defines the following variables: +# QWT_FOUND - the system has Qwt +# QWT_INCLUDE_DIR - where to find qwt_plot.h +# QWT_INCLUDE_DIRS - qwt includes +# QWT_LIBRARY - where to find the Qwt library +# QWT_LIBRARIES - aditional libraries +# QWT_MAJOR_VERSION - major version +# QWT_MINOR_VERSION - minor version +# QWT_PATCH_VERSION - patch version +# QWT_VERSION_STRING - version (ex. 5.2.1) +# QWT_ROOT_DIR - root dir (ex. /usr/local) + +#============================================================================= +# Copyright 2010-2013, Julien Schueller +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# The views and conclusions contained in the software and documentation are those +# of the authors and should not be interpreted as representing official policies, +# either expressed or implied, of the FreeBSD Project. +#============================================================================= + + +find_path ( QWT_INCLUDE_DIR + NAMES qwt_plot.h + HINTS ${QT_INCLUDE_DIR} + PATH_SUFFIXES qwt qwt-qt3 qwt-qt4 qwt-qt5 + ) + +set ( QWT_INCLUDE_DIRS ${QWT_INCLUDE_DIR} ) + +# version +set ( _VERSION_FILE ${QWT_INCLUDE_DIR}/qwt_global.h ) +if ( EXISTS ${_VERSION_FILE} ) + file ( STRINGS ${_VERSION_FILE} _VERSION_LINE REGEX "define[ ]+QWT_VERSION_STR" ) + if ( _VERSION_LINE ) + string ( REGEX REPLACE ".*define[ ]+QWT_VERSION_STR[ ]+\"(.*)\".*" "\\1" QWT_VERSION_STRING "${_VERSION_LINE}" ) + string ( REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\1" QWT_MAJOR_VERSION "${QWT_VERSION_STRING}" ) + string ( REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\2" QWT_MINOR_VERSION "${QWT_VERSION_STRING}" ) + string ( REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\3" QWT_PATCH_VERSION "${QWT_VERSION_STRING}" ) + endif () +endif () + + +# check version +set ( _QWT_VERSION_MATCH TRUE ) +if ( Qwt_FIND_VERSION AND QWT_VERSION_STRING ) + if ( Qwt_FIND_VERSION_EXACT ) + if ( NOT Qwt_FIND_VERSION VERSION_EQUAL QWT_VERSION_STRING ) + set ( _QWT_VERSION_MATCH FALSE ) + endif () + else () + if ( QWT_VERSION_STRING VERSION_LESS Qwt_FIND_VERSION ) + set ( _QWT_VERSION_MATCH FALSE ) + endif () + endif () +endif () + + +find_library ( QWT_LIBRARY + NAMES qwt qwt-qt3 qwt-qt4 qwt-qt5 + ) + +set ( QWT_LIBRARIES ${QWT_LIBRARY} ) + + +# try to guess root dir from include dir +if ( QWT_INCLUDE_DIR ) + string ( REGEX REPLACE "(.*)/include.*" "\\1" QWT_ROOT_DIR ${QWT_INCLUDE_DIR} ) + # try to guess root dir from library dir +elseif ( QWT_LIBRARY ) + string ( REGEX REPLACE "(.*)/lib[/|32|64].*" "\\1" QWT_ROOT_DIR ${QWT_LIBRARY} ) +endif () + + +# handle the QUIETLY and REQUIRED arguments +include ( FindPackageHandleStandardArgs ) +find_package_handle_standard_args( Qwt6 DEFAULT_MSG QWT_LIBRARY QWT_INCLUDE_DIR _QWT_VERSION_MATCH ) + +mark_as_advanced ( + QWT_LIBRARY + QWT_LIBRARIES + QWT_INCLUDE_DIR + QWT_INCLUDE_DIRS + QWT_MAJOR_VERSION + QWT_MINOR_VERSION + QWT_PATCH_VERSION + QWT_VERSION_STRING + QWT_ROOT_DIR + ) diff --git a/src/atelierui.rc b/src/atelierui.rc --- a/src/atelierui.rc +++ b/src/atelierui.rc @@ -8,27 +8,24 @@ + - - Run - - - + diff --git a/src/dialogs/CMakeLists.txt b/src/dialogs/CMakeLists.txt --- a/src/dialogs/CMakeLists.txt +++ b/src/dialogs/CMakeLists.txt @@ -1,6 +1,5 @@ set(dialogs_SRCS profilesdialog.cpp - connectsettingsdialog.cpp choosefiledialog.cpp ) add_library(AtelierDialogs STATIC ${dialogs_SRCS}) diff --git a/src/dialogs/choosefiledialog.cpp b/src/dialogs/choosefiledialog.cpp --- a/src/dialogs/choosefiledialog.cpp +++ b/src/dialogs/choosefiledialog.cpp @@ -33,7 +33,7 @@ files_list.append(file.toLocalFile()); } listWigdet->addItems(files_list); - connect(listWigdet, &QListWidget::currentTextChanged, [ & ](const QString& t){ + connect(listWigdet, &QListWidget::currentTextChanged, [ this ](const QString& t){ m_choosen_file = t; }); auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); diff --git a/src/dialogs/connectsettingsdialog.h b/src/dialogs/connectsettingsdialog.h deleted file mode 100644 --- a/src/dialogs/connectsettingsdialog.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Atelier KDE Printer Host for 3D Printing - Copyright (C) <2016> - Author: Lays Rodrigues - laysrodrigues@gmail.com - Chris Rizzitello - rizzitello@kde.org - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#pragma once - -#include -#include -#include -#include -#include - -class ConnectSettingsDialog : public QDialog -{ - Q_OBJECT - -public: - explicit ConnectSettingsDialog(QWidget *parent = nullptr); - -private: - void initDisplay(); - void initData(); - void updateSerialPort(const QStringList &ports); - AtCore *atcore; - QSettings settings; - QMap profileData(); - void accept(); - QComboBox *serialPortCB; - QComboBox *deviceProfileCB; - QDialogButtonBox *buttonBox; -signals: - void startConnection(const QString port, const QMap data); -}; diff --git a/src/dialogs/connectsettingsdialog.cpp b/src/dialogs/connectsettingsdialog.cpp deleted file mode 100644 --- a/src/dialogs/connectsettingsdialog.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* Atelier KDE Printer Host for 3D Printing - Copyright (C) <2016> - Author: Lays Rodrigues - laysrodrigues@gmail.com - Chris Rizzitello - rizzitello@kde.org - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "connectsettingsdialog.h" -#include -#include -#include -#include -#include - -ConnectSettingsDialog::ConnectSettingsDialog(QWidget *parent) : - QDialog(parent), - atcore(new AtCore) -{ - initDisplay(); - initData(); - setWindowTitle(i18n("Connect to Printer")); - atcore->setSerialTimerInterval(100); - connect(atcore, &AtCore::portsChanged, this, &ConnectSettingsDialog::updateSerialPort); - connect(buttonBox, &QDialogButtonBox::accepted, this, &ConnectSettingsDialog::accept); - connect(buttonBox, &QDialogButtonBox::rejected, this, &ConnectSettingsDialog::close); -} - -void ConnectSettingsDialog::initDisplay() -{ - serialPortCB = new QComboBox; - serialPortCB->setEditable(true); - QLabel *deviceLabel = new QLabel(i18n("Device")); - QHBoxLayout *deviceLayout = new QHBoxLayout; - deviceLayout->addWidget(deviceLabel); - deviceLayout->addWidget(serialPortCB); - - deviceProfileCB = new QComboBox; - QHBoxLayout *profileLayout = new QHBoxLayout; - QLabel *profileLabel = new QLabel(i18n("Profile")); - profileLayout->addWidget(profileLabel); - profileLayout->addWidget(deviceProfileCB); - - buttonBox = new QDialogButtonBox(); - buttonBox->addButton(i18n("Connect"),QDialogButtonBox::AcceptRole); - buttonBox->addButton(QDialogButtonBox::Cancel); - - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addLayout(deviceLayout); - mainLayout->addLayout(profileLayout); - mainLayout->addWidget(buttonBox); - - setLayout(mainLayout); -} - -void ConnectSettingsDialog::initData() -{ - settings.beginGroup("GeneralSettings"); - QStringList profiles = settings.childGroups(); - settings.endGroup(); - deviceProfileCB->addItems(profiles); -} - -void ConnectSettingsDialog::updateSerialPort(const QStringList &ports) -{ - serialPortCB->clear(); - if(!ports.isEmpty()) { - serialPortCB->addItems(ports); - } -} - -QMap ConnectSettingsDialog::profileData() -{ - QString profile = deviceProfileCB->currentText(); - settings.beginGroup("GeneralSettings"); - settings.beginGroup(profile); - QMap data; - data["bps"] = settings.value(QStringLiteral("bps"), QStringLiteral("115200")); - data["bedTemp"] = settings.value(QStringLiteral("maximumTemperatureBed"), QStringLiteral("0")); - data["hotendTemp"] = settings.value(QStringLiteral("maximumTemperatureExtruder"), QStringLiteral("0")); - data["firmware"] = settings.value(QStringLiteral("firmware"),QStringLiteral("Auto-Detect")); - data["postPause"] = settings.value(QStringLiteral("postPause"),QStringLiteral("")); - data["name"] = profile; - settings.endGroup(); - settings.endGroup(); - return data; -} - -void ConnectSettingsDialog::accept() -{ - if (deviceProfileCB->currentText().isEmpty()) { - QMessageBox::critical(this, i18n("Error"), i18n("Please, create a profile to connect on Settings!")); - return; - } - if (serialPortCB->currentText().isEmpty()) { - QMessageBox::critical(this, i18n("Error"), i18n("Please, connect a serial device to continue!")); - return; - } - emit startConnection(serialPortCB->currentText(), profileData()); - close(); -} diff --git a/src/dialogs/profilesdialog.cpp b/src/dialogs/profilesdialog.cpp --- a/src/dialogs/profilesdialog.cpp +++ b/src/dialogs/profilesdialog.cpp @@ -39,12 +39,12 @@ ui->baudCB->addItems(SERIAL::BAUDS); ui->baudCB->setCurrentText(QLatin1String("115200")); ui->profileCB->setAutoCompletion(true); - connect(ui->profileCB, static_cast(&QComboBox::currentIndexChanged), [ = ] { + connect(ui->profileCB, static_cast(&QComboBox::currentIndexChanged), [ this ] { loadSettings(); }); updateCBProfiles(); - connect(ui->buttonBox, &QDialogButtonBox::clicked, [ = ](QAbstractButton * btn) { + connect(ui->buttonBox, &QDialogButtonBox::clicked, [ this ](QAbstractButton * btn) { switch (ui->buttonBox->buttonRole(btn)) { case QDialogButtonBox::ResetRole: loadSettings(); @@ -57,16 +57,16 @@ } }); - connect(ui->heatedBedCK, &QCheckBox::clicked, [ = ](const bool & status) { + connect(ui->heatedBedCK, &QCheckBox::clicked, [ this ](const bool & status) { ui->bedTempSB->setEnabled(status); }); - connect(ui->cartesianRB, &QRadioButton::clicked, [ = ]() { + connect(ui->cartesianRB, &QRadioButton::clicked, [ this ]() { ui->cartesianGB->setHidden(false); ui->deltaGB->setHidden(true); }); - connect(ui->deltaRB, &QRadioButton::clicked, [ = ]() { + connect(ui->deltaRB, &QRadioButton::clicked, [ this ]() { ui->cartesianGB->setHidden(true); ui->deltaGB->setHidden(false); }); diff --git a/src/mainwindow.h b/src/mainwindow.h --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -60,11 +60,13 @@ QTabWidget *m_instances; void setupLateralArea(); + void newAtCoreInstance(); void initWidgets(); void setupActions(); void openFile(); - void newConnection(const QString& port, const QMap& profile); + void atCoreInstanceNameChange(const QString &name); signals: void extruderCountChanged(int count); + void profilesChanged(); }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -18,7 +18,6 @@ */ #include "mainwindow.h" #include "ui_mainwindow.h" -#include #include #include #include @@ -44,6 +43,16 @@ ui->setupUi(this); initWidgets(); setupActions(); + connect(m_instances, &QTabWidget::tabCloseRequested, [this] (int index){ + QWidget *tempWidget= m_instances->widget(index); + delete tempWidget; + + if(m_instances->count() == 1) { + m_instances->setTabsClosable(false); + m_instances->setMovable(false); + } + }); + } MainWindow::~MainWindow() @@ -53,10 +62,9 @@ void MainWindow::initWidgets() { - auto newInstanceWidget = new AtCoreInstanceWidget(); - m_instances->addTab(newInstanceWidget, i18n("Connect your printer")); setupLateralArea(); + newAtCoreInstance(); // View: // Sidebar, Sidevar Controls, Printer Tabs. @@ -69,13 +77,25 @@ centralLayout->addWidget(splitter); ui->centralwidget->setLayout(centralLayout); } - +void MainWindow::newAtCoreInstance() +{ + auto newInstanceWidget = new AtCoreInstanceWidget(); + QString name = QString::number(m_instances->addTab(newInstanceWidget, i18n("Connect a printer"))); + newInstanceWidget->setObjectName(name); + connect(this, &MainWindow::profilesChanged, newInstanceWidget, &AtCoreInstanceWidget::updateProfileData); + connect(newInstanceWidget, &AtCoreInstanceWidget::connectionChanged, this, &MainWindow::atCoreInstanceNameChange); + + if(m_instances->count() > 1) { + m_instances->setTabsClosable(true); + m_instances->setMovable(true); + } +} // Move to LateralArea. void MainWindow::setupLateralArea() { m_lateral.m_toolBar = new QWidget(); m_lateral.m_stack = new QStackedWidget(); - auto *buttonLayout = new QVBoxLayout(); + auto buttonLayout = new QVBoxLayout(); auto setupButton = [this, buttonLayout](const QString& key, const QString& text, const QIcon& icon, QWidget *w) { auto *btn = new QPushButton(m_lateral.m_toolBar); @@ -96,7 +116,7 @@ }; auto *gcodeEditor = new GCodeEditorWidget(this); - connect(gcodeEditor, &GCodeEditorWidget::updateClientFactory, this, [&](KTextEditor::View* view){ + connect(gcodeEditor, &GCodeEditorWidget::updateClientFactory, this, [this](KTextEditor::View* view){ guiFactory()->removeClient(m_currEditorView); guiFactory()->addClient(view); m_currEditorView = view; @@ -117,21 +137,16 @@ action->setText(i18n("&Open GCode")); connect(action, &QAction::triggered, this, &MainWindow::openFile); - action = actionCollection()->addAction(QStringLiteral("connect")); - action->setText(i18n("&Connect")); - connect(action, &QAction::triggered, [ & ]{ - std::unique_ptr csd(new ConnectSettingsDialog); - connect(csd.get(), &ConnectSettingsDialog::startConnection, [ & ](const QString& port, const QMap& data) { - newConnection(port, data); - }); - csd->exec(); - }); + action = actionCollection()->addAction(QStringLiteral("new_instance")); + action->setText(i18n("&New Connection")); + connect(action, &QAction::triggered, this, &MainWindow::newAtCoreInstance); action = actionCollection()->addAction(QStringLiteral("profiles")); action->setText(i18n("&Profiles")); - connect(action, &QAction::triggered, [ & ] { + connect(action, &QAction::triggered, [this] { std::unique_ptr pd(new ProfilesDialog); pd->exec(); + emit(profilesChanged()); }); #ifdef Q_OS_LINUX @@ -165,18 +180,8 @@ } } } -void MainWindow::newConnection(const QString& port, const QMap& profile) + +void MainWindow::atCoreInstanceNameChange(const QString &name) { - const int tabs = m_instances->count(); - if(tabs == 1){ - auto instance = qobject_cast(m_instances->currentWidget()); - if(!instance->connected()){ - instance->startConnection(port, profile); - m_instances->setTabText(m_instances->currentIndex(), profile["name"].toString()); - return; - } - } - auto newInstanceWidget = new AtCoreInstanceWidget(); - m_instances->addTab(newInstanceWidget, profile["name"].toString()); - newInstanceWidget->startConnection(port, profile); + m_instances->setTabText(sender()->objectName().toInt(),name); } diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -1,4 +1,5 @@ include_directories(../dialogs) +include_directories(${QWT_INCLUDE_DIR}) set(widgets_SRCS gcodeeditorwidget.cpp @@ -11,20 +12,23 @@ logwidget.cpp videomonitorwidget.cpp atcoreinstancewidget.cpp + thermowidget.cpp ) add_library(AtelierWidgets STATIC ${widgets_SRCS}) -target_link_libraries(AtelierWidgets - Qt5::Core - Qt5::Widgets +target_link_libraries(AtelierWidgets + Qt5::Core + Qt5::Widgets Qt5::SerialPort - KF5::Solid - KF5::I18n - KF5::TextEditor + KF5::Solid + KF5::I18n + KF5::TextEditor Qt5::Charts Qt5::Multimedia Qt5::MultimediaWidgets - AtCore::AtCore) + AtCore::AtCore + ${QWT_LIBRARY} + ) add_subdirectory(3dview) diff --git a/src/widgets/atcoreinstancewidget.h b/src/widgets/atcoreinstancewidget.h --- a/src/widgets/atcoreinstancewidget.h +++ b/src/widgets/atcoreinstancewidget.h @@ -17,12 +17,14 @@ */ #pragma once -#include -#include -#include #include +#include #include - +#include +#include +#include +#include +#include namespace Ui { class AtCoreInstanceWidget; @@ -49,14 +51,23 @@ bool connected(); void setOpenFiles(const QList& files); +public slots: + void updateProfileData(); + private: Ui::AtCoreInstanceWidget* ui; AtCore m_core; QToolBar *m_mainToolBar; + QComboBox *m_comboPort; + QComboBox *m_comboProfile; + QPushButton *m_connectButton; + QToolBar *m_connectToolBar; + QWidget *m_connectWidget; QToolBar *m_toolBar; QMap profileData; QList m_files; QAction *m_printAction; + QSettings m_settings; void initConnectsToAtCore(); void printFile(const QUrl& fileName); void pausePrint(); @@ -71,7 +82,11 @@ void buildToolbar(); void buildMainToolbar(); void print(); + void updateSerialPort(const QStringList &ports); + void buildConnectionToolbar(); + void connectButtonClicked(); signals: void extruderCountChanged(int count); void disableDisconnect(bool b); + void connectionChanged(QString name); }; diff --git a/src/widgets/atcoreinstancewidget.cpp b/src/widgets/atcoreinstancewidget.cpp --- a/src/widgets/atcoreinstancewidget.cpp +++ b/src/widgets/atcoreinstancewidget.cpp @@ -36,12 +36,16 @@ ui->printProgressWidget->setVisible(false); buildMainToolbar(); buildToolbar(); + buildConnectionToolbar(); enableControls(false); + updateProfileData(); initConnectsToAtCore(); + m_mainToolBar->setHidden(true); } AtCoreInstanceWidget::~AtCoreInstanceWidget() { + m_core.closeConnection(); delete ui; } @@ -55,14 +59,14 @@ m_toolBar->addAction(lb); auto homeAll = new QAction("All"); - connect(homeAll, &QAction::triggered, [&]{ + connect(homeAll, &QAction::triggered, [this]{ m_core.home(); }); m_toolBar->addAction(homeAll); for(auto homes : std::map{{"X", AtCore::X}, {"Y", AtCore::Y}, {"Z", AtCore::Z}}) { auto home = new QAction(homes.first); - connect(home, &QAction::triggered, [&, homes] { + connect(home, &QAction::triggered, [this, homes] { m_core.home(homes.second); }); m_toolBar->addAction(home); @@ -96,15 +100,8 @@ m_mainToolBar = new QToolBar(); m_mainToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - auto disconnectAction = new QAction(style()->standardIcon(QStyle::SP_DialogCloseButton), i18n("Disconnect")); - connect(this, &AtCoreInstanceWidget::disableDisconnect, disconnectAction, &QAction::setDisabled); - connect(disconnectAction, &QAction::triggered, [&](){ - m_core.closeConnection(); - }); - m_mainToolBar->addAction(disconnectAction); - m_printAction = new QAction(style()->standardIcon(QStyle::SP_MediaPlay),i18n("Print")); - connect(m_printAction, &QAction::triggered, [ & ](){ + connect(m_printAction, &QAction::triggered, [ this ](){ if(m_core.state() == AtCore::BUSY) { pausePrint(); return; @@ -119,7 +116,7 @@ auto stopAction = new QAction(style()->standardIcon(QStyle::SP_MediaStop),i18n("Stop")); connect(stopAction, &QAction::triggered, this, &AtCoreInstanceWidget::stopPrint); - connect(stopAction, &QAction::triggered, [&](){ + connect(stopAction, &QAction::triggered, [this](){ m_printAction->setText(i18n("Print")); m_printAction->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); }); @@ -130,20 +127,91 @@ m_mainToolBar->addAction(disableMotorsAction); ui->mainToolBarLayout->addWidget(m_mainToolBar); - ui->mainToolBarLayout->addStretch(); } -void AtCoreInstanceWidget::startConnection(const QString& serialPort, const QMap& profiles){ - m_core.initSerial(serialPort, profiles["bps"].toInt()); - if(m_core.state() == AtCore::CONNECTING){ - QString fw = profiles["firmware"].toString(); - if( fw != QString("Auto-Detect")){ - m_core.loadFirmwarePlugin(fw); + +void AtCoreInstanceWidget::buildConnectionToolbar() +{ + m_connectToolBar = new QToolBar(); + m_comboPort = new QComboBox; + m_comboPort->setEditable(true); + QLabel *deviceLabel = new QLabel(i18n("Device")); + QHBoxLayout *deviceLayout = new QHBoxLayout; + deviceLayout->addWidget(deviceLabel); + deviceLayout->addWidget(m_comboPort,100); + + m_comboProfile = new QComboBox; + m_comboProfile->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed); + QHBoxLayout *profileLayout = new QHBoxLayout; + QLabel *profileLabel = new QLabel(i18n("Profile")); + profileLayout->addWidget(profileLabel); + profileLayout->addWidget(m_comboProfile,100); + + QHBoxLayout *connectLayout = new QHBoxLayout; + connectLayout->addLayout(deviceLayout,50); + connectLayout->addLayout(profileLayout,50); + + m_connectWidget = new QWidget(); + m_connectWidget->setLayout(connectLayout); + m_connectToolBar->addWidget(m_connectWidget); + + m_connectButton = new QPushButton(i18n("Connect")); + m_connectButton->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + connect(this, &AtCoreInstanceWidget::disableDisconnect, m_connectButton, &QPushButton::setDisabled); + connect(m_connectButton, &QPushButton::clicked, this, &AtCoreInstanceWidget::connectButtonClicked); + ui->mainToolBarLayout->addWidget(m_connectToolBar); + ui->mainToolBarLayout->addWidget(m_connectButton); + +} + +void AtCoreInstanceWidget::connectButtonClicked() +{ + if(m_core.state() == AtCore::DISCONNECTED) { + if (m_comboProfile->currentText().isEmpty()) { + QMessageBox::critical(this, i18n("Error"), i18n("Please, create a profile to connect on Settings!")); + 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. + QString profile = m_comboProfile->currentText(); + m_settings.beginGroup("GeneralSettings"); + m_settings.beginGroup(profile); + QMap data; + data["bps"] = m_settings.value(QStringLiteral("bps"), QStringLiteral("115200")); + data["bedTemp"] = m_settings.value(QStringLiteral("maximumTemperatureBed"), QStringLiteral("0")); + data["hotendTemp"] = m_settings.value(QStringLiteral("maximumTemperatureExtruder"), QStringLiteral("0")); + data["firmware"] = m_settings.value(QStringLiteral("firmware"),QStringLiteral("Auto-Detect")); + data["postPause"] = m_settings.value(QStringLiteral("postPause"),QStringLiteral("")); + data["name"] = profile; + m_settings.endGroup(); + m_settings.endGroup(); + + //then connect + m_core.initSerial(m_comboPort->currentText(), data["bps"].toInt()); + if(m_core.state() == AtCore::CONNECTING){ + profileData = data; + QString fw = profileData["firmware"].toString(); + if( fw != QString("Auto-Detect")){ + m_core.loadFirmwarePlugin(fw); + } + emit(connectionChanged(profileData["name"].toString())); } + } else { + m_core.closeConnection(); + emit(connectionChanged(i18n("Connect a Printer"))); } } void AtCoreInstanceWidget::initConnectsToAtCore() { + m_core.setSerialTimerInterval(100); + // Handle device changes + connect(&m_core, &AtCore::portsChanged, this, &AtCoreInstanceWidget::updateSerialPort); + // Handle AtCore status change connect(&m_core, &AtCore::stateChanged, this, &AtCoreInstanceWidget::handlePrinterStatusChanged); @@ -155,32 +223,32 @@ connect(ui->bedExtWidget, &BedExtruderWidget::extTemperatureChanged, &m_core, &AtCore::setExtruderTemp); // Connect AtCore temperatures changes on Atelier Plot - connect(&m_core.temperature(), &Temperature::bedTemperatureChanged, [ & ](const float& temp) { + connect(&m_core.temperature(), &Temperature::bedTemperatureChanged, [ this ](const float& temp) { checkTemperature(0x00, 0, temp); ui->plotWidget->appendPoint(i18n("Actual Bed"), temp); ui->plotWidget->update(); ui->bedExtWidget->updateBedTemp(temp); }); - connect(&m_core.temperature(), &Temperature::bedTargetTemperatureChanged, [ & ](const float& temp) { + connect(&m_core.temperature(), &Temperature::bedTargetTemperatureChanged, [ this ](const float& temp) { checkTemperature(0x01, 0, temp); ui->plotWidget->appendPoint(i18n("Target Bed"), temp); ui->plotWidget->update(); ui->bedExtWidget->updateBedTargetTemp(temp); }); - connect(&m_core.temperature(), &Temperature::extruderTemperatureChanged, [ & ](const float& temp) { + connect(&m_core.temperature(), &Temperature::extruderTemperatureChanged, [ this ](const float& temp) { checkTemperature(0x02, 0, temp); ui->plotWidget->appendPoint(i18n("Actual Ext.1"), temp); ui->plotWidget->update(); ui->bedExtWidget->updateExtTemp(temp); }); - connect(&m_core.temperature(), &Temperature::extruderTargetTemperatureChanged, [ & ](const float& temp) { + connect(&m_core.temperature(), &Temperature::extruderTargetTemperatureChanged, [ this ](const float& temp) { checkTemperature(0x03, 0, temp); ui->plotWidget->appendPoint(i18n("Target Ext.1"), temp); ui->plotWidget->update(); ui->bedExtWidget->updateExtTargetTemp(temp); }); - connect(ui->pushGCodeWidget, &PushGCodeWidget::push, [ & ](QString command) { + connect(ui->pushGCodeWidget, &PushGCodeWidget::push, [ this ](QString command) { ui->logWidget->addLog("Push " + command); m_core.pushCommand(command); }); @@ -240,6 +308,10 @@ static QString stateString; switch (newState) { case AtCore::CONNECTING: { + m_core.setSerialTimerInterval(0); + m_connectButton->setText(i18n("Disconnect")); + m_connectToolBar->setHidden(true); + m_mainToolBar->setHidden(false); stateString = i18n("Connecting..."); connect(&m_core, &AtCore::receivedMessage, this, &AtCoreInstanceWidget::checkReceivedCommand); connect(m_core.serial(), &SerialLayer::pushedCommand, this, &AtCoreInstanceWidget::checkPushedCommands); @@ -256,6 +328,10 @@ disconnect(&m_core, &AtCore::receivedMessage, this, &AtCoreInstanceWidget::checkReceivedCommand); disconnect(m_core.serial(), &SerialLayer::pushedCommand, this, &AtCoreInstanceWidget::checkPushedCommands); ui->logWidget->addLog(i18n("Serial disconnected")); + m_core.setSerialTimerInterval(100); + m_connectButton->setText(i18n("Connect")); + m_connectToolBar->setHidden(false); + m_mainToolBar->setHidden(true); enableControls(false); } break; case AtCore::STARTPRINT: { @@ -368,3 +444,18 @@ { m_files = files; } + +void AtCoreInstanceWidget::updateSerialPort(const QStringList &ports) +{ + m_comboPort->clear(); + m_comboPort->addItems(ports); +} + +void AtCoreInstanceWidget::updateProfileData() +{ + m_settings.beginGroup("GeneralSettings"); + QStringList profiles = m_settings.childGroups(); + m_settings.endGroup(); + m_comboProfile->clear(); + m_comboProfile->addItems(profiles); +} diff --git a/src/widgets/axiscontrol.cpp b/src/widgets/axiscontrol.cpp --- a/src/widgets/axiscontrol.cpp +++ b/src/widgets/axiscontrol.cpp @@ -93,7 +93,7 @@ setScene(new QGraphicsScene()); - auto createPie = [ = ](QLatin1Char axis, int value, int size, int angle) { + auto createPie = [ this ](QLatin1Char axis, int value, int size, int angle) { auto pie = new PieButton(axis, value, size, angle); pie->setPalette(this->palette()); connect(pie, &PieButton::clicked, this, &AxisControl::clicked); @@ -103,7 +103,7 @@ scene()->addItem(pie); }; - auto createRect = [ = ](QLatin1Char axis, int value, int size, int xPos, int yPos) { + auto createRect = [ this ](QLatin1Char axis, int value, int size, int xPos, int yPos) { auto z = new RectButton(axis, value, size); z->setPalette(this->palette()); z->setPos(xPos, yPos); diff --git a/src/widgets/bedextruderwidget.h b/src/widgets/bedextruderwidget.h --- a/src/widgets/bedextruderwidget.h +++ b/src/widgets/bedextruderwidget.h @@ -1,6 +1,8 @@ /* Atelier KDE Printer Host for 3D Printing Copyright (C) <2016> Author: Lays Rodrigues - laysrodriguessilva@gmail.com + Tomaz Canabraza - tcanabrava@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 @@ -17,14 +19,12 @@ */ #pragma once -#include -#include +#include #include +#include +#include -namespace Ui -{ -class BedExtruderWidget; -} +class ThermoWidget; class BedExtruderWidget : public QWidget { @@ -38,15 +38,16 @@ void updateExtTemp(const float temp); void updateBedTargetTemp(const float temp); void updateExtTargetTemp(const float temp); - void stopHeating(); private: - Ui::BedExtruderWidget *ui; QMap extruderMap; - void heatExtruderClicked(bool clicked); - void heatBedClicked(bool clicked); + ThermoWidget *m_bedThermo = nullptr; + ThermoWidget *m_extruderThermo = nullptr; + QWidget *m_extruderBox = nullptr; + QHBoxLayout *m_extrudersLayout = nullptr; + int currentExtruder(); - int extruderCount = 0; + int m_extruderCount = 0; signals: void bedTemperatureChanged(int tmp, bool andWait); diff --git a/src/widgets/bedextruderwidget.cpp b/src/widgets/bedextruderwidget.cpp --- a/src/widgets/bedextruderwidget.cpp +++ b/src/widgets/bedextruderwidget.cpp @@ -1,7 +1,9 @@ /* Atelier KDE Printer Host for 3D Printing Copyright (C) <2016> Author: Lays Rodrigues - laysrodriguessilva@gmail.com - + Tomaz Canabraza - tcanabrava@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 @@ -15,104 +17,96 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "bedextruderwidget.h" -#include "ui_bedextruderwidget.h" -#include #include +#include +#include +#include +#include "bedextruderwidget.h" +#include "thermowidget.h" + BedExtruderWidget::BedExtruderWidget(QWidget *parent) : QWidget(parent), - ui(new Ui::BedExtruderWidget) + m_bedThermo(new ThermoWidget(this, QString(i18n("Bed")))), + m_extruderThermo(new ThermoWidget(this, QString(i18n("HotEnd")))), + m_extruderBox(new QWidget(this)), + m_extrudersLayout(new QHBoxLayout) { - ui->setupUi(this); + m_bedThermo->setScale(0, 150); + m_extruderThermo->setScale(0, 250); + m_extruderBox->setLayout(m_extrudersLayout); + + auto *layout = new QGridLayout; + + auto *label = new QLabel(i18n("Active Extruder:")); + m_extrudersLayout->addWidget(label); + + layout->addWidget(m_extruderBox, 0, 0, 1, -1); + layout->addWidget(m_bedThermo, 1, 0); + layout->addWidget(m_extruderThermo, 1, 1); + + setLayout(layout); //Add Default Extruder setExtruderCount(1); - connect(ui->heatBedPB, &QPushButton::clicked, this, &BedExtruderWidget::heatBedClicked); - connect(ui->heatExtPB, &QPushButton::clicked, this, &BedExtruderWidget::heatExtruderClicked); - connect(ui->bedTempSB, static_cast(&QDoubleSpinBox::valueChanged), [ = ](double tmp) { - if (ui->heatBedPB->isChecked()) { - emit bedTemperatureChanged(tmp,ui->bedAndWaitCB->isChecked()); - } - }); + connect(m_bedThermo, &ThermoWidget::targetTemperatureChanged, [this](double v) { + qDebug() << "Receiving the temperature change for bed"; + emit bedTemperatureChanged((int)v, false); + }); - connect(ui->extTempSB, static_cast(&QDoubleSpinBox::valueChanged), [ = ](double tmp) { - if (ui->heatExtPB->isChecked()) { - emit extTemperatureChanged(tmp, currentExtruder(),ui->extAndWaitCB->isChecked()); - } - }); + connect(m_extruderThermo, &ThermoWidget::targetTemperatureChanged, [this](double v) { + qDebug() << "Receiving the temperature changed for thermo"; + emit extTemperatureChanged((int)v, currentExtruder(), false); + }); } BedExtruderWidget::~BedExtruderWidget() { - delete ui; } void BedExtruderWidget::setExtruderCount(int value) { - if (value == extruderCount) { + value > 1 ? m_extruderBox->setVisible(true) : m_extruderBox->setVisible(false); + if (value == m_extruderCount) { return; - } else if (extruderCount < value) { + } else if (m_extruderCount < value) { //loop for the new buttons - for (int i = extruderCount; i < value; i++) { + for (int i = m_extruderCount; i < value; i++) { auto *rb = new QRadioButton(QString::number(i + 1)); - ui->extRadioButtonLayout->addWidget(rb); + m_extrudersLayout->addWidget(rb); extruderMap.insert(i, rb); } } else { //remove buttons - need to test it! - for (int i = extruderCount; i >= value; i--) { + for (int i = m_extruderCount; i >= value; i--) { auto *rb = extruderMap.value(i); - ui->extRadioButtonLayout->removeWidget(rb); + m_extrudersLayout->removeWidget(rb); extruderMap.remove(i); delete (rb); } } - extruderCount = value; + m_extruderCount = value; } void BedExtruderWidget::updateBedTemp(const float temp) { - ui->bedCurrTempLB->setText(QString::number(temp)); + m_bedThermo->setCurrentTemperature(temp); } void BedExtruderWidget::updateExtTemp(const float temp) { - ui->extCurrTempLB->setText(QString::number(temp)); + m_extruderThermo->setCurrentTemperature(temp); } void BedExtruderWidget::updateBedTargetTemp(const float temp) { - ui->bedTargetTempLB->setText(QString::number(temp) + " ºC"); + m_bedThermo->setTargetTemperature(temp); } void BedExtruderWidget::updateExtTargetTemp(const float temp) { - ui->extTargetTempLB->setText(QString::number(temp) + " ºC"); -} - -void BedExtruderWidget::stopHeating() -{ - emit bedTemperatureChanged(0,ui->bedAndWaitCB->isChecked()); - for (int i = 0; i < extruderCount; i++) { - emit extTemperatureChanged(0, i,ui->extAndWaitCB->isChecked()); - } - ui->heatBedPB->setChecked(false); - ui->heatExtPB->setChecked(false); -} - -void BedExtruderWidget::heatExtruderClicked(bool clicked) -{ - int temp = ui->extTempSB->value() * clicked; - emit extTemperatureChanged(temp, currentExtruder(),ui->extAndWaitCB->isChecked()); -} - -void BedExtruderWidget::heatBedClicked(bool clicked) -{ - int temp = ui->bedTempSB->value() * clicked; - emit bedTemperatureChanged(temp,ui->bedAndWaitCB->isChecked()); - + m_extruderThermo->setTargetTemperature(temp); } int BedExtruderWidget::currentExtruder() diff --git a/src/widgets/bedextruderwidget.ui b/src/widgets/bedextruderwidget.ui deleted file mode 100644 --- a/src/widgets/bedextruderwidget.ui +++ /dev/null @@ -1,182 +0,0 @@ - - - BedExtruderWidget - - - - 0 - 0 - 266 - 247 - - - - Form - - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - - - ºC - - - 0 - - - 150.000000000000000 - - - - - - - Heat - - - true - - - - - - - Target Temperature: - - - - - - - 0 ºC - - - - - - - Current Temperature: - - - - - - - 0 ºC - - - - - - - Qt::Horizontal - - - - - - - Hotend - - - Qt::AlignCenter - - - - - - - ºC - - - 0 - - - 250.000000000000000 - - - - - - - Bed - - - Qt::AlignCenter - - - - - - - Heat - - - true - - - - - - - Target Temperature: - - - - - - - 0 ºC - - - - - - - Current Temperature: - - - - - - - 0 ºC - - - - - - - - - - andWait - - - - - - - andWait - - - - - - - - diff --git a/src/widgets/plotwidget.h b/src/widgets/plotwidget.h --- a/src/widgets/plotwidget.h +++ b/src/widgets/plotwidget.h @@ -1,6 +1,9 @@ /* Atelier KDE Printer Host for 3D Printing Copyright (C) <2016> - Author: Patrick José Pereira - patrickelectric@gmail.com + Author: Patrick José Pereira - patrickjp@kde.org + Tomaz Canabrava + Lays Rodrigues + Chris Rizzitello 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 @@ -35,40 +38,34 @@ * * @param name p_name: plot name */ - void newPlot(QString name); + void newPlot(const QString &name); /** * @brief Delete plot with name * * @param name p_name: name */ - void deletePlot(QString name); + void deletePlot(const QString &name); /** * @brief Append point to plot * * @param name p_name: plot name * @param value p_value: value */ - void appendPoint(QString name, float value); + void appendPoint(const QString &name, float value); /** * @brief Update plot list, need to run after ALL plots added * */ void update(); private: - - QChartView *_chart; - - QHash _name2Index; - class plot { public: - explicit plot() + explicit plot() : _series(new QLineSeries()) { - _series = new QLineSeries(); }; ~plot() @@ -82,7 +79,7 @@ _series->append(now.toMSecsSinceEpoch(), value); } - void setName(QString name) + void setName(const QString &name) { _name = name; _series->setName(_name); @@ -94,20 +91,24 @@ _series->append(now.toMSecsSinceEpoch(), 0.0); } - QLineSeries *serie() + QLineSeries *serie() const { return _series; } - QString name() + QString name() const { return _name; } private: QLineSeries *_series; QString _name; }; + QChartView *_chart; + QDateTimeAxis *_axisX; + QValueAxis *_axisY; + QHash _name2Index; QVector _plots; }; diff --git a/src/widgets/plotwidget.cpp b/src/widgets/plotwidget.cpp --- a/src/widgets/plotwidget.cpp +++ b/src/widgets/plotwidget.cpp @@ -1,6 +1,9 @@ /* Atelier KDE Printer Host for 3D Printing Copyright (C) <2016> - Author: Patrick José Pereira - patrickelectric@gmail.com + Author: Patrick José Pereira - patrickjp@kde.org + Tomaz Canabrava + Lays Rodrigues + Chris Rizzitello 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 @@ -21,74 +24,62 @@ #include PlotWidget::PlotWidget(QWidget *parent) : - QWidget(parent) + QWidget(parent), + _chart(new QChartView()), + _axisX(new QDateTimeAxis()), + _axisY(new QValueAxis()) { - _chart = new QChartView; QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addWidget(_chart); - this->setLayout(mainLayout); + setLayout(mainLayout); + + _axisX->setTickCount(3); + _axisX->setFormat(QStringLiteral("hh:mm:ss")); + _axisY->setLabelFormat(QStringLiteral("%d")); + _axisY->setTitleText(i18n("Temp.")); + + _chart->chart()->addAxis(_axisY, Qt::AlignLeft); + _chart->chart()->addAxis(_axisX, Qt::AlignBottom); + _chart->chart()->axisY()->setRange(0, 3e2); + _chart->chart()->axisX()->setRange(QDateTime::currentDateTime().addSecs(-120), QDateTime::currentDateTime()); + _chart->setRenderHint(QPainter::Antialiasing); + if (palette().text().color().value() >= QColor(Qt::lightGray).value()) { + _chart->chart()->setTheme(QChart::ChartThemeDark); + } newPlot(i18n("Actual Bed")); newPlot(i18n("Target Bed")); // The extruder need to be added after some signal emitted (ExtruderCountChanged) newPlot(i18n("Actual Ext.1")); newPlot(i18n("Target Ext.1")); - update(); + } -void PlotWidget::newPlot(QString name) +void PlotWidget::newPlot(const QString &name) { - // Create a new plot _name2Index[name] = _plots.size(); plot _newPlot; _newPlot.setName(name); + _chart->chart()->addSeries(_newPlot.serie()); + _newPlot.serie()->attachAxis(_axisY); + _newPlot.serie()->attachAxis(_axisX); _plots.append(_newPlot); } -void PlotWidget::deletePlot(QString name) +void PlotWidget::deletePlot(const QString &name) { _plots.remove(_name2Index[name]); - _name2Index[name] = -1; + _name2Index.remove(name); } -void PlotWidget::appendPoint(QString name, float value) +void PlotWidget::appendPoint(const QString &name, float value) { _plots[_name2Index[name]].pushPoint(value); } void PlotWidget::update() { - static bool firstTimeCheck = true; - static QDateTimeAxis *axisX = new QDateTimeAxis; - static QValueAxis *axisY = new QValueAxis; - - // After already executed, update time axis - if (firstTimeCheck == false) { - _chart->chart()->axisX()->setRange(QDateTime::currentDateTime().addSecs(-120), QDateTime::currentDateTime()); - return; - } - - firstTimeCheck = false; - - axisX->setTickCount(3); - axisX->setFormat(QStringLiteral("hh:mm:ss")); - - axisY->setLabelFormat(QStringLiteral("%d")); - axisY->setTitleText(i18n("Temp.")); - - _chart->chart()->addAxis(axisY, Qt::AlignLeft); - _chart->chart()->addAxis(axisX, Qt::AlignBottom); - - _chart->chart()->axisY()->setRange(0, 3e2); _chart->chart()->axisX()->setRange(QDateTime::currentDateTime().addSecs(-120), QDateTime::currentDateTime()); - - for (auto plot : _plots) { - _chart->chart()->addSeries(plot.serie()); - plot.serie()->attachAxis(axisY); - plot.serie()->attachAxis(axisX); - } - - _chart->setRenderHint(QPainter::Antialiasing); } PlotWidget::~PlotWidget() diff --git a/src/widgets/pushgcodewidget.cpp b/src/widgets/pushgcodewidget.cpp --- a/src/widgets/pushgcodewidget.cpp +++ b/src/widgets/pushgcodewidget.cpp @@ -38,8 +38,7 @@ layout->addItem(items); this->setLayout(layout); - connect(bt, &QPushButton::clicked, [ = ] { + connect(bt, &QPushButton::clicked, [ this ] { push(input->text()); }); } - diff --git a/src/widgets/ratescontrolwidget.cpp b/src/widgets/ratescontrolwidget.cpp --- a/src/widgets/ratescontrolwidget.cpp +++ b/src/widgets/ratescontrolwidget.cpp @@ -23,13 +23,13 @@ ui(new Ui::RatesControlWidget) { ui->setupUi(this); - connect(ui->flowRateSB, static_cast(&QDoubleSpinBox::valueChanged), [ = ](float value){ + connect(ui->flowRateSB, static_cast(&QDoubleSpinBox::valueChanged), [ this ](float value){ emit flowRateChanged(value); }); - connect(ui->fanSpeedSB, static_cast(&QDoubleSpinBox::valueChanged), [ = ](float value){ + connect(ui->fanSpeedSB, static_cast(&QDoubleSpinBox::valueChanged), [ this ](float value){ emit fanSpeedChanged(value); }); - connect(ui->printSpeedSB, static_cast(&QDoubleSpinBox::valueChanged), [ = ](float value){ + connect(ui->printSpeedSB, static_cast(&QDoubleSpinBox::valueChanged), [ this ](float value){ emit printSpeedChanged(value); }); diff --git a/src/widgets/thermowidget.h b/src/widgets/thermowidget.h new file mode 100644 --- /dev/null +++ b/src/widgets/thermowidget.h @@ -0,0 +1,64 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2018> + Author: Tomaz Canabrava - tcanabrava@kde.org + Chris Rizzitello - rizzitello@kde.org + Lays Rodrigues - laysrodriguessilva@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#pragma once + +#include +#include + +class QKeyEvent; +class QPaintEvent; +class QFocusEvent; +class QWheelEvent; + +class ThermoWidget : public QwtDial { + Q_OBJECT + +public: + ThermoWidget(QWidget *parent, QString name); + + void drawNeedle( QPainter *painter, const QPointF ¢er, + double radius, double dir, QPalette::ColorGroup colorGroup ) const; + + void setCurrentTemperature(double temperature); + void setTargetTemperature(double temperature); + +signals: + void targetTemperatureChanged(double targetTemperature); + +protected: + void focusInEvent(QFocusEvent *event); + void focusOutEvent(QFocusEvent *event); + void keyPressEvent (QKeyEvent *event); + void paintEvent(QPaintEvent *event); + void wheelEvent(QWheelEvent *event); + +private: + QwtDialSimpleNeedle *m_currentTemperatureNeedle; + QwtDialSimpleNeedle *m_targetTemperatureNeedle; + + QString m_currentTemperatureTextFromEditor = QString("-"); + QString m_name; + + QTimer *m_cursorTimer = nullptr; + bool m_paintCursor = false; + int m_cursorPos = 0; + double m_currentTemperature; + double m_targetTemperature; +}; diff --git a/src/widgets/thermowidget.cpp b/src/widgets/thermowidget.cpp new file mode 100644 --- /dev/null +++ b/src/widgets/thermowidget.cpp @@ -0,0 +1,280 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2018> + Author: Tomaz Canabrava - tcanabrava@kde.org + Chris Rizzitello - rizzitello@kde.org + Lays Rodrigues - laysrodriguessilva@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thermowidget.h" + +ThermoWidget::ThermoWidget(QWidget *parent, QString name) : QwtDial(parent), + m_targetTemperatureNeedle(new QwtDialSimpleNeedle(QwtDialSimpleNeedle::Arrow, Qt::red, Qt::darkRed)), + m_name(name), + m_currentTemperature(0), + m_targetTemperature(0) +{ + setScaleArc(40, 320); + //make our current temperature needle here so we can set it to match text color. + m_currentTemperatureNeedle = new QwtDialSimpleNeedle(QwtDialSimpleNeedle::Arrow, true, palette().text().color()); + setNeedle(m_currentTemperatureNeedle); + setReadOnly(false); + setFocusPolicy(Qt::StrongFocus); + + m_cursorTimer = new QTimer(); + connect (m_cursorTimer, &QTimer::timeout, [&] { + m_paintCursor = !m_paintCursor; + update(); + }); +} + +void ThermoWidget::keyPressEvent(QKeyEvent* event) +{ + //set our target text length. + int slen = m_currentTemperatureTextFromEditor.length() -1; + // be sure our cursor posistion is valid. + if(slen < 0) { + m_currentTemperatureTextFromEditor = '-'; + m_cursorPos = 0; + } else if(slen > 2) { + m_cursorPos = 2; + } + //parse the key events. + if (event->key() >= Qt::Key_0 && event->key() <= Qt::Key_9) { + auto tmp = m_currentTemperatureTextFromEditor; + + if(m_cursorPos == slen) { + tmp.append(event->key()); + } else { + tmp.insert(m_cursorPos,event->key()); + } + + if(tmp.startsWith('0')) { + tmp.remove(0,1); + } + + if(tmp.contains('-')) { + tmp.remove('-'); + //push the cursor back to negate advancement; + m_cursorPos--; + } + if (tmp.toInt() <= upperBound() && tmp.toInt() >= lowerBound()) { + m_currentTemperatureTextFromEditor = tmp; + if (m_cursorPos <= slen) { + m_cursorPos++; + } + } + } else if ( event->key() == Qt::Key_Delete && m_currentTemperatureTextFromEditor.count()) { + m_currentTemperatureTextFromEditor.remove(m_cursorPos, 1); + if(m_cursorPos < slen) { + m_cursorPos = slen; + } + m_cursorPos--; + } else if ( event->key() == Qt::Key_Backspace && m_currentTemperatureTextFromEditor.count()) { + if(m_cursorPos <= slen) { + m_cursorPos--; + m_currentTemperatureTextFromEditor.remove(m_cursorPos, 1); + } + } else if (event->key() == Qt::Key_Enter) { + m_targetTemperature = m_currentTemperatureTextFromEditor.toInt(); + } else if (event->key() == Qt::Key_Escape) { + m_currentTemperatureTextFromEditor = '0'; + } else if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Plus) { + if (m_targetTemperature != upperBound()) { + m_currentTemperatureTextFromEditor = QString::number(m_targetTemperature + 1); + } + } else if (event->key() == Qt::Key_Down || event->key() == Qt::Key_Minus) { + if (m_targetTemperature != lowerBound()) { + m_currentTemperatureTextFromEditor = QString::number(m_targetTemperature - 1); + } + } else if (event->key() == Qt::Key_PageUp) { + if (m_targetTemperature + 10 > upperBound()) { + m_currentTemperatureTextFromEditor = QString::number(upperBound()); + } else { + m_currentTemperatureTextFromEditor = QString::number(m_targetTemperature + 10); + } + } else if (event->key() == Qt::Key_PageDown) { + if (m_targetTemperature - 10 < lowerBound()) { + m_currentTemperatureTextFromEditor = QString::number(lowerBound()); + } else { + m_currentTemperatureTextFromEditor = QString::number(m_targetTemperature - 10); + } + } + + else if (event->key() == Qt::Key_Right) { + if(m_cursorPos < slen) { + m_cursorPos++; + } + } else if (event->key() == Qt::Key_Left) { + if(m_cursorPos > 0) { + m_cursorPos--; + } + } + else { + QwtDial::keyPressEvent(event); + return; + } + + if (m_targetTemperature != m_currentTemperatureTextFromEditor.toInt()) { + m_targetTemperature = m_currentTemperatureTextFromEditor.toInt(); + emit targetTemperatureChanged(m_targetTemperature); + update(); + event->accept(); + } +} + +void ThermoWidget::wheelEvent(QWheelEvent* event) +{ + if (event->angleDelta().y() > 0) { + if (m_targetTemperature + 10 > upperBound()) { + m_currentTemperatureTextFromEditor = QString::number(upperBound()); + } else { + m_currentTemperatureTextFromEditor = QString::number(m_targetTemperature + 10); + } + } else if (event->angleDelta().y() < 0) { + if (m_targetTemperature - 10 < lowerBound()) { + m_currentTemperatureTextFromEditor = QString::number(lowerBound()); + } else { + m_currentTemperatureTextFromEditor = QString::number(m_targetTemperature - 10); + } + } + + if (m_targetTemperature != m_currentTemperatureTextFromEditor.toInt()) { + m_targetTemperature = m_currentTemperatureTextFromEditor.toInt(); + emit targetTemperatureChanged(m_targetTemperature); + update(); + } + event->accept(); +} + +void ThermoWidget::focusOutEvent(QFocusEvent* event) +{ + if (m_targetTemperature != m_currentTemperatureTextFromEditor.toInt()) { + m_targetTemperature = m_currentTemperatureTextFromEditor.toInt(); + emit targetTemperatureChanged(m_targetTemperature); + event->accept(); + } + m_cursorTimer->stop(); + m_paintCursor = false; + update(); +} + +void ThermoWidget::focusInEvent(QFocusEvent* event) +{ + m_cursorTimer->start(1000); + event->accept(); +} + +void ThermoWidget::paintEvent(QPaintEvent* event) +{ + QwtDial::paintEvent(event); + const QString currentText = QString::number(m_currentTemperature); + + QFontMetrics fm(font()); + const double targetWidth = fm.width(m_currentTemperatureTextFromEditor); + const double currentWidth = fm.width(currentText); + const double nameWidth = fm.width(m_name); + const double wWidth = fm.width('W'); + const double cursorWidth = fm.width('0'); + + + const double height = fm.height(); + const double halfWidth = geometry().width() / 2; + const double xposTarget = halfWidth - (targetWidth / 2); + const double xposCurrent = halfWidth - (currentWidth / 2); + const double xposName = halfWidth - (nameWidth / 2); + const double xposCursor = xposTarget + (cursorWidth * m_cursorPos); + double ypos = geometry().height() / 2 + height * 2; + QPainter p(this); + QColor color = palette().color(QPalette::Text); + + //draw a box to put our target into as a user hint. + p.fillRect(QRect(halfWidth - wWidth , ypos - (height * 0.66), wWidth * 2, (height * 0.9)),palette().color(QPalette::AlternateBase)); + + if(m_paintCursor) { + p.setPen(palette().color(QPalette::Text)); + p.drawText(xposCursor , ypos, QChar('_')); + } + + p.setPen(Qt::red); + p.drawText(xposTarget, ypos, m_currentTemperatureTextFromEditor); + + ypos += height + 2; + + p.setPen(color); + p.drawText(xposCurrent, ypos, QString::number(m_currentTemperature)); + ypos += height + 2; + + p.setPen(color); + p.drawText(xposName, ypos, m_name); +} + +void ThermoWidget::drawNeedle( QPainter *painter, const QPointF ¢er, double radius, double dir, QPalette::ColorGroup colorGroup ) const +{ + Q_UNUSED( dir ); + + const double relativePercent = upperBound() - lowerBound(); + const double currentTemperaturePercent = (m_currentTemperature - lowerBound()) / relativePercent; + const double targetTemperaturePercent = (m_targetTemperature - lowerBound()) / relativePercent; + const double currentTemperatureAngle = (maxScaleArc() - minScaleArc()) * currentTemperaturePercent + minScaleArc(); + const double targetTemperatureAngle = (maxScaleArc() - minScaleArc()) * targetTemperaturePercent + minScaleArc(); + + // Qt coordinates and Qwt coordinates differ. + // the "begin" of our coordinates in Qt: -130 + // the "span" of our coordinates in Qt: -180 + // Negative values means clockwise in Qt dialect. + const double qtBeginAngle = -130; + const double coolZone = - (targetTemperatureAngle - minScaleArc()); + int yPos = geometry().height() / 2 - radius; + int xPos = geometry().width() / 2 - radius; + + QRadialGradient grad(center,radius); + grad.setColorAt(0.75,QColor(0,0,0,0)); + grad.setColorAt(0.85,QColor(255,0,0,196)); + grad.setColorAt(0.95,QColor(255,110,60,196)); + + painter->setBrush(grad); + painter->drawPie(xPos,yPos, radius * 2, radius * 2, qtBeginAngle * 16, coolZone* 16); + + m_targetTemperatureNeedle->draw(painter, center, radius * 1.3, 360 - targetTemperatureAngle - origin(), colorGroup); + m_currentTemperatureNeedle->draw(painter, center, radius, 360 - currentTemperatureAngle - origin(), colorGroup); +} + +void ThermoWidget::setCurrentTemperature(double temperature) +{ + if (m_currentTemperature != temperature) { + m_currentTemperature = temperature; + update(); + } +} + +void ThermoWidget::setTargetTemperature(double temperature) +{ + if (m_targetTemperature != temperature) { + m_currentTemperatureTextFromEditor = QString::number(temperature); + m_targetTemperature = temperature; + emit targetTemperatureChanged(m_targetTemperature); + update(); + } + +} diff --git a/src/widgets/videomonitorwidget.cpp b/src/widgets/videomonitorwidget.cpp --- a/src/widgets/videomonitorwidget.cpp +++ b/src/widgets/videomonitorwidget.cpp @@ -64,7 +64,7 @@ .replaceInStrings( QRegExp("^"), "v4l2:///dev/")); #endif - connect(_playPB, &QPushButton::clicked, [=](bool b){ + connect(_playPB, &QPushButton::clicked, [this, _playPB, _sourceCB](bool b){ if(b){ _playPB->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); QString source = _sourceCB->currentText(); @@ -84,7 +84,7 @@ VideoMonitorWidget::~VideoMonitorWidget() { - + } void VideoMonitorWidget::handleError()