From 91999427d1eb93529b0118e81a7014a01104b62d Mon Sep 17 00:00:00 2001 From: Vladslav P Date: Sat, 24 Jun 2023 15:04:41 +0300 Subject: [PATCH] ui_builder: constexpr c_def initialization --- src/applications/CMakeLists.txt | 2 + src/applications/gqrx/dcontrols.cpp | 148 ++++---- src/applications/gqrx/dcontrols.h | 390 ++++--------------- src/applications/gqrx/dcontrols_ui.cpp | 188 ++++----- src/applications/gqrx/main.cpp | 1 + src/applications/gqrx/mainwindow.cpp | 42 +-- src/applications/gqrx/mainwindow.h | 4 +- src/applications/gqrx/tagged_union.cpp | 23 ++ src/applications/gqrx/tagged_union.h | 503 +++++++++++++++++++++++++ src/qtgui/bookmarks.cpp | 14 +- 10 files changed, 808 insertions(+), 507 deletions(-) create mode 100644 src/applications/gqrx/tagged_union.cpp create mode 100644 src/applications/gqrx/tagged_union.h diff --git a/src/applications/CMakeLists.txt b/src/applications/CMakeLists.txt index ff81e17c6d..d094410b61 100644 --- a/src/applications/CMakeLists.txt +++ b/src/applications/CMakeLists.txt @@ -14,6 +14,8 @@ add_source_files(SRCS_LIST gqrx/recentconfig.cpp gqrx/recentconfig.h gqrx/file_resources.cpp + gqrx/tagged_union.h + gqrx/tagged_union.cpp gqrx/dcontrols.h gqrx/dcontrols.cpp gqrx/dcontrols_ui.h diff --git a/src/applications/gqrx/dcontrols.cpp b/src/applications/gqrx/dcontrols.cpp index 5c85476771..eebb8e12cc 100644 --- a/src/applications/gqrx/dcontrols.cpp +++ b/src/applications/gqrx/dcontrols.cpp @@ -25,9 +25,43 @@ #include "dcontrols.h" #include "dsp/format_converter.h" -static const c_def::preset_list mode_map(); +struct mode_map_helper +{ + c_def::v_preset presets[Modulations::MODE_COUNT]{}; + constexpr mode_map_helper & init() + { + for(int k=0;k store{ +static constexpr std::array store{ c_def() .idx(C_TEST) @@ -47,7 +81,6 @@ c_def() .config_key("test") // .tab("Tab0") .bookmarks_column(-1) - .bookmarks_key("-1") .v_type(V_INT) .def(0) .min(0) @@ -57,9 +90,6 @@ c_def() .readable(true) .writable(true) .event(false) - .presets( - { - }) , @@ -203,17 +233,7 @@ c_def() .min(FILE_FORMAT_CF) .max(FILE_FORMAT_COUNT) .step(1) - .presets([](){ - c_def::preset_list ret{}; - for(int k=FILE_FORMAT_CF;k"}, {"Normal","Normal",FILTER_PRESET_NORMAL,"."}, {"Narrow","Narrow",FILTER_PRESET_NARROW,"<"}, @@ -1654,7 +1669,7 @@ c_def() .def(1) .min(0) .max(2) - .presets({ + .presets((c_def::v_preset[]){ {"Soft","Soft",Modulations::FILTER_SHAPE_SOFT}, {"Normal","Normal",Modulations::FILTER_SHAPE_NORMAL}, {"Sharp","Sharp",Modulations::FILTER_SHAPE_SHARP}, @@ -1671,13 +1686,12 @@ c_def() .dock(D_RXOPT) .scope(S_GUI) .v3_config_group("receiver") - .config_key("") .v_type(V_STRING) .def("Medium") .min("") .max("") .event(1) - .presets({ + .presets((c_def::v_preset[]){ {"0","Fast","Fast"}, {"1","Medium","Medium"}, {"2","Slow","Slow"}, @@ -1696,7 +1710,6 @@ c_def() .dock(D_RXOPT) .scope(S_GUI) .v3_config_group("audio") - .config_key("") .v_type(V_BOOLEAN) .def(1) .min(0) @@ -1736,7 +1749,6 @@ c_def() .dock(D_RXOPT) .scope(S_VFO) .v3_config_group("receiver") - .config_key("") .v_type(V_DOUBLE) .def(3.0) .min(0.0) @@ -1867,7 +1879,6 @@ c_def() .dock(D_RXOPT) .scope(S_GUI) .v3_config_group("audio") - .config_key("") .v_type(V_BOOLEAN) .def(1) .min(0) @@ -1929,7 +1940,7 @@ c_def() .max(100.0) .step(0.1) .event(true) - .presets({ + .presets((c_def::v_preset[]){ {"0","0 db",0.0}, {"-6","-6 db",-6.0}, }) @@ -1998,7 +2009,6 @@ c_def() .dock(D_AUDIO) .scope(S_VFO) .v3_config_group("audio") - .config_key("") .v_type(V_BOOLEAN) .def(0) .min(0) @@ -2017,7 +2027,6 @@ c_def() .dock(D_AUDIO) .scope(S_VFO) .v3_config_group("audio") - .config_key("") .v_type(V_BOOLEAN) .def(0) .min(0) @@ -2035,7 +2044,6 @@ c_def() .dock(D_AUDIO) .scope(S_RX) .v3_config_group("audio") - .config_key("") .v_type(V_BOOLEAN) .def(0) .min(0) @@ -2217,7 +2225,7 @@ c_def() .bookmarks_column(27) .bookmarks_key("REC DIR") .v_type(V_STRING) - .def(QDir::homePath().toStdString()) + .def("") .min("") .max("") .step("") @@ -2394,7 +2402,6 @@ c_def() .window(W_CHILD) .scope(S_VFO) .v3_config_group("audio") - .config_key("") .v_type(V_STRING) .def("") .min("") @@ -2413,7 +2420,6 @@ c_def() .window(W_CHILD) .scope(S_VFO) .v3_config_group("audio") - .config_key("") .v_type(V_BOOLEAN) .def(0) .min(0) @@ -2663,7 +2669,7 @@ c_def() .max(100) .step(1) .event(true) - .presets({ + .presets((c_def::v_preset[]){ {"Center","Center",0} }) , @@ -2786,7 +2792,6 @@ c_def() .v3_config_group("receiver") .config_key("nb3gain") .bookmarks_column(-1) - .bookmarks_key("") .v_type(V_DOUBLE) .frac_digits(1) .def(5.0) @@ -2818,7 +2823,7 @@ c_def() .min(10.0) .max(75000.0) .step(10.0) - .presets( + .presets((c_def::v_preset[]) { {"0","Voice (2.5 kHz)",2500.0}, {"1","Voice (5 kHz)",5000.0}, @@ -2840,16 +2845,14 @@ c_def() .demod_specific(true) .demodgroup(Modulations::GRP_NFMPLL) .v3_config_group("receiver") - .config_key("") .bookmarks_column(-1) - .bookmarks_key("") .v_type(V_DOUBLE) .frac_digits(0) .def(2500.0) .min(10.0) .max(75000.0) .step(10.0) - .presets( + .presets((c_def::v_preset[]) { {"0","Voice (2.5 kHz)",2500.0}, {"1","Voice (5 kHz)",5000.0}, @@ -2879,7 +2882,7 @@ c_def() .min(0.0) .max(1000.0) .step(1.0) - .presets( + .presets((c_def::v_preset[]) { {"0","Off",0.0}, {"1","25 us",25.0}, @@ -2905,9 +2908,7 @@ c_def() .demod_specific(true) .demodgroup(Modulations::GRP_NFM) .v3_config_group("receiver") - .config_key("") .bookmarks_column(-1) - .bookmarks_key("") .v_type(V_BOOLEAN) .def(0) .min(0) @@ -2930,7 +2931,6 @@ c_def() .v3_config_group("receiver") .config_key("fmpll_damping_factor") .bookmarks_column(-1) - .bookmarks_key("") .v_type(V_DOUBLE) .frac_digits(2) .def(0.7) @@ -2978,7 +2978,6 @@ c_def() .v3_config_group("receiver") .config_key("subtone_filter") .bookmarks_column(-1) - .bookmarks_key("") .v_type(V_BOOLEAN) .def(0) .min(0) @@ -3008,7 +3007,7 @@ c_def() .min(0.0001) .max(0.01) .step(0.0001) - .presets( + .presets((c_def::v_preset[]) { {"Fast","Fast",0.01}, {"Medium","Medium",0.001}, @@ -3164,7 +3163,7 @@ c_def() .min(0.0) .max(1000.0) .step(1.0) - .presets( + .presets((c_def::v_preset[]) { {"0","Off",0.0}, {"1","25 us",25.0}, @@ -3196,7 +3195,7 @@ c_def() .min(0.0) .max(1000.0) .step(1.0) - .presets( + .presets((c_def::v_preset[]) { {"0","Off",0.0}, {"1","25 us",25.0}, @@ -3228,7 +3227,7 @@ c_def() .min(0.0) .max(1000.0) .step(1.0) - .presets( + .presets((c_def::v_preset[]) { {"0","Off",0.0}, {"1","25 us",25.0}, @@ -3396,6 +3395,22 @@ c_def() std::array, C_COUNT> conf_base::observers{}; +c_def::preset_list::iterator c_def::preset_list::find(const std::string & what) const +{ + for(std::size_t k=0;k -#include -#include -#include -#include +#include "tagged_union.h" #include "receivers/defines.h" #include "receivers/modulations.h" @@ -267,14 +263,6 @@ enum gui_window W_COUNT }; -enum value_type -{ - V_INT=0, - V_DOUBLE, - V_STRING, - V_BOOLEAN -}; - enum convenient_placement { PLACE_NONE=-3, @@ -309,287 +297,74 @@ enum alignments // Macros are ugly, but convenient #define DD(T,N,I) \ T d_##N{I};\ - inline const T & N () const {return d_##N;}\ - inline c_def & N (const T & n_##N){d_##N=n_##N; return *this;} + constexpr inline const T & N () const {return d_##N;}\ + constexpr inline c_def & N (const T & n_##N){d_##N=n_##N; return *this;} +#define DS(N,I) \ + const char * d_##N{I};\ + constexpr inline const char * N () const {return d_##N;}\ + constexpr inline c_def & N (const char * n_##N){d_##N=n_##N; return *this;} struct c_def; struct c_def { - class v_union + using v_union = ::tag_union; + struct v_preset { - enum tag_type - { - TAG_INT=0, - TAG_DOUBLE, - TAG_STRING - }; - tag_type tag; - union union_type { - int64_t i; - double d; - std::string s; - union_type():i(0){} - ~union_type(){} - } value; - public: - v_union():tag(TAG_INT) - { - value.i=0; - } - v_union(const c_def::v_union& other):tag(other.tag) - { - switch(tag) - { - case TAG_STRING: - new (&value.s) std::string(other.value.s); - break; - case TAG_DOUBLE: - value.d=other.value.d; - break; - case TAG_INT: - value.i=other.value.i; - break; - } - } - v_union(const char *init):tag(TAG_STRING) - { - new (&value.s) std::string(init); - } - v_union(const std::string &init):tag(TAG_STRING) - { - new (&value.s) std::string(init); - } - v_union(const float &init):tag(TAG_DOUBLE) - { - value.d = (double)init; - } - v_union(const double &init):tag(TAG_DOUBLE) - { - value.d = init; - } - v_union(const int &init):tag(TAG_INT) - { - value.i = init; - } - v_union(const long int &init):tag(TAG_INT) - { - value.i = init; - } - v_union(const long long int &init):tag(TAG_INT) - { - value.i = init; - } - v_union(const bool &init):tag(TAG_INT) - { - value.i = init; - } - v_union(const value_type vt, const std::string & from) - { - switch(vt) - { - case V_INT: - value.i=stoll(from); - tag=TAG_INT; - break; - case V_DOUBLE: - value.d=stod(from); - tag=TAG_DOUBLE; - break; - case V_STRING: - new (&value.s) std::string(from); - tag=TAG_STRING; - break; - case V_BOOLEAN: - value.i=(from=="true"); - tag=TAG_INT; - break; - } - } - ~v_union() - { - if(tag==TAG_STRING) - value.s.~basic_string(); - } - void typecheck(const tag_type required, const char * msg) const - { - if(tag!=required) - { - dprint(msg); - //throw does not work as expected here - //emit a message and exit - exit(1); - } - } - operator int() const - { - typecheck(TAG_INT, "invalid cast to int"); - return value.i; - } - operator long int() const - { - typecheck(TAG_INT, "invalid cast to int"); - return value.i; - } - operator long long int() const - { - typecheck(TAG_INT, "invalid cast to int"); - return value.i; - } - operator bool() const - { - typecheck(TAG_INT, "invalid cast to bool"); - return value.i; - } - operator double() const - { - typecheck(TAG_DOUBLE, "invalid cast to double"); - return value.d; - } - operator float() const - { - typecheck(TAG_DOUBLE, "invalid cast to float"); - return value.d; - } - operator std::string() const - { - typecheck(TAG_STRING, "invalid cast to string"); - return value.s; - } - const std::string to_string() const - { - switch(tag) - { - case TAG_INT: - return std::to_string(value.i); - case TAG_DOUBLE: - return std::to_string(value.d); - case TAG_STRING: - return value.s; - default: - return ""; - } - } - void dprint(const char * x="") const - { - switch(tag) - { - case TAG_INT: - std::cerr<<"v_union:i="< + constexpr preset_list & from(const v_preset (&init) [N]) { - if(tag!=other.tag) - { - dprint("invalid comparison"); - other.dprint("invalid comparison"); - return false; - } - return true; + n_items = N; + items = init; + return *this; } - bool operator < (const v_union & other) const + template + constexpr preset_list & from(v_preset (&init) [N]) { - if(!typecheck_cmp(other)) - return false; - switch(tag) - { - case TAG_INT: - return value.i (const v_union & other) const + constexpr const v_preset & operator [] (const std::size_t what) { - if(!typecheck_cmp(other)) - return false; - switch(tag) - { - case TAG_INT: - return value.i>other.value.i; - break; - case TAG_DOUBLE: - return value.d>other.value.d; - break; - case TAG_STRING: - return value.s>other.value.s; - break; - } - return false; + return items[what]; } - bool operator == (const v_union & other) const + iterator find(const std::string & what) const; + iterator find(const v_union & what) const; + template + constexpr static preset_list make(v_preset (&init) [N]) { - if(!typecheck_cmp(other)) - return false; - switch(tag) - { - case TAG_INT: - return value.i==other.value.i; - break; - case TAG_DOUBLE: - return value.d==other.value.d; - break; - case TAG_STRING: - return value.s==other.value.s; - break; - } - return false; - } - v_union& operator=(const v_union& other) + return preset_list{N, init}; + }; + + template + constexpr static preset_list make(const v_preset (&init) [N]) { - if(tag == TAG_STRING) - { - if(other.tag != TAG_STRING) - value.s.~basic_string(); - else - value.s=other.value.s; - } - if(tag != TAG_STRING && other.tag == TAG_STRING) - new (&value.s) std::string(other.value.s); - else{ - switch(other.tag) - { - case TAG_INT: - value.i=other.value.i; - break; - case TAG_DOUBLE: - value.d=other.value.d; - break; - case TAG_STRING: - break; - } - } - tag=other.tag; - return *this; - } - }; - struct v_preset - { - std::string key; - std::string display;//FIXME: implement translation - v_union value; - std::string shortcut; - v_preset(const std::string &n_key, const std::string &n_display, const v_union &n_value, const std::string & n_shortcut="") - :key(n_key),display(n_display),value(n_value),shortcut(n_shortcut) - {} + return preset_list{N, init}; + }; }; struct grid_placement { - grid_placement(int n_row=0,int n_column=0, int n_rowspan=1, + constexpr grid_placement(int n_row=0,int n_column=0, int n_rowspan=1, int n_colspan=1,int alignment=ALIGN_DEFAULT) :column(n_column),row(n_row),colspan(n_colspan),rowspan(n_rowspan) ,align(alignments(alignment)) @@ -603,58 +378,50 @@ struct c_def }; DD(c_id,idx,c_id(-1)) DD(c_id,base,c_id(-1)) - DD(std::string,name,"Unnamed") - DD(std::string,title,"Default title") //FIXME: implement translation + DS(name,"Unnamed") + DS(title,"Default title") //FIXME: implement translation DD(grid_placement,title_placement,grid_placement(PLACE_NEXT,0)) - DD(std::string,next_title,"Default next title") //FIXME: implement translation + DS(next_title,"Default next title") //FIXME: implement translation DD(grid_placement,next_placement,grid_placement(PLACE_NONE,PLACE_NONE)) DD(grid_placement,placement,grid_placement(PLACE_SAME,1)) - DD(std::string,hint,"Default tooltip") //FIXME: implement translation - DD(std::string,icon,"") - DD(std::string,shortcut,"") - DD(std::string,tab,"") //FIXME: implement translation + DS(hint,"Default tooltip") //FIXME: implement translation + DS(icon,nullptr) + DS(shortcut,nullptr) + DS(tab,nullptr) //FIXME: implement translation DD(gui_type,g_type,G_TEXT) DD(gui_dock,dock,D_INPUTCTL) DD(gui_window,window,W_BASE) DD(value_scope,scope,S_RX) DD(bool,demod_specific,false) //should be hidden if current demod does not match demod member DD(Modulations::grp,demodgroup,Modulations::GRP_COUNT) - DD(std::string,v3_config_group,"V3_DEFAULT") - DD(std::string,v4_config_group,"V4_DEFAULT") - DD(std::string,config_key,"Unnamed") + DS(v3_config_group,"V3_DEFAULT") + DS(v4_config_group,"V4_DEFAULT") + DS(config_key,nullptr) DD(int,bookmarks_column,-1) - DD(std::string,bookmarks_key,"-1") + DS(bookmarks_key,nullptr) DD(value_type, v_type,V_INT) - DD(std::string,suffix,"") - DD(std::string,prefix,"") - DD(v_union,def,0) - DD(v_union,min,0) - DD(v_union,max,0) - DD(v_union,step,0) //for slider or double spinbox + DS(suffix,"") + DS(prefix,"") + DD(tag_union_const,def,0) + DD(tag_union_const,min,0) + DD(tag_union_const,max,0) + DD(tag_union_const,step,0) //for slider or double spinbox DD(int,frac_digits,0)//for double spinbox DD(bool,readable,true) DD(bool,writable,true) DD(bool,event,false) - using preset_list=std::vector; + //using preset_list=std::vector; //DD(preset_map,presets,{}) preset_list d_presets{}; - std::map d_kpresets{}; - std::map d_ipresets{}; - inline const preset_list& presets() const {return d_presets;} - inline const std::map & kpresets() const {return d_kpresets;} - inline const std::map & ipresets() const {return d_ipresets;} - inline c_def & presets(const preset_list & n_presets) + constexpr const preset_list& presets() const {return d_presets;} + template constexpr c_def & presets(v_preset (&init) [N]) { - d_presets = n_presets; - std::map n_kpresets{}; - std::map n_ipresets{}; - for(unsigned k=0; k(init); + return *this; + } + template constexpr c_def & presets(const v_preset (&init) [N]) + { + d_presets = preset_list::make(init); return *this; } public: @@ -664,6 +431,7 @@ struct c_def }; #undef DD +#undef DS struct conf_base { diff --git a/src/applications/gqrx/dcontrols_ui.cpp b/src/applications/gqrx/dcontrols_ui.cpp index 3e22e8e1a0..6d582f7dca 100644 --- a/src/applications/gqrx/dcontrols_ui.cpp +++ b/src/applications/gqrx/dcontrols_ui.cpp @@ -27,10 +27,10 @@ QWidget * dcontrols_ui::gen_none(const c_id id) { QWidget * parent = obtainParent(); auto & def = c_def::all()[id]; - if(!def.shortcut().empty()) + if(def.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + action->setShortcut(QKeySequence(def.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){changed_gui(id, def.def());}); } @@ -57,20 +57,20 @@ QWidget * dcontrols_ui::gen_text(const c_id id) } for(auto it=def.presets().begin(); it!=def.presets().end();++it) { - QAction* action = new QAction(QString::fromStdString(it->display), parent); + QAction* action = new QAction(it->display, parent); m->addAction(action); - parent->connect(action, &QAction::triggered, [=](){widget->setText(QString::fromStdString(it->value));}); - if(!it->shortcut.empty()) + parent->connect(action, &QAction::triggered, [=](){widget->setText(QString(it->value));}); + if(it->shortcut) { - action->setShortcut(QKeySequence(QString::fromStdString(it->shortcut))); + action->setShortcut(QKeySequence(it->shortcut)); parent->addAction(action); } } } - if(!def.shortcut().empty()) + if(def.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + action->setShortcut(QKeySequence(def.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->setFocus();}); } @@ -103,8 +103,8 @@ QWidget * dcontrols_ui::gen_spinbox(const c_id id) widget->setMinimum(def.min()); widget->setMaximum(def.max()); widget->setSingleStep(def.step()); - widget->setSuffix(QString::fromStdString(def.suffix())); - widget->setPrefix(QString::fromStdString(def.prefix())); + widget->setSuffix(QString(def.suffix())); + widget->setPrefix(QString(def.prefix())); widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter); if(def.presets().size() > 0) { @@ -118,21 +118,21 @@ QWidget * dcontrols_ui::gen_spinbox(const c_id id) } for(auto it=def.presets().begin(); it!=def.presets().end();++it) { - QAction* action = new QAction(QString::fromStdString(it->display), parent); + QAction* action = new QAction(it->display, parent); m->addAction(action); auto lambda = [=](){widget->setValue(it->value);}; parent->connect(action, &QAction::triggered, lambda); - if(!it->shortcut.empty()) + if(it->shortcut) { - action->setShortcut(QKeySequence(QString::fromStdString(it->shortcut))); + action->setShortcut(QKeySequence(it->shortcut)); parent->addAction(action); } } } - if(!def.shortcut().empty()) + if(def.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + action->setShortcut(QKeySequence(def.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->setFocus();}); } @@ -187,8 +187,8 @@ QWidget * dcontrols_ui::gen_doublespinbox(const c_id id) exit(1); } widget->setDecimals(def.frac_digits()); - widget->setSuffix(QString::fromStdString(def.suffix())); - widget->setPrefix(QString::fromStdString(def.prefix())); + widget->setSuffix(QString(def.suffix())); + widget->setPrefix(QString(def.prefix())); widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter); if(def.presets().size() > 0) { @@ -197,7 +197,7 @@ QWidget * dcontrols_ui::gen_doublespinbox(const c_id id) m=ui_menus[id]=new QMenu(parent); for(auto it=def.presets().begin(); it!=def.presets().end();++it) { - QAction* action = new QAction(QString::fromStdString(it->display), parent); + QAction* action = new QAction(it->display, parent); m->addAction(action); switch(def.v_type()) { @@ -212,17 +212,17 @@ QWidget * dcontrols_ui::gen_doublespinbox(const c_id id) break; default:; } - if(!it->shortcut.empty()) + if(it->shortcut) { - action->setShortcut(QKeySequence(QString::fromStdString(it->shortcut))); + action->setShortcut(QKeySequence(it->shortcut)); parent->addAction(action); } } } - if(!def.shortcut().empty()) + if(def.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + action->setShortcut(QKeySequence(def.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->setFocus();}); } @@ -281,14 +281,14 @@ QWidget * dcontrols_ui::gen_checkbox(const c_id id) { QWidget * parent = obtainParent(); auto & def = c_def::all()[id]; - QCheckBox * widget = new QCheckBox(QString::fromStdString(def.name()), parent); + QCheckBox * widget = new QCheckBox(QString(def.name()), parent); if(def.writable()) { parent->connect(widget, QOverload::of(&QCheckBox::stateChanged), [=](int val){changed_gui(id, val==Qt::Checked);} ); - if(!def.shortcut().empty()) + if(def.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + action->setShortcut(QKeySequence(def.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->toggle();}); } @@ -322,25 +322,25 @@ QWidget * dcontrols_ui::gen_combo(const c_id id) { case V_INT: for(auto it=def.presets().begin(); it!=def.presets().end();++it) - widget->addItem(QString::fromStdString(it->display),(long long int)it->value); + widget->addItem(it->display,(long long int)it->value); parent->connect(widget, QOverload::of(&QComboBox::currentIndexChanged), [=](int val){changed_gui(id, widget->currentData().toLongLong());} ); break; case V_BOOLEAN: for(auto it=def.presets().begin(); it!=def.presets().end();++it) - widget->addItem(QString::fromStdString(it->display),bool(it->value)); + widget->addItem(it->display,bool(it->value)); parent->connect(widget, QOverload::of(&QComboBox::currentIndexChanged), [=](int val){changed_gui(id, widget->currentData().toBool());} ); break; case V_DOUBLE: for(auto it=def.presets().begin(); it!=def.presets().end();++it) - widget->addItem(QString::fromStdString(it->display),double(it->value)); + widget->addItem(it->display,double(it->value)); parent->connect(widget, QOverload::of(&QComboBox::currentIndexChanged), [=](int val){changed_gui(id, widget->currentData().toDouble());} ); break; case V_STRING: for(auto it=def.presets().begin(); it!=def.presets().end();++it) - widget->addItem(QString::fromStdString(it->display),QString::fromStdString(it->value)); + widget->addItem(it->display,QString(it->value)); parent->connect(widget, QOverload::of(&QComboBox::currentIndexChanged), [=](int val){changed_gui(id, widget->currentData().toString().toStdString());} ); parent->connect(widget, &QComboBox::currentTextChanged, @@ -353,17 +353,17 @@ QWidget * dcontrols_ui::gen_combo(const c_id id) } int k = 0; for(auto it=def.presets().begin(); it!=def.presets().end();++it,++k) - if(!it->shortcut.empty()) + if(it->shortcut) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(it->shortcut))); + action->setShortcut(QKeySequence(it->shortcut)); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->setCurrentIndex(k);}); } - if(!def.shortcut().empty()) + if(def.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + action->setShortcut(QKeySequence(def.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->setFocus();}); } @@ -465,19 +465,19 @@ QWidget * dcontrols_ui::gen_stringcombo(const c_id id) [=](const QString & val){changed_gui(id, val.toStdString());} ); for(auto it=def.presets().begin(); it!=def.presets().end();++it) { - if(!it->shortcut.empty()) + if(it->shortcut) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(it->shortcut))); + action->setShortcut(QKeySequence(it->shortcut)); parent->addAction(action); - parent->connect(action, &QAction::triggered, [=](){widget->setCurrentText(QString::fromStdString(it->value));}); + parent->connect(action, &QAction::triggered, [=](){widget->setCurrentText(QString(it->value));}); } - widget->addItem(QString::fromStdString(it->display),QString::fromStdString(it->value)); + widget->addItem(it->display,QString(it->value)); } - if(!def.shortcut().empty()) + if(def.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + action->setShortcut(QKeySequence(def.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->setFocus();}); } @@ -558,7 +558,7 @@ QWidget * dcontrols_ui::gen_slider(const c_id id) } for(auto it=def.presets().begin(); it!=def.presets().end();++it) { - QAction* action = new QAction(QString::fromStdString(it->display), parent); + QAction* action = new QAction(it->display, parent); m->addAction(action); switch(def.v_type()) { @@ -577,17 +577,17 @@ QWidget * dcontrols_ui::gen_slider(const c_id id) //TODO: implement switching between string preset values? break; } - if(!it->shortcut.empty()) + if(it->shortcut) { - action->setShortcut(QKeySequence(QString::fromStdString(it->shortcut))); + action->setShortcut(QKeySequence(it->shortcut)); parent->addAction(action); } } } - if(!def.shortcut().empty()) + if(def.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + action->setShortcut(QKeySequence(def.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->setFocus();}); } @@ -688,7 +688,7 @@ QWidget * dcontrols_ui::gen_logslider(const c_id id) } for(auto it=def.presets().begin(); it!=def.presets().end();++it) { - QAction* action = new QAction(QString::fromStdString(it->display), parent); + QAction* action = new QAction(it->display, parent); m->addAction(action); switch(def.v_type()) { @@ -702,17 +702,17 @@ QWidget * dcontrols_ui::gen_logslider(const c_id id) throw std::runtime_error("logslider requires double value"); break; } - if(!it->shortcut.empty()) + if(it->shortcut) { - action->setShortcut(QKeySequence(QString::fromStdString(it->shortcut))); + action->setShortcut(QKeySequence(it->shortcut)); parent->addAction(action); } } } - if(!def.shortcut().empty()) + if(def.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + action->setShortcut(QKeySequence(def.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->setFocus();}); } @@ -765,7 +765,7 @@ QWidget * dcontrols_ui::gen_rangeslider(const c_id id) if(def1.v_type() != def2.v_type()) { const QString ex=QString("ctkRangeSlider incorrect definition: %1 .v_type=%2 !=%3 .v_type=%4 ") - .arg(QString::fromStdString(def1.name())).arg(int(def1.v_type())).arg(QString::fromStdString(def2.name())).arg(int(def2.v_type())); + .arg(def1.name()).arg(int(def1.v_type())).arg(def2.name()).arg(int(def2.v_type())); throw std::runtime_error(ex.toStdString().c_str()); } QWidget * parent = obtainParent(); @@ -831,7 +831,7 @@ QWidget * dcontrols_ui::gen_rangeslider(const c_id id) } for(auto it=def1.presets().begin(); it!=def1.presets().end();++it) { - QAction* action = new QAction(QString::fromStdString(it->display), parent); + QAction* action = new QAction(it->display, parent); m->addAction(action); switch(def1.v_type()) { @@ -850,9 +850,9 @@ QWidget * dcontrols_ui::gen_rangeslider(const c_id id) //TODO: implement switching between string preset values? break; } - if(!it->shortcut.empty()) + if(it->shortcut) { - action->setShortcut(QKeySequence(QString::fromStdString(it->shortcut))); + action->setShortcut(QKeySequence(it->shortcut)); parent->addAction(action); } } @@ -871,7 +871,7 @@ QWidget * dcontrols_ui::gen_rangeslider(const c_id id) } for(auto it=def2.presets().begin(); it!=def2.presets().end();++it) { - QAction* action = new QAction(QString::fromStdString(it->display), parent); + QAction* action = new QAction(it->display, parent); m->addAction(action); switch(def2.v_type()) { @@ -890,17 +890,17 @@ QWidget * dcontrols_ui::gen_rangeslider(const c_id id) //TODO: implement switching between string preset values? break; } - if(!it->shortcut.empty()) + if(it->shortcut) { - action->setShortcut(QKeySequence(QString::fromStdString(it->shortcut))); + action->setShortcut(QKeySequence(it->shortcut)); parent->addAction(action); } } } - if(def1.shortcut() != "") + if(def1.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def1.shortcut()))); + action->setShortcut(QKeySequence(def1.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->setFocus();}); } @@ -975,7 +975,7 @@ QWidget * dcontrols_ui::gen_menuaction(const c_id id) auto & def = c_def::all()[id]; if(def.base()<0) throw std::runtime_error("gen_menuaction ("+std::to_string(id)+") \""+std::string(def.name())+"\" base is not set"); - QAction * widget = new QAction(QString::fromStdString(def.title()), parent); + QAction * widget = new QAction(QString(def.title()), parent); QMenu * m = ui_menus[def.base()]; if(!m) { @@ -987,9 +987,9 @@ QWidget * dcontrols_ui::gen_menuaction(const c_id id) m->addAction(widget); parent->connect(widget, QOverload::of(&QAction::triggered), [=](bool val){changed_gui(id, def.def());} ); ui_actions[id]=widget; - if(!def.shortcut().empty()) + if(def.shortcut()) { - widget->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + widget->setShortcut(QKeySequence(def.shortcut())); parent->addAction(widget); } return nullptr; @@ -1001,7 +1001,7 @@ QWidget * dcontrols_ui::gen_menucheckbox(const c_id id) auto & def = c_def::all()[id]; if(def.base()<0) throw std::runtime_error("gen_menucheckbox ("+std::to_string(id)+") \""+std::string(def.name())+"\" base is not set"); - QAction * widget = new QAction(QString::fromStdString(def.title()), parent); + QAction * widget = new QAction(QString(def.title()), parent); QMenu * m = ui_menus[def.base()]; if(!m) { @@ -1015,9 +1015,9 @@ QWidget * dcontrols_ui::gen_menucheckbox(const c_id id) { widget->setCheckable(true); parent->connect(widget, QOverload::of(&QAction::triggered), [=](bool val){changed_gui(id, val);} ); - if(!def.shortcut().empty()) + if(def.shortcut()) { - widget->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + widget->setShortcut(QKeySequence(def.shortcut())); parent->addAction(widget); } } @@ -1041,7 +1041,7 @@ QWidget * dcontrols_ui::gen_button(const c_id id) { QWidget * parent = obtainParent(); auto & def = c_def::all()[id]; - QPushButton * widget = new QPushButton(QString::fromStdString(def.name()), parent); + QPushButton * widget = new QPushButton(QString(def.name()), parent); if(def.base() < 0) parent->connect(widget, QOverload::of(&QPushButton::clicked), [=](bool val){changed_gui(id, def.def());} ); else @@ -1051,12 +1051,12 @@ QWidget * dcontrols_ui::gen_button(const c_id id) set_gui(def.base(), def.def()); } ); widget->setMinimumSize(10,0); - if(def.icon() != "") - widget->setIcon(QIcon(QString::fromStdString(def.icon()))); - if(!def.shortcut().empty()) + if(def.icon()) + widget->setIcon(QIcon(QString(def.icon()))); + if(def.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + action->setShortcut(QKeySequence(def.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->click();}); } @@ -1067,19 +1067,19 @@ QWidget * dcontrols_ui::gen_togglebutton(const c_id id) { QWidget * parent = obtainParent(); auto & def = c_def::all()[id]; - QPushButton * widget = new QPushButton(QString::fromStdString(def.name()), parent); + QPushButton * widget = new QPushButton(QString(def.name()), parent); if(def.writable()) { widget->setCheckable(true); parent->connect(widget, QOverload::of(&QPushButton::clicked), [=](bool val){changed_gui(id, val);} ); } widget->setMinimumSize(10,0); - if(def.icon() != "") - widget->setIcon(QIcon(QString::fromStdString(def.icon()))); - if(!def.shortcut().empty()) + if(def.icon()) + widget->setIcon(QIcon(QString(def.icon()))); + if(def.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + action->setShortcut(QKeySequence(def.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->click();}); } @@ -1117,22 +1117,22 @@ void dcontrols_ui::set_label(QWidget * w, const c_id id, const c_def::v_union &v { case V_INT: case V_BOOLEAN: - widget->setText(QString::fromStdString(def.prefix()) + widget->setText(QString(def.prefix()) +QString::number(qint64(value)) - +QString::fromStdString(def.suffix()) + +QString(def.suffix()) ); break; case V_DOUBLE: widget->setText(QString("%1%2%3") - .arg(QString::fromStdString(def.prefix())) + .arg(def.prefix()) .arg(double(value),1,'f',def.frac_digits()) - .arg(QString::fromStdString(def.suffix())) + .arg(def.suffix()) ); break; case V_STRING: - widget->setText(QString::fromStdString(def.prefix()) + widget->setText(QString(def.prefix()) +QString::fromStdString(value.to_string()) - +QString::fromStdString(def.suffix()) + +QString(def.suffix()) ); break; } @@ -1161,21 +1161,21 @@ QWidget * dcontrols_ui::gen_colorpicker(const c_id id) if(def.writable()) { parent->connect(widget, &QtColorPicker::colorChanged, [=](const QColor & val){changed_gui(id, qint64(val.rgb()));} ); - if(!def.shortcut().empty()) + if(def.shortcut()) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(def.shortcut()))); + action->setShortcut(QKeySequence(def.shortcut())); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->setFocus();}); } } for(auto it=def.presets().begin(); it!=def.presets().end();++it) { - widget->insertColor(QColor::fromRgb(qint64(it->value)), QString::fromStdString(it->display)); - if(!it->shortcut.empty()) + widget->insertColor(QColor::fromRgb(qint64(it->value)), it->display); + if(it->shortcut) { QAction * action = new QAction(parent); - action->setShortcut(QKeySequence(QString::fromStdString(it->shortcut))); + action->setShortcut(QKeySequence(it->shortcut)); parent->addAction(action); parent->connect(action, &QAction::triggered, [=](){widget->setCurrentColor(QColor::fromRgb(qint64(it->value)));}); } @@ -1315,7 +1315,7 @@ QWidget * dcontrols_ui::construct_widget(const c_id id) return nullptr; if(ui_widgets[id]==nullptr) return nullptr; - ui_widgets[id]->setToolTip(QString::fromStdString(c_def::all()[id].hint())); + ui_widgets[id]->setToolTip(QString(c_def::all()[id].hint())); return ui_widgets[id]; } return nullptr; @@ -1346,7 +1346,7 @@ void dcontrols_ui::add_control(const c_id id) QWidget * control = construct_widget(id); if(!control) return; - if(d.tab() != "") + if(d.tab()) { throw std::runtime_error("dcontrols_ui::add_control: Use dcontrols_ui_tabbed to create tabbed widget"); }else if(d.demod_specific()) @@ -1367,9 +1367,9 @@ void dcontrols_ui::grid_insert(QGridLayout * into, c_def::grid_placement & place if(d.title_placement().row!=PLACE_NONE) { set_placement(placement,d.title_placement()); - auto label = new QLabel(QString::fromStdString(d.title()), what->parentWidget()); + auto label = new QLabel(QString(d.title()), what->parentWidget()); label->setTextFormat(Qt::PlainText); - label->setToolTip(QString::fromStdString(c_def::all()[id].hint())); + label->setToolTip(QString(c_def::all()[id].hint())); label->setSizePolicy(toQtSizePol(placement.align, QSizePolicy::Minimum), QSizePolicy::Minimum); //label->setMinimumSize(10,10); into->addWidget(label,placement.row,placement.column,placement.rowspan,placement.colspan,toQtAlignment(placement.align, Qt::AlignRight)); @@ -1384,9 +1384,9 @@ void dcontrols_ui::grid_insert(QGridLayout * into, c_def::grid_placement & place if(d.next_placement().row!=PLACE_NONE) { set_placement(placement,d.next_placement()); - auto label = new QLabel(QString::fromStdString(d.next_title()), what->parentWidget()); + auto label = new QLabel(QString(d.next_title()), what->parentWidget()); label->setTextFormat(Qt::PlainText); - label->setToolTip(QString::fromStdString(c_def::all()[id].hint())); + label->setToolTip(QString(c_def::all()[id].hint())); label->setSizePolicy(toQtSizePol(placement.align, QSizePolicy::Minimum), QSizePolicy::Minimum); //label->setMinimumSize(10,10); into->addWidget(label,placement.row,placement.column,placement.rowspan,placement.colspan,toQtAlignment(placement.align, Qt::AlignRight)); @@ -1457,9 +1457,9 @@ void dcontrols_ui_tabbed::add_control(const c_id id) QWidget * control = construct_widget(id); if(!control) return; - if(d.tab() != "") + if(d.tab()) { - const QString tabName(QString::fromStdString(d.tab())); + const QString tabName(d.tab()); if(!ui_tabs.contains(tabName)) { QWidget * widget=obtainParent(); @@ -1516,7 +1516,7 @@ void dcontrols_ui_stacked::add_control(const c_id id) QWidget * control = construct_widget(id); if(!control) return; - if(d.tab() != "") + if(d.tab()) { throw std::runtime_error("dcontrols_ui::add_control: Use dcontrols_ui_tabbed to create tabbed widget"); }else if(d.demod_specific()) diff --git a/src/applications/gqrx/main.cpp b/src/applications/gqrx/main.cpp index 9df8d157c4..f23c8bef74 100644 --- a/src/applications/gqrx/main.cpp +++ b/src/applications/gqrx/main.cpp @@ -39,6 +39,7 @@ #include "mainwindow.h" #include "gqrx.h" +#include "dcontrols.h" #include diff --git a/src/applications/gqrx/mainwindow.cpp b/src/applications/gqrx/mainwindow.cpp index 48cd5c8ef3..2c76759a1e 100644 --- a/src/applications/gqrx/mainwindow.cpp +++ b/src/applications/gqrx/mainwindow.cpp @@ -65,7 +65,7 @@ using namespace std::chrono_literals; #include "qtgui/bandplan.h" Q_DECLARE_METATYPE(c_id) -Q_DECLARE_METATYPE(c_def::v_union) +Q_DECLARE_METATYPE(tag_union) using std::chrono::high_resolution_clock; using std::chrono::duration_cast; using std::chrono::duration; @@ -86,7 +86,7 @@ MainWindow::MainWindow(const QString& cfgfile, bool edit_conf, QWidget *parent) { auto t1 = high_resolution_clock::now(); qRegisterMetaType(); - qRegisterMetaType(); + qRegisterMetaType(); ui->setupUi(this); @@ -401,7 +401,7 @@ MainWindow::MainWindow(const QString& cfgfile, bool edit_conf, QWidget *parent) m_recent_config = new RecentConfig(m_cfg_dir, ui->menu_RecentConfig); connect(m_recent_config, SIGNAL(loadConfig(const QString &)), this, SLOT(loadConfigSlot(const QString &))); - connect(this,SIGNAL(observer_signal(const c_id, const c_def::v_union)), this, SLOT(observer_slot(const c_id, const c_def::v_union)), Qt::QueuedConnection); + connect(this,SIGNAL(observer_signal(const c_id, const tag_union)), this, SLOT(observer_slot(const c_id, const tag_union)), Qt::QueuedConnection); // restore last session if (!loadConfig(cfgfile, true, true)) @@ -550,22 +550,22 @@ void MainWindow::get_gui(const c_id id, c_def::v_union & value) const static void loadSetting(QPointer m_settings, const c_def & def, c_def::v_union & v) { - const auto vkey = QString::fromStdString(def.config_key()); + const auto vkey = QString(def.config_key()); bool conv_ok = false; if(def.presets().size()>0) { //may be stored as preset key QString qdef(""); { - auto it=def.ipresets().find(def.def()); - if(it!=def.ipresets().end()) - qdef=QString::fromStdString(def.presets()[it->second].key); + auto it=def.presets().find(def.def()); + if(it!=def.presets().end()) + qdef=QString::fromStdString(it->key); } std::string ss = m_settings->value(vkey,qdef).toString().toStdString(); - auto it=def.kpresets().find(ss); - if(it!=def.kpresets().end()) + auto it=def.presets().find(ss); + if(it!=def.presets().end()) { - v=def.presets()[it->second].value; + v=it->value; return; } } @@ -582,7 +582,7 @@ static void loadSetting(QPointer m_settings, const c_def & def, c_def v=def.def(); break; case V_STRING: - v=m_settings->value(vkey,QString::fromStdString(def.def())).toString().toStdString(); + v=m_settings->value(vkey,QString(def.def())).toString().toStdString(); break; case V_BOOLEAN: v=m_settings->value(vkey,bool(def.def())).toBool(); @@ -824,7 +824,7 @@ bool MainWindow::loadConfig(const QString& cfgfile, bool check_crash, const auto & def=defs[j]; if(!(def.writable()&&def.readable())) continue; - if((def.scope()!=S_VFO)&&(def.config_key()!="")) + if((def.scope()!=S_VFO)&&def.config_key()) { c_def::v_union v(0); const c_id id=c_id(j); @@ -943,17 +943,17 @@ bool MainWindow::saveConfig(const QString& cfgfile) static void storeSetting(QPointer m_settings, const c_def & def, const c_def::v_union & v) { - const auto vkey = QString::fromStdString(def.config_key()); + const auto vkey = QString(def.config_key()); if(def.presets().size()>0) { //try to store by preset key - auto it=def.ipresets().find(v); - if(it!=def.ipresets().end()) + auto it=def.presets().find(v); + if(it!=def.presets().end()) { - if(def.def()==v) + if(v==def.def()) m_settings->remove(vkey); else - m_settings->setValue(vkey,QString::fromStdString(def.presets()[it->second].key)); + m_settings->setValue(vkey,QString(it->key)); return; } } @@ -1050,7 +1050,7 @@ void MainWindow::storeSession() const auto & def=defs[j]; if(!(def.writable()&&def.readable())) continue; - if((def.scope()==S_VFO)&&(def.config_key()!="")) + if((def.scope()==S_VFO)&&def.config_key()) { c_def::v_union v(0); const c_id id = c_id(j); @@ -1077,7 +1077,7 @@ void MainWindow::storeSession() const auto & def = defs[j]; if(!(def.writable()&&def.readable())) continue; - if((def.scope()==S_RX)&&(def.config_key()!="")) + if((def.scope()==S_RX)&&def.config_key()) { c_def::v_union v(0); const c_id id = c_id(j); @@ -1086,7 +1086,7 @@ void MainWindow::storeSession() storeSetting(m_settings, def, v); m_settings->endGroup(); } - if((def.scope()==S_GUI)&&(def.config_key()!="")) + if((def.scope()==S_GUI)&&def.config_key()) { c_def::v_union v(0); const c_id id = c_id(j); @@ -1122,7 +1122,7 @@ void MainWindow::readRXSettings(int ver, double actual_rate) const auto & def=defs[j]; if(!(def.writable()&&def.readable())) continue; - if((def.scope()==S_VFO)&&(def.config_key()!="")) + if((def.scope()==S_VFO)&&def.config_key()) { const c_id id=c_id(j); if(ver < 4) diff --git a/src/applications/gqrx/mainwindow.h b/src/applications/gqrx/mainwindow.h index bb63496a07..9d056e9eea 100644 --- a/src/applications/gqrx/mainwindow.h +++ b/src/applications/gqrx/mainwindow.h @@ -62,7 +62,7 @@ class MainWindow : public QMainWindow, public dcontrols_ui void sigAudioRecEvent(const QString filename, bool is_running); void requestPlotterUpdate(); void sigSaveProgress(const qint64); - void observer_signal(const c_id, const c_def::v_union); + void observer_signal(const c_id, const tag_union); public: explicit MainWindow(const QString& cfgfile, bool edit_conf, QWidget *parent = nullptr); @@ -190,7 +190,7 @@ public slots: void frequencyObserver(const c_id id, const c_def::v_union &value); private slots: - void observer_slot(const c_id id, const c_def::v_union value); + void observer_slot(const c_id id, const tag_union value); /* RecentConfig */ void loadConfigSlot(const QString &cfgfile); diff --git a/src/applications/gqrx/tagged_union.cpp b/src/applications/gqrx/tagged_union.cpp new file mode 100644 index 0000000000..ad44f4b431 --- /dev/null +++ b/src/applications/gqrx/tagged_union.cpp @@ -0,0 +1,23 @@ +/* -*- c++ -*- */ +/* + * Gqrx SDR: Software defined radio receiver powered by GNU Radio and Qt + * https://gqrx.dk/ + * + * Copyright 2023 vladisslav2011@gmail.com. + * + * Gqrx 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, or (at your option) + * any later version. + * + * Gqrx 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 Gqrx; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#include "tagged_union.h" diff --git a/src/applications/gqrx/tagged_union.h b/src/applications/gqrx/tagged_union.h new file mode 100644 index 0000000000..0675f3fdfb --- /dev/null +++ b/src/applications/gqrx/tagged_union.h @@ -0,0 +1,503 @@ +/* -*- c++ -*- */ +/* + * Gqrx SDR: Software defined radio receiver powered by GNU Radio and Qt + * https://gqrx.dk/ + * + * Copyright 2023 vladisslav2011@gmail.com. + * + * Gqrx 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, or (at your option) + * any later version. + * + * Gqrx 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 Gqrx; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef INCLUDED_TAGGED_UNION_H +#define INCLUDED_TAGGED_UNION_H + +#include +#include +#include +#include +#include +#include +#include + +enum value_type +{ + V_INT=0, + V_DOUBLE, + V_STRING, + V_BOOLEAN +}; + +struct tag_union_const +{ + enum tag_type + { + TAG_INT=0, + TAG_DOUBLE, + TAG_STRING + }; + tag_type tag; + union union_type { + int64_t i; + double d; + const char * s; + constexpr union_type(int64_t init):i(init){} + constexpr union_type(double init):d(init){} + constexpr union_type(const char * init):s(init){} + } value; + constexpr tag_union_const():tag(TAG_INT),value(int64_t(0)){} + constexpr tag_union_const(const char *init):tag(TAG_STRING),value(init){} + constexpr tag_union_const(const float &init):tag(TAG_DOUBLE),value(double(init)){} + constexpr tag_union_const(const double &init):tag(TAG_DOUBLE),value(init){} + constexpr tag_union_const(const int &init):tag(TAG_INT),value(int64_t(init)){} + constexpr tag_union_const(const long int &init):tag(TAG_INT),value(int64_t(init)){} + constexpr tag_union_const(const long long int &init):tag(TAG_INT),value(int64_t(init)){} + constexpr tag_union_const(const unsigned &init):tag(TAG_INT),value(int64_t(init)){} + constexpr tag_union_const(const bool &init):tag(TAG_INT),value(int64_t(init)){} + constexpr void typecheck(const tag_type required, const char * msg) const + { + if(tag!=required) + { + dprint(msg); + //throw does not work as expected here + //emit a message and exit + exit(1); + } + } + constexpr operator int() const + { + typecheck(TAG_INT, "invalid cast to int"); + return value.i; + } + constexpr operator long int() const + { + typecheck(TAG_INT, "invalid cast to int"); + return value.i; + } + constexpr operator long long int() const + { + typecheck(TAG_INT, "invalid cast to int"); + return value.i; + } + constexpr operator bool() const + { + typecheck(TAG_INT, "invalid cast to bool"); + return value.i; + } + constexpr operator double() const + { + typecheck(TAG_DOUBLE, "invalid cast to double"); + return value.d; + } + constexpr operator float() const + { + typecheck(TAG_DOUBLE, "invalid cast to float"); + return value.d; + } + constexpr operator const char *() const + { + typecheck(TAG_STRING, "invalid cast to string"); + return value.s; + } + constexpr void dprint(const char * x="") const + { + switch(tag) + { + case TAG_INT: + std::cerr<<"v_union:i="< (const tag_union_const & other) const + { + if(!typecheck_cmp(other)) + return false; + switch(tag) + { + case TAG_INT: + return value.i>other.value.i; + break; + case TAG_DOUBLE: + return value.d>other.value.d; + break; + case TAG_STRING: + return value.s>other.value.s; + break; + } + return false; + } + constexpr bool operator == (const tag_union_const & other) const + { + if(!typecheck_cmp(other)) + return false; + switch(tag) + { + case TAG_INT: + return value.i==other.value.i; + break; + case TAG_DOUBLE: + return value.d==other.value.d; + break; + case TAG_STRING: + return value.s==other.value.s; + break; + } + return false; + } +}; + +class tag_union +{ + enum tag_type + { + TAG_INT=0, + TAG_DOUBLE, + TAG_STRING + }; + tag_type tag; + union union_type { + int64_t i; + double d; + std::string s; + union_type():i(0){} + ~union_type(){} + } value; + public: + tag_union():tag(TAG_INT) + { + value.i=0; + } + tag_union(const tag_union_const& other):tag(tag_type(other.tag)) + { + switch(tag) + { + case TAG_STRING: + new (&value.s) std::string(other.value.s); + break; + case TAG_DOUBLE: + value.d=other.value.d; + break; + case TAG_INT: + value.i=other.value.i; + break; + } + } + tag_union(const tag_union& other):tag(other.tag) + { + switch(tag) + { + case TAG_STRING: + new (&value.s) std::string(other.value.s); + break; + case TAG_DOUBLE: + value.d=other.value.d; + break; + case TAG_INT: + value.i=other.value.i; + break; + } + } + tag_union(const char *init):tag(TAG_STRING) + { + new (&value.s) std::string(init); + } + tag_union(const std::string &init):tag(TAG_STRING) + { + new (&value.s) std::string(init); + } + tag_union(const float &init):tag(TAG_DOUBLE) + { + value.d = (double)init; + } + tag_union(const double &init):tag(TAG_DOUBLE) + { + value.d = init; + } + tag_union(const int &init):tag(TAG_INT) + { + value.i = init; + } + tag_union(const long int &init):tag(TAG_INT) + { + value.i = init; + } + tag_union(const long long int &init):tag(TAG_INT) + { + value.i = init; + } + tag_union(const bool &init):tag(TAG_INT) + { + value.i = init; + } + tag_union(const value_type vt, const std::string & from) + { + switch(vt) + { + case V_INT: + value.i=stoll(from); + tag=TAG_INT; + break; + case V_DOUBLE: + value.d=stod(from); + tag=TAG_DOUBLE; + break; + case V_STRING: + new (&value.s) std::string(from); + tag=TAG_STRING; + break; + case V_BOOLEAN: + value.i=(from=="true"); + tag=TAG_INT; + break; + } + } + ~tag_union() + { + if(tag==TAG_STRING) + value.s.~basic_string(); + } + void typecheck(const tag_type required, const char * msg) const + { + if(tag!=required) + { + dprint(msg); + //throw does not work as expected here + //emit a message and exit + exit(1); + } + } + operator int() const + { + typecheck(TAG_INT, "invalid cast to int"); + return value.i; + } + operator long int() const + { + typecheck(TAG_INT, "invalid cast to int"); + return value.i; + } + operator long long int() const + { + typecheck(TAG_INT, "invalid cast to int"); + return value.i; + } + operator bool() const + { + typecheck(TAG_INT, "invalid cast to bool"); + return value.i; + } + operator double() const + { + typecheck(TAG_DOUBLE, "invalid cast to double"); + return value.d; + } + operator float() const + { + typecheck(TAG_DOUBLE, "invalid cast to float"); + return value.d; + } + operator std::string() const + { + typecheck(TAG_STRING, "invalid cast to string"); + return value.s; + } + const std::string to_string() const + { + switch(tag) + { + case TAG_INT: + return std::to_string(value.i); + case TAG_DOUBLE: + return std::to_string(value.d); + case TAG_STRING: + return value.s; + default: + return ""; + } + } + void dprint(const char * x="") const + { + switch(tag) + { + case TAG_INT: + std::cerr<<"tag_union:i="< (const tag_union & other) const + { + if(!typecheck_cmp(other)) + return false; + switch(tag) + { + case TAG_INT: + return value.i>other.value.i; + break; + case TAG_DOUBLE: + return value.d>other.value.d; + break; + case TAG_STRING: + return value.s>other.value.s; + break; + } + return false; + } + bool operator == (const tag_union & other) const + { + if(!typecheck_cmp(other)) + return false; + switch(tag) + { + case TAG_INT: + return value.i==other.value.i; + break; + case TAG_DOUBLE: + return value.d==other.value.d; + break; + case TAG_STRING: + return value.s==other.value.s; + break; + } + return false; + } + bool operator != (const tag_union & other) const + { + return !(*this == other); + } + tag_union& operator=(const tag_union& other) + { + if(tag == TAG_STRING) + { + if(other.tag != TAG_STRING) + value.s.~basic_string(); + else + value.s=other.value.s; + } + if(tag != TAG_STRING && other.tag == TAG_STRING) + new (&value.s) std::string(other.value.s); + else{ + switch(other.tag) + { + case TAG_INT: + value.i=other.value.i; + break; + case TAG_DOUBLE: + value.d=other.value.d; + break; + case TAG_STRING: + break; + } + } + tag=other.tag; + return *this; + } +#if 0 + tag_union& operator=(const tag_union_const& other) + { + if(tag == TAG_STRING) + { + if(tag_type(other.tag) != TAG_STRING) + value.s.~basic_string(); + else + value.s=std::string(other.value.s); + } + if(tag != TAG_STRING && tag_type(other.tag) == TAG_STRING) + new (&value.s) std::string(other.value.s); + else{ + switch(tag_type(other.tag)) + { + case TAG_INT: + value.i=other.value.i; + break; + case TAG_DOUBLE: + value.d=other.value.d; + break; + case TAG_STRING: + break; + } + } + tag=tag_type(other.tag); + return *this; + } +#endif +}; +#endif \ No newline at end of file diff --git a/src/qtgui/bookmarks.cpp b/src/qtgui/bookmarks.cpp index ec4c8cb6b6..ef53410477 100644 --- a/src/qtgui/bookmarks.cpp +++ b/src/qtgui/bookmarks.cpp @@ -238,6 +238,8 @@ Bookmarks::Bookmarks() const int bcol=defs[k].bookmarks_column(); if(bcol>0) { + if(!defs[k].bookmarks_key()) + continue; if(m_idx_struct[bcol].fromString) { std::cerr<<"Conflicting bookmark definitions:\nlocal["<< @@ -249,9 +251,9 @@ Bookmarks::Bookmarks() m_idx_struct[bcol].name=QString::fromStdString(defs[k].bookmarks_key()); m_idx_struct[bcol].fromString=[=](BookmarkInfo & to, const QString & from) -> bool { //lookup preset - auto it = defs[k].kpresets().find(from.toStdString()); - if(it != defs[k].kpresets().end()) - return to.set_value(c_id(k),defs[k].presets()[it->second].value); + auto it = defs[k].presets().find(from.toStdString()); + if(it != defs[k].presets().end()) + return to.set_value(c_id(k),it->value); //no preset c_def::v_union tmp(defs[k].v_type(),from.toStdString()); //TODO: validate tmp @@ -262,9 +264,9 @@ Bookmarks::Bookmarks() c_def::v_union tmp; from.get_value(c_id(k), tmp); //lookup preset - auto it = defs[k].ipresets().find(tmp); - if(it != defs[k].ipresets().end()) - return QString::fromStdString(defs[k].presets()[it->second].key); + auto it = defs[k].presets().find(tmp); + if(it != defs[k].presets().end()) + return QString(it->key); //no preset switch(defs[k].v_type()) {