PDA

View Full Version : how to get the last groupbox changed event in my program?



saman_artorious
28th July 2012, 17:12
consider the following scenario, there's a list view on the left side of the window, so each clicked item in the list would lead to an associated page in the stackedPage widget on the right side. This window is setup to take care of camera settings. There are two things which I would like to discuss with you about how the process should go on when the user clicks the APPLY button; to apply the new settings:

1. Each time this window pops on, the user may not be able in setting all the options of the list view items, so from a general point of view, It's better that I know which list views has the user clicked to change the setting!

2. For each list item, as I said there is a few group box items on the stackedpage containing radiobuttons. I exactly need to know which radio buttons have new settings so that I can only configure those when the user clicks on the APPLY button.

what I am looking for is exactly how I can implement this scenario minimizing the code ?

amleto
28th July 2012, 17:22
I think you should not try to implement it that way. You are asking 'how do I query my ui to find out which data is dirty?'. The answer is 'you should not be doing that anyway'.

You can easily resolve this issue with signals. when the user makes a change, the gui should emit that changed value through a signal. Then you will know exactly what has changed, and what the new value is. The receiver of these signals is then responsible for efficient updating of your settings, and you do not need to query the ui at all - this decouples the ui from the data.

saman_artorious
28th July 2012, 17:46
I understand, this is good if the data gets manipulated by the SLOT on the fly by emission.
But, we also need to take into account that nothing is gonna change before the user clicks the APPLY button after all.
This way, imagine, when APPLY happens, 10 radio buttons inside 10 different group boxes have been updated. Therefore, the slot should keep track of all
changes signaled to it until APPLY is clicked.
how can I keep track of all group boxes then? considering that I need the values as well as group box ids or string names, to know what function to call.

amleto
28th July 2012, 18:03
I understand, this is good if the data gets manipulated by the SLOT on the fly by emission.
No, this does not have to be for on-the-fly manipulation of your 'real config'.

But, we also need to take into account that nothing is gonna change before the user clicks the APPLY button after all.
Yes. What I have said is perfectly compatible with that.

how can I keep track of all group boxes then?
Sigh. You are back to coupling ui to data?

You have some class that accepts the ui signals. This class knows the variable and the new value. When user hits 'apply', signal is sent from ui to the class that holds the updated values, and then that class finally pushes the changes into the current config.

saman_artorious
28th July 2012, 18:13
I understand, this is good if the data gets manipulated by the SLOT on the fly by emission.
No, this does not have to be for on-the-fly manipulation of your 'real config'.

But, we also need to take into account that nothing is gonna change before the user clicks the APPLY button after all.
Yes. What I have said is perfectly compatible with that.

how can I keep track of all group boxes then?
Sigh. You are back to coupling ui to data?

You have some class that accepts the ui signals. This class knows the variable and the new value. When user hits 'apply', signal is sent from ui to the class that holds the updated values, and then that class finally pushes the changes into the current config.

: ) what about if the user makes some changes n then clicks Cancel? this way new values are updated in the class without setting the configurations
and there would be no way to get back to the previous settings..

amleto
28th July 2012, 18:56
no, wrong again. The 'real' config has not changed so of course the original state can be recovered.

saman_artorious
28th July 2012, 19:11
no, wrong again. The 'real' config has not changed so of course the original state can be recovered.

m sorry, this still looks not clear to me. imagine we have 2 group boxes, 3 radio buttons in each. in the settings class we have QRadioButton variables for each of the 9 radiobuttons. we use these variables to store the configuration. could you clarify your visulaization with this?

amleto
28th July 2012, 19:40
There shouldn't be any radio buttons in a settings class. Settings are data.

your gui might be 2 group boxes with 3 radio buttons each, but this only represents two variables, each with 3 possible values

e.g. gui:

speed group box
- fast
- medium
- slow

size group box
- big
- medium
- small

That represents data (speed, size):


struct Config
{
QString speed;
QString size;
};


That would be held in some config store:


class IConfigSource
{
public:
virtual Config config() const;
virtual void setConfig(const Config& cfg);
};

class ConfigSource : public IConfigSource
{
public:
Config config() const {return config_;}
void setConfig(const Config& cfg) {config_ = cfg;}

private:
Config config_;
};


which could be updated via something lile


class ConfigUpdater : QObject
{
Q_OBJECT
public:
ConfigUpdater(IConfigSource& src) : src_(src) {}

public slots:
void apply() {src_.setConfig(tempConfig);}
void cancel() (tempConfig = src_.config();)

void updateSpeed(QString s) {tempConfig_.Speed = s;}
void updateSize(QString s) {tempConfig_.Size = s;}

private:
Config tempConfig_;
IConfigSource& src_
};


Of course, still to be considered is how to deal with valid options for particular variables, but let's not do that right now...

saman_artorious
29th July 2012, 08:12
the main window that my settings menu reside on is a QMainWindow. you think it is better to create a variable of type ConfigUpdater in the MainWindow class or modify the QMainWindow class to ConfigUpdater? here is more info:


struct Config
{
/* General Options */
QString general_key_lock;
QString general_back_light;
QString general_slow_shutter;
QString general_high_resolution;
QString general_picture_flip;
QString general_freeze;
QString general_lr_reverse;
QString general_slow_shutter_power;
QString general_icr_power;

QString general_shutter;
QString general_automatic_exposure;
QString general_aperture_control;
QString general_iris;

QString general_camera_wb;
QString general_external_lock;
QString general_stabilizer;

/* WD settings */
QString wide_dynamic;
QString wd_screen_display;
QString wd_highlightCorrection;
QString wd_shadowCorrection;
QString wd_detectionSens;

/* Picture Effect */
QString picture_effect_setting;
QString picture_flip_setting;

};

class IConfigSource
{
public:
virtual Config config() const;
virtual void setConfig(const Config& cfg);
};

class ConfigSource : public IConfigSource
{
public:
Config config() const {return config_;}
void setConfig(const Config& cfg) {config_ = cfg;}

private:
Config config_;
};

class ConfigUpdater : QObject
{
Q_OBJECT
public:
ConfigUpdater(ConfigSource& src) : src_(src) {}

public slots:
void apply () {src_.setConfig(tempConfig_);}
void cancel() {tempConfig_ = src_.config();}

void updateGeneralBackLight(QString s) {tempConfig_.general_back_light = s;}
void updateGeneralKeyLock(QString s) {tempConfig_.general_key_lock = s;}
void updateGeneralSlowShutter(QString s) {tempConfig_.general_slow_shutter = s;}
void updateGeneralHighResolution(QString s) {tempConfig_.general_high_resolution = s;}
void updateGeneralPictureFlip(QString s) {tempConfig_.general_picture_flip = s;}
void updateGeneralFreeze(QString s) {tempConfig_.general_freeze = s;}
void updateGeneralLRReverse(QString s) {tempConfig_.general_lr_reverse = s;}
void updateGeneralSlowShutterPower(QString s) {tempConfig_.general_slow_shutter_power = s;}
void updateGeneralICRPower(QString s) {tempConfig_.general_icr_power = s;}

void updateGeneralShutter(QString s) {tempConfig_.general_shutter = s;}
void updateGeneralAutomaticExposure(QString s) {tempConfig_.general_automatic_exposure = s;}
void updateGeneralApertureControl(QString s) {tempConfig_.general_aperture_control = s;}
void updateGeneralIris(QString s) {tempConfig_.general_iris = s;}
void updateGeneralCameraWB(QString s) {tempConfig_.general_camera_wb = s;}
void updateGeneralExternalLock(QString s) {tempConfig_.general_external_lock = s;}
void updateGeneralStabilizer(QString s) {tempConfig_.general_stabilizer = s;}


private:
Config tempConfig_;
ConfigSource& src_;
};


namespace Ui {
class SettingsWindow;
}

class SettingsWindow : public QMainWindow
{
Q_OBJECT

public:
explicit SettingsWindow(QWidget *parent = 0);

~SettingsWindow();

signals:
void sendToPLC(QByteArray );
public slots:
void getRow(QModelIndex);
private slots:
void on_pushButton_5_clicked();

void on_pushButton_3_clicked();

private:

private:
Ui::SettingsWindow *ui;


};

saman_artorious
29th July 2012, 11:41
this is separate question of what I asked above. could you see if what i say is correct:
the settings Mainwindow is called by the Application main window. So, to set the settings menu to default values the first time the it pops up, Config structure shall be passed as a parameter from Main window to the settings Window. (i don't know if a data structure could be passed to the settings window when it is called ? if not so, shall I hide the setting window each time instead of cloding it?) -- If I send the Config default data as a parameter to settings window, what happens after the window closes? would all Config data structure be removed from memory? if so, our both temp and src_ structures gets released?

amleto
29th July 2012, 12:13
Again, mainwindow is a gui construct so it shouldn't get too friendly with the settings. And the mainwindow isn't even the gui window where you change the settings.

As for your other questions, they are covered by basic c++ understanding so maybe better in a different thread.

saman_artorious
29th July 2012, 12:42
Again, mainwindow is a gui construct so it shouldn't get too friendly with the settings. And the mainwindow isn't even the gui window where you change the settings.

As for your other questions, they are covered by basic c++ understanding so maybe better in a different thread.

I didn't get the answer to my question clearly. How should I progress considering my previous post?

amleto
29th July 2012, 12:58
you think it is better to create a variable of type ConfigUpdater in the MainWindow class or modify the QMainWindow class to ConfigUpdater?
Neither.

Config structure shall be passed as a parameter from Main window to the settings Window
No, Config structure shouldn't even be in mainwindow.

what happens after the window closes? would all Config data structure be removed from memory? if so, our both temp and src_ structures gets released?
Be aware there is a difference between a window hiding and a window closing/being destroyed. As for what happens when a class is destroyed, this follows normal rules of c++ and Qt clean-up considering Qt parenting. You can read about this elsewhere.

Imo you should consider a class that knows about the config source, and also knows how to create the gui. Then it would just require a signal/slot connection to show the config gui with up-to-date config.

saman_artorious
29th July 2012, 14:04
you think it is better to create a variable of type ConfigUpdater in the MainWindow class or modify the QMainWindow class to ConfigUpdater?
Neither.

Config structure shall be passed as a parameter from Main window to the settings Window
No, Config structure shouldn't even be in mainwindow.

what happens after the window closes? would all Config data structure be removed from memory? if so, our both temp and src_ structures gets released?
Be aware there is a difference between a window hiding and a window closing/being destroyed. As for what happens when a class is destroyed, this follows normal rules of c++ and Qt clean-up considering Qt parenting. You can read about this elsewhere.

Imo you should consider a class that knows about the config source, and also knows how to create the gui. Then it would just require a signal/slot connection to show the config gui with up-to-date config.

one more question, the MainWindow initially keeps the default setting value which can pass through to the settings mainwindow when it is called. it can also be stored in the settings window though. My question is that whenever the settings window closes, new updated settings gets lost! if I send the updated values to the Main caller window via signal, then whenever the settings window gets called, it would receive the last updated settings from the caller window. is this a good way? because I cannot find any other way to keep the updated values as the settings window loses all data each time it is closed?

amleto
29th July 2012, 14:13
one more question, the MainWindow initially keeps the default setting value..
Why do you ask for explicit information then ignore it?

because I cannot find any other way to keep the updated values as the settings window loses all data each time it is closed?
No. It seems like you didn't read anything from the post you quoted.

saman_artorious
29th July 2012, 14:25
one more question, the MainWindow initially keeps the default setting value..
Why do you ask for explicit information then ignore it?

because I cannot find any other way to keep the updated values as the settings window loses all data each time it is closed?
No. It seems like you didn't read anything from the post you quoted.

what I suggested is exactly what is here:

Imo you should consider a class that knows about the config source, and also knows how to create the gui. Then it would just require a signal/slot connection to show the config gui with up-to-date config.

amleto
29th July 2012, 14:33
one more question, the MainWindow initially keeps the default setting value which can pass through to the settings mainwindow when it is called. it can also be stored in the settings window though. My question is that whenever the settings window closes, new updated settings gets lost!

What do you think the ConfigSource is for?

amleto
29th July 2012, 16:39
just for illustrative purposes (ie if you copy/paste it wont work...)



class IGuiCreator : public QObject
{
public slots:
virtual QWidget* create() const = 0;
};

class ConfigMgr : QObject
{
public:
ConfigMgr(IConfigSource& src, const IGuiCreator& guiCreator) ...

public slots:
void showGui()
{
// get current config
// make gui & setup with config
}


signals:
// we need to change ConfigSource to emit signals when apply() is called so we can link that signal with this one
void configChanged(const Config&);

private:
IConfigSource& src_;
const IGuiCreator& guiCreator_;
};


int main(...)
{
QApplication app(...);

ConfigMgr mgr;
MainWindow yourmainwindow;

QObject::connect( /* connect signal 'show config gui' from mainwindow to slot 'show config gui' on config mgr */ );

/* you can connect the configChanged() signal here as well */

yourmainwindow.show();
app.exec();
}

saman_artorious
31st July 2012, 12:34
one more question, the MainWindow initially keeps the default setting value which can pass through to the settings mainwindow when it is called. it can also be stored in the settings window though. My question is that whenever the settings window closes, new updated settings gets lost!

What do you think the ConfigSource is for?

I want you to help me clarify the following problem please.
1. I do not know if this way is but, but I added a reference to ConfigSource in the Settings class constructor. So, before the Main Window get destructed, I can save the src_ values permanently to a file. I hope this is not redundant, or maybe we don't need it as the ConfigSource and updater classes exist. ?

2. As we used a reference to refer to src_, the program gives unexpected error when I call it's cancel and update methods to update it.


This is inside Main Window constructor, before I call the Settings Window


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ConfigSource cfg;
settings = new SettingsWindow(cfg,this);



Settings and Config classes


#ifndef SETTINGSWINDOW_H
#define SETTINGSWINDOW_H

#include <QMainWindow>
#include <QModelIndex>

#include <QSignalMapper>
#include <QRadioButton>
#include <QSpinBox>
#include <QTimer>

#include "cameracommands.h"

struct Config
{
/* General Options */
QString general_key_lock;
QString general_back_light;
};


class ConfigSource
{
public:

ConfigSource() {

config_.general_aperture_control = "Reset";
config_.general_automatic_exposure = "Full Auto";
config_.general_back_light = "OFF";
}

Config config() const {return config_;}

void setConfig(const Config& cfg) {config_ = cfg;}

private:

Config config_;
};

class ConfigUpdater : public QObject
{
Q_OBJECT
public:
ConfigUpdater(ConfigSource& src) : src_(src) {}

public slots:

void apply () {src_.setConfig(tempConfig_);}
void cancel() {tempConfig_ = src_.config();}

public:

void updateGeneralBackLight(QString s) {tempConfig_.general_back_light = s; qDebug() << "BackLight updated :)";}
void updateGeneralKeyLock(QString s) {tempConfig_.general_key_lock = s; qDebug() << "KeyLock updated :)";}

Config tempConfig_;
ConfigSource& src_;
};

//----------------------------

namespace Ui {
class SettingsWindow;
}

class SettingsWindow : public QMainWindow
{
Q_OBJECT

public:
explicit SettingsWindow(ConfigSource &src, QWidget *parent = 0);

~SettingsWindow();

private slots:
void on_pushButton_5_clicked();
void on_pushButton_3_clicked();
void on_sendToMainButton_clicked();

private:
void print_config(Config cfg);

Ui::SettingsWindow *ui;
ConfigUpdater *config_updater;
};

#endif // SETTINGSWINDOW_H




Settings Window cpp


SettingsWindow::SettingsWindow(ConfigSource &src, QWidget *parent) :
QMainWindow(parent),
ui(new Ui::SettingsWindow)
{
/* initializations */
ui->setupUi(this);
config_updater = new ConfigUpdater(src);


As I mentioned above, the program terminates when I attempt to call he Cancel and Update method!

config_updater->cancel();

saman_artorious
1st August 2012, 06:12
Problem solved.