class RequestsOperations(QWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.initUI()
        self.__ops = []

    def initUI(self):
        self.layout = QFormLayout()
        self.layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
        self.layout.setLabelAlignment(Qt.AlignLeft)
        self.layout.setFormAlignment(Qt.AlignLeft | Qt.AlignTop)

        twoListsOfSets = QWidget()
        twoListsOfSets.setLayout(QHBoxLayout())
        twoListsOfSets.layout().setContentsMargins(5, 10, 5, 5)
        twoListsOfSets.layout().setSpacing(0)

        effect = QGraphicsDropShadowEffect()
        effect.setBlurRadius(10)
        effect.setColor(QColor(0, 0, 0, 160))
        effect.setOffset(0.0)

        self.requestList = QListView()
        self.requestList.setSpacing(3)
        self.requestList.setAutoFillBackground(True)
        self.requestList.setGraphicsEffect(effect)
        self.requestList.setFrameStyle(QFrame.NoFrame)
        self.requestList.viewport().setAutoFillBackground(False)
        self.requestList.setFlow(QListView.LeftToRight)
        self.requestList.setWrapping(True)
        self.requestList.setResizeMode(QListView.Adjust)
        self.requestList.setUniformItemSizes(True)
        self.requestsModel = QStandardItemModel()
        self.requestList.setModel(self.requestsModel)

        effect = QGraphicsDropShadowEffect()
        effect.setBlurRadius(10)
        effect.setColor(QColor(0, 0, 0, 160))
        effect.setOffset(0.0)

        self.requestList2 = QListView()
        self.requestList2.setSpacing(3)
        self.requestList2.setAutoFillBackground(True)
        self.requestList2.setGraphicsEffect(effect)
        self.requestList2.setFrameStyle(QFrame.NoFrame)
        self.requestList2.viewport().setAutoFillBackground(False)
        self.requestList2.setFlow(QListView.LeftToRight)
        self.requestList2.setWrapping(True)
        self.requestList2.setResizeMode(QListView.Adjust)
        self.requestList2.setUniformItemSizes(True)
        self.requestsModel2 = QStandardItemModel()
        self.requestList2.setModel(self.requestsModel2)

        twoListsOfSets.layout().addWidget(self.requestList)
        twoListsOfSets.layout().addWidget(self.requestList2)

        self.layout.addRow("SETS", twoListsOfSets)
        self.layout.addRow(HorizontalLine(self))

        self.operationSelection = QGroupBox()
        self.operationSelection.setFlat(True)
        self.operationSelection.setLayout(QVBoxLayout())

        self.buttonIntersection = QRadioButton("Intersection")
        self.operationSelection.layout().addWidget(self.buttonIntersection)
        self.buttonIntersection.clicked.connect(
            self.__disableSecondRequestList)
        self.buttonIntersection.click()

        self.buttonUnion = QRadioButton("Union")
        self.operationSelection.layout().addWidget(self.buttonUnion)
        self.buttonUnion.clicked.connect(self.__disableSecondRequestList)

        self.buttonDiff = QRadioButton("Difference")
        self.operationSelection.layout().addWidget(self.buttonDiff)
        self.buttonDiff.clicked.connect(self.__enableSecondRequestList)

        self.layout.addRow("OPERATION", self.operationSelection)

        self.buttonApplyWidget = QWidget()
        self.buttonApplyWidget.setSizePolicy(QSizePolicy.Expanding,
                                             QSizePolicy.Preferred)
        self.buttonApplyLayout = QHBoxLayout()
        self.buttonApplyLayout.setContentsMargins(0, 0, 0, 0)
        self.buttonApplyWidget.setLayout(self.buttonApplyLayout)
        self.buttonApply = QPushButton("Apply")
        self.buttonApply.clicked.connect(self.__applyOp)
        self.operationSelection.layout().addWidget(self.buttonApply)
        self.buttonApplyLayout.addWidget(self.buttonApply,
                                         alignment=Qt.AlignRight)
        self.layout.addRow("", self.buttonApplyWidget)
        self.layout.addRow(HorizontalLine(self))

        self.layout.addRow("RESULTS", None)

        self.resultingSets = QTableView()
        self.resultingSets.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.resultingSets.verticalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)
        self.resultingSets.setModel(OperationsTableModel())
        self.layout.addRow(self.resultingSets)
        self.layout.addRow(HorizontalLine(self))

        self.outputSetSelection = QComboBox()
        self.outputSetSelection.setSizePolicy(QSizePolicy.MinimumExpanding,
                                              QSizePolicy.Fixed)
        self.layout.addRow("OUTPUT SET", self.outputSetSelection)

        self.setLayout(self.layout)

    def outputSet(self):
        return self.outputSetSelection.currentText()

    def setOutputSet(self, outputSetName):
        self.outputSetSelection.setCurrentText(outputSetName)

    @property
    def ops(self):
        return copy.deepcopy(self.__ops)

    def __applyOp(self):
        includedSets = [
            self.requestsModel.item(i).text()
            for i in range(self.requestsModel.rowCount())
            if self.requestsModel.item(i).data(Qt.CheckStateRole) == QVariant(
                Qt.Checked)
        ]

        if self.buttonUnion.isChecked():
            if len(includedSets) > 1:
                opName = SetNameManagement.getUniqueSetName()
                self.addOp(OverpassUnion(opName), includedSets)
                logging.info("Union created.")
            else:
                logging.error("The union must have at least two sets.")
        elif self.buttonIntersection.isChecked():
            if len(includedSets) > 1:
                opName = SetNameManagement.getUniqueSetName()
                self.addOp(OverpassIntersection(opName), includedSets)
                logging.info("Intersection created.")
            else:
                logging.error("The intersection must have at least two sets.")
        elif self.buttonDiff.isChecked():
            excludedSets = [
                self.requestsModel2.item(i).text()
                for i in range(self.requestsModel2.rowCount())
                if self.requestsModel2.item(i).data(Qt.CheckStateRole) ==
                QVariant(Qt.Checked)
            ]

            if len(includedSets) == 1 and len(excludedSets) > 0:
                opName = SetNameManagement.getUniqueSetName()
                self.addOp(OverpassDiff(includedSets[0], opName), excludedSets)
                logging.info("Difference created.")
            else:
                logging.error(
                    "The difference must have only one set selected in the first list and at least one in the other."
                )
        logging.debug("LINE")

    def addOp(self, op, sets=None):
        SetNameManagement.assign(op.name)
        self.__ops.append(op)
        if sets is not None:
            op.addSets(sets)
        self.resultingSets.model().addOp(op.name, op)
        self.addRequest(op.name)
        self.cleanRequestList()

    def __enableSecondRequestList(self):
        self.requestList2.show()

    def __disableSecondRequestList(self):
        self.requestList2.hide()

    def addRequest(self, name):
        self.requestsModel.beginInsertRows(QModelIndex(),
                                           self.requestsModel.rowCount(),
                                           self.requestsModel.rowCount())
        item = QStandardItem(name)
        item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
        item.setData(QVariant(Qt.Unchecked), Qt.CheckStateRole)
        self.requestsModel.appendRow(item)
        self.requestsModel.endInsertRows()

        self.requestsModel2.beginInsertRows(QModelIndex(),
                                            self.requestsModel2.rowCount(),
                                            self.requestsModel2.rowCount())
        item = QStandardItem(name)
        item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
        item.setData(QVariant(Qt.Unchecked), Qt.CheckStateRole)
        self.requestsModel2.appendRow(item)
        self.requestsModel2.endInsertRows()

        self.outputSetSelection.addItem(name)

    def removeSetAndDependencies(self, setName):
        removeList = [setName]

        for set in removeList:
            logging.info("Removing set '{}'.".format(set))
            removeList.extend(
                [i for i in self.__removeSet(set) if i not in removeList])
        logging.debug("LINE")

    def __removeSet(self, setName):
        dependencies = []
        for op in self.__ops:
            op.removeSet(setName)
            if not op.isValid():
                dependencies.append(op.name)

        for i in range(self.requestsModel.rowCount()):
            if self.requestsModel.item(i).text() == setName:
                self.requestsModel.beginRemoveRows(QModelIndex(), i, i)
                self.requestsModel.removeRow(i)
                self.requestsModel.endInsertRows()

                self.requestsModel2.beginRemoveRows(QModelIndex(), i, i)
                self.requestsModel2.removeRow(i)
                self.requestsModel2.endInsertRows()

                self.outputSetSelection.removeItem(i)
                break

        for op in self.__ops:
            if op.name == setName:
                self.resultingSets.model().removeOp(setName)
                self.__ops.remove(op)
                break

        SetNameManagement.releaseName(setName)

        return dependencies

    def reset(self):
        while len(self.ops) > 0:
            self.removeSetAndDependencies(self.ops[0].name)

    def cleanRequestList(self):
        for i in range(self.requestsModel.rowCount()):
            self.requestsModel.item(i).setData(QVariant(Qt.Unchecked),
                                               Qt.CheckStateRole)
            self.requestsModel2.item(i).setData(QVariant(Qt.Unchecked),
                                                Qt.CheckStateRole)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Backspace and self.resultingSets.hasFocus():

            advice = "Are you sure?\nAll sets containing this one will be deleted if they are no longer valid"
            reply = QMessageBox.question(self, "Remove request operation",
                                         advice)

            if reply == QMessageBox.Yes:
                select = self.resultingSets.selectionModel()
                while len(select.selectedRows()) > 0:
                    self.removeSetAndDependencies(
                        self.resultingSets.model().getOpByIndex(
                            select.selectedRows()[0].row()))

        event.accept()
Exemplo n.º 2
0
class MainForm(QDialog):
    def __init__(self, parent=None):
        super(MainForm, self).__init__(parent)

        self.model = ships.ShipTableModel("ships.dat")
        tableLabel1 = QLabel("Table &1")
        self.tableView1 = QTableView()
        tableLabel1.setBuddy(self.tableView1)
        self.tableView1.setModel(self.model)
        self.tableView1.setItemDelegate(ships.ShipDelegate(self))  # 使用自己定义的委托
        tableLabel2 = QLabel("Table &2")
        self.tableView2 = QTableView()
        tableLabel2.setBuddy(self.tableView2)
        self.tableView2.setModel(self.model)
        self.tableView2.setItemDelegate(ships.ShipDelegate(self))

        addShipButton = QPushButton("&Add Ship")
        removeShipButton = QPushButton("&Remove Ship")
        exportButton = QPushButton("E&xport...")
        quitButton = QPushButton("&Quit")
        if not MAC:
            addShipButton.setFocusPolicy(Qt.NoFocus)
            removeShipButton.setFocusPolicy(Qt.NoFocus)
            exportButton.setFocusPolicy(Qt.NoFocus)
            quitButton.setFocusPolicy(Qt.NoFocus)

        buttonLayout = QHBoxLayout()
        buttonLayout.addWidget(addShipButton)
        buttonLayout.addWidget(removeShipButton)
        buttonLayout.addWidget(exportButton)
        buttonLayout.addStretch()
        buttonLayout.addWidget(quitButton)
        splitter = QSplitter(Qt.Horizontal)
        vbox = QVBoxLayout()
        vbox.addWidget(tableLabel1)
        vbox.addWidget(self.tableView1)
        widget = QWidget()
        widget.setLayout(vbox)
        splitter.addWidget(widget)
        vbox = QVBoxLayout()
        vbox.addWidget(tableLabel2)
        vbox.addWidget(self.tableView2)
        widget = QWidget()
        widget.setLayout(vbox)
        splitter.addWidget(widget)
        layout = QVBoxLayout()
        layout.addWidget(splitter)
        layout.addLayout(buttonLayout)
        self.setLayout(layout)

        for tableView in (self.tableView1, self.tableView2):
            header = tableView.horizontalHeader()
            header.sectionClicked[int].connect(self.sortTable)

        addShipButton.clicked.connect(self.addShip)
        removeShipButton.clicked.connect(self.removeShip)
        exportButton.clicked.connect(self.export)
        quitButton.clicked.connect(self.accept)

        self.setWindowTitle("Ships (delegate)")
        QTimer.singleShot(0, self.initialLoad)

    def initialLoad(self):
        if not QFile.exists(self.model.filename):
            self.model.beginResetModel()
            for ship in ships.generateFakeShips():
                self.model.ships.append(ship)
                self.model.owners.add(str(ship.owner))
                self.model.countries.add(str(ship.country))
            self.model.endResetModel()
            self.model.dirty = False
        else:
            try:
                self.model.load()
            except IOError as e:
                QMessageBox.warning(self, "Ships - Error",
                                    "Failed to load: {0}".format(e))
        self.model.sortByName()
        self.resizeColumns()

    def resizeColumns(self):
        self.tableView1.resizeColumnsToContents()
        self.tableView2.resizeColumnsToContents()

    def reject(self):
        self.accept()

    def accept(self):
        if (self.model.dirty and QMessageBox.question(
                self, "Ships - Save?", "Save unsaved changes?",
                QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes):
            try:
                self.model.save()
            except IOError as e:
                QMessageBox.warning(self, "Ships - Error",
                                    "Failed to save: {0}".format(e))
        QDialog.accept(self)

    def sortTable(self, section):
        if section in (ships.OWNER, ships.COUNTRY):
            self.model.sortByCountryOwner()
        elif section == ships.TEU:
            self.model.sortByTEU()
        else:
            self.model.sortByName()
        self.resizeColumns()

    def addShip(self):
        row = self.model.rowCount()
        self.model.insertRows(row)
        index = self.model.index(row, 0)
        tableView = self.tableView1
        if self.tableView2.hasFocus():
            tableView = self.tableView2
        tableView.setFocus()
        tableView.setCurrentIndex(index)
        tableView.edit(index)

    def removeShip(self):
        tableView = self.tableView1
        if self.tableView2.hasFocus():
            tableView = self.tableView2
        index = tableView.currentIndex()
        if not index.isValid():
            return
        row = index.row()
        name = self.model.data(self.model.index(row, ships.NAME))
        owner = self.model.data(self.model.index(row, ships.OWNER))
        country = self.model.data(self.model.index(row, ships.COUNTRY))
        if (QMessageBox.question(
                self, "Ships - Remove",
                "Remove {0} of {1}/{2}?".format(name, owner, country),
                QMessageBox.Yes | QMessageBox.No) == QMessageBox.No):
            return
        self.model.removeRows(row)
        self.resizeColumns()

    def export(self):
        filename = str(
            QFileDialog.getSaveFileName(self, "Ships - Choose Export File",
                                        ".", "Export files (*.txt)")[0])
        if not filename:
            return
        #htmlTags = QRegExp(r"<[^>]+>")
        htmlTags = "<[^>]+>"
        #htmlTags.setMinimal(True)
        nonDigits = "[., ]"
        self.model.sortByCountryOwner()
        fh = None
        try:
            fh = QFile(filename)
            if not fh.open(QIODevice.WriteOnly):
                raise IOError(str(fh.errorString()))
            stream = QTextStream(fh)
            stream.setCodec("UTF-8")
            for row in range(self.model.rowCount()):
                name = self.model.data(self.model.index(row, ships.NAME))
                owner = self.model.data(self.model.index(row, ships.OWNER))
                country = self.model.data(self.model.index(row, ships.COUNTRY))
                teu = self.model.data(self.model.index(row, ships.TEU))
                teu = re.sub(nonDigits, "", teu)
                description = self.model.data(
                    (self.model.index(row, ships.DESCRIPTION)))
                description = re.sub(htmlTags, "", description)
                stream << name << "|" << owner << "|" << country \
                       << "|" << str(teu) << "|" << description << "\n"
        except EnvironmentError as e:
            QMessageBox.warning(self, "Ships - Error",
                                "Failed to export: {0}".format(e))
        finally:
            if fh:
                fh.close()
        QMessageBox.warning(
            self, "Ships - Export",
            "Successfully exported ship to {0}".format(filename))
Exemplo n.º 3
0
class ProwlerTableWidget(ProwlerSqlWidget):
    """Base class for all table-based SQL widgets. Takes care of selection management and context menu."""

    # Notifier for selection changes in the main table. Use the selected_ids property to access the selection.
    selection_changed = pyqtSignal()
    double_clicked = pyqtSignal()

    def __init__(self, parent=None):
        super(ProwlerTableWidget, self).__init__(parent=parent)
        self.context_menu_actions = []

        # Set up the model and table
        sort_model = QSortFilterProxyModel(self)
        sort_model.setSourceModel(self.model)

        self.table = QTableView(self)
        self.table.setModel(sort_model)
        self.table.setSortingEnabled(True)

        # Extended row selection by default
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.table.selectionModel().selectionChanged.connect(
            self.selection_changed)

        # Editing disabled by default
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)

        # Enable custom context menu
        self.table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table.customContextMenuRequested.connect(self.context_menu)

        # Set default header behaviour
        self.table.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)

        # Add the table to a layout, add the layout to the widget
        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)

        layout.addWidget(self.table)
        self.setLayout(layout)

        # Connect the double_clicked signal
        self.table.doubleClicked.connect(self.double_clicked)

    @property
    def selected_ids(self):
        """Return the values in the 'id' column for each selected row."""
        id_idx_list = self.table.selectionModel().selectedRows(
            self.model.fieldIndex('id'))
        return [idx.data() for idx in id_idx_list]

    def get_selected_id(self):
        """Return the last id in self.selected_ids, or None."""
        return self.selected_ids[-1] if self.selected_ids else None

    def context_menu(self, point):
        """Generate a popup menu from the actions in self.context_menu_actions."""
        menu = QMenu(self)
        menu.addActions(self.context_menu_actions)

        point = self.table.viewport().mapToGlobal(point)
        menu.popup(point)

    def add_context_action(self, action):
        """Add an action to the context menu."""
        self.context_menu_actions.append(action)

    def add_context_actions(self, actions):
        """Adds all actions in an iterable."""
        self.context_menu_actions.extend(actions)

    def remove_context_action(self, action):
        """Remove an action from the context menu."""
        self.context_menu_actions.remove(action)

    def hasFocus(self):
        return self.table.hasFocus()
Exemplo n.º 4
0
class MainForm(QDialog):
    def __init__(self, parent=None):
        super(MainForm, self).__init__(parent)

        self.model = ships.ShipTableModel("ships.dat")  #创建一个shipmodel
        tableLabel1 = QLabel("Table &1")
        self.tableView1 = QTableView()
        tableLabel1.setBuddy(self.tableView1)
        self.tableView1.setModel(self.model)
        tableLabel2 = QLabel("Table &2")
        self.tableView2 = QTableView()
        tableLabel2.setBuddy(self.tableView2)
        self.tableView2.setModel(self.model)

        addShipButton = QPushButton("&Add Ship")
        removeShipButton = QPushButton("&Remove Ship")
        quitButton = QPushButton("&Quit")
        if not MAC:
            addShipButton.setFocusPolicy(
                Qt.NoFocus)  #设置按钮接受键盘焦点方式,NoFocus不接受焦点
            removeShipButton.setFocusPolicy(Qt.NoFocus)
            quitButton.setFocusPolicy(Qt.NoFocus)

        buttonLayout = QHBoxLayout()
        buttonLayout.addWidget(addShipButton)
        buttonLayout.addWidget(removeShipButton)
        buttonLayout.addStretch()
        buttonLayout.addWidget(quitButton)
        splitter = QSplitter(Qt.Horizontal)
        vbox = QVBoxLayout()
        vbox.addWidget(tableLabel1)
        vbox.addWidget(self.tableView1)
        widget = QWidget()
        widget.setLayout(vbox)
        splitter.addWidget(widget)
        vbox = QVBoxLayout()
        vbox.addWidget(tableLabel2)
        vbox.addWidget(self.tableView2)
        widget = QWidget()
        widget.setLayout(vbox)
        splitter.addWidget(widget)
        layout = QVBoxLayout()
        layout.addWidget(splitter)
        layout.addLayout(buttonLayout)
        self.setLayout(layout)

        # 为每个水平标题连接到sortTable方法上
        for tableView in (self.tableView1, self.tableView2):
            header = tableView.horizontalHeader()  # 返回水平标题,QHeaderView
            header.sectionClicked[int].connect(
                self.sortTable
            )  # 点击标题绑定信号,点击某个部分时会发出此信号。该部分的逻辑索引由logicalIndex指定

        addShipButton.clicked.connect(self.addShip)
        removeShipButton.clicked.connect(self.removeShip)
        quitButton.clicked.connect(self.accept)

        self.setWindowTitle("Ships (model)")
        QTimer.singleShot(0,
                          self.initialLoad)  # 设置定时器,启动时间0,调用initialLoad方法初始化数据

    def initialLoad(self):
        if not QFile.exists(self.model.filename):
            self.model.beginResetModel()
            for ship in ships.generateFakeShips(
            ):  # generateFakeShips构造Ship对象列表
                self.model.ships.append(ship)
                self.model.owners.add(str(ship.owner))
                self.model.countries.add(str(ship.country))
            self.model.endResetModel()
            self.model.dirty = False
        else:
            try:
                self.model.load()
            except IOError as e:
                QMessageBox.warning(self, "Ships - Error",
                                    "Failed to load: {0}".format(e))
        self.model.sortByName()
        self.resizeColumns()

    # 对两个表格视图NAME,OWNER,COUNTRY,TEU列,按照内容改变列大小
    def resizeColumns(self):
        for tableView in (self.tableView1, self.tableView2):
            for column in (ships.NAME, ships.OWNER, ships.COUNTRY, ships.TEU):
                tableView.resizeColumnToContents(column)

    # QDialog.reject() 隐藏模式对话框并将result code 设置为Rejected 拒绝
    def reject(self):
        print()
        self.accept()

    # QDialog.accept() 隐藏模式对话框并将result code 设置为Accepted 接受
    def accept(self):
        if (self.model.dirty and QMessageBox.question(
                self, "Ships - Save?", "Save unsaved changes?",
                QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes):
            try:
                self.model.save()
            except IOError as e:
                QMessageBox.warning(self, "Ships - Error",
                                    "Failed to save: {0}".format(e))
        QDialog.accept(self)

    #table视图排序方法
    def sortTable(self, section):
        if section in (ships.OWNER, ships.COUNTRY):
            self.model.sortByCountryOwner()
        else:
            self.model.sortByName()
        self.resizeColumns()

    # 槽方法,添加一个船
    def addShip(self):
        row = self.model.rowCount()  # 获取模型数据条数
        self.model.insertRows(row)  # 在最后插入一条
        index = self.model.index(row, 0)  # 获得插入的index
        # 判断键盘焦点在哪个表格视图上
        tableView = self.tableView1
        if self.tableView2.hasFocus():
            tableView = self.tableView2
        tableView.setFocus()  # 设置焦点
        tableView.setCurrentIndex(index)  # 设置当前行
        tableView.edit(index)  # 编辑当前行

    # 槽方法,删除一个船
    def removeShip(self):
        # 判断键盘焦点在哪个表格视图上
        tableView = self.tableView1
        if self.tableView2.hasFocus():
            tableView = self.tableView2
        index = tableView.currentIndex()
        if not index.isValid(
        ):  # PyQt5.QtCore.QModelIndex.isValid() 此模型索引有效返回true,无效返回false
            return
        row = index.row()  # 返回此模型索引引用的行
        name = self.model.data(self.model.index(
            row,
            ships.NAME))  # QModelIndex QAbstractTableModel.index() 返回指定行,列的索引
        owner = self.model.data(  # QVariant QAbstractItemModel.data() 返回索引所引用项目的给定角色下存储的数据
            self.model.index(row, ships.OWNER))
        country = self.model.data(self.model.index(row, ships.COUNTRY))
        if (QMessageBox.question(
                self, "Ships - Remove",
                "Remove {0} of {1}/{2}?".format(name, owner, country),
                QMessageBox.Yes | QMessageBox.No) == QMessageBox.No):
            return
        self.model.removeRows(row)
        self.resizeColumns()