title: How can I save and reload items in QListWidgets after closing app?
body: <p>I'm quite new in the world of programming in python. I'm coding a GUI that allows users to insert some data. I'm using PyQt5 and trying to use some functions to save and reload widgets state from the .ini file after reopening the app.
  That's just an example of code:</p>
  
  <pre><code>from PyQt5.QtCore import *
  from PyQt5 import QtCore, QtGui, QtWidgets
  
  
  class Ui_Form(object):
      def setupUi(self, Form):
          Form.setObjectName("Form")
          Form.resize(366, 376)
          self.pushButton = QtWidgets.QPushButton(Form)
          self.pushButton.setGeometry(QtCore.QRect(60, 70, 93, 28))
          self.pushButton.setObjectName("pushButton")
          self.listWidget = QtWidgets.QListWidget(Form)
          self.listWidget.setGeometry(QtCore.QRect(60, 110, 256, 192))
          self.listWidget.setObjectName("listWidget")
          self.lineEdit = QtWidgets.QLineEdit(Form)
          self.lineEdit.setGeometry(QtCore.QRect(170, 70, 113, 21))
          self.lineEdit.setObjectName("lineEdit")
  
          self.retranslateUi(Form)
          QtCore.QMetaObject.connectSlotsByName(Form)
  
      def retranslateUi(self, Form):
          _translate = QtCore.QCoreApplication.translate
          Form.setWindowTitle(_translate("Form", "Form"))
          self.pushButton.setText(_translate("Form", "ADD"))
  
  class MyForm(QtWidgets.QWidget):
      settings = QSettings("gui.ini", QSettings.IniFormat)
  
      def __init__(self, parent=None):
          QtWidgets.QWidget.__init__(self, parent)
          self.ui = Ui_Form()
          self.ui.setupUi(self)
  
          restore(self.settings)
  
          self.ui.pushButton.clicked.connect(self.addbutton)
  
      def addbutton(self):
          if self.ui.lineEdit.text():
              self.ui.listWidget.addItem(self.ui.lineEdit.text().upper())
              self.ui.lineEdit.setText("")
  
      def closeEvent(self, event):
          save(self.settings)
          QtWidgets.QWidget.closeEvent(self, event)
  
  def value_is_valid(val):
      if isinstance(val, QtGui.QPixmap):
          return not val.isNull()
      return True
  
  
  def restore(settings):
      finfo = QtCore.QFileInfo(settings.fileName())
  
      if finfo.exists() and finfo.isFile():
          for w in QtWidgets.qApp.allWidgets():
              if w.objectName():
                  mo = w.metaObject()
                  for i in range(mo.propertyCount()):
                      prop = mo.property(i)
                      name = prop.name()
                      last_value = w.property(name)
                      key = "{}/{}".format(w.objectName(), name)
                      if not settings.contains(key):
                          continue
                      val = settings.value(key, type=type(last_value),)
                      if (
                          val != last_value
                          and value_is_valid(val)
                          and prop.isValid()
                          and prop.isWritable()
                      ):
                          w.setProperty(name, val)
  
  
  def save(settings):
      for w in QtWidgets.qApp.allWidgets():
          if w.objectName():
              mo = w.metaObject()
              for i in range(mo.propertyCount()):
                  prop = mo.property(i)
                  name = prop.name()
                  key = "{}/{}".format(w.objectName(), name)
                  val = w.property(name)
                  if value_is_valid(val) and prop.isValid() and prop.isWritable():
                      settings.setValue(key, w.property(name))
  
  if __name__ == "__main__":
      import sys
  
      app = QtWidgets.QApplication(sys.argv)
      form = MyForm()
  
      form.show()
      sys.exit(app.exec_())
  </code></pre>
  
  <p>I'd like to save and reload items from the QListWidgets in my form. At the moment it doesn't happen. Any help and suggestion is appreciated. Thanks</p>
  
  #
  
  <p>UPDATE:</p>
  
  <p>Thanks @NicholasTJ I think that's very usefull. Just one last question. As first parameter of
  <code>def gui_save(ui: QWidget, settings: QSettings, uiName="uiwidget")</code> when I call this method and use "self", it seems is not working.
  That's an example linking to my first answer:</p>
  
  <pre><code>gui_save(self, self.settings, MyForm)
  </code></pre>
  
  <p>These are the definitions I'm trying to use:</p>
  
  <pre><code>from PyQt5 import QtWidgets
  from PyQt5.QtCore import QSettings
  from PyQt5.QtWidgets import *
  import inspect
  
  
  def GetHandledTypes():
      return QComboBox, QLineEdit, QCheckBox, QRadioButton, QSpinBox, QSlider, QListWidget
  
  
  def IsHandledType(widget):
      return any(isinstance(widget, t) for t in GetHandledTypes())
  
  
  # ===================================================================
  # save "ui" controls and values to registry "setting"
  # ===================================================================
  
  def gui_save(ui: QWidget, settings: QSettings, uiName="uiwidget"):
      namePrefix = f"{uiName}/"
      settings.setValue(namePrefix + "geometry", ui.saveGeometry())
  
      for name, obj in QtWidgets.qApp.allWidgets():
          if not IsHandledType(obj):
              continue
  
          name = obj.objectName()
          value = None
          if isinstance(obj, QComboBox):
              index = obj.currentIndex()  # get current index from combobox
              value = obj.itemText(index)  # get the text for current index
  
          if isinstance(obj, QLineEdit):
              value = obj.text()
  
          if isinstance(obj, QCheckBox):
              value = obj.isChecked()
  
          if isinstance(obj, QRadioButton):
              value = obj.isChecked()
  
          if isinstance(obj, QSpinBox):
              value = obj.value()
  
          if isinstance(obj, QSlider):
              value = obj.value()
  
          if isinstance(obj, QListWidget):
              settings.beginWriteArray(name)
              for i in range(obj.count()):
                  settings.setArrayIndex(i)
                  settings.setValue(namePrefix + name, obj.item(i).text())
              settings.endArray()
          elif value is not None:
              settings.setValue(namePrefix + name, value)
  
  
  # ===================================================================
  # restore "ui" controls with values stored in registry "settings"
  # ===================================================================
  
  def gui_restore(ui: QWidget, settings: QSettings, uiName="uiwidget"):
      from distutils.util import strtobool
  
      namePrefix = f"{uiName}/"
      geometryValue = settings.value(namePrefix + "geometry")
      if geometryValue:
          ui.restoreGeometry(geometryValue)
  
      for name, obj in inspect.getmembers(ui):
          if not IsHandledType(obj):
              continue
  
          name = obj.objectName()
          value = None
          if not isinstance(obj, QListWidget):
              value = settings.value(namePrefix + name)
              if value is None:
                  continue
  
          if isinstance(obj, QComboBox):
              index = obj.findText(value)  # get the corresponding index for specified string in combobox
  
              if index == -1:  # add to list if not found
                  obj.insertItems(0, [value])
                  index = obj.findText(value)
                  obj.setCurrentIndex(index)
              else:
                  obj.setCurrentIndex(index)  # preselect a combobox value by index
  
          if isinstance(obj, QLineEdit):
              obj.setText(value)
  
          if isinstance(obj, QCheckBox):
              obj.setChecked(strtobool(value))
  
          if isinstance(obj, QRadioButton):
              obj.setChecked(strtobool(value))
  
          if isinstance(obj, QSlider):
              obj.setValue(int(value))
  
          if isinstance(obj, QSpinBox):
              obj.setValue(int(value))
  
          if isinstance(obj, QListWidget):
              size = settings.beginReadArray(namePrefix + name)
              for i in range(size):
                  settings.setArrayIndex(i)
                  value = settings.value(namePrefix + name)
                  if value is not None:
                      obj.addItem(value)
              settings.endArray()
  </code></pre>