Commit 8f84332d authored by Leander Schulten's avatar Leander Schulten
Browse files

Improve ProgramBlock Editor

parent 6a786692
......@@ -69,23 +69,57 @@ Item{
anchors.top: parent.top
anchors.right: parent.right
anchors.bottom: parent.bottom
ProgramBlockEditor{
anchors.top: parent.top
anchors.bottom: parent.bottom
Layout.fillWidth: true
id: programEditor
programBlock: listView.currentItem.itemData;
onShowPropertiesChanged: propertiesView.update()
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
}
RoundButton{
id:button_add_entry
text: "Add Entry"
anchors.bottom: parent.bottom
anchors.left: button_run.right
anchors.leftMargin: 15
onClicked: {
programEditor.updatePossibleEntries();
addEntry.visible = true;
}
}
RoundButton{
id:button_add_connection
text: "Add Connection"
anchors.bottom: parent.bottom
anchors.left: button_add_entry.right
anchors.leftMargin: 15
}
}
ColumnLayout{
anchors.top: parent.top
anchors.bottom: parent.bottom
Layout.preferredWidth: 200
Layout.maximumWidth: 200
visible: programEditor.showProperties
spacing: 0
Rectangle{
id:line
......@@ -127,10 +161,31 @@ Item{
highlight: Rectangle{
color: "lightgrey"
}
onCurrentItemChanged: update()
function update(){
if(propertiesView.currentIndex<0)
return;
var data = propertiesView.currentItem.itemData;
print("type : " + data.type)
if(data.type>=0&&data.type<=3){
slider.visible = true;
// Wenn die folgenden zwei zeilen fehlen, wird der value beim setzten auf die grenzen gesetzt und dann verändert
slider.to = 9999999999;
slider.from = -9999999999999;
slider.value = data.value;
slider.from = data.minValue;
slider.to = data.maxValue;
slider.stepSize = (data.type==0||data.type==1)?1:0;
slider.snapMode = (data.type==0||data.type==1)?Slider.SnapAlways:Slider.NoSnap;
print("stepSize : " + slider.stepSize)
}else{
if(data.type===4){
checkBox.checked = data.value
}
slider.visible = false;
}
checkBox.visible = data.type === 4;
}
}
......@@ -146,8 +201,6 @@ Item{
ColumnLayout{
Layout.maximumHeight: 250
Layout.preferredHeight: 250
Label{
Layout.margins: 5
Layout.preferredHeight: contentHeight
......@@ -158,12 +211,100 @@ Item{
}
Slider{
id:slider
onValueChanged: {
propertiesView.currentItem.itemData.value = value;
print(propertiesView.currentItem.itemData.name + " set value to " + value)
}
Text{
text: slider.stepSize===0?slider.value.toFixed(2):slider.value.toFixed(0);
anchors.bottom: slider.handle.top
anchors.bottomMargin: 7
anchors.horizontalCenter: slider.handle.horizontalCenter
}
}
CheckBox{
id:checkBox
}
Rectangle{
height: 1
Layout.preferredWidth: 190
Layout.leftMargin: 5
color: "lightgrey"
}
CheckBox{
id:forward
text: "Forward property to user."
}
Label{
text: "Propertyname for the user:"
Layout.leftMargin: 10
color: forward.checked?"black":"grey"
}
TextInputField{
Layout.preferredWidth: 190
Layout.leftMargin: 10
Layout.bottomMargin: 10
enabled: forward.checked
color: forward.checked?"black":"grey"
}
}
}
}
Popup{
x: (parent.width - width) / 2
y: (parent.height - height) / 2
//modality: Qt.WindowModal
id:addEntry
//title: "Choose entry"
width:300
contentItem: RowLayout {
anchors.left: addEntry.left;
anchors.right: addEntry.right;
Layout.fillWidth: true
ColumnLayout{
Layout.fillWidth: true
ComboBox{
textRole: "display"
id:comboBoxEntry
Layout.fillWidth: true
model: programEditor.possibleEntryModel
}
RowLayout{
Label{
text:"Length/Size"
}
TextInputField{
Layout.fillWidth: true
id:text_size
text:"50"
validator: IntValidator{
bottom: 1
top: 1000
}
}
}
RowLayout{
Button{
Layout.fillWidth: true
text:"Cancel"
onClicked: addEntry.visible = false
}
Button{
Layout.fillWidth: true
text:"Create"
enabled: comboBoxEntry.currentIndex>=0 && text_size.text.length>0
onClicked: {
addEntry.visible = false;
programEditor.addEntry(comboBoxEntry.currentIndex,text_size.text)
}
}
}
}
}
}
}
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.3
import custom.licht 1.0
import Qt.labs.handlers 1.0
Label{
z: 10
objectName: "Test"
//DragHandler{}
clip: true
background: Rectangle{
color:"lightblue"
}
id:label
ToolTip.text: label.text
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
//ToolTip.enabled: label.width<label.contentWidth
}
......@@ -69,8 +69,65 @@ ProgramBlockEditor::ProgramBlockEditor():programBlockEntry(engine,QUrl("qrc:/Pro
}
Q_DECLARE_METATYPE(Modules::PropertyBase *)
void ProgramBlockEditor::updatePossibleEntries(){
QStringList l;
using namespace Modules;
for(const auto & m : ModuleManager::singletone()->getProgrammModules()){
l << QString::fromStdString(m.name()) + "(Program)";
}
for(const auto & m : ModuleManager::singletone()->getFilterModules()){
l << QString::fromStdString(m.name()) + "(Filter)";
}
for(const auto & m : ModuleManager::singletone()->getConsumerModules()){
l << QString::fromStdString(m.name()) + "(Consumer)";
}
possibleEntryModel.setStringList(l);
}
void ProgramBlockEditor::addEntry(int index, int size){
if(index < 0 || index >= possibleEntryModel.rowCount()){
return;
}
using namespace Modules;
QString name = possibleEntryModel.data(possibleEntryModel.index(index)).toString();
if(name.endsWith("(Program)")){
auto p = ModuleManager::singletone()->createProgramm(name.left(name.length()-9).toStdString());
if(p){
p->setOutputLength(size);
programBlock->addProgramm(p);
qDebug() << "added";
recreateView();
}else{
qDebug()<<"Invalid pointer for : " << name;
}
} else if(name.endsWith("(Filter)")){
auto p = ModuleManager::singletone()->createFilter(name.left(name.length()-8).toStdString());
if(p){
p->setInputLength(size);
programBlock->addFilter(Modules::detail::Connection(p),1);
qDebug() << "added";
recreateView();
}else{
qDebug()<<"Invalid pointer for : " << name;
}
} else if(name.endsWith("(Consumer)")){
auto p = ModuleManager::singletone()->createConsumer(name.left(name.length()-10).toStdString());
if(p){
p->setInputLength(size);
programBlock->addConsumer(Modules::detail::Connection(p));
recreateView();
qDebug() << "added";
}else{
qDebug()<<"Invalid pointer for : " << name;
}
}else{
qDebug() << "ERROR : " << name;
}
}
void ProgramBlockEditor::recreateView(){
for(auto i : this->childItems()){
if(i->objectName()=="removeable")
i->setParentItem(nullptr);
}
if(!programBlock)
......@@ -83,8 +140,9 @@ void ProgramBlockEditor::recreateView(){
component->setProperty("text",p.get()->getName());
component->setX(0);
component->setY(y);
component->setWidth(p.get()->getOutputLength());
component->setWidth(p.get()->getOutputLength() * scale);
component->setProperty("propertyBase",QVariant::fromValue(static_cast<PropertyBase*>(p.get())));
component->setObjectName("removeable");
y += 70;
components[p.get()] = component;
}
......@@ -93,8 +151,9 @@ void ProgramBlockEditor::recreateView(){
component->setProperty("text",dynamic_cast<Named*>(p.second.source.get())->getName());
component->setX(0);
component->setY(y);
component->setWidth(p.second.source.get()->getInputLength());
component->setWidth(p.second.source.get()->getInputLength() * scale);
component->setProperty("propertyBase",QVariant::fromValue(dynamic_cast<PropertyBase*>(p.second.source.get())));
component->setObjectName("removeable");
y += 70;
components[dynamic_cast<Named*>(p.second.source.get())] = component;
}
......@@ -103,8 +162,9 @@ void ProgramBlockEditor::recreateView(){
component->setProperty("text",dynamic_cast<Named*>(p.source.get())->getName());
component->setX(0);
component->setY(y);
component->setWidth(p.source.get()->getInputLength());
component->setWidth(p.source.get()->getInputLength() * scale);
component->setProperty("propertyBase",QVariant::fromValue(dynamic_cast<PropertyBase*>(p.source.get())));
component->setObjectName("removeable");
y += 70;
components[dynamic_cast<Named*>(p.source.get())] = component;
}
......@@ -117,14 +177,15 @@ void ProgramBlockEditor::recreateView(){
component->setParentItem(this);
QQmlEngine::setObjectOwnership(component,QQmlEngine::JavaScriptOwnership);
component->setProperty("targetStartIndex",c.second.startIndex);
component->setProperty("targetLength",c.first);
component->setProperty("targetLength",c.first*scale);
component->setProperty("sourceStartIndex",index);
component->setProperty("sourceLength",c.first);
component->setProperty("sourceLength",c.first*scale);
const auto elem1 = components[dynamic_cast<Named*>(c.second.targed)];
component->setProperty("targetBaseline",elem1->y() + elem1->height());
const auto elem2 = components[dynamic_cast<Named*>(p.second.source.get())];
component->setProperty("sourceBaseline",elem2->y());
component->setProperty("color",QColor(23,255,23));
component->setObjectName("removeable");
index += c.first;
QObject::connect(elem1,&QQuickItem::xChanged,[=](){
......@@ -150,14 +211,15 @@ void ProgramBlockEditor::recreateView(){
component->setParentItem(this);
QQmlEngine::setObjectOwnership(component,QQmlEngine::JavaScriptOwnership);
component->setProperty("targetStartIndex",c.second.startIndex);
component->setProperty("targetLength",c.first);
component->setProperty("targetLength",c.first*scale);
component->setProperty("sourceStartIndex",index);
component->setProperty("sourceLength",c.first);
component->setProperty("sourceLength",c.first*scale);
const auto elem1 = components[dynamic_cast<Named*>(c.second.targed)];
component->setProperty("targetBaseline",elem1->y() + elem1->height());
const auto elem2 = components[dynamic_cast<Named*>(p.source.get())];
component->setProperty("sourceBaseline",elem2->y());
component->setProperty("color",QColor(23,255,23));
component->setObjectName("removeable");
index += c.first;
QObject::connect(elem1,&QQuickItem::xChanged,[=](){
......@@ -183,6 +245,38 @@ void ProgramBlockEditor::recreateView(){
}
}
void print(PropertyInformationModel * p){
for(const auto &o:*p){
qDebug()<<o->getName() << o->getValue();
}
}
template<typename TargetType>
void transferData(::detail::PropertyInformation *pi,Modules::Property * p){
p->asNumeric<TargetType>()->setValue(pi->getValue().value<TargetType>());
}
void detail::PropertyInformation::updateValue(){
qDebug()<<"set value";
using namespace Modules;
switch (getType()) {
case Property::Double: transferData<double>(this,property);
break;
case Property::Float: transferData<float>(this,property);
break;
case Property::Int: transferData<int>(this,property);
break;
case Property::Long: transferData<long>(this,property);
break;
case Property::Bool:
property->asBool()->setValue(getValue().toBool());
break;
case Property::String:
property->asString()->setValue(getValue().toString().toStdString());
}
}
template<typename SourceType>
void transferData(Modules::Property & p, ::detail::PropertyInformation &pi){
pi.setValue(p.asNumeric<SourceType>()->getValue());
......@@ -208,6 +302,7 @@ void ProgramBlockEditor::mouseReleaseEvent(QMouseEvent *event){
comp = comp->parentItem();
}
if(comp->property("propertyBase").isValid()){
print(getPropertyInformationModel());
Modules::PropertyBase * pb = comp->property("propertyBase").value<Modules::PropertyBase*>();
if(propertyInformationModel.size()>pb->getProperties().size()){
for(auto i = propertyInformationModel.cbegin()+pb->getProperties().size();i!=propertyInformationModel.cend();++i){
......@@ -223,6 +318,7 @@ void ProgramBlockEditor::mouseReleaseEvent(QMouseEvent *event){
for(auto t = propertyInformationModel.cbegin();t!=propertyInformationModel.cend();++t,++s){
auto & tp = **t;
auto & sp = **s;
tp.property = *s;
tp.setDescription(QString::fromStdString(sp.getDescription()));
tp.setName(QString::fromStdString(sp.getName()));
tp.setType(sp.type);
......@@ -245,6 +341,7 @@ void ProgramBlockEditor::mouseReleaseEvent(QMouseEvent *event){
}
}
print(getPropertyInformationModel());
setShowProperties(true);
}else{
......
......@@ -4,6 +4,7 @@
#include <QQuickItem>
#include "programms/programblock.h"
#include "programms/modulemanager.h"
#include <QStringListModel>
namespace detail {
class PropertyInformation : public QObject{
......@@ -11,7 +12,9 @@ namespace detail {
public:
typedef Modules::Property::Type Type;
Q_ENUM(Type)
Modules::Property * property = nullptr;
private:
void updateValue();
//auto generated class:
QVariant minValue;
QVariant maxValue;
......@@ -52,6 +55,7 @@ namespace detail {
void setValue( const QVariant _value){
if(_value != value){
value = _value;
updateValue();
emit valueChanged();
}
}
......@@ -125,23 +129,42 @@ class PropertyInformationModel : public ModelVector<detail::PropertyInformation*
class ProgramBlockEditor : public QQuickItem
{
Q_OBJECT
Modules::ProgramBlock * programBlock;
Modules::ProgramBlock * programBlock = nullptr;
PropertyInformationModel propertyInformationModel;
bool showProperties;
QStringListModel possibleEntryModel;
Q_PROPERTY(Modules::ProgramBlock* programBlock READ getProgramBlock WRITE setProgramBlock NOTIFY programBlockChanged)
Q_PROPERTY(PropertyInformationModel * propertyInformationModel READ getPropertyInformationModel CONSTANT)
Q_PROPERTY(QAbstractListModel * possibleEntryModel READ getPossibleEntryModel 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;
double scale = 2;
bool run;
private:
void recreateView();
public:
/** Wird vom ModuleProgramView aufgerufen wenn ein neuer entry hinzugefügt werden soll
*
*
*/
Q_INVOKABLE void updatePossibleEntries();
/**
* @brief addEntry fügt den Entry an position index im possibleEntryModel hinzu
* @param index Der index im possibleEntryModel
* @param size Die inputoutput größe des entries
*/
Q_INVOKABLE void addEntry(int index, int size);
static QQmlEngine * engine;
ProgramBlockEditor();void setProgramBlock( Modules::ProgramBlock* _programBlock){
ProgramBlockEditor();
void setProgramBlock( Modules::ProgramBlock* _programBlock){
if(_programBlock != programBlock){
qDebug () << "Program Block changed";
programBlock = _programBlock;
recreateView();
run = Modules::ModuleManager::singletone()->controller().isProgramRunning(programBlock);
emit runChanged();
emit programBlockChanged();
}
}
......@@ -151,15 +174,31 @@ public:
PropertyInformationModel *getPropertyInformationModel() {
return &propertyInformationModel;
}
QAbstractListModel *getPossibleEntryModel() {
return &possibleEntryModel;
}
void setShowProperties( const bool _showProperties){
if(_showProperties != showProperties){
//if(_showProperties != showProperties){
showProperties = _showProperties;
emit showPropertiesChanged();
}
//}
}
bool getShowProperties() const {
return showProperties;
}
void setRun( const bool _run){
if(_run != run){
run = _run;
if(run)
Modules::ModuleManager::singletone()->controller().runProgramm(*std::find_if(Modules::ProgramBlockManager::model.cbegin(),Modules::ProgramBlockManager::model.cend(),[&](const auto &v){return v.get()==programBlock;}));
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;
......@@ -167,6 +206,7 @@ protected:
signals:
void programBlockChanged();
void showPropertiesChanged();
void runChanged();
};
#endif // PROGRAMBLOCKEDITOR_H
......@@ -34,6 +34,11 @@ void Controller::stopProgramm(std::shared_ptr<ProgramBlock> pb){
runningProgramms.erase(std::remove(runningProgramms.begin(),runningProgramms.end(),pb),runningProgramms.end());
pb->stop();
}
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();
}
bool Controller::isProgramRunning(ProgramBlock * pb){
std::unique_lock<std::mutex> l(vectorLock);
......
......@@ -35,6 +35,7 @@ public:
~Controller(){run_ = false;thread.join();}
void runProgramm(std::shared_ptr<ProgramBlock> pb);
void stopProgramm(std::shared_ptr<ProgramBlock> pb);
void stopProgramm(ProgramBlock* pb);
bool isProgramRunning(ProgramBlock * pb);
};
}
......
......@@ -97,7 +97,7 @@ namespace Modules {
std::set<std::shared_ptr<Program>> programs;
// verschiedene Ebenen von Filtern
std::map<int,detail::Connection> filter;
std::multimap<int,detail::Connection> filter;
// a list of all consumer and their connections
std::vector<detail::Connection> consumer;
......@@ -187,7 +187,7 @@ namespace Modules {
}
const std::set<std::shared_ptr<Program>> & getPrograms()const{return programs;}
// verschiedene Ebenen von Filtern
const std::map<int,detail::Connection> & getFilter()const{return filter;}
const std::multimap<int,detail::Connection> & getFilter()const{return filter;}
// a list of all consumer and their connections
const std::vector<detail::Connection> getConsumer()const{return consumer;}
......
......@@ -23,7 +23,7 @@ namespace Modules {
std::string name;
std::string description;
public:
const enum Type {Int, Long, Float, Double, Bool, String} type;
const enum Type {Int=0, Long=1, Float=2, Double=3, Bool=4, String=5} type;
protected:
Property(Type t):type(t){}
public:
......
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