added feature of grouping of parameter
This commit is contained in:
parent
a099eab1ea
commit
2db79cf7c4
11 changed files with 313 additions and 36 deletions
|
|
@ -397,7 +397,8 @@ HEADERS += src/version_check.h \
|
|||
src/parameter/parameterslider.h \
|
||||
src/parameter/parametercheckbox.h \
|
||||
src/parameter/parametertext.h \
|
||||
src/parameter/parametervector.h
|
||||
src/parameter/parametervector.h \
|
||||
src/parameter/groupwidget.h
|
||||
|
||||
SOURCES += \
|
||||
src/libsvg/libsvg.cc \
|
||||
|
|
@ -532,7 +533,8 @@ SOURCES += \
|
|||
src/parameter/parameterslider.cpp \
|
||||
src/parameter/parametercheckbox.cpp \
|
||||
src/parameter/parametertext.cpp \
|
||||
src/parameter/parametervector.cpp
|
||||
src/parameter/parametervector.cpp \
|
||||
src/parameter/groupwidget.cpp
|
||||
|
||||
|
||||
# ClipperLib
|
||||
|
|
|
|||
|
|
@ -34,6 +34,11 @@ std::string LocalScope::dump(const std::string &indent) const
|
|||
for(const auto &ass : this->assignments) {
|
||||
if( ass.has_annotations()){
|
||||
|
||||
const Annotation *group =ass.annotation("Group");
|
||||
if( group != NULL){
|
||||
dump<<group->dump();
|
||||
}
|
||||
|
||||
const Annotation *Description=ass.annotation("Description");
|
||||
if( Description != NULL){
|
||||
dump<<Description->dump();
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ void ParameterWidget::begin()
|
|||
this->scrollAreaWidgetContents->layout()->removeWidget(w);
|
||||
delete w;
|
||||
}
|
||||
anyLayout = new QVBoxLayout();
|
||||
}
|
||||
|
||||
void ParameterWidget::addEntry(ParameterVirtualWidget *entry)
|
||||
|
|
@ -92,7 +93,7 @@ void ParameterWidget::addEntry(ParameterVirtualWidget *entry)
|
|||
policy.setHorizontalStretch(0);
|
||||
policy.setVerticalStretch(0);
|
||||
entry->setSizePolicy(policy);
|
||||
this->scrollAreaWidgetContents->layout()->addWidget(entry);
|
||||
anyLayout->addWidget(entry);
|
||||
}
|
||||
|
||||
void ParameterWidget::end()
|
||||
|
|
@ -109,6 +110,45 @@ void ParameterWidget::end()
|
|||
|
||||
void ParameterWidget::connectWidget()
|
||||
{
|
||||
// clear previous entries in groupMap and entries
|
||||
clear();
|
||||
|
||||
vector<string> global;
|
||||
if(groupMap.find("Global")!=groupMap.end()){
|
||||
global=groupMap["Global"].parameterVector;
|
||||
groupMap["Global"].parameterVector.clear();
|
||||
}
|
||||
|
||||
for(group_map::iterator it = groupMap.begin(); it != groupMap.end(); ) {
|
||||
vector<string> gr;
|
||||
gr=it->second.parameterVector;
|
||||
if(gr.empty()|| it->first=="Hidden"){
|
||||
it=groupMap.erase(it);
|
||||
}
|
||||
else{
|
||||
|
||||
it->second.parameterVector.insert( it->second.parameterVector.end(), global.begin(), global.end() );
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
begin();
|
||||
for(group_map::iterator it = groupMap.begin(); it != groupMap.end(); it++) {
|
||||
vector<string> gr;
|
||||
gr=it->second.parameterVector;
|
||||
|
||||
for(int i=0;i <gr.size();i++){
|
||||
AddParameterWidget(gr[i]);
|
||||
}
|
||||
GroupWidget *groupWidget =new GroupWidget(it->second.show ,QString::fromStdString(it->first));
|
||||
groupWidget->setContentLayout(*anyLayout);
|
||||
this->scrollAreaWidgetContents->layout()->addWidget(groupWidget);
|
||||
anyLayout = new QVBoxLayout();
|
||||
}
|
||||
end();
|
||||
}
|
||||
|
||||
void ParameterWidget::clear(){
|
||||
for(entry_map_t::iterator it = entries.begin(); it != entries.end();) {
|
||||
if(!(*it).second->set){
|
||||
it=entries.erase(it);
|
||||
|
|
@ -116,41 +156,58 @@ void ParameterWidget::connectWidget()
|
|||
it++;
|
||||
}
|
||||
}
|
||||
for(group_map::iterator it = groupMap.begin(); it != groupMap.end(); it++) {
|
||||
it->second.parameterVector.clear();
|
||||
}
|
||||
|
||||
|
||||
begin();
|
||||
for(entry_map_t::iterator it = entries.begin(); it != entries.end(); it++) {
|
||||
if(groupMap.find(it->second->groupName) == groupMap.end()){
|
||||
groupInst enter;
|
||||
enter.parameterVector.push_back(it->first);
|
||||
enter.show=false;
|
||||
groupMap[it->second->groupName]=enter;
|
||||
}
|
||||
else{
|
||||
groupMap[it->second->groupName].parameterVector.push_back(it->first);
|
||||
|
||||
ParameterVirtualWidget *entry ;
|
||||
switch (it->second->target) {
|
||||
case COMBOBOX:{
|
||||
entry = new ParameterComboBox(it->second,descriptionShow);
|
||||
break;
|
||||
}
|
||||
case SLIDER:{
|
||||
entry = new ParameterSlider(it->second,descriptionShow);
|
||||
break;
|
||||
}
|
||||
case CHECKBOX:{
|
||||
entry = new ParameterCheckBox(it->second,descriptionShow);
|
||||
break;
|
||||
}
|
||||
case TEXT:{
|
||||
entry = new ParameterText(it->second,descriptionShow);
|
||||
break;
|
||||
}
|
||||
case NUMBER:{
|
||||
entry = new ParameterSpinBox(it->second,descriptionShow);
|
||||
break;
|
||||
}
|
||||
case VECTOR:{
|
||||
entry = new ParameterVector(it->second,descriptionShow);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ParameterWidget::AddParameterWidget(string parameterName){
|
||||
ParameterVirtualWidget *entry ;
|
||||
switch (entries[parameterName]->target) {
|
||||
case COMBOBOX:{
|
||||
entry = new ParameterComboBox(entries[parameterName],descriptionShow);
|
||||
break;
|
||||
}
|
||||
if(it->second->target!=UNDEFINED){
|
||||
connect(entry, SIGNAL(changed()), this, SLOT(onValueChanged()));
|
||||
addEntry(entry);
|
||||
case SLIDER:{
|
||||
entry = new ParameterSlider(entries[parameterName],descriptionShow);
|
||||
break;
|
||||
}
|
||||
case CHECKBOX:{
|
||||
entry = new ParameterCheckBox(entries[parameterName],descriptionShow);
|
||||
break;
|
||||
}
|
||||
case TEXT:{
|
||||
entry = new ParameterText(entries[parameterName],descriptionShow);
|
||||
break;
|
||||
}
|
||||
case NUMBER:{
|
||||
entry = new ParameterSpinBox(entries[parameterName],descriptionShow);
|
||||
break;
|
||||
}
|
||||
case VECTOR:{
|
||||
entry = new ParameterVector(entries[parameterName],descriptionShow);
|
||||
break;
|
||||
}
|
||||
}
|
||||
end();
|
||||
if(entries[parameterName]->target!=UNDEFINED){
|
||||
connect(entry, SIGNAL(changed()), this, SLOT(onValueChanged()));
|
||||
addEntry(entry);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,15 +30,18 @@
|
|||
|
||||
#include "parameterextractor.h"
|
||||
#include "ui_ParameterWidget.h"
|
||||
|
||||
#include "groupwidget.h"
|
||||
|
||||
class ParameterWidget : public QWidget, public Ui::ParameterWidget, public ParameterExtractor
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
typedef std::map<std::string,groupInst > group_map;
|
||||
group_map groupMap;
|
||||
typedef enum { UNDEFINED, COMBOBOX, SLIDER, CHECKBOX, TEXT, NUMBER, VECTOR } parameter_type_t;
|
||||
QTimer autoPreviewTimer;
|
||||
bool descriptionShow;
|
||||
QVBoxLayout * anyLayout;
|
||||
|
||||
public:
|
||||
ParameterWidget(QWidget *parent = 0);
|
||||
|
|
@ -57,4 +60,6 @@ protected:
|
|||
void begin();
|
||||
void addEntry(class ParameterVirtualWidget *entry);
|
||||
void end();
|
||||
void clear();
|
||||
void AddParameterWidget(string parameterName);
|
||||
};
|
||||
|
|
|
|||
75
src/parameter/groupwidget.cpp
Normal file
75
src/parameter/groupwidget.cpp
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#include "groupwidget.h"
|
||||
|
||||
#include <QPropertyAnimation>
|
||||
|
||||
GroupWidget::GroupWidget(bool &show, const QString & title, const int animationDuration, QWidget *parent) : QWidget(parent), animationDuration(animationDuration) {
|
||||
toggleButton.setStyleSheet("QToolButton { border: none; }");
|
||||
toggleButton.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
toggleButton.setText(title);
|
||||
toggleButton.setCheckable(true);
|
||||
|
||||
headerLine.setFrameShape(QFrame::HLine);
|
||||
headerLine.setFrameShadow(QFrame::Sunken);
|
||||
headerLine.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
|
||||
|
||||
contentArea.setStyleSheet("QScrollArea { background-color: white; border: none; }");
|
||||
contentArea.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
// start out collapsed
|
||||
contentArea.setMaximumHeight(0);
|
||||
contentArea.setMinimumHeight(0);
|
||||
// let the entire widget grow and shrink with its content
|
||||
toggleAnimation.addAnimation(new QPropertyAnimation(this, "minimumHeight"));
|
||||
toggleAnimation.addAnimation(new QPropertyAnimation(this, "maximumHeight"));
|
||||
toggleAnimation.addAnimation(new QPropertyAnimation(&contentArea, "maximumHeight"));
|
||||
|
||||
this->show=&show;
|
||||
toggleButton.setChecked(show);
|
||||
|
||||
// don't waste space
|
||||
mainLayout.setVerticalSpacing(0);
|
||||
mainLayout.setContentsMargins(0, 0, 0, 0);
|
||||
int row = 0;
|
||||
mainLayout.addWidget(&toggleButton, row, 0, 1, 1, Qt::AlignLeft);
|
||||
mainLayout.addWidget(&headerLine, row++, 2, 1, 1);
|
||||
mainLayout.addWidget(&contentArea, row, 0, 1, 3);
|
||||
setLayout(&mainLayout);
|
||||
QObject::connect(&toggleButton, SIGNAL(toggled(bool)),this, SLOT(onclicked(bool)));
|
||||
}
|
||||
|
||||
|
||||
void GroupWidget::onclicked(const bool checked){
|
||||
toggleButton.setArrowType(toggleButton.isChecked() ? Qt::DownArrow : Qt::RightArrow);
|
||||
toggleAnimation.setDirection(toggleButton.isChecked() ? QAbstractAnimation::Forward : QAbstractAnimation::Backward);
|
||||
toggleAnimation.start();
|
||||
if(toggleButton.isChecked()){
|
||||
*(this->show)=true;
|
||||
}else{
|
||||
*(this->show)=false;
|
||||
}
|
||||
this->animationDuration=300;
|
||||
}
|
||||
|
||||
void GroupWidget::setContentLayout(QLayout & contentLayout) {
|
||||
delete contentArea.layout();
|
||||
contentArea.setLayout(&contentLayout);
|
||||
const int collapsedHeight = sizeHint().height() - contentArea.maximumHeight();
|
||||
int contentHeight = contentLayout.sizeHint().height();
|
||||
for (int i = 0; i < toggleAnimation.animationCount() - 1; ++i) {
|
||||
QPropertyAnimation * GroupWidgetAnimation = static_cast<QPropertyAnimation *>(toggleAnimation.animationAt(i));
|
||||
GroupWidgetAnimation->setDuration(animationDuration);
|
||||
GroupWidgetAnimation->setStartValue(collapsedHeight);
|
||||
GroupWidgetAnimation->setEndValue(collapsedHeight + contentHeight);
|
||||
}
|
||||
QPropertyAnimation * contentAnimation = static_cast<QPropertyAnimation *>(toggleAnimation.animationAt(toggleAnimation.animationCount() - 1));
|
||||
contentAnimation->setDuration(animationDuration);
|
||||
contentAnimation->setStartValue(0);
|
||||
contentAnimation->setEndValue(contentHeight);
|
||||
|
||||
if(*(this->show)){
|
||||
toggleButton.setArrowType(Qt::DownArrow);
|
||||
toggleAnimation.start();
|
||||
}else{
|
||||
toggleButton.setArrowType(Qt::RightArrow);
|
||||
}
|
||||
|
||||
}
|
||||
37
src/parameter/groupwidget.h
Normal file
37
src/parameter/groupwidget.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef GROUPWIDGET_H
|
||||
#define GROUPWIDGET_H
|
||||
|
||||
|
||||
#include <QFrame>
|
||||
#include <QGridLayout>
|
||||
#include <QParallelAnimationGroup>
|
||||
#include <QScrollArea>
|
||||
#include <QToolButton>
|
||||
#include <QWidget>
|
||||
#include <vector>
|
||||
|
||||
struct groupInst{
|
||||
std::vector<std::string> parameterVector;
|
||||
bool show;
|
||||
};
|
||||
|
||||
class GroupWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
private:
|
||||
QGridLayout mainLayout;
|
||||
QToolButton toggleButton;
|
||||
QFrame headerLine;
|
||||
QParallelAnimationGroup toggleAnimation;
|
||||
QScrollArea contentArea;
|
||||
int animationDuration;
|
||||
bool *show;
|
||||
public:
|
||||
groupInst groupinst;
|
||||
explicit GroupWidget(bool &show,const QString & title = "", const int animationDuration = 0, QWidget *parent = 0);
|
||||
void setContentLayout(QLayout & contentLayout);
|
||||
|
||||
private slots:
|
||||
void onclicked(bool);
|
||||
};
|
||||
|
||||
#endif // GROUPWIDGET_H
|
||||
|
|
@ -55,10 +55,20 @@ void ParameterObject::setAssignment(Context *ctx, const Assignment *assignment,
|
|||
description=QString::fromStdString(v->toString());
|
||||
}
|
||||
}
|
||||
|
||||
const Annotation *group = assignment->annotation("Group");
|
||||
if (group) {
|
||||
const ValuePtr v = group->evaluate(ctx, "text");
|
||||
if (v->type() == Value::STRING) {
|
||||
groupName=v->toString();
|
||||
}
|
||||
} else{
|
||||
groupName="Parameters";
|
||||
}
|
||||
}
|
||||
|
||||
bool ParameterObject::operator == (const ParameterObject &second)
|
||||
{
|
||||
return (this->defaultValue == second.defaultValue && this->values==second.values &&
|
||||
this->description == second.description);
|
||||
this->description == second.description && this->groupName == second.groupName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ public:
|
|||
QString description;
|
||||
string name;
|
||||
bool set;
|
||||
string groupName;
|
||||
|
||||
private:
|
||||
Value::ValueType vt;
|
||||
|
|
|
|||
42
testdata/scad/customizer/group.scad
vendored
Normal file
42
testdata/scad/customizer/group.scad
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// combo box for nunber
|
||||
Numbers=2; // [0, 1, 2, 3]
|
||||
|
||||
// combo box for string
|
||||
Strings="foo"; // [foo, bar, baz]
|
||||
|
||||
//labeled combo box for numbers
|
||||
Labeled_values=10; // [10:L, 20:M, 30:L]
|
||||
|
||||
//labeled combo box for string
|
||||
Labeled_value="S"; // [S:Small, M:Medium, L:Large]
|
||||
|
||||
/*[ Global ]*/
|
||||
// slider widget for number
|
||||
slider =34; // [10:100]
|
||||
|
||||
//step slider for number
|
||||
stepSlider=2; //[0:5:100]
|
||||
|
||||
/* [Hidden] */
|
||||
|
||||
//description
|
||||
Variable = true; //comment
|
||||
|
||||
/*[Global] */
|
||||
|
||||
// spinbox with step size 23
|
||||
Spinbox = 5; //23
|
||||
|
||||
/* [Textbox] */
|
||||
|
||||
//Text box for vector with more than 4 elements
|
||||
Vector=[12,34,44,43,23,23];//comment
|
||||
|
||||
// Text box for string
|
||||
String="hello"; //comment
|
||||
|
||||
/* [Special vector] */
|
||||
//Text box for vector with less than or equal to 4 elements
|
||||
Vector2=[12,34,45,23]; //any thing
|
||||
|
||||
echo(String);
|
||||
|
|
@ -1613,6 +1613,7 @@ add_cmdline_test(customizertest EXE ${OPENSCAD_BINPATH} ARGS -o SUFFIX ast FILES
|
|||
${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/allmodulescomment.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/allfunctionscomment.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/allexpressionscomment.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/group.scad
|
||||
)
|
||||
|
||||
# Tests using the actual OpenSCAD binary
|
||||
|
|
|
|||
42
tests/regression/customizertest/group-expected.ast
Normal file
42
tests/regression/customizertest/group-expected.ast
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
@Description("combo box for nunber")
|
||||
@Parameter([0, 1, 2, 3])
|
||||
Numbers = 2;
|
||||
@Description("combo box for string")
|
||||
@Parameter(["foo", "bar", "baz"])
|
||||
Strings = "foo";
|
||||
@Description("labeled combo box for numbers")
|
||||
@Parameter([[10, "L"], [20, "M"], [30, "L"]])
|
||||
Labeled_values = 10;
|
||||
@Description("labeled combo box for string")
|
||||
@Parameter([["S", "Small"], ["M", "Medium"], ["L", "Large"]])
|
||||
Labeled_value = "S";
|
||||
@Group(" Global ")
|
||||
@Description("slider widget for number")
|
||||
@Parameter([10 : 100])
|
||||
slider = 34;
|
||||
@Group(" Global ")
|
||||
@Description("step slider for number")
|
||||
@Parameter([0 : 5 : 100])
|
||||
stepSlider = 2;
|
||||
@Group("Hidden")
|
||||
@Description("description")
|
||||
@Parameter("comment")
|
||||
Variable = true;
|
||||
@Group("Global")
|
||||
@Description("spinbox with step size 23")
|
||||
@Parameter(23)
|
||||
Spinbox = 5;
|
||||
@Group("Textbox")
|
||||
@Description("Text box for vector with more than 4 elements")
|
||||
@Parameter("comment")
|
||||
Vector = [12, 34, 44, 43, 23, 23];
|
||||
@Group("Textbox")
|
||||
@Description("Text box for string")
|
||||
@Parameter("comment")
|
||||
String = "hello";
|
||||
@Group("Special vector")
|
||||
@Description("Text box for vector with less than or equal to 4 elements")
|
||||
@Parameter("any thing")
|
||||
Vector2 = [12, 34, 45, 23];
|
||||
echo(String);
|
||||
|
||||
Loading…
Reference in a new issue