[SOLVED] Saving custom user settings in Qt



  • Hi,

    I'm currently saving and loading the position and the size of the window as follow.

    @void MainWindow::saveSettings()
    {
    QSettings settings("tuDesign", "Tool");
    settings.setValue("geometry", saveGeometry());
    }

    void MainWindow::loadSettings()
    {
    QSettings settings("tuDesign", "Tool");
    restoreGeometry(settings.value("geometry").toByteArray());
    }

    void MainWindow::on_pushButton_saveSettings_clicked()
    {
    saveSettings();
    }@

    ... everything is working fine but I would like to be able to save some other things not just the window settings for instance I have a color picker that changes the color of some recangles and I was wondering if it was possible to save the last color picked by the user.

    @void MainWindow::on_pushButton_ColorPick_clicked()
    {
    QColor myColor;
    myColor = QColorDialog::getColor(Qt:blue), this);
    }@

    How can I save the last color picked by the user when the saveSettings() function is called?

    Thanks a lot!



  • QSettings can save QVariant and QColor can be converted to/from QVariant.

    So in your project, create a class that stores configuration parameters and recent values (e.g. recently browsed directory in dialogs, or your recently selected color) and that handles saving/loading them with QSettings (or more sophisticated with XML).



  • Wow, that sounds a little complicated. Can you show me a little example?

    Thanks a lot!



  • Here is an example:

    ...saving the color:

    @void MyClass::saveSettings() {

    QSettings mySettings("My Company", "App Name");
    
    mySettings.beginGroup("MainWindow");
    
    // The getColor() member function/method return a QColor object.
    
    mySettings.setValue("MyColor", getColor().rgba());
    
    mySettings.endGroup();
    

    }// saveSettings@

    ...loading the color:

    @void MyClass::loadSettings() {

    QSettings mySettings("My Company", "App Name");
    
    mySettings.beginGroup("MainWindow");
    
    if(mySettings.contains("MyColor")) {
    
        QColor myColor;
    
        myColor.setRgba(mySettings.value("MyColor").toUInt());
    
        // Now you can restore the saved color.
    
        setColor(myColor);
    
    }// if
    
    mySettings.endGroup();
    

    }// loadSettings
    @



  • I will give it a try. Thanks a lot for your help!



  • Hi,

    Josué V. Herrera
    I have been playing around with the code you provided but I cannot make it to load the settings.

    Originally I was getting an error saying that setColor and getColor were not declared in this scope...

    for the getColor I changed it to
    @mySettings.setValue("MyColor", myColor);@
    Where myColor is a global variable placed in the constructor.

    This is the initial value of myColor variable.
    @myColor = QColor(85, 170, 0, 110);@
    Problem solved for the getColor error.

    But I can not make it to read the last color saved. I know its working because I use the qDebug() and when I run the saveSettings function it show the last color being saved.

    Any Idea what can I do (try) to make the setColor() function work? I know the setColor is not part of the QSettings so I think I'm missing a piece of code here.

    Thanks a lot.



  • Well, setColor and getColor both are just hypothetical member functions, that was just an example.

    My suggestion here was to have two public methods, where you could set/get the current color to/from a private QColor object. Something like this:

    myyclass.h:
    @public:

    inline void setColor(const QObject &myCurrentColor) {

    myColor = myCurrentColor;

    }// setColor

    inline const QColor& getColor() {

    return myColor;

    }// getColor

    private:

    QColor myColor;@



  • I see, make sense, let me give a try.

    Thank you for your help.



  • And please... try not to use global variables, especially not for things like this.



  • I have been trying to put the code Josué V. Herrera provided to me but I'm having a hard time making it work since he presented a few C++ concepts here, such as...

    @inline const QColor& getColor()
    inline void setColor(const QObject &myCurrentColor)@

    Inline functions?
    QColor before the function name?
    Reference functions (&getColor)?

    All these are concepts I still don't fully understand in C++, I don't know how to prototype these type of functions nor how they work, I'm LOST.

    I know I know, but before I give up with this I want to give it another shot, in fact I already other methods to avoid bothering you guys again, such as writing and reading the color from/to a file, but unfortunately I ran into problems, I don't thick it is possible to convert QColor to QString.

    I think this is the most challenging thing for me so far, I have spent HOURS trying but no luck. I'm going to show my whole mess in case there is someone willing to help me. Feel free to pass since I can imagine how frustrating is got to be dealing with people like me, but I have tried hard, believe me.

    All I need is to save the last color selected by the user (colorPart). The code presented here of course doesn't work and its presented as Josué V. Herrera gave it to me as a starting point since I don't want to create more confusion with my wonderful coding methods, also despite the fact that I have a memory leak, I'm actually deleting QGraphicsScene in my real program.

    CPP file:
    @MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    partColor = QColor(85, 170, 0, 110);
    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    void MainWindow::on_pushButton_Draw_clicked()
    {
    scene = new QGraphicsScene(0 ,0 ,360,180);
    ui->graphicsView->setScene(scene);
    QBrush partBrush(partColor);
    QPen partPen(Qt::white);
    partPen.setWidth(2);
    rectangle = scene->addRect(5, 5, 50, 50, partPen, partBrush);
    }

    void MainWindow::on_pushButton_colorPick_clicked()
    {
    partColor = QColorDialog::getColor(QColor(partColor), this);
    }

    //***************
    // SAVE SETTINGS
    //***************
    void MainWindow::on_pushButton_saveSettings_clicked()
    {
    QSettings mySettings("CompanyName", "myApp");
    mySettings.beginGroup("MainWindow");
    mySettings.setValue("MyColor", getColor().rgba());
    mySettings.endGroup();
    }

    void MainWindow::on_pushButton_loadSettings_clicked()
    {
    QSettings mySettings("CompanyName", "myApp");
    mySettings.beginGroup("MainWindow");
    if(mySettings.contains("MyColor"))
    {
    QColor myColor;
    myColor.setRgba(mySettings.value("MyColor").toUInt());
    setColor(myColor);
    }
    mySettings.endGroup();
    }

    inline void setColor(const QObject &myCurrentColor)
    {
    myColor = myCurrentColor;
    }

    inline const QColor& getColor()
    {
    return myColor;
    }@

    .h File:

    @namespace Ui {
    class MainWindow;
    }
    class MainWindow : public QMainWindow
    {
    Q_OBJECT
    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    inline void setColor(const QObject &myCurrentColor);
    inline const QColor& getColor();
    private slots:
    void on_pushButton_Draw_clicked();
    void on_pushButton_colorPick_clicked();
    void on_pushButton_saveSettings_clicked();
    void on_pushButton_loadSettings_clicked();
    private:
    Ui::MainWindow *ui;
    QGraphicsScene *scene;
    QGraphicsRectItem *rectangle;

    QColor myColor;
    QColor partColor;
    QBrush partBrush;
    

    };
    #endif // MAINWINDOW_H@

    Thank you in advance!



  • You didn't specify the class to which these methods belong, and this is mandatory. Based in your example the declaration should look like this:

    .cpp file:

    @inline void MainWindow::setColor(const QObject &myCurrentColor)
    {
    myColor = myCurrentColor;
    }

    inline const QColor& MainWindow::getColor()
    {
    return myColor;
    }@

    ...I didn't include this to my example because my declaration was at the .h file.

    ...about the "inline functions":http://en.wikipedia.org/wiki/Inline_function

    ...the QColor before the function name means this function will return a QColor object, in this case a reference to a QColor object.



  • inlines don't go in implementation files, they go in the headers.

    fs_tigre:
    [quote]Inline functions?[/quote]
    inline isn't much special. It is just a hint to the compiler on how to optimize the code. The basic idea is that the actual function call is replaced with whatever is in the inline function at the place where it is used. That removes a function call (which costs time), but can increase the size of the resulting code.

    [quote]QColor before the function name?[/quote]
    That's just the return type of the function. If you don't understand that, please get a basic C++ book...

    [quote]Reference functions (&getColor)?[/quote]
    No, the & belongs to the return type, so QColor& getColor(). The idea is that the function, instead of returning a copy of the color, returns a reference to the actual QColor data in the setting. That allows you to directly change it in one go. Compare:
    @
    //using value-based semantics
    QColor col = myObject.getColor();
    col = col.setAlphaF(0.5); //change the color in some way
    myObject.setColor(); //now set the changed color back on the object

    //using a reference
    myObject.getColor().setAlphaF(0.5);
    @

    Note that references are not used often in Qt. Qt usually uses pointers instead. There are Qt functions that return a reference though, like QPoint::rx() and QPoint::ry(). Returning references can be useful, but I would recommend not to overuse it. You are basically giving away control from your class to whoever is using the API over internal values. That is only seldom what you want. For instance, once you gave away the reference, your class no longer is notified when the value changes and thus can not react on that or make sure the value if valid.



  • Duplicated post.



  • Thank you both for your help and for the good information provided.

    [quote author="Josué V. Herrera" date="1344392547"]You didn't specify the class to which these methods belong, and this is mandatory. Based in your example the declaration should look like this:

    .cpp file:

    @inline void MainWindow::setColor(const QObject &myCurrentColor)
    {
    myColor = myCurrentColor;
    }

    inline const QColor& MainWindow::getColor()
    {
    return myColor;
    }@
    [/quote]

    Well I actually forgot to add that in my example but I have tried that before and I keep getting errors.

    error: no matching function for call to 'MainWindow::setColor(QColor&)
    candidates are: void MainWindow::setColor(const QObject&)
    In member function 'void MainWindow::setColor(const QObject&)':

    error: no match for 'operator=' in '((MainWindow*)this)->MainWindow::myColor = myCurrentColor'
    candidates are: QColor& QColor::operator=(const QColor&)
    note:QColor& QColor::operator=(Qt::GlobalColor)

    Any idea what could be causing these errors?

    Thanks a lot



  • Read carefully. The errors quite clearly state what the problem is.



  • bq. error: no matching function for call to ‘MainWindow::setColor(QColor&)

    I do have that function!

    Sorry if I dont see the obvious.



  • is it possible QmlApplicationViewer can be used or manipulated in other class rather than main.



  • [quote author="fs_tigre" date="1344421000"]bq. error: no matching function for call to ‘MainWindow::setColor(QColor&)

    I do have that function!

    Sorry if I dont see the obvious.
    [/quote]

    No, you don't have that function. From your error (my highlight):

    [quote author="fs_tigre" date="1344420694"]error: no matching function for call to 'MainWindow::setColor(QColor&)
    candidates are: void MainWindow::setColor(const QObject&)
    In member function 'void MainWindow::setColor(const QObject&)':
    [/quote]

    What makes you think QColor& is the same as a const QObject&?

    And, while we're at it: QObject cannot be copied, so you cannot use it as a function argument the way you do. Pass around pointers instead.



  • Oh, I see, I do have setColor function but I'm passing a different parameter of what was specified in the header which makes it a completely different function. I was just using the code provided by Josué V. Herrera, and to be quite honest, if that's wrong I wont be able to find a solution or fix the problem. I do understand the error but I do not know the solution.

    Thanks



  • Code people give you here on the forum is usually not mend to be used as-is. Often, it is "brain-to-terminal": something you quickly write down in the forum editor itself, untested and probably even not compiling. The idea of such code is that it is a teaching tool; a way of pointing you towards a solution, but often not the solution itself. Copy pasting such snippets is not learning, as it does not promote understanding. If you can only solve your issue by using completely ready-made code offered by others, then you have a serious problem that can only be solved by either really starting to study, or by shelling out some money to start paying a consultant to help you with your project.



  • Understood, Thanks.

    I have said this a few times, I already took a c++ class, read a Qt book but some times is just hard to get everything understood in less than a year. I do programming as a hobby, I actually work full time as Mechanical Engineer.

    On this case I think my problem is a poor understanding of C++ in general but pass by reference and pointers are the main issue in this situation.

    I know I know, sorry for the time you guys wasted here.

    Thanks a lot for all of your previous help.



  • I cannot believe it, it's working, after a few hours, I finally made this thing work.

    Made a few changes including, changing @inline void setColor(const QObject &myCurrentColor);@ to @void setColor(const QColor &myCurrentColor);@

    Even though it doesn't seem like I want to learn, I do, but sometimes it's hard, especially when you are not a programmer.

    Thanks a lot to all that helped.



  • I didn't say nothing about using inline functions in implementation files, because I was not sure why I always use it at headers. Obviously I read it in some book and now I do it without thinking.

    I'm sorry about my mistake specifying QObject instead of QColor, as Andre said that was “brain-to-terminal”, just an example, a possible solution.

    Glad to hear that finally you got it.

    Note: I'm not sure if I should correct my snippet of code for future readers. I think this could break the sequence of the posts. Andre, what do you think about this?



  • How would you format the color as a QColor entry in an INI type file?

    I want to read in a value from the file to set the initial color



  • How would you format the color as a QColor entry in an INI type file?

    I want to read in a value from the file to set the initial color


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.