Search code examples
c++qtc++11qpushbuttonqsettings

save and load modifications with qsettings


I have 2 windows ( window 1 ) & ( window 2 ) : see pictures. -On window 1 there is an "edit" button that should open window 2 ( and load modifs saved on window 2 ) -On window 2, I have 96 buttons which are initially green, if I click on one it becomes red. The "OK" button that I have should close window 2 and save the modifications ( red buttons ). If I re-open window 2 by clicking on the "edit" button of window 1, the red buttons of the last step should stay red and become uncheckable. How can I do that with QSettings ? This is my code of the savesettings method : ( I don't know if it is correct or not but I think yes !)

void Vessels::SaveSettings()
{
        QSettings setting("My_vessels","My_selected_vessels");
        setting.beginGroup("Vessels");
        if (ui->pushButton_4->isChecked()){
        ui->pushButton_4->setCheckable(false);}
        setting.setValue("selected",ui->pushButton_4->isCheckable());
        setting.endGroup();
}

I am facing 2 problems : 1) The save and load buttons ( which are in this case respectively "OK" and "Edit" ) are not from the same window. 2) I don't know how to implement the loadSettings method that I should append to the "Edit" button.

enter image description here


Solution

  • Here is your solution, as I have come up with, please test on your side, its working for me:

    Solved screen-shot

    File: QSettings2.pro

    #-------------------------------------------------
    #
    # Project created by QtCreator 2020-01-23T19:21:17
    #
    #-------------------------------------------------
    
    QT       += core gui
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    TARGET = QSettings2
    TEMPLATE = app
    
    # The following define makes your compiler emit warnings if you use
    # any feature of Qt which has been marked as deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS
    
    # You can also make your code fail to compile if you use deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    CONFIG += c++11
    
    SOURCES += \
            dialog.cpp \
            main.cpp \
            mainwindow.cpp
    
    HEADERS += \
            dialog.h \
            mainwindow.h
    
    FORMS += \
            dialog.ui \
            mainwindow.ui
    
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    

    File: dialog.h

    #ifndef DIALOG_H
    #define DIALOG_H
    
    #include <QDialog>
    
    class QLabel;
    class QSettings;
    namespace Ui {
    class Dialog;
    }
    
    class Dialog : public QDialog
    {
        Q_OBJECT
    
    public:
        Dialog(QSettings *settings, QWidget *parent = nullptr);
        ~Dialog();
    
    private slots:
        void on_pushButtonOK_clicked();
        void on_pushButtonCancel_clicked();
    
    private:
        QLabel* CreateNewLabel(QString text, QWidget* parent);
        void saveSettings();
        void loadSettings();
        Ui::Dialog *ui;
        QSettings *m_settings;
        const int ROWS = 8, COLS = 12;
    };
    
    #endif // DIALOG_H
    

    File: mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    
    class QSettings;
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private slots:
        void on_pushButton_clicked();
    
    private:
        Ui::MainWindow *ui;
        QSettings* m_settings;
    };
    
    #endif // MAINWINDOW_H
    

    File: dialog.cpp

    #include "dialog.h"
    #include "ui_dialog.h"
    #include <QGridLayout>
    #include <QDebug>
    #include <QSettings>
    
    Dialog::Dialog(QSettings *settings, QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Dialog),
        m_settings(settings)
    {
        ui->setupUi(this);
        ui->frame->setStyleSheet(QString());//we did draw border just for design time view
        ui->pushButton_Circular->hide();
    
        QGridLayout *gridLayout = new QGridLayout();
    
        //gridLayout->setColumnStretch(0, 1);
        //gridLayout->setRowStretch(0, 1);
    
        for(int i = 1; i <= COLS; i++)
        {
            //gridLayout->setColumnStretch(i, 1);
            QLabel *label = CreateNewLabel(QString::number(i), this);
            gridLayout->addWidget(label, 0, i);
        }
    
        for(int i = 1; i <= ROWS; i++)
        {
            //gridLayout->setRowStretch(i, 1);
            QLabel *label = CreateNewLabel(QString("%1").arg(static_cast<char>('A' + i -1)), this);
            gridLayout->addWidget(label, i, 0);
        }
    
        QString buttonIdText;
        for(int i = 1; i <= ROWS; i++)
        {
            for(int j = 1; j<= COLS; j++)
            {
                QPushButton *button = new QPushButton(this);
                button->setMaximumSize(40, 40);
                button->setMinimumSize(40, 40);
                button->setStyleSheet(ui->pushButton_Circular->styleSheet());
                button->setCheckable(true);
    
                buttonIdText = QString::number((i-1)*COLS + j);
                button->setText(buttonIdText);
                button->setObjectName("GridButton_" + buttonIdText);
    
                gridLayout->addWidget(button, i, j);
            }
        }
    
        ui->frame->setLayout(gridLayout);
        loadSettings();
    }
    
    Dialog::~Dialog()
    {
        delete ui;
    }
    
    QLabel *Dialog::CreateNewLabel(QString text, QWidget *parent)
    {
        QLabel *label = new QLabel(text, parent);
        label->setFont(QFont(label->font().family(), 10, 500));
        label->setAlignment(Qt::AlignCenter);
        label->setStyleSheet("background-color: rgb(170, 0, 0);");
        label->setMaximumSize(40, 40);
        label->setMinimumSize(40, 40);
        return label;
    }
    
    void Dialog::saveSettings()
    {
        QString key;
        QVariant value;
        m_settings->beginGroup("GridButtonsStatus");
        foreach(QObject *childObject, ui->frame->children())
        {
            if(QPushButton *button = qobject_cast<QPushButton*>(childObject))
            {
                key = button->objectName();
                value = button->isChecked();
                m_settings->setValue(key, value);
            }
        }
        m_settings->endGroup();
        m_settings->sync();
    }
    
    void Dialog::loadSettings()
    {
        QString key;
        m_settings->beginGroup("GridButtonsStatus");
        for(int i = 1; i <= ROWS * COLS; i++)
        {
            key = QString("GridButton_%1").arg(i);
            qDebug() << "--- key = " << key <<", value = " <<  m_settings->value(key) << endl;
            QPushButton *button = ui->frame->findChild<QPushButton*>(key); //key was push button object name
            if(button)
            {
                bool is_Checked = m_settings->value(key, false).toBool();
                button->setChecked(is_Checked);
                button->setEnabled(!is_Checked);
            }
        }
        m_settings->endGroup();
    }
    
    void Dialog::on_pushButtonOK_clicked()
    {
        saveSettings();
        close();
    }
    
    void Dialog::on_pushButtonCancel_clicked()
    {
        close();
    }
    

    File: main.cpp

    #include "mainwindow.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    

    File: mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "dialog.h"
    
    #include <QSettings>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow), m_settings(new QSettings(qAppName() + ".ini", QSettings::IniFormat))
    {
        ui->setupUi(this);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    #include <QDebug>
    void MainWindow::on_pushButton_clicked()
    {
        Dialog dialog(m_settings);
        dialog.exec();
    }
    

    File: dialog.ui

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>Dialog</class>
     <widget class="QDialog" name="Dialog">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>730</width>
        <height>501</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>Dialog</string>
      </property>
      <widget class="QLabel" name="label">
       <property name="geometry">
        <rect>
         <x>50</x>
         <y>10</y>
         <width>331</width>
         <height>31</height>
        </rect>
       </property>
       <property name="font">
        <font>
         <pointsize>14</pointsize>
         <weight>75</weight>
         <bold>true</bold>
        </font>
       </property>
       <property name="text">
        <string>Choose your vessels:</string>
       </property>
      </widget>
      <widget class="QPushButton" name="pushButtonOK">
       <property name="geometry">
        <rect>
         <x>560</x>
         <y>440</y>
         <width>160</width>
         <height>41</height>
        </rect>
       </property>
       <property name="text">
        <string>OK</string>
       </property>
      </widget>
      <widget class="QPushButton" name="pushButton_Circular">
       <property name="geometry">
        <rect>
         <x>20</x>
         <y>440</y>
         <width>40</width>
         <height>40</height>
        </rect>
       </property>
       <property name="styleSheet">
        <string notr="true">QPushButton {
        border-radius: 20px;
        border-style: outset;
        background: qradialgradient(
            cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,
            radius: 1.35, stop: 0 green, stop: 1 #009900
            );
        padding: 5px;
        }
    
    QPushButton:hover {
        background: qradialgradient(
            cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,
             radius: 1.35, stop: 0 red, stop: 1 #004400
            );
        }
    
    QPushButton:checked {
        border-style: inset;
        background: qradialgradient(
            cx: 0.4, cy: -0.1, fx: 0.4, fy: -0.1,
            radius: 1.35, stop: 0 red, stop: 1 #990000
            );
        }
    </string>
       </property>
       <property name="text">
        <string/>
       </property>
       <property name="checkable">
        <bool>true</bool>
       </property>
       <property name="checked">
        <bool>false</bool>
       </property>
      </widget>
      <widget class="QFrame" name="frame">
       <property name="geometry">
        <rect>
         <x>20</x>
         <y>50</y>
         <width>520</width>
         <height>360</height>
        </rect>
       </property>
       <property name="sizePolicy">
        <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
         <horstretch>0</horstretch>
         <verstretch>0</verstretch>
        </sizepolicy>
       </property>
       <property name="minimumSize">
        <size>
         <width>520</width>
         <height>360</height>
        </size>
       </property>
       <property name="maximumSize">
        <size>
         <width>520</width>
         <height>360</height>
        </size>
       </property>
       <property name="styleSheet">
        <string notr="true">border:1px solid red</string>
       </property>
       <property name="frameShape">
        <enum>QFrame::StyledPanel</enum>
       </property>
       <property name="frameShadow">
        <enum>QFrame::Raised</enum>
       </property>
      </widget>
      <widget class="QPushButton" name="pushButtonCancel">
       <property name="geometry">
        <rect>
         <x>370</x>
         <y>440</y>
         <width>160</width>
         <height>41</height>
        </rect>
       </property>
       <property name="text">
        <string>CANCEL</string>
       </property>
      </widget>
      <zorder>frame</zorder>
      <zorder>label</zorder>
      <zorder>pushButtonOK</zorder>
      <zorder>pushButton_Circular</zorder>
      <zorder>pushButtonCancel</zorder>
     </widget>
     <resources/>
     <connections/>
    </ui>
    

    File: mainwindow.ui

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>MainWindow</class>
     <widget class="QMainWindow" name="MainWindow">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>573</width>
        <height>374</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>MainWindow</string>
      </property>
      <widget class="QWidget" name="centralWidget">
       <widget class="QLabel" name="label">
        <property name="geometry">
         <rect>
          <x>40</x>
          <y>20</y>
          <width>271</width>
          <height>81</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <pointsize>14</pointsize>
          <weight>75</weight>
          <bold>true</bold>
         </font>
        </property>
        <property name="text">
         <string>Prepare YourSolutions</string>
        </property>
       </widget>
       <widget class="QLabel" name="label_2">
        <property name="geometry">
         <rect>
          <x>50</x>
          <y>150</y>
          <width>91</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Solution 1</string>
        </property>
       </widget>
       <widget class="QPushButton" name="pushButton">
        <property name="geometry">
         <rect>
          <x>154</x>
          <y>152</y>
          <width>101</width>
          <height>31</height>
         </rect>
        </property>
        <property name="text">
         <string>Edit</string>
        </property>
       </widget>
      </widget>
     </widget>
     <layoutdefault spacing="6" margin="11"/>
     <resources/>
     <connections/>
    </ui>