From b7b2681c74d509109782c42ea0deb3ddcf1ad5e2 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Thu, 2 Jan 2014 23:29:48 +0100 Subject: [PATCH] Add GUI Settings page to enable/disable features. --- icons/license.txt | 3 ++ icons/prefsFeatures.png | Bin 0 -> 6099 bytes openscad.qrc | 1 + src/Preferences.cc | 55 ++++++++++++++++------- src/Preferences.h | 3 ++ src/Preferences.ui | 96 ++++++++++++++++++++++++++++++++++++++-- src/feature.cc | 37 +++++++++++----- src/feature.h | 21 ++++++--- 8 files changed, 179 insertions(+), 37 deletions(-) create mode 100644 icons/license.txt create mode 100644 icons/prefsFeatures.png diff --git a/icons/license.txt b/icons/license.txt new file mode 100644 index 00000000..97e6931b --- /dev/null +++ b/icons/license.txt @@ -0,0 +1,3 @@ +Taken from http://tango.freedesktop.org/Tango_Icon_Library, version 0.8.90 / public domain: + +- prefsFeatures.png (converted from preferences-system.svg) diff --git a/icons/prefsFeatures.png b/icons/prefsFeatures.png new file mode 100644 index 0000000000000000000000000000000000000000..2fb0a5581fd6e2f2b891bc668d563006f7ebd1ac GIT binary patch literal 6099 zcmV;^7cA(BP)x!VF78tOk! z7})|s{E+YhQUf6;A;cjL@_x(xWf)17PO4uY3zGbx`a4hj@Dl-V zXxLmy7~PkZl}*;JSqDPMb?g@&VwIvWsZF=zTIbaYMWeIMHZ}jQqM}0FTj*DxmLUJ=_4$-}6$`1ND2Vj+Ej@Vn#H`~- z54^r)$r66gzyY9g`HDRs9NHHR1OlJ8Op}z9ltNJy7={7UG+|j56h%RPem-0-7wPD@ zGQ&tEtmO}^*mp00UwiE}_QviHe*}Ws!lEKFeb!9E7=y>>h0Sh9Z@6bhTBr{lIDYuI zm5Ub}_iT)h80$|+B7Zh*>U8qJvPuHrx}JABonVaNgF^>!{`|SL;ABR1b@j!&tMgU2 z(DBcZcx1}7sVFWjg^&^>c_O`iXl`oag7Y>|>rXa5^VF5$XY^i3e#3^EUr5L=x3r$; zzu)tokW#|sa)D9`DJA0ZIHZ(VxL^@fO=DD%TkfX5%|G}>snqEqO6lk3Eu4?ii4$&s z1^{1{A9EHiV2Y}iL#iKc{o&82+*5D>s9wM6*AleqO2=jM-S>8LLI^ZX0{}=VVHgH% zHXCNmoW%eQP!GDhx*&n|HQ)W(@msRowr;Ec4uQ|#1U)9ys z-O{iS6b}Oc7Xpf+KvmU@$`6Bci&Fr1WW)#|z%2`=na&8nG}AECX>iMgLV>P80MTea zRAAtE;o!YzS`MzU9Y6qGmtyGw3%i^(qp$}o&9LX1OVXNf)pHPdJxze&doGbg(4msz_qIZ zDG3_B|IF9MokMN_Cjy3PnlzbAA{L9m@6W>8HS36?Dv#J*`oA_dHo8ZDvt!2&wQ<{) zeMC`oJw4EC21)B1m#000Io%VypR z^!DxlD^IFqkIiN)nLls3B7{IZkwA{m10f~2#bF5!%d~K{D>$box zDvvS=MEj%g`}{CX6NX{H@AqTvqhDk#tu2KEvHrqnf7FWg$4JshFv=9M`jIsxH#Zl_ zWHK|O-?*+4l$K1u$&<&O$z>8je=+Vtr6>R$P!Plwo}>)Py! z`7;?IKu=!;xmkV$yTh`r{VF);FB6I;NZKcWUZL>57ry<6p~nSp*tU6#rs?ay^56*5%V!;f?C`ETq7%V3}s@*vH3& zrfJZ1Ju@>8FHelI%=jHv?UC<{d@mdhZz6%|3(b!eJ~D;<~d#;%swIo&P>0=yKrn=Yyc~3gdSz2{8@LqTsCo9upWdxyeN%tDVO#w_ z5<>n{)#|mFI%O)PlsCYS9sqfA-Hz!8l;pcEG&es>tKxG zLfZwr_4Y1EmeooXZOZ)>vx(d3Kv#DUiVE@&425y(%mvB0_-6HUPwcoCF2zkFFqO+! z>^yLAe@;v5`TK?7Lyfg%RG3nlvB!r~B9Xwkb7zs4mk&izpzAu~@i>ynB>a9qyk0L7 zi3Adf1Y9l`6h%RHRyHnn^dezc+4nD;NxU8xf}t>q^79Z1_u*tys}#ce&(+U8c~78k zIRewTee*Mf&^kh>r()q^I%(1**WN?obeC&z=#j7h0$g0+S|8;_KG^ zJH{A;VHmh}?HUwCL2+?0q?8B*0w9DSKR+M4e}5P)ZC6k+e+IJr9t1;S36ffi31}XX2y%iTlkD<_4I8dz+}iDbyNZInU0znMuBmz~1K-uv z1w~O%P*8yP_kV<@<_lObcRKR(vJvX(MNYOK;oc}dK6wt38-Ks?JKy~FClQV&pX3%& zV`KfppybV|Q>H0jc%+I^N|8t;5DJBG`rIY7v~^(K>}e=0$U(R_f-Jumy}kW7cCs0T zc}^L)dLbpbczEN+O&{Fzc*!TZv$0{r_umtetZlu}!r$5bmJmX~ZnvZDN)Rn=9hg0{ z97P4W=u30gIc(aP>;g3#Z#`MXUR9b|-XcS(L8-0-&j-5D*1#_lh>7uz%6a_*Ey!FnT zqW$89h()oi=DRg5pK9>3H4T3urECOHs3=rW%49liGLM7e^YeUIwxAqk6H5?{#o%%} z5s3~$FIzMR6N+=e7=zdAg`y}hEfc%m+{rtxc63XNF5S3s67vh2q$o*vj;~$K8uu*Lj5;aBHOLN;jj-uH)Fw^saR4m2b^=nVlgnr;C8#A zD1*Mj&ewm-ySlqBQ<+-!{PVTlpDOUOs)iQ`!OP2+%)+$tQYYlOqyO;Yu(Di%TqBJOehHj{ovM z4&t4Cr?70%Tr8SD6E2qvsZP1CVv^<&KI_02Rb?VY;1 zI>-O@9-p*&>qCTK_x#yqv|`?L($$+lERhDJK#o_(wNMP{G>4D^`93=c1P&cN3no+8 z_KgK{$&zKnvMd;efp|O)RaN0|I3R?8VHjYH!Dh2T(=^0lG5l`lZ$vyEdp|LbFMrpz z`mJ13*3{1iA@5EtE7X=&%%VL}1O4$dIOi}ej!3@&%M!3Shh=d@;s(4<9Uv4Pfj-!I zCv2)jad8P54sxW^X^5dHEu|EeWr6cScirJ|V8Vn6gFfzVA=N!po5{X0tUat?Uzp#ety6uY>FSY(`*q8sKfKOiC zxKt?QXhE(&Z&l?2C7$94MF#_vLI~uzb$D$GdIA>_?l_BqND!P0C=^f_MQ>yP0Ez$9 zVKxXUpZf6V5gb49F%(6~z+09D(=;=i5mHK|(`gJ048ZTt!Xux1glL-fmkrzMfA~jH z^~tNZtRs}{npBc!e`w_bmP|`@_a(qNhufi`ILi*s1x}qlg;b&+Om~4Qc7QSz=eUtb zrg5(IG5}Qf?Reo(w#dR9KYp{VmIalrj_T8J?3Y%YxVILtbt^ zE?sV4x_94RQn`G^o=>dDCsj54H3<35jPep~RpopZGdO~M3D`7>(p)FX3fxGgEgU~_ zdE>#)HZJ4{M_{Leggx^ zG_qV8{4NdIZVheMqB#8FQ5cDSFq<1pbA#zlle@O(pdo2k%|I)4v&0|D; zo(1qqJZMS-8` zx|;jo(mAZ8I1fFMBou`VLc29&xpbUp?Z%-aM`6VK!ECNUXqyuSei!U^9Zl!jMX0CG z0?69-T^s*p+@0FS`tMOnwpT8H5L3#hARdor!q$Y4%n=h+RWn-Pa=FlYp+z1#d{A=1 zzg)e3)35IseEQnI%Sm(dM*#jqX;H5DOyzt^DZ_wa!edvEfN^uK6&-lKO>a=Pps($~L{rT6hkV@RjdP!t6&mkUj2PRSD|kEglB!!_$`4&D-Y@!C3v z#`RYL{8?dsj$AlzDk;p*!ayR8Y>$QFM)8hEmzn;gXOYP_nT>;ZwP;@t_ z=0bjs2QIsglV{p_Z(qa&#TVM&sNQqClWF7j`dUKhODk8bLP>EcqR}X%lu%U_ob$}4 zMk+OUic`}xxLhurJat^0J=-)uiJ1Gn?`^t#Q}EJ9Hy5i=-y%fLUNCn$omi3wpT`A- z0(m|gvRv9Av`5F)&;Wk}Dvln?N97z*N9=Z7D z#ydXS*062!%Zw>6tX#1Qg#|^3L?Rh@0GVAJ!!RJFgx~Ln-C@VR{d;*JaP7Fyll{O` zPd#OhyPPSUKE)`R_0Wn6Iv8xIF(Fh`4 zZ6K;0Om%^34tQKnWc!@BcqxETPZScO>TaL`VB`8tFLG{e-G5*&y1F{y@pvGm%!H{; z(?olFJ6c*=(AwIHGiS~qol0X-#bU-7TNI9l|Kz6YIH9zvC_jgK+zyoH`!ONUfrPcQAN{_poP$gy$#ruC+2y|Vw{UWCITc)i|?ssn(}=Y!AZ z%Q!lmb9mfdMnLWxbAOx++JjWF35#=ZE)eez z!%C;XbT^3R1W|0r^0@#)(RB8LCAl~rZGLS7A=S2_vo0Kfkhfqo47G(0B{D|Z^zxQE z`~HLbzOiEYgYf(P5JEszRlNJ|;3}yo3cOzL;NIOp%#x5dY#l3v5E}pnfJ(ueLOs#X zkm-_~X%FM*xgfa3GoBUa0;Xjm-WMF~Y1IL$+M($>d>#ibv|W*gVI-oL_Bw&JqY@eM`|v$ptf_tBZ(gp|4}7riFDoBd3BTVDMN!b*Js6S7 z%F2Sz=R>%+2VGqOC6!EnKnT%?+93wdC;_&iWasI`k;@%jh(re9b7>Hxpe@c3?+t=5 z4McN+YEDS1AV1rUfq^8hUh5*}KzCzb^X@nR2LSts+&-c%8zICoBy=5s3P2kp=_9`x zZYKcymiorpNF?%42M_H>Fc^Tx<3V|OIm*k+k)555NF;(IM-FkzwD#84*8TISa#aSv zGyD&uzoXezwD3!P{R56E6ALLJ68-U12HG@|FyeinnhQ*KK@bH#j{_d34X2yV2_uDafu9zxKeUS#9+;;=Rh=gQDCWhkj5?nnMMoHWa_l*5OP?43Jrjx*HLJ^$*pE5fok z?Fom_)^ev5`TY6w@ey?cL;que04Nz% zxKgzI>91boRtxB;x>8A*lvJ6-+4bLJElwj~tV!f$%$5_cU$> zU=599Ym9qqXpG4b`RK$(z|&D$!$yzy5#Nas^U28jk$L8x0dS9=Kw=#qHaUytD}6Du zf(wcK91ol}1&X2qOoP*5L$2QiMhQ-yY~m>+8SXjp+6!i)Cw`Mk#aIm(YBV1u2#g_+ z(cfF+BtA~MP9SV(^1R|<>^gC|UGTac&{YNTcmgfwT6ioL z3x&_V{#Wt9$xZ;~P`X*8hVRWWej5vNbUs$OH>-CnAy@=}Z^Y!nMypuC;wM(xa;7wZ z&|Cnp*)*O`nM_CtDR_Id`K_--E`QK9N`=R2v^A>nBYO@b#yc4`=E*p7#dXJTZlWb4 z+a#ovVz>bNO~w=fKy9`H%{}9@_o<$|IZUya3oG7|=sJI-@BG^xV^kwtMnmIflKwXV{{Qmz Ze*kM(Fj@*)5g-5n002ovPDHLkV1lw&xGDeu literal 0 HcmV?d00001 diff --git a/openscad.qrc b/openscad.qrc index 28b6a72d..6fd7e479 100644 --- a/openscad.qrc +++ b/openscad.qrc @@ -1,5 +1,6 @@ + icons/prefsFeatures.png icons/stopbutton.png icons/prefsAdvanced.png icons/prefs3DView.png diff --git a/src/Preferences.cc b/src/Preferences.cc index 0f3115e8..6ec9c9d6 100644 --- a/src/Preferences.cc +++ b/src/Preferences.cc @@ -35,6 +35,7 @@ #include "AutoUpdater.h" #ifdef ENABLE_CGAL #include "CGALCache.h" +#include "feature.h" #endif Preferences *Preferences::instance = NULL; @@ -86,13 +87,13 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent) this->defaultmap["advanced/openCSGLimit"] = RenderSettings::inst()->openCSGTermLimit; this->defaultmap["advanced/forceGoldfeather"] = false; - // Toolbar QActionGroup *group = new QActionGroup(this); - group->addAction(prefsAction3DView); - group->addAction(prefsActionEditor); - group->addAction(prefsActionUpdate); - group->addAction(prefsActionAdvanced); + addPrefPage(group, prefsAction3DView, page3DView); + addPrefPage(group, prefsActionEditor, pageEditor); + addPrefPage(group, prefsActionUpdate, pageUpdate); + addPrefPage(group, prefsActionFeatures, pageFeatures); + addPrefPage(group, prefsActionAdvanced, pageAdvanced); connect(group, SIGNAL(triggered(QAction*)), this, SLOT(actionTriggered(QAction*))); prefsAction3DView->setChecked(true); @@ -140,6 +141,7 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent) this->polysetCacheSizeEdit->setValidator(validator); this->opencsgLimitEdit->setValidator(validator); + setupFeaturesPage(); updateGUI(); RenderSettings::inst()->setColors(this->colorschemes[getValue("3dview/colorscheme").toString()]); @@ -150,21 +152,42 @@ Preferences::~Preferences() removeDefaultSettings(); } +void +Preferences::addPrefPage(QActionGroup *group, QAction *action, QWidget *widget) +{ + group->addAction(action); + prefPages[action] = widget; +} void Preferences::actionTriggered(QAction *action) { - if (action == this->prefsAction3DView) { - this->stackedWidget->setCurrentWidget(this->page3DView); - } - else if (action == this->prefsActionEditor) { - this->stackedWidget->setCurrentWidget(this->pageEditor); - } - else if (action == this->prefsActionUpdate) { - this->stackedWidget->setCurrentWidget(this->pageUpdate); - } - else if (action == this->prefsActionAdvanced) { - this->stackedWidget->setCurrentWidget(this->pageAdvanced); + this->stackedWidget->setCurrentWidget(prefPages[action]); +} + +void +Preferences::setupFeaturesPage() +{ + int row = 0; + for (Feature::const_iterator it = Feature::begin();it != Feature::end();it++) { + gridLayoutExperimentalFeatures->addItem(new QSpacerItem(1, 8, QSizePolicy::Expanding, QSizePolicy::Fixed), row, 1, 1, 1, Qt::AlignCenter); + row++; + const Feature *feature = (*it); + QCheckBox *cb = new QCheckBox(feature->get_name().c_str(), pageFeatures); + QFont bold_font(cb->font()); + bold_font.setBold(true); + cb->setFont(bold_font); + gridLayoutExperimentalFeatures->addWidget(cb, row, 0, 1, 2, Qt::AlignLeading); + row++; + QLabel *l = new QLabel(feature->get_description().c_str(), pageFeatures); + l->setTextFormat(Qt::RichText); + gridLayoutExperimentalFeatures->addWidget(l, row, 1, 1, 1, Qt::AlignLeading); + row++; } + // Force fixed indentation, the checkboxes use column span of 2 so + // first row is not constrained in size by the visible controls. The + // fixed size space essentially gives the first row the width of the + // spacer item itself. + gridLayoutExperimentalFeatures->addItem(new QSpacerItem(20, 0, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 0, 1, 1, Qt::AlignLeading); } void Preferences::on_colorSchemeChooser_itemSelectionChanged() diff --git a/src/Preferences.h b/src/Preferences.h index 46567939..addb7e52 100644 --- a/src/Preferences.h +++ b/src/Preferences.h @@ -44,9 +44,12 @@ private: void keyPressEvent(QKeyEvent *e); void updateGUI(); void removeDefaultSettings(); + void setupFeaturesPage(); + void addPrefPage(QActionGroup *group, QAction *action, QWidget *widget); QSettings::SettingsMap defaultmap; QHash > colorschemes; + QHash prefPages; static Preferences *instance; }; diff --git a/src/Preferences.ui b/src/Preferences.ui index d67db6a5..78a1cf6a 100644 --- a/src/Preferences.ui +++ b/src/Preferences.ui @@ -6,8 +6,8 @@ 0 0 - 473 - 320 + 823 + 433 @@ -27,7 +27,7 @@ - 2 + 3 @@ -136,7 +136,7 @@ - Monaco + DejaVu Sans 12 @@ -323,6 +323,78 @@ + + + + 0 + + + + + + + + 75 + true + + + + Features + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 803 + 311 + + + + + + + 8 + + + + + + + Qt::Vertical + + + + 20 + 282 + + + + + + + + + + + + @@ -465,6 +537,7 @@ + @@ -515,6 +588,21 @@ Update + + + true + + + + :/icons/prefsFeatures.png:/icons/prefsFeatures.png + + + Features + + + Enable/Disable experimental features + + diff --git a/src/feature.cc b/src/feature.cc index 5beece10..7f36547d 100644 --- a/src/feature.cc +++ b/src/feature.cc @@ -4,23 +4,26 @@ #include #include "feature.h" +#include "printutils.h" /** - * Feature registration map for later lookup. This must be initialized + * Feature registration map/list for later lookup. This must be initialized * before the static feature instances as those register with this map. */ -std::map Feature::feature_map; +Feature::map_t Feature::feature_map; +Feature::list_t Feature::feature_list; /* * List of features, the names given here are used in both command line * argument to enable the option and for saving the option value in GUI * context. */ -const Feature Feature::ExperimentalConcatFunction("concat"); +const Feature Feature::ExperimentalConcatFunction("experimental/concat-function", "Enable the concat() function."); -Feature::Feature(std::string name) : enabled_cmdline(false), enabled_options(false), name(name) +Feature::Feature(const std::string name, const std::string description) : enabled_cmdline(false), enabled_options(false), name(name), description(description) { feature_map[name] = this; + feature_list.push_back(this); } Feature::~Feature() @@ -32,6 +35,11 @@ const std::string& Feature::get_name() const return name; } +const std::string& Feature::get_description() const +{ + return description; +} + void Feature::set_enable_cmdline() { enabled_cmdline = true; @@ -49,15 +57,10 @@ bool Feature::is_enabled() const } return enabled_options; } - -bool operator ==(const Feature& lhs, const Feature& rhs) -{ - return lhs.get_name() == rhs.get_name(); -} -bool operator !=(const Feature& lhs, const Feature& rhs) +void Feature::enable(bool status) { - return !(lhs == rhs); + set_enable_options(status); } void Feature::enable_feature(std::string feature_name) @@ -65,6 +68,8 @@ void Feature::enable_feature(std::string feature_name) map_t::iterator it = feature_map.find(feature_name); if (it != feature_map.end()) { (*it).second->set_enable_cmdline(); + } else { + PRINTB("WARNING: Ignoring request to enable unknown feature '%s'.", feature_name); } } @@ -76,6 +81,16 @@ void Feature::enable_feature(std::string feature_name, bool status) } } +Feature::iterator Feature::begin() +{ + return feature_list.begin(); +} + +Feature::iterator Feature::end() +{ + return feature_list.end(); +} + void Feature::dump_features() { for (map_t::iterator it = feature_map.begin(); it != feature_map.end(); it++) { diff --git a/src/feature.h b/src/feature.h index 3c97edca..77e283ca 100644 --- a/src/feature.h +++ b/src/feature.h @@ -5,8 +5,13 @@ #include #include #include +#include class Feature { +public: + typedef std::vector list_t; + typedef list_t::iterator iterator; + private: /** * Set to true in case the matching feature was given as commandline @@ -19,12 +24,14 @@ private: */ bool enabled_options; - std::string name; + const std::string name; + const std::string description; typedef std::map map_t; static map_t feature_map; - - Feature(std::string name); + static list_t feature_list; + + Feature(std::string name, std::string description); virtual ~Feature(); virtual void set_enable_cmdline(); virtual void set_enable_options(bool status); @@ -33,11 +40,13 @@ public: static const Feature ExperimentalConcatFunction; const std::string& get_name() const; + const std::string& get_description() const; bool is_enabled() const; - - friend bool operator ==(const Feature& lhs, const Feature& rhs); - friend bool operator !=(const Feature& lhs, const Feature& rhs); + void enable(bool status); + + static iterator begin(); + static iterator end(); static void dump_features(); static void enable_feature(std::string feature_name);