hfhc2
hfhc2

Reputation: 4421

Options for program

I am doing some algorithmic work using C++. My algorithms have some options which I need to be able to add to my program with as little effort as possible. I am currently using this code.

Everything works as expected: I added some code to my program so I can call the binary with arguments like -oopt1=val1,opt2=val2 and the options are set automatically.

The problem is that I am also writing a GUI at the same time. Now every kind of option has to be able to be set/requested using the GUI. However, I might need a spinbox for an integer value and a check box for a boolean option. I am using Qt as a toolkit, so I could just write a member function that returns a QWidget* which is the appropriate base class.

However, I do not want any GUI-specific code in the header where I declare my options, since I would like to separate the GUI from the rest of the program. I could subclass any Option to create an appropriate QWidget*, but if I get a list of OptBase*, I wouldn't know what kind of widget I should create.

Is there some way that I can keep the GUI separated from the rest of the program while still being able to create appropriate widgets?

Upvotes: 0

Views: 172

Answers (2)

Philip Stuyck
Philip Stuyck

Reputation: 7467

For me the solution is to create an abstract factory : The factory should have an interface with two abstract methods to createBoolOption and CreateChoiceOption. Possibly more methods are needed You can then make two concrete implementations of this interface where one is returning the same ones as you are doing now, but when you are running in QT you can use a different implementation that returns an optbase derived class that does know how to create a widget. You can even use multiple inheritance (ie a second interface) so that you don't have to create a method in the first interface to specifically create a widget. Of course then in running the QT application you have to explicitely cast to the second interface, when you want to create the widget. The abstract factory itself should be passed to constructor of algobase. Ie dependency injection.

class ifactory{
public:
  virtual Option<bool>* createBoolOption()=0;
  virtual ChoiceOption<Mode>*  createChoiceOption()=0;
  virtual Widget* createWidget()=0; //here or in another interface
};

class ConcreteNonGuiFactory : public ifactory{
  virtual Option<bool>* createBoolOption();
  virtual ChoiceOption<Mode>* createChoiceOption();
  virtual Widget* createWidget()={;}; 
};

class ConcreteGuiFactory : public ifactory{
  virtual Option<bool>* createBoolOption();
  virtual ChoiceOption<Mode>* createChoiceOption();
  virtual Widget* createWidget(); 
}; 

class Algo1 : public AlgoBase{
public:
   Algo1(ifactory& f):factory(f){
      ChoiceOption<Mode>* opt = factory.createChoiceOption();
   }
private:
   ifactory factory;
}

If the creation of the widget is in a different interface you can reduce your dependencies. In this example at least the widget has to be forward declared.

Upvotes: 2

Valentin H
Valentin H

Reputation: 7458

You need a bunch of variables to be accessed by both setter (GUI, commang-line parser) and getter (algorithm function). QVariant should be fine. As you options have names, they also have implicitly types. Getter should retrieve the value by their name and explicitly make type conversion. Setter shouldn't care - QVariant will.

Create a singleton instance which has a map of option-names. Implement slots triggered by GUI value-change signals, set values in map. e.g:

class VarTable
{
   static VarTable & instance(){ static VarTable inst; return inst; }
   QMap<QString, QVariant> _map;
public: 
   void setVar( QString n, QVariant v ){ _map[n] = v };
   QVariant getVar( QString n ) const { return _map[n]; }
};

//Call in Slot triggered by a value-change signal (e.g. QEditLine::returnPressed)
VarTable::instance().setVal( "option1", val1 );

//Regrieve in non-gui code
QString option1 = VarTable::instance().getVal( "option1" ).toString();

Regards

P.S.: I've not compiled the code, mey have some typos.

Upvotes: 1

Related Questions