1

I need support to my little software with Qwidget and QTreeWidgets. see below figure.

enter image description here

This is how my Qwidget looks like. I want to restore Qtreewidget items and widget when I close the window and restore it with previous selection. as Marked on the figure below.As you see in my scripts below, I have used Qsettings, I have tried to fix it with pickle but does not work.

enter image description here

Any improvement in coding is welcoming.

from PyQt5 import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import*
from PyQt5.QtGui import *
import sys
import pickle

iconroot = QFileInfo(__file__).absolutePath()
ORGANIZATION_NAME = 'Circularcolumn App'
ORGANIZATION_DOMAIN = 'Circular shape'
APPLICATION_NAME = 'QSettings program'
SETTINGS_TRAY = 'settings/tray'

class usedcircularshape(QDialog):
    def __init__(self, parent=None):
    super().__init__(parent)

    self.setWindowTitle("Frequently used shape")
    self.setWindowIcon(QIcon(iconroot+"/images/circularcolumnnorebar.png"))
    #self.setStyleSheet("background-color:#f2f2f2")

    self.addbutton = QPushButton("Add")
    self.addbutton.clicked.connect(self.add)
    self.deletebutton = QPushButton("Delete")
    self.deletebutton.clicked.connect(self.delete)

    self.okbutton = QPushButton("Ok")
    self.okbutton.setCursor(Qt.PointingHandCursor)
    #self.okbutton.clicked.connect(self.hidethiswindow)
    self.okbutton.clicked.connect(self.savesetting)

    self.cancelbutton = QPushButton("Cancel")
    self.cancelbutton.setCursor(Qt.PointingHandCursor)
    self.cancelbutton.clicked.connect(self.loadsetting)
    #self.cancelbutton.clicked.connect(self.close)

    self.addimage()
    self.qlabeltodefinesection()
    self.treewidget()

    self.sectionnamecircular = QLabel('Section name: ')
    self.sectionnamecircularindata = QLineEdit('Define en name to section')
    self.sectionnamecircularindata.setObjectName("sectionnamecircularindata")
    self.sectionnamecircular.setBuddy(self.sectionnamecircularindata)
    self.sectionnamecircular.setFocus()
    self.grid_sectionname = QHBoxLayout()
    self.grid_sectionname.addWidget(self.sectionnamecircular)
    self.grid_sectionname.addWidget(self.sectionnamecircularindata)

    self.boxlayout = QGridLayout()
    self.boxlayout.addLayout(self.grid_sectionname,0,0,1,2)
    self.boxlayout.addWidget(self.treewidget,1,0,5,2)
    self.boxlayout.addWidget(self.addbutton,2,2)
    self.boxlayout.addWidget(self.deletebutton,3,2)
    self.boxlayout.addWidget(self.imagelabel,6,0)
    self.boxlayout.addLayout(self.qlabelhboxgrid ,6,1)
    self.boxlayout.addWidget(self.okbutton,8,1)
    self.boxlayout.addWidget(self.cancelbutton,8,2)
    self.setLayout(self.boxlayout)
    try:
        self.loadsetting()
    except ( ValueError, TypeError):
        pass

def treewidget(self):
    self.treewidget = QTreeWidget(self)
    self.treewidget.setColumnCount(1)
    self.treewidget.setColumnWidth(1,20)
    self.treewidget.setHeaderItem(QTreeWidgetItem(['Standard Section Library']))
    #self.treewidget.addTopLevelItem(QTreeWidgetItem(['Standard Sectiontype']))
    self.treewidget.setRootIsDecorated(True)

    self.firstparentitem = QTreeWidgetItem(self.treewidget)
    self.firstparentitem.setText(0,'Circular shapes')
    self.firstparentitem.setIcon(0,QIcon(iconroot+"/images/circularcolumnnorebar.png"))

    standardsectionlist = ["D100","D150","D200","D250","D300","D350","D400","D450","D500","D550","D600","D650"
                           ,"D700","D750","D800","D850","D900","D950","D1000"]

    for i in standardsectionlist:
        self.firstparentitem.addChild(QTreeWidgetItem(["%s"%i]))

    self.secondparentitem = QTreeWidgetItem(self.treewidget)
    self.secondparentitem.setText(0,'Customized')
    self.secondparentitem.setIcon(0,QIcon(iconroot+"/images/circularcolumnnorebar.png"))    
    self.secondchilditem = QTreeWidgetItem(["D235"])    
    self.secondparentitem.insertChild(0,self.secondchilditem)
    self.secondchilditem.setChildIndicatorPolicy(QTreeWidgetItem.DontShowIndicator)
    self.treewidget.move(15,15)
    self.treewidget.setGeometry(15,15,200,600)
    self.treewidget.setAlternatingRowColors(True)
    self.treewidget.expandItem ( self.firstparentitem )
    self.show() 

    print(self.treewidget.headerItem().text(0))
    print(self.treewidget.columnCount())
    print(self.treewidget.currentColumn())

    print(self.treewidget.indexFromItem(self.firstparentitem).row())
    print(self.firstparentitem.childCount())
    print(self.firstparentitem.child(1).text(0))
    print(self.firstparentitem.text(0))
    print(self.treewidget.headerItem().text(0))
    print(self.treewidget.topLevelItem(0).text(0))
    print(self.firstparentitem.isSelected())
    print(self.treewidget.selectedItems())
    print(self.secondchilditem.text(1))

    branchstyle = '''QTreeWidget {border:none;} 

    QTreeView::branch:has-siblings:!adjoins-item {
        border-image: url(images/vline.png) 0;}

    QTreeView::branch:has-siblings:adjoins-item {
        border-image: url(images/branch-more.png) 0;}

    QTreeView::branch:!has-children:!has-siblings:adjoins-item {
        border-image: url(images/branch-end.png) 0;}

    QTreeView::branch:has-children:!has-siblings:closed,
    QTreeView::branch:closed:has-children:has-siblings {
        border-image: none;
        image: url(images/branch-closed.png);}

    QTreeView::branch:open:has-children:!has-siblings,
    QTreeView::branch:open:has-children:has-siblings {
        border-image: none;
        image: url(images/branch-open.png);}'''

    self.treewidget.setStyleSheet(branchstyle)
    self.treewidget.itemClicked.connect(self.currentitem)
    self.treewidget.currentItemChanged.connect(self.current_item_changed)

   #@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem, QtWidgets.QTreeWidgetItem)
def current_item_changed(self, current, previous):
   #print('\ncurrent: {}, \nprevious: {}'.format(current, previous))
    print(current.text(0),previous)


def add(self):
    text, ok = QInputDialog.getText(self, "Add custom section", "Enter section geometry f.ex as D325 or just 325 in mm: ")

    if ok:
        self.secondchilditem = QTreeWidgetItem(["%s"% text])
        self.secondparentitem.insertChild(0,self.secondchilditem)
        self.treewidget.expandItem ( self.secondparentitem )
        self.gettext = text

    print(self.secondparentitem.child(0), self.gettext)


def delete(self):
    self.secondparentitem.takeChild(0)

def currentitem(self):
    print(self.treewidget.currentItem().text(0),self.treewidget.selectedItems())
    self.itemtext = self.treewidget.currentItem().text(0)

    if self.itemtext == self.firstparentitem.text(0) or self.itemtext == self.secondparentitem.text(0):
        return None
    elif self.itemtext == self.treewidget.topLevelItem(0).text(0):
        return None
    elif self.itemtext == None:
        return None
    else:
        self.select_circular_section = int(self.itemtext.translate({ord('D'):None}))   
        print(self.itemtext, self.treewidget.selectedItems, self.select_circular_section)

        area = str(format(3.1416/4*(self.select_circular_section)**2,'0.2E'))
        inerti = str(format(3.1416/64*pow(self.select_circular_section,4),'0.2E'))

        self.qlabelcirculardiameterselected = QLabel('')
        qlabelcircularareaselected = QLabel('')
        qlabelcircularinertimomentselected = QLabel("")
        emptylabel1 = QLabel('     ')

        self.qlabelcirculardiameterselected.setText('%s    mm '% self.select_circular_section)
        qlabelcircularareaselected.setText('{}    mm2 ' .format(area))
        qlabelcircularinertimomentselected.setText("%s    mm4 " %(inerti))

        qlabelhboxgridselected = QGridLayout()
        qlabelhboxgridselected.addWidget(emptylabel1,0,0)
        qlabelhboxgridselected.addWidget(self.qlabelcirculardiameterselected,1,0)
        qlabelhboxgridselected.addWidget(qlabelcircularareaselected,2,0)
        qlabelhboxgridselected.addWidget(qlabelcircularinertimomentselected,3,0)
        qlabelhboxgridselected.addWidget(emptylabel1,4,0,5,0)       

        return print(self.itemtext, self.treewidget.selectedItems, self.select_circular_section), self.boxlayout.addLayout(qlabelhboxgridselected ,6,2),self.qlabelcirculardiameterselected     

def addimage(self):
    self.imagelabel = QLabel()
    self.circularimage = QPixmap(iconroot+"/images/circularcolumnnorebard.png").scaled(230,230,Qt.KeepAspectRatio)
    self.imagelabel.setPixmap(self.circularimage) 
    self.imagelabel.setGeometry(15,15,15,15)

def hidethiswindow(self):   
    if self.itemtext == self.firstparentitem.text(0) or self.itemtext == self.secondparentitem.text(0):
        QMessageBox.about(self,'Error selection','Please, select a section not a text')
    elif self.itemtext == self.treewidget.topLevelItem(0).text(0):
        QMessageBox.about(self,'Error selection','Please, select a section not a text')
    elif self.itemtext == None:
        QMessageBox.about(self,'Error selection','Please, select a section not a text')
    else:
        self.savesetting()
        self.hide() 

def qlabeltodefinesection(self):    
    self.qlabelcirculardiameter = QLabel('    D = ')
    self.qlabelcirculararea = QLabel('    A = ')
    self.qlabelcircularinertimoment = QLabel("    I = ")
    self.emptylabel = QLabel('     ')   
    self.qlabelhboxgrid = QGridLayout()
    self.qlabelhboxgrid.addWidget(self.emptylabel,0,0)
    self.qlabelhboxgrid.addWidget(self.qlabelcirculardiameter,1,0)
    self.qlabelhboxgrid.addWidget(self.qlabelcirculararea,2,0)
    self.qlabelhboxgrid.addWidget(self.qlabelcircularinertimoment,3,0)
    self.qlabelhboxgrid.addWidget(self.emptylabel,4,0,5,0)


def savesetting(self):
    settings = QSettings(ORGANIZATION_NAME,APPLICATION_NAME)
    #settings = QSettings('config.ini',QSettings.IniFormat)
    settings.beginGroup('D')
    settings.setValue(SETTINGS_TRAY,self.geometry())
    settings.setValue("LineEdit",self.sectionnamecircularindata.text())
    settings.setValue("Selectitem",self.treewidget.currentItem())
    settings.setValue("Label",self.qlabelcirculardiameterselected)
    settings.endGroup()
    print('Saved', )
    #self.hide()   

def loadsetting(self):
    settings = QSettings(ORGANIZATION_NAME,APPLICATION_NAME)
    #settings = QSettings('config.ini',QSettings.IniFormat)
    settings.beginGroup('D')
    myrect = settings.value(SETTINGS_TRAY)
    restorelineEdit = settings.value("LineEdit",'')
    restoreselectsection = settings.value("Selectitem",)
    restoreqlabel =  settings.value("Label",'')
    self.setGeometry(myrect)
    self.sectionnamecircularindata.setText(restorelineEdit)
    self.treewidget.setCurrentItem(restoreselectsection)
    settings.endGroup()        

if __name__ == "__main__":

QCoreApplication.setApplicationName(ORGANIZATION_NAME)
QCoreApplication.setOrganizationDomain(ORGANIZATION_DOMAIN)
QCoreApplication.setApplicationName(APPLICATION_NAME)

app = QApplication(sys.argv)
subwindow=usedcircularshape()
subwindow.show()
app.exec()

What does the code do?

This is engineering software, to concrete columns, the idea is a user should be able to pick a standard section e.g. D350, D means diameter and 350 is diameter of circular concrete column in unit mm. User has ability to add custom shapes of circular columns. And when user click and select in from Qtreewidget a section, this section should remain and be global available for further calculation, which is not shown her. This is a widget to geometry defining within big concrete software. I would below further explain the code. First I create Qdialog and create Qtreewidget, an image for clarification and Qlabel based an item selection. Within Qtreewidget I first create a parentitem and give it an name “ Circular shapes”

self.firstparentitem = QTreeWidgetItem(self.treewidget)
self.firstparentitem.setText(0,'Circular shapes')

Then parentitem has children, to define and add those, first I create a list with standard sections

    standardsectionlist = ["D100","D150","D200","D250","D300","D350","D400","D450","D500","D550","D600","D650"
                       ,"D700","D750","D800","D850","D900","D950","D1000"]

And do for condition to add children to parentitem.

    for i in standardsectionlist:
    self.firstparentitem.addChild(QTreeWidgetItem(["%s"%i]))

later I define second parentitem and give a name “Customized” and define a list then later add item of list as child to second parentitem. For user should be able to add and remove childitem from second parentitem I create 2 buttons

self.addbutton = QPushButton("Add")
self.deletebutton = QPushButton("Delete")

Addbutton has a function to add children item to second parentitem. Deletebutton has a function to remove first childitem from second parentitem.

def currentitem(self):

currentitem function has a function when user click and select an item within Qtreewidget, it takes currenitem text and remove D letter from it and convert it into int, then display it as D = Diameter, A = Area ect…

def hidethiswindow(self)

hidethiswindow function this one guide the user either to select an item or to cancel the widget, in case user by mistake has selected headeritem, a error message will arise and tell to select child item. Powerfull is’t it!

The rest code is to display and Qsettings. Hope this explains the code.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Pavel.D
  • 561
  • 1
  • 15
  • 41
  • In SO you should ask a question by POST, so Ask Question says, do not say Ask Questions, please edit your question and remove the questions, those questions you should do in other POST. – eyllanesc Aug 30 '18 at 15:44
  • 1
    I edited the question to one by post. – Pavel.D Aug 30 '18 at 18:03
  • Could you explain what your code does, also those marks with yellow color in the image are relevant? – eyllanesc Aug 30 '18 at 18:11
  • I have explained what my code do or want to do!. Please do not hesitate to ask if you have more questions. – Pavel.D Aug 30 '18 at 19:26
  • I understand what you want to do, but I am confused by the meaning of 1 and 2 in yellow on the second image. Are they relevant? – eyllanesc Aug 30 '18 at 19:28
  • I would remove 1 and 2 yellow on the second image tomorrow. – Pavel.D Aug 30 '18 at 19:32
  • When you say *previous selection* do you mean items D345-D235 or the blue selection of item D550? – eyllanesc Aug 30 '18 at 19:33
  • I mean by that, when I select an childitem either from Circular shapes or Customised and hide the Widget, for instance I pick and select D200 then hide the widget, later restore the widget, I would like to have selection remain still on D200, this is what I mean previous selection. – Pavel.D Aug 30 '18 at 19:38

1 Answers1

0

What you have to do is save the data of each item for this I have created the itemToTuple method that returns a tuple of the data to be saved, also given that saved tuple you must set those properties and for that you use the tupleToItem function (if you want add more information of the items you only have to modify those methods). But to save all the items of QTreeWidget, the whole tree must be traversed. For this, the dataFromChild method that returns the data of the item and its children is used. The inverse process, that is, given the data must be established in all the items, dataToChild must be used, which establishes the respective data to the item and its children.

Also I have divided the application into several classes to have it sorted, if you want the information of a widget to be saved you must create a method called writeSettings(...) with a format similar to the ones I show then the application will call in the closeEvent(...) method. Similarly, you can create the readSettings(...) method and call it in its constructor.

import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets

iconroot = os.path.dirname(__file__)
ORGANIZATION_NAME = 'Circularcolumn App'
ORGANIZATION_DOMAIN = 'Circular shape'
APPLICATION_NAME = 'QSettings program'
SETTINGS_TRAY = 'settings/tray'

QSS = """
QTreeWidget{
    border:none;
 } 

QTreeView::branch:has-siblings:!adjoins-item {
   border-image: url(images/vline.png) 0;
}

QTreeView::branch:has-siblings:adjoins-item {
    border-image: url(images/branch-more.png) 0;
}

QTreeView::branch:!has-children:!has-siblings:adjoins-item {
    border-image: url(images/branch-end.png) 0;
}

QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings {
    border-image: none;
    image: url(images/branch-closed.png);
}

QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:open:has-children:has-siblings {
    border-image: none;
    image: url(images/branch-open.png);
}
"""


class TreeWidget(QtWidgets.QTreeWidget):
    currentTextChanged = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(TreeWidget, self).__init__(parent)
        self.currentItemChanged.connect(self.onCurrentItemChanged)
        self.setHeaderLabel('Standard Section Library')
        self.setRootIsDecorated(True)
        self.setAlternatingRowColors(True)
        self.readSettings()
        self.expandAll()

    def onCurrentItemChanged(self, current, previous):
        if current not in [self.topLevelItem(ix) for ix in range(self.topLevelItemCount())]:
            self.currentTextChanged.emit(current.text(0))

    def readSettings(self):
        settings = QtCore.QSettings()
        settings.beginGroup("TreeWidget")
        values = settings.value("items")
        if values is None:
            self.loadDefault()
        else:
            TreeWidget.dataToChild(values, self.invisibleRootItem())
            self.customized_item = None
            for ix in range(self.topLevelItemCount()):
                tlevel_item = self.topLevelItem(ix)
                if tlevel_item.text(0) == "Customized":
                    self.customized_item = tlevel_item
        settings.endGroup()

    def writeSettings(self):
        settings = QtCore.QSettings()
        settings.beginGroup("TreeWidget")
        settings.setValue("items", TreeWidget.dataFromChild(self.invisibleRootItem()))
        settings.endGroup()

    def loadDefault(self):
        standardsectionlist = ["D100","D150","D200","D250","D300","D350","D400","D450","D500",
        "D550","D600","D650","D700","D750","D800","D850","D900","D950","D1000"]
        rootItem = QtWidgets.QTreeWidgetItem(self, ['Circular shapes'])
        rootItem.setIcon(0, QtGui.QIcon(os.path.join(iconroot,"images/circularcolumnnorebar.png")))
        for element in standardsectionlist:
            rootItem.addChild(QtWidgets.QTreeWidgetItem([element]))

        self.customized_item = QtWidgets.QTreeWidgetItem(self, ["Customized"])
        self.customized_item.setIcon(0, QtGui.QIcon(os.path.join(iconroot,"images/circularcolumnnorebar.png")))

    @staticmethod
    def dataToChild(info, item):
        TreeWidget.tupleToItem(info["data"], item)
        for val in info["childrens"]:
            child = QtWidgets.QTreeWidgetItem()
            item.addChild(child)
            TreeWidget.dataToChild(val, child)

    @staticmethod
    def tupleToItem(t, item):
        # set values to item
        ba, isSelected = t
        ds = QtCore.QDataStream(ba)
        ds >> item
        item.setSelected(isSelected) 

    @staticmethod
    def dataFromChild(item):
        l = []
        for i in range(item.childCount()):
            child = item.child(i)
            l.append(TreeWidget.dataFromChild(child))
        return {"childrens": l, "data": TreeWidget.itemToTuple(item)}

    @staticmethod
    def itemToTuple(item):
        # return values from item
        ba = QtCore.QByteArray()
        ds = QtCore.QDataStream(ba, QtCore.QIODevice.WriteOnly)
        ds << item
        return ba, item.isSelected()


class InfoWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(InfoWidget, self).__init__(parent)
        hlay = QtWidgets.QHBoxLayout(self)
        plabel = QtWidgets.QLabel()
        pixmap = QtGui.QPixmap(os.path.join(iconroot, "images/circularcolumnnorebard.png"))\
                    .scaled(230, 230, QtCore.Qt.KeepAspectRatio)
        plabel.setPixmap(pixmap)
        hlay.addWidget(plabel)
        self.ilabel = QtWidgets.QLabel()
        hlay.addWidget(self.ilabel)
        hlay.addStretch()
        self.readSettings()

    @QtCore.pyqtSlot(str)
    def setData(self, text):
        try:
            circular_section = int(text.translate({ord('D'): ""}))
            area = (3.1416/4)*(circular_section**2)
            inertia = (3.1416/64)*circular_section**4
            fmt = "D = {}mm\nA = {:0.2E}mm2\n I  = {:0.2E}mm4"
            self.ilabel.setText(fmt.format(circular_section, area, inertia))
        except ValueError:
            pass

    def readSettings(self):
        settings = QtCore.QSettings()
        settings.beginGroup("InfoWidget")
        self.ilabel.setText(settings.value("text", ""))
        settings.endGroup()

    def writeSettings(self):
        settings = QtCore.QSettings()
        settings.beginGroup("InfoWidget")
        settings.setValue("text", self.ilabel.text())
        settings.endGroup()


class CircularDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(CircularDialog, self).__init__(parent)
        grid = QtWidgets.QGridLayout(self)

        self.tree = TreeWidget()
        self.infoWidget = InfoWidget()

        section_lay = QtWidgets.QHBoxLayout()
        section_label = QtWidgets.QLabel("Section name: ")
        section_edit = QtWidgets.QLineEdit('Define en name to section')
        section_lay.addWidget(section_label)
        section_lay.addWidget(section_edit)

        self.tree.currentTextChanged.connect(self.infoWidget.setData)

        button_layout = QtWidgets.QVBoxLayout()
        add_button = QtWidgets.QPushButton("Add")
        add_button.clicked.connect(self.addItem)
        delete_button = QtWidgets.QPushButton("Delete")
        delete_button.clicked.connect(self.removeItem)
        button_layout.addWidget(add_button, alignment=QtCore.Qt.AlignBottom)
        button_layout.addWidget(delete_button, alignment=QtCore.Qt.AlignTop)

        buttonBox = QtWidgets.QDialogButtonBox()
        buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        buttonBox.accepted.connect(self.accept) 
        buttonBox.rejected.connect(self.reject)

        # for windows, posible bug
        self.accepted.connect(self.write_all_data)
        self.rejected.connect(self.write_all_data)

        grid.addLayout(section_lay, 0, 0)
        grid.addWidget(self.tree, 1, 0)
        grid.addLayout(button_layout, 1, 1)
        grid.addWidget(self.infoWidget, 2, 0, 1, 2)
        grid.addWidget(buttonBox, 3, 0, 1, 2)
        self.readSettings()

    def readSettings(self):
        settings = QtCore.QSettings()
        settings.beginGroup("CircularDialog")
        self.setGeometry(settings.value("geometry", QtCore.QRect(300, 300, 400, 600)))
        settings.endGroup()

    def writeSettings(self):
        settings = QtCore.QSettings()
        settings.beginGroup("CircularDialog")
        settings.setValue("geometry", self.geometry())
        settings.endGroup()

    def closeEvent(self, event):
        self.write_all_data()
        super(CircularDialog, self).closeEvent(event)

    def write_all_data(self):
        for children in self.findChildren(QtWidgets.QWidget) + [self]:
            if hasattr(children, "writeSettings"):
                children.writeSettings()

    def addItem(self):
        text, ok = QtWidgets.QInputDialog.getText(self, "Add custom section", 
            "Enter section geometry f.ex as D325 or just 325 in mm: ")
        if ok:
            it = QtWidgets.QTreeWidgetItem([text])
            self.tree.customized_item.addChild(it)

    def removeItem(self):
        it = self.tree.customized_item.takeChild(0)
        del it


if __name__ == '__main__':
    QtCore.QCoreApplication.setApplicationName(ORGANIZATION_NAME)
    QtCore.QCoreApplication.setOrganizationDomain(ORGANIZATION_DOMAIN)
    QtCore.QCoreApplication.setApplicationName(APPLICATION_NAME)

    app = QtWidgets.QApplication(sys.argv)
    app.setStyleSheet(QSS)
    w = CircularDialog()
    w.show()
    sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thanks for quick reply. Yes a better way to rewrite scripts and more professional. But it seems it does not work for me, it can't restore selection and others. I need to understand what you have done. I can see that you fix "setData" very beautifull. – Pavel.D Aug 31 '18 at 06:53
  • @ZardashtYousef How strange, I've tried it several times, just in case it eliminates your configuration file that you should have created. On the other hand which version of python you use and what version of PyQt5 – eyllanesc Aug 31 '18 at 06:54
  • @ZardashtYousef try it back, as it points you delete the configuration file, if you want to know its location print settings.fileName (). If my answer helps you, do not forget to mark it as correct, if you do not know how to do it, review the [tour], that is the best way to thank. – eyllanesc Aug 31 '18 at 07:01