Cannot read boolean from ini file
Asked Answered
G

3

5

I have problem with loading boolean from ini file in PyQt5 app.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5 import QtCore
from PyQt5.QtCore import QSettings, QVariant
from PyQt5.QtWidgets import (
    QApplication, QCheckBox, QDialog, QGridLayout,
    QLabel, QLayout, QPushButton
)


class Settings(QDialog):
    "settings GUI"

    _settings = None

    def __init__(self):
        super(Settings, self).__init__()
        self._ui()

    def _ui(self):
        self._chk_test = QCheckBox()
        self._chk_test.setText("test checkbox")

        self._settings = QSettings("settings.ini", QSettings.IniFormat)
        self._settings.setFallbacksEnabled(False)

        # load configuration
        self._chk_test.setChecked(
            self._bool(self._settings.value("test_value", True)))

        # save settings
        btn_save = QPushButton("save")
        btn_save.clicked.connect(self._save_settings)

        # setting layouts
        grid_layout = QGridLayout()
        grid_layout.addWidget(self._chk_test, 0, 0, 1, 1)
        grid_layout.addWidget(btn_save, 0, 1, 1, 1)
        grid_layout.setSizeConstraint(QLayout.SetFixedSize)
        grid_layout.setHorizontalSpacing(100)
        grid_layout.setVerticalSpacing(5)

        self.setWindowTitle("Boolean")
        self.setLayout(grid_layout)
        self.show()

    def _save_settings(self):
        self._settings.setValue("test_value", self._chk_test.isChecked())
        self.close()

    def _bool(self, str):
        if str == "true":
            return True
        else:
            return False


if __name__ == "__main__":
    app = QApplication(sys.argv)
    ui = Settings()
    sys.exit(app.exec_())

When I'm try to load boolean using

self._settings.value("test_value", True).toBool()

or

QVariant(self._settings.value("test_value", True)).toBool()

I'm getting AttributeError:

'str' / 'QVariant' object has no attribute 'toBool()'. 

I've written custom _bool method but I'm wondering if there's better way to solve it.

Ginkgo answered 25/11, 2016 at 19:48 Comment(2)
shorter: return str == "true"Stormie
Nice trick, thanks ! I did not see that in Qt docs, I though it does not exist, however you can find it in PyQt doc.Gutenberg
S
13

They add third argument type= to set type for result. So you can use type=bool and get Python True/False instead of string "true"/"false"

a = self._settings.value("test_value", True, type=bool)
print('a:', type(a), a)

b = self._settings.value("test_value", True)
print('b:', type(b), b)

result

a: <class 'bool'> True
b: <class 'str'> true

Found in Google: https://riverbankcomputing.com/pipermail/pyqt/2011-January/029032.html

  • Added the optional type keyword argument to QSettings.value() to allow the type of the returned value to be specified.
Stormie answered 25/11, 2016 at 20:21 Comment(1)
Thanks for your answer. It's exactly what I wanted to do.Ginkgo
F
1

Assuming self._settings.value("test_value", True) returns a string whose value is "true", you could do

self._chk_test.setChecked(
            self._settings.value("test_value", True) == "true")

However, if you need to do this multiple times I would keep the custom method (but make it more compact as @furas has suggested):

def _bool(self, str):
    return str == "true"
Fattish answered 25/11, 2016 at 20:13 Comment(1)
It returns a string whose value can be "true" or "false" and I wanted to make it boolean. Answer I was looking for is given above..Ginkgo
S
0

I mucked around with mixtures of the above solutions and for me, I found out what is really important for saving a lot of time testing, is to clear the settings before setting them.

self._settings.clear()
self._settings.setValue("test_value", False)
print(self._settings.value("test_value", type=bool)

This solution works for me on macOS and Windows.

The other thing to be careful about when working cross platform is always use the same case and never use case to differentiate two words. Windows init file is case insensitive while macOS is case sensitive.

Salve answered 12/9, 2023 at 8:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.