Commit 7e592cc1 authored by Leander Schulten's avatar Leander Schulten
Browse files

Move programblock running/not_running logic from the controller to the...

Move programblock running/not_running logic from the controller to the programblock and extend it to the states: stopped/running/paused
parent b071de73
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
import custom.licht 1.0
import QtQuick.Dialogs 1.2
......@@ -99,6 +99,7 @@ Item{
Layout.fillWidth: true
id: programEditor
programBlock: listView.currentItem.itemData;
property var status: programBlock.status;
onShowPropertiesChanged: propertiesView.update()
onOpenRightClickEntry: {
rightClickMenu.x = x;
......@@ -110,22 +111,53 @@ Item{
popup_addConnectionAsk.inputName = to
popup_addConnectionAsk.visible = true;
}
// enum Status{Stopped=0, Running=1, Paused=2}
RoundButton{
id: button_startStop
icon.source: programEditor.programBlock.status === 1 ? "qrc:icons/stop.svg" : programEditor.programBlock.status === 0 ? "qrc:icons/play.svg":"qrc:icons/replay.svg"
anchors.bottom: parent.bottom
anchors.leftMargin: 15
anchors.left: parent.left
checked: programEditor.programBlock.status === 1
onClicked: {
if(programEditor.programBlock.status === 0){
programEditor.programBlock.start();
} else if(programEditor.programBlock.status === 1){
programEditor.programBlock.stop();
} else if(programEditor.programBlock.status === 2){
programEditor.programBlock.restart();
}
}
ToolTip.visible: hovered
ToolTip.delay: 1000
ToolTip.text: programEditor.programBlock.status === 1 ? "Stop" : programEditor.programBlock.status === 0 ? "Play":"Replay"
}
RoundButton{
id: button_run
checkable: true
checked: programEditor.run
onCheckedChanged: programEditor.run = checked
text: programEditor.run ? "Stop" : "Run"
width: 70
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: 15
}
id: button_pauseResume
icon.source: programEditor.programBlock.status === 1 ? "qrc:icons/pause.svg" : "qrc:icons/resume.png"
visible: programEditor.programBlock.status !== 0;
checked: programEditor.programBlock.status === 1
anchors.bottom: parent.bottom
anchors.leftMargin: 15
anchors.left: button_startStop.right
onClicked: {
if(programEditor.programBlock.status === 1){
programEditor.programBlock.pause();
} else if(programEditor.programBlock.status === 2){
programEditor.programBlock.resume();
}
}
ToolTip.visible: hovered
ToolTip.delay: 1000
ToolTip.text: programEditor.programBlock.status === 1 ? "Pause" : "Resume"
}
RoundButton{
id:button_add_entry
text: "Add Entry"
anchors.bottom: parent.bottom
anchors.left: button_run.right
anchors.left: button_pauseResume.right
anchors.leftMargin: 15
onClicked: {
programEditor.updatePossibleEntries();
......
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M6 6h12v12H6z"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></svg>
\ No newline at end of file
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 100 125" enable-background="new 0 0 100 100" xml:space="preserve">
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<path d="M71.254,28.628h-42c-2.757,0-5,2.243-5,5v42c0,2.757,2.243,5,5,5h42c2.757,0,5-2.243,5-5v-42 C76.254,30.871,74.011,28.628,71.254,28.628z"/>
</svg>
\ No newline at end of file
......@@ -109,6 +109,7 @@ int main(int argc, char *argv[])
qRegisterMetaType<UserManagment::Permission>("Permission");
qRegisterMetaType<Modules::detail::PropertyInformation::Type>("Type");
qRegisterMetaType<Modules::ValueType>("ValueType");
qRegisterMetaType<Modules::ProgramBlock::Status>("Status");
qRegisterMetaType<Modules::PropertiesVector*>("PropertiesVector*");
Settings settings;
settings.setJsonSettingsFilePath("QTJSONFile.json");
......
......@@ -143,7 +143,6 @@ class ProgramBlockEditor : public QQuickItem
Q_PROPERTY(QAbstractListModel * outputDataProducerModel READ getOutputDataProducerModel CONSTANT)
Q_PROPERTY(QAbstractListModel * inputDataConsumerModel READ getInputDataConsumerModel CONSTANT)
Q_PROPERTY(bool showProperties READ getShowProperties WRITE setShowProperties NOTIFY showPropertiesChanged)
Q_PROPERTY(bool run READ getRun WRITE setRun NOTIFY runChanged)
QQmlComponent programBlockEntry;
QQmlComponent programBlockConnection;
enum {None, MovePermanent, MoveTemporarily, AddConnection, AddReverseConnection} dragType = None;
......@@ -204,9 +203,7 @@ public:
qDebug () << "Program Block changed";
programBlock = _programBlock;
recreateView();
run = Modules::ModuleManager::singletone()->controller().isProgramRunning(programBlock);
setShowProperties(false);
emit runChanged();
emit programBlockChanged();
}
}
......@@ -235,21 +232,6 @@ public:
bool getShowProperties() const {
return showProperties;
}
void setRun( const bool _run){
if(_run != run){
run = _run;
if(run){
auto iter = std::find_if(Modules::ProgramBlockManager::model.cbegin(),Modules::ProgramBlockManager::model.cend(),[&](const auto &v){return v.get()==programBlock;});
if(iter != Modules::ProgramBlockManager::model.cend())
Modules::ModuleManager::singletone()->controller().runProgramm(*iter);
}else
Modules::ModuleManager::singletone()->controller().stopProgramm(programBlock);
emit runChanged();
}
}
bool getRun() const {
return run;
}
protected:
virtual void mouseReleaseEvent(QMouseEvent *event)override;
virtual void mouseMoveEvent(QMouseEvent *event)override;
......
......@@ -14,7 +14,9 @@ void Controller::run() noexcept{
std::unique_lock<std::mutex> l(vectorLock);
for(auto pb = runningProgramms.begin() ; pb != runningProgramms.end();){
if((*pb)->doStep(1)){
deletingProgramBlock = (*pb).get();
(**pb).stop();
deletingProgramBlock = nullptr;
pb = runningProgramms.erase(pb);
}else{
++pb;
......@@ -25,19 +27,19 @@ void Controller::run() noexcept{
void Controller::runProgramm(std::shared_ptr<ProgramBlock> pb){
std::unique_lock<std::mutex> l(vectorLock);
runningProgramms.push_back(pb);
pb->start();
runningProgramms.push_back(pb);
}
void Controller::stopProgramm(std::shared_ptr<ProgramBlock> pb){
// preventing deadlocks, this method is called when call stop on a ProgramBlock, wich is called in function run
if(deletingProgramBlock == pb.get())
return;
std::unique_lock<std::mutex> l(vectorLock);
runningProgramms.erase(std::remove(runningProgramms.begin(),runningProgramms.end(),pb),runningProgramms.end());
pb->stop();
runningProgramms.erase(std::remove(runningProgramms.begin(),runningProgramms.end(),pb),runningProgramms.end());
}
void Controller::stopProgramm(ProgramBlock* pb){
std::unique_lock<std::mutex> l(vectorLock);
runningProgramms.erase(std::remove_if(runningProgramms.begin(),runningProgramms.end(),[&](const auto &v){return v.get()==pb;}),runningProgramms.end());
pb->stop();
runningProgramms.erase(std::remove_if(runningProgramms.begin(),runningProgramms.end(),[&](const auto &v){return v.get()==pb;}),runningProgramms.end());
}
bool Controller::isProgramRunning(ProgramBlock * pb){
......
......@@ -5,7 +5,7 @@
#include <thread>
#include <mutex>
#include <condition_variable>
#include "programms/programblock.h"
#include "programblock.h"
namespace Modules {
......@@ -20,6 +20,8 @@ class Controller
std::condition_variable wait;
std::vector<std::shared_ptr<ProgramBlock>> runningProgramms;
std::mutex vectorLock;
ProgramBlock * deletingProgramBlock = nullptr;
friend class ProgramBlock;
void run() noexcept;
public:
Controller();
......@@ -33,6 +35,7 @@ public:
}
void stop(){run_=false;}
~Controller(){run_ = false;if(thread.joinable())thread.join();}
private:
void runProgramm(std::shared_ptr<ProgramBlock> pb);
void stopProgramm(std::shared_ptr<ProgramBlock> pb);
void stopProgramm(ProgramBlock* pb);
......
......@@ -251,18 +251,70 @@ namespace Modules {
newConsumer->start();
}
void ProgramBlock::restart(Controller * c){
stop();
start(c);
}
void ProgramBlock::start(){
for(auto & p : programs){
p->start();
}
for(auto i = consumer.cbegin(); i != consumer.cend();++i){
static_cast<Consumer*>(i->source.get())->start();
start(&ModuleManager::singletone()->controller());
}
void ProgramBlock::restart(){
restart(&ModuleManager::singletone()->controller());
}
void ProgramBlock::resume(){
resume(&ModuleManager::singletone()->controller());
}
void ProgramBlock::start(Controller * c){
if(status!=Running && c){
for(auto & p : programs){
p->start();
}
for(auto i = consumer.cbegin(); i != consumer.cend();++i){
static_cast<Consumer*>(i->source.get())->start();
}
setStatus(Running);
c->runProgramm(shared_from_this());
controller = c;
}
}
void ProgramBlock::stop(){
for(auto i = consumer.cbegin(); i != consumer.cend();++i){
static_cast<Consumer*>(i->source.get())->stop();
if(status==Running && controller){
for(auto i = consumer.cbegin(); i != consumer.cend();++i){
static_cast<Consumer*>(i->source.get())->stop();
}
setStatus(Stopped);
controller->stopProgramm(shared_from_this());
controller = nullptr;
}
}
void ProgramBlock::pause(){
if(status==Running&&controller){
for(auto i = consumer.cbegin(); i != consumer.cend();++i){
static_cast<Consumer*>(i->source.get())->stop();
}
setStatus(Paused);
controller->stopProgramm(shared_from_this());
controller = nullptr;
}
}
void ProgramBlock::resume(Controller * c){
if(status==Paused && c){
//start consumer
for(auto i = consumer.cbegin(); i != consumer.cend();++i){
static_cast<Consumer*>(i->source.get())->start();
}
setStatus(Running);
controller = c;
controller->runProgramm(shared_from_this());
}else if (status == Stopped) {
start(c);
}
}
......
......@@ -75,13 +75,15 @@ namespace Modules {
}
class ModuleManager;
class Controller;
/**
* @brief The ProgramBlock class is the combination of programms, filter and Consumer. THE PROGRAMM_BLOCK OWNS THE POINTER!
* Es legt fest welche Bereiche des outputs in welche bereiche des inputs gelangen(Programm -> Filter -> Consumer)
*/
class ProgramBlock : public QObject, public AbstractProgramm
class ProgramBlock : public QObject, public AbstractProgramm, public std::enable_shared_from_this<ProgramBlock>
{
Q_OBJECT
friend class ModuleManager;
/* Input n programms
m filters
......@@ -92,8 +94,14 @@ namespace Modules {
load from json, get object from Module Manager throug name
*/
QString name;
Controller * controller = nullptr;
public:
enum Status{Stopped=0, Running=1, Paused=2}status = Stopped;
Q_ENUM(Status)
private:
Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
Q_OBJECT
Q_PROPERTY(Status status READ getStatus NOTIFY statusChanged)
std::set<std::shared_ptr<Program>> programs;
// verschiedene Ebenen von Filtern
......@@ -277,18 +285,46 @@ namespace Modules {
}
signals:
void nameChanged();
void statusChanged();
public:
ProgramBlock(const QJsonObject&);
virtual bool doStep(time_diff_t)override;
/**
* @brief start starts all used Programs and Consumer
* @brief start start the program block if not running
*/
void start(Controller * c);
Q_INVOKABLE void start();
/**
* @brief restart this function restart or start the program
*/
void start();
void restart(Controller * c);
Q_INVOKABLE void restart();
/**
* @brief stop stop all used Consumer
*/
void stop();
Q_INVOKABLE void stop();
/**
* @brief pause an running program or do nothing
*/
Q_INVOKABLE void pause();
/**
* @brief resume resume an paused program or start an stopped program
*/
void resume(Controller * c);
Q_INVOKABLE void resume();
Status getStatus()const{return status;}
void writeJsonObject(QJsonObject&);
private:
/**
* @brief setStatus use this function to set the status, this function emit a signal when the status changed
* @param s the new status
*/
void setStatus(Status s){
if(s!=status){
status = s;
emit statusChanged();
}
}
};
......@@ -306,6 +342,7 @@ namespace Modules {
}
Q_DECLARE_METATYPE(Modules::ProgramBlock::Status)
/*namespace std {
template<>
......
......@@ -50,5 +50,10 @@
<file>ProgramBlockConnection.qml</file>
<file>VerticalTabBar.qml</file>
<file>VerticalTabButton.qml</file>
<file>icons/resume.png</file>
<file>icons/replay.svg</file>
<file>icons/material-pause.svg</file>
<file>icons/material-play.svg</file>
<file>icons/material-stop.svg</file>
</qresource>
</RCC>
......@@ -48,7 +48,7 @@ void Test::createProgrammBlockAndTestRunIt(){
con->addFilter(first,0);
con->addFilter(second,1);
con->addConsumer(third);
mm->controller().runProgramm(con);
con->start(&mm->controller());
mm->controller().start();
ProgramBlockManager::model.push_back(con);
}
......@@ -29,7 +29,7 @@ void TestProgrammBlock::test(){
pb->addConsumer(l);
controller.start();
controller.runProgramm(pb);
pb->start(&controller);
this_thread::sleep_for(20ms);
controller.stop();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment