예제 #1
0
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.setLayout(QVBoxLayout())

        tv1 = QTableView(self)
        tv2 = QTableView(self)
        model = QStandardItemModel(8, 4, self)
        proxy = SortFilterProxyModel(self)
        proxy.setSourceModel(model)
        tv1.setModel(model)
        tv2.setModel(proxy)
        self.layout().addWidget(tv1)
        self.layout().addWidget(tv2)

        for i in range(model.rowCount()):
            for j in range(model.columnCount()):
                item = QStandardItem()
                item.setData(random_word(), Qt.DisplayRole)
                model.setItem(i, j, item)

        flayout = QFormLayout()
        self.layout().addLayout(flayout)
        for i in range(model.columnCount()):
            le = QLineEdit(self)
            flayout.addRow("column: {}".format(i), le)
            le.textChanged.connect(lambda text, col=i: proxy.setFilterByColumn(
                QRegExp(text, Qt.CaseSensitive, QRegExp.FixedString), col))
예제 #2
0
class ObjectNameListEditor(ManageItemsDialog):
    """A dialog to select the object name list for a relationship using Google-like search bars."""
    def __init__(self, parent, index, object_class_names, object_names_lists,
                 current_object_names):
        """Initializes widget.

        Args:
            parent (DataStoreForm)
            index (QModelIndex)
            object_class_names (list): string object class names
            object_names_lists (list): lists of string object names
            current_object_names (list)
        """
        super().__init__(parent, None)
        self.setWindowTitle("Select objects")
        self._index = index
        self.model = QStandardItemModel(self)
        self.init_model(object_class_names, object_names_lists,
                        current_object_names)
        self.table_view.setModel(self.model)
        self.resize_window_to_columns()
        self.table_view.verticalHeader().hide()
        delegate = SearchBarDelegate(self)
        self.table_view.setItemDelegate(delegate)
        self.connect_signals()

    def connect_signals(self):
        """Connect signals to slots."""
        super().connect_signals()
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)

    def init_model(self, object_class_names, object_names_lists,
                   current_object_names):
        self.model.setHorizontalHeaderLabels(object_class_names)
        item_list = []
        for k, object_names_list in enumerate(object_names_lists):
            try:
                obj_name = current_object_names[k]
            except IndexError:
                obj_name = None
            qitem = QStandardItem(obj_name)
            qitem.setData(object_names_list, role=Qt.UserRole)
            item_list.append(qitem)
        self.model.invisibleRootItem().appendRow(item_list)

    @Slot()
    def accept(self):
        self._index.model().setData(
            self._index, ",".join(
                self.model.index(0, j).data()
                for j in range(self.model.columnCount())))
        super().accept()
예제 #3
0
class FiltersForm(QDialog):
    def __init__(self, filter_id, columns, headersname, parent=None):
        super(FiltersForm, self).__init__(parent)
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.setWindowModality(Qt.ApplicationModal)
        self.setWindowTitle('Filter')
        self.filter_id = filter_id
        self.columns = columns
        self.main_form = parent

        #form
        self.line_filters = [self.ui.lineEditfilter_1,
                             self.ui.lineEditfilter_2,
                             self.ui.lineEditfilter_3,
                             self.ui.lineEditfilter_4,
                             self.ui.lineEditfilter_5]

        for line in self.line_filters:
            line.setClearButtonEnabled(True)
            line.setEnabled(False)
            line.textChanged.connect(self.make_filter)

        #table
        self.table = self.ui.tableViewcolumns
        self.sti = QStandardItemModel()
        self.table.setModel(self.sti)
        self.table.verticalHeader().setDefaultSectionSize(10)
        self.table.horizontalHeader().setDefaultSectionSize(172)
        self.table.setSortingEnabled(True)

        #treeWidget
        self.tw = self.ui.treeWidgetasignet
        self.tw.setHeaderLabels(['Name'] + headersname)
        self.tw.setAlternatingRowColors(True)

        """
        set controls data
        """
        self.sti.setHorizontalHeaderLabels(headersname)
        self.sti.setColumnCount(len(headersname))
        self.setrowdata(columns)

        """
        signals
        """
        self.ui.pushButtonaddnew.clicked.connect(self.add_new_parent_node)
        self.tw.itemChanged.connect(self.uncheck_others_items_tree)
        self.ui.pushButtonadddata.clicked.connect(self.add_children)
        self.ui.pushButtonremovenodes.clicked.connect(self.delete_tree_items)
        self.ui.checkBoxCheckAll.stateChanged.connect(lambda: self.select_deselect_rows(self.ui.checkBoxCheckAll))
        self.ui.checkBoxnotassigne.stateChanged.connect(lambda: self.show_not_assigned_rows(self.ui.checkBoxnotassigne))
        self.ui.pushButtonrun.clicked.connect(self.make_assigned)
        self.ui.pushButtonremove_fitlers_text.clicked.connect(self.clear_all_filter_line)

        """
        function
        """
        self.get_data_from_database()
        self.set_filter_line_enable()
        self.start_rows = self.get_all_data_table()

    """
    
    tree functions
    
    """

    def add_new_parent_node(self):

        value = self.ui.lineEditaddnew.text()
        if len(value) > 0:
            if self.isunique(value):
                newnod = QTreeWidgetItem(self.tw, [value])
                newnod.setCheckState(0, Qt.CheckState.Unchecked)
                self.ui.lineEditaddnew.setText("")
                # save to database
                self.save_data_from_tree()
            else:
                QMessageBox.critical(self, 'Uwaga!!!',
                     "Podana nazwa już istnieje.",
                     QMessageBox.Ok)


    def isunique(self, name):
        """
        check the new value is unice int tree view
        :param name:
        :return:
        """
        #read data from tree view
        root = self.tw.invisibleRootItem()
        child_count = root.childCount()
        nodesname = []
        for i in range(child_count):
            item = root.child(i)
            nodesname.append(item.text(0))

        nodesname = [x.upper() for x in nodesname]
        if name.upper() in nodesname:
            return False
        else:
            return True

    def uncheck_others_items_tree(self, item, column):
        """
        leve only one checked item
        :param item:
        :param column:
        :return:
        """
        self.tw.blockSignals(True)
        root = self.tw.invisibleRootItem()
        child_count = root.childCount()
        for i in range(child_count):
            item2 = root.child(i)
            if item.text(column) != item2.text(0):
                item2.setCheckState(0, Qt.CheckState.Unchecked)
            else:
                if item.parent() is None:
                    item.setCheckState(0, Qt.CheckState.Checked)
        self.tw.blockSignals(False)

    def delete_tree_items(self):
        """
        delete checked items from tree
        :return:
        """
        root = self.tw.invisibleRootItem()
        child_count = root.childCount()
        transfers = []

        #delete main node
        for i in reversed(range(child_count)):
            item = root.child(i)
            if item.checkState(0) == Qt.CheckState.Checked:
                children = item.takeChildren()
                for child in children:
                    temchild = []
                    for colnr in range(self.tw.columnCount())[1:]:
                        temchild.append(child.text(colnr))
                    transfers.append(temchild)
                root.removeChild(item)
            #delete childe node
            if item is not None:
                child_count = item.childCount()
                for j in reversed(range(child_count)):
                    itemch = item.child(j)
                    if itemch.checkState(1) == Qt.CheckState.Checked:
                        temchild = []
                        for colnr in range(self.tw.columnCount())[1:]:
                            temchild.append(itemch.text(colnr))
                        transfers.append(temchild)
                        item.removeChild(itemch)

        self.start_rows += [x for x in transfers if x not in self.start_rows]

        self.add_rowto_table(transfers)

        # save to database
        self.save_data_from_tree()

    def get_checked_item(self):
        """
        :return: return checked item in tree view
        """
        root = self.tw.invisibleRootItem()
        child_count = root.childCount()
        for i in range(child_count):
            item = root.child(i)
            if item.checkState(0) == Qt.CheckState.Checked:
                return item

    def add_children(self):
        """
        adding items from list to tree
        :return:
        """
        childlist = self.getCheckedItemsTable()
        item = self.get_checked_item()


        if item is None:
            QMessageBox.critical(self, 'Uwaga!!!',
                                 "Elementy nie zostały przeniesione\nZaznacz kategorie po prawej stronie.",
                                 QMessageBox.Ok)
        else:
            #remove exist childs from tree
            self.remove_child_if_exist_in_tree(childlist)

            #add value to list
            for ch in childlist:
                newitem = QTreeWidgetItem(item, ch)
                newitem.setCheckState(1, Qt.CheckState.Unchecked)
                #remove item from start list
                ch.pop(0)
                if ch in self.start_rows:
                    self.start_rows.remove(ch)

            self.removeCheckedItemsTable()

        #save to database
        self.save_data_from_tree()

    def save_data_from_tree(self):
        """
        1) delete in data base all categorys for filter
        2) save all catecorys and under categroy to database
        """

        #delete all categorys
        session = Session()
        filter_ = session.query(FilterF).get(self.filter_id)
        delete_q = Category.__table__.delete().where(Category.filter_id == filter_.id)
        session.execute(delete_q)
        session.commit()

        root = self.tw.invisibleRootItem()
        child_count = root.childCount()

        for i in range(child_count):
            item = root.child(i)
            if item.parent() is None:
                parent_name = item.text(0)
                all_childs = []
                for j in range(item.childCount()):
                    childs = [item.child(j).text(i) for i in range(self.tw.columnCount())[1:]]
                    all_childs.append(childs)

                new_category = Category(parent_name, all_childs)
                filter_.categorys.append(new_category)

        session.commit()
        session.close()

    def get_data_from_database(self):
        """
        get all categorys for filter and send to show in treewidget
        """

        session = Session()
        categorys = session.query(Category).filter_by(filter_id=self.filter_id).all()
        self.tw.blockSignals(True)
        for category in categorys:
            head = QTreeWidgetItem(self.tw, [category.name])
            head.setCheckState(0, Qt.CheckState.Unchecked)
            for item in category.items:
                newch = QTreeWidgetItem(head, [''] + item)
                newch.setCheckState(1, Qt.CheckState.Unchecked)
        self.tw.blockSignals(False)

    def get_all_tree_children(self):
        """
        get all children from tree widget
        :return: tuple all chldren
        """
        iterator = QTreeWidgetItemIterator(self.tw)
        all_child = []
        while iterator.value():
            item = iterator.value()
            if item.parent() is not None:
                parentchild = [item.text(i) for i in range(self.tw.columnCount())[1:]]
                all_child.append(parentchild)

            iterator += 1
        return all_child

    def remove_child_if_exist_in_tree(self, exists_childs):
        """
        remove item from tree widget if is in exists_childs list
        :param exists_childs:
        :return:
        """
        exists_childs = list(list(b.strip().lower() for b in a) for a in exists_childs)
        iterator = QTreeWidgetItemIterator(self.tw)

        while iterator.value():
            item = iterator.value()
            if item.parent() is not None:
                parentchild = [item.text(i) for i in range(self.tw.columnCount())[1:]]
                parentchild = list(a.strip().lower() for a in parentchild)
                parentchild = ['']+parentchild
                if parentchild in exists_childs:
                    item.parent().removeChild(item)
                    continue
            iterator += 1

    """
    
    table view functions
    
    """
    def setrowdata(self, columns):
        """
        add data to table rows
        :param columns:
        :return:
        """
        for row in range(len(columns)):
            for col in range(len(columns[row])):
                item = QStandardItem(columns[row][col])
                item.setEditable(False)
                if col == 0:
                    item.setCheckable(True)
                self.sti.setItem(row, col, item)

    def getCheckedItemsTable(self):
        """
        return table with checked items
        :return:
        """
        checkeditems = []
        for i in range(self.sti.rowCount()):
            if self.sti.item(i, 0).checkState() == 2:
                temp_col = [self.sti.item(i, j).text() for j in range(self.sti.columnCount())]
                checkeditems.append([""]+temp_col)

        return checkeditems

    def removeCheckedItemsTable(self):
        """
        remove row frol list table
        :return:
        """
        for i in reversed(range(self.sti.rowCount())):
            if self.sti.item(i, 0).checkState() == 2:
                self.sti.removeRow(i)

    def get_all_data_table(self):
        """
        get all rows from table
        :return: list of rows
        """
        rows = []
        for row in range(self.sti.rowCount()):
            cols = []
            for col in range(self.sti.columnCount()):
                cols.append(self.sti.item(row, col).text())
            rows.append(cols)
        return rows

    def add_rowto_table(self, newrows):
        """
        add row form filter to table if not
        allready exist in table
        :return:
        """
        tabledata = self.get_all_data_table()

        for nr, row in enumerate(newrows):
            if row not in tabledata:
                rowcount = self.sti.rowCount()
                self.sti.setRowCount(rowcount)
                for col in range(len(row)):
                    item = QStandardItem(str(newrows[nr][col]))
                    if col == 0:
                        item.setCheckable(True)
                    self.sti.setItem(rowcount, col, item)

    def select_deselect_rows(self, chcontrol):
        """
        check or unchecked checbox in table
        :param chcontrol:
        :return:
        """
        for rnr in range(self.sti.rowCount()):
            if chcontrol.isChecked():
                item = self.sti.item(rnr, 0)
                item.setCheckState(Qt.CheckState.Checked)
            else:
                item = self.sti.item(rnr, 0)
                item.setCheckState(Qt.CheckState.Unchecked)

    def removeAllItemsTable(self):
        """
        remove all rows from list table
        :return:
        """
        for i in reversed(range(self.sti.rowCount())):
                self.sti.removeRow(i)

    def show_not_assigned_rows(self, chcontrol):
        """
        if checbox is check, show in table only rows not exist in tree
        :param chcontrol: status of checkbox control
        :return:
        """

        if chcontrol.isChecked():

            treeitems = self.get_all_tree_children()
            # columns = self.columns # czy tutaj nie powinien korzystac s start_rows
            columns = self.start_rows
            notassigned = self.set_not_assigned(treeitems, columns)
            if self.is_filter_empty():
                self.add_rowto_table(notassigned)
            else:
                self.make_filter()
        else:
            # self.setrowdata(self.columns)
            self.setrowdata(self.start_rows)

    def set_not_assigned(self, treeitems, columns):

        self.removeAllItemsTable()
        treeitems = list(list(b.strip().lower() for b in a) for a in treeitems)
        columns = list(list(b.strip().lower() for b in a) for a in columns)

        notassigned = []
        for nr, row in enumerate(columns):
            if row not in treeitems:
                notassigned.append(columns[nr])

        return notassigned


    """
    
    Form "filters" function
    
    """
    def make_assigned(self):
        self.main_form.assign_value_for_filter(self.filter_id)

    def set_filter_line_enable(self):
        """
        Make liene_filters eneble for the number of columns
        :return:
        """
        for col_nr in range(self.sti.columnCount()):
            self.line_filters[col_nr].setEnabled(True)

    def clear_all_filter_line(self):
        """
        clear all line_filter
        :return:
        """
        for fil in self.line_filters:
            fil.setText("")

    def make_filter(self):

        if self.ui.checkBoxnotassigne.checkState() == Qt.CheckState.Checked:
            rows = self.set_not_assigned(self.get_all_tree_children(), self.columns)
        else:
            rows = self.start_rows

        # if len(rows) == 0: #dlaczego rows jest 't'
        #     rows = self.start_rows

        line_texts = [lin.text() for lin in self.line_filters if lin.isEnabled()]
        filterrow = FilterRows(rows, *line_texts)
        final_list = filterrow.works_rows()

        self.removeAllItemsTable()
        self.add_rowto_table(final_list)

    def is_filter_empty(self):
        """
        check if filter line contains anny strings
        :return:
        """
        for lin in self.line_filters:
            if len(lin.text()) > 0:
                return False
        return True
예제 #4
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None, flags=Qt.WindowFlags()):
        super(MainWindow, self).__init__(parent, flags)

        self.dayWidth = 70
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.initModel()
        self.initActions()
        self.initItemDelegate()
        self.initGrid()

        leftView = self.ui.ganttView.leftView()
        leftView.setColumnHidden(1, True)
        leftView.setColumnHidden(2, True)
        leftView.setColumnHidden(3, True)
        leftView.setColumnHidden(4, True)
        leftView.setColumnHidden(5, True)
        leftView.header().setStretchLastSection(True)

        self.ui.ganttView.leftView().customContextMenuRequested.connect(
            self.showContextMenu)
        self.ui.ganttView.selectionModel().selectionChanged.connect(
            self.enableActions)
        self.ui.ganttView.graphicsView().clicked.connect(self.slotClicked)
        self.ui.ganttView.graphicsView().qrealClicked.connect(
            self.slotDoubleClicked)

    def initModel(self):
        self.model = QStandardItemModel(0, 6, self)
        self.model.setHeaderData(0, Qt.Horizontal, "Task")
        self.ui.ganttView.setModel(self.model)

        self.l = QWidget(self)
        self.l.setWindowTitle("Legend")
        self.l.show()
        ##self.l.setModel(self.model)

        self.constraintModel = ConstraintModel(self)
        self.ui.ganttView.setConstraintModel(self.constraintModel)

    def initActions(self):
        self.newEntryAction = QAction("New entry", self)
        self.newEntryAction.setShortcut(QKeySequence.New)
        self.newEntryAction.triggered.connect(self.addNewEntry)

        self.removeEntryAction = QAction("Remove entry", self)
        self.removeEntryAction.setShortcut(QKeySequence.Delete)
        self.removeEntryAction.triggered.connect(self.removeEntry)

        self.demoAction = QAction("Demo entry", self)
        self.demoAction.triggered.connect(self.addDemoEntry)

        self.printAction = QAction("Print Preview...", self)
        self.printAction.triggered.connect(self.printPreview)

        self.zoomInAction = QAction("Zoom In", self)
        self.zoomInAction.setShortcut(QKeySequence.ZoomIn)
        self.zoomInAction.triggered.connect(self.zoomIn)

        self.zoomOutAction = QAction("Zoom Out", self)
        self.zoomOutAction.setShortcut(QKeySequence.ZoomOut)
        self.zoomOutAction.triggered.connect(self.zoomOut)

        self.ui.ganttView.leftView().setContextMenuPolicy(Qt.CustomContextMenu)
        self.ui.ganttView.leftView().addAction(self.newEntryAction)
        self.ui.ganttView.leftView().addAction(self.removeEntryAction)

        menuBar = QMenuBar(self)
        self.setMenuBar(menuBar)
        entryMenu = menuBar.addMenu("Entry")
        entryMenu.addAction(self.newEntryAction)
        entryMenu.addAction(self.removeEntryAction)
        entryMenu.addSeparator()
        entryMenu.addAction(self.demoAction)
        entryMenu.addSeparator()
        entryMenu.addAction(self.printAction)

        zoomMenu = menuBar.addMenu("Zoom")
        zoomMenu.addAction(self.zoomInAction)
        zoomMenu.addAction(self.zoomOutAction)

        ##self.enableActions(QItemSelection())

    def initItemDelegate(self):
        delegate = EntryDelegate(self.constraintModel, self)
        self.ui.ganttView.leftView().setItemDelegate(delegate)

    def initGrid(self):
        self.grid = DateTimeGrid()
        self.grid.setDayWidth(self.dayWidth)
        self.ui.ganttView.setGrid(self.grid)

    def showContextMenu(self, pos):
        if not self.ui.ganttView.leftView().indexAt(pos).isValid():
            self.ui.ganttView.selectionModel().clearSelection()

        menu = QMenu(self.ui.ganttView.leftView())
        menu.addAction(self.newEntryAction)
        menu.addAction(self.removeEntryAction)
        menu.exec_(self.ui.ganttView.leftView().viewport().mapToGlobal(pos))

    def enableActions(self, selected):
        if len(selected.indexes()) == 0:
            self.newEntryAction.setEnabled(True)
            self.removeEntryAction.setEnabled(False)
            return

        selectedIndex = selected.indexes()[0]
        dataType = self.model.data(self.model.index(selectedIndex.row(), 1))
        if dataType in [KDGantt.TypeEvent, KDGantt.TypeTask]:
            self.newEntryAction.setEnabled(False)
            self.removeEntryAction.setEnabled(True)
            return

        self.newEntryAction.setEnabled(True)
        self.removeEntryAction.setEnabled(True)

    def addNewEntry(self):
        dialog = EntryDialog(self.model)
        dialog.setWindowTitle("New Entry")
        if dialog.exec_() == QDialog.Rejected:
            dialog = None
            return

        selectedIndexes = self.ui.ganttView.selectionModel().selectedIndexes()
        if len(selectedIndexes) > 0:
            parent = selectedIndexes[0]
        else:
            parent = QModelIndex()

        if not self.model.insertRow(self.model.rowCount(parent), parent):
            return

        row = self.model.rowCount(parent) - 1
        if row == 0 and parent.isValid():
            self.model.insertColumns(self.model.columnCount(paren), 5, parent)

        self.model.setData(self.model.index(row, 0, parent), dialog.name())
        self.model.setData(self.model.index(row, 1, parent), dialog.type())
        if dialog.type() != KDGantt.TypeSummary:
            self.model.setData(self.model.index(row, 2, parent),
                               dialog.startDate(), KDGantt.StartTimeRole)
            self.model.setData(self.model.index(row, 3, parent),
                               dialog.endDate(), KDGantt.EndTimeRole)

        self.model.setData(self.model.index(row, 4, parent),
                           dialog.completion())
        self.model.setData(self.model.index(row, 5, parent), dialog.legend())

        self.addConstraint(dialog.depends(), self.model.index(row, 0, parent))
        self.setReadOnly(self.model.index(row, 0, parent), dialog.readOnly())

        dialog = None

    def setReadOnly(self, index, readOnly):
        row = index.row()
        parent = index.parent()

        for column in range(0, 5):
            item = self.model.itemFromIndex(
                self.model.index(row, column, parent))
            flags = None
            if readOnly:
                flags = item.flags() & ~Qt.ItemIsEditable
            else:
                flags = item.flags() | Qt.ItemIsEditable
            item.setFlags(flags)

    def addConstraint(self, index1, index2):
        if not index1.isValid() or not index2.isValid():
            return

        c = Constraint(index1, index2)
        self.ui.ganttView.constraintModel().addConstraint(c)

    def addConstraintFromItem(self, item1, item2):
        self.addConstraint(self.model.indexFromItem(item1),
                           self.model.indexFromItem(item2))

    def removeEntry(self):
        selectedIndexes = self.ui.ganttView.selectionModel().selectedIndexes()
        if len(selectedIndexes) > 0:
            index = selectedIndexes[0]
        else:
            index = QModelIndex()

        if not index.isValid():
            return

        self.model.removeRow(index.row(), index.parent())

    def addDemoEntry(self):
        softwareRelease = MyStandardItem("Software Release")
        codeFreeze = MyStandardItem("Code Freeze")
        codeFreeze.setData(KDGantt.TextPositionRole,
                           StyleOptionGanttItem.Right)
        packaging = MyStandardItem("Packaging")
        upload = MyStandardItem("Upload")
        testing = MyStandardItem("Testing")
        updateDocumentation = MyStandardItem("Update Documentation")

        now = QDateTime.currentDateTime()
        softwareRelease.appendRow([
            codeFreeze,
            MyStandardItem(KDGantt.TypeEvent),
            MyStandardItem(now, KDGantt.StartTimeRole)
        ])
        softwareRelease.appendRow([
            packaging,
            MyStandardItem(KDGantt.TypeTask),
            MyStandardItem(now.addDays(5), KDGantt.StartTimeRole),
            MyStandardItem(now.addDays(10), KDGantt.EndTimeRole)
        ])
        softwareRelease.appendRow([
            upload,
            MyStandardItem(KDGantt.TypeTask),
            MyStandardItem(
                now.addDays(10).addSecs(2 * 60 * 60), KDGantt.StartTimeRole),
            MyStandardItem(now.addDays(11), KDGantt.EndTimeRole)
        ])
        softwareRelease.appendRow([
            testing,
            MyStandardItem(KDGantt.TypeTask),
            MyStandardItem(now.addSecs(3 * 60 * 60), KDGantt.StartTimeRole),
            MyStandardItem(now.addDays(5), KDGantt.EndTimeRole)
        ])
        softwareRelease.appendRow([
            updateDocumentation,
            MyStandardItem(KDGantt.TypeTask),
            MyStandardItem(now.addSecs(3 * 60 * 60), KDGantt.StartTimeRole),
            MyStandardItem(now.addDays(3), KDGantt.EndTimeRole)
        ])
        self.model.appendRow(
            [softwareRelease,
             MyStandardItem(KDGantt.TypeSummary)])
        self.addConstraintFromItem(codeFreeze, packaging)
        self.addConstraintFromItem(codeFreeze, testing)
        self.addConstraintFromItem(codeFreeze, updateDocumentation)
        self.addConstraintFromItem(packaging, upload)
        self.addConstraintFromItem(testing, packaging)
        self.addConstraintFromItem(updateDocumentation, packaging)

    def zoomIn(self):
        self.dayWidth += 10
        if self.dayWidth > 400:
            self.grid.setScale(DateTimeGrid.ScaleHour)
        self.grid.setDayWidth(self.dayWidth)

    def zoomOut(self):
        self.dayWidth -= 10

        if self.dayWidth < 10:
            self.dayWidth = 10

        if self.dayWidth <= 400:
            self.grid.setScale(DateTimeGrid.ScaleDay)

        self.grid.setDayWidth(self.dayWidth)

    def printPreview(self):
        preview = QLabel(self, Qt.Window)
        preview.setAttribute(Qt.WA_DeleteOnClose)
        preview.setScaledContents(True)
        preview.setWindowTitle("Print Preview")
        pix = QPixmap(1000, 300)
        pix.fill(Qt.white)

        p = QPainter(pix)
        p.setRenderHints(QPainter.Antialiasing)
        self.ui.ganttView.print_(p, pix.rect())

        preview.setPixmap(pix)
        preview.show()

    def slotClicked(self, index):
        self.statusBar().showMessage(
            "(%d,%d,_,%s) clicked" %
            (index.row(), index.column(), index.model()))

    def slotDoubleClicked(self, index):
        self.statusBar().showMessage(
            "(%d,%d,_,%s) qreal clicked" %
            (index.row(), index.column(), index.model()))
예제 #5
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.setWindowTitle("VW Competitive")
        self.setWindowIcon(QIcon(':/images/vw.png'))
        """
        Test wstawienia wartosci do tabeli
        """
        self.table = QTableView()
        self.setCentralWidget(self.table)
        self.sti = QStandardItemModel()
        self.sti.setColumnCount(6)
        self.table.setModel(self.sti)
        self.table.verticalHeader().setDefaultSectionSize(10)
        self.table.horizontalHeader().setDefaultSectionSize(200)
        self.headers = [
            'Year', 'Month', 'Week', 'Sector', 'Category', 'Sub Category',
            'Produkt(4)', 'Branża(I)', 'Kategoria(II)', 'Dział(III)',
            'Producer', 'Brand', 'Sub Brand', 'Film Code', 'Film Code 2',
            'Media', 'Glowne Medium', 'Medium', 'Wydawca Nadawca',
            'Periodyczność', 'Duration', 'Typ reklamy', 'Forma Reklamy',
            'Typ Strony', 'L.emisji', 'Sum.Str', 'Cost', 'PT/OFF', 'TRP',
            'TRP30', 'Channel group', 'Channel type', 'Wyprz', 'Upus', 'Rabat',
            'Wyprze Upust Rabat', 'Model', 'Brand final',
            'Subbrand (brand+Model)', 'Brand Type', 'Segment_detailed',
            'Segment', 'Segment_combined', 'Campaign Type'
        ]
        """
        Forms
        """
        self.excel_form = ExcelForm(self.headers, self)
        self.connect_form = ConnectRaports(self)
        self.filechoser = FileChoser(self)
        self.for_find_duplicate = FindDuplicate(self)
        self.filters_manager = FiltersManager(self)

        self.sti.setHorizontalHeaderLabels(self.headers)
        self.sti.setColumnCount(len(self.headers))
        self.table.setSortingEnabled(True)
        #self.table.horizontalHeader().connect()
        self.connect(self.table.horizontalHeader(),
                     SIGNAL("sectionClicked(int)"), self.showfilterforms)

        self.createActions()
        self.createMenus()
        self.createStatusBar()
        self.readSettings()
        self.set_color_on_header()

    def closeEvent(self, event):
        self.close()

    def open(self):
        self.filechoser.show()
        self.filechoser.clead_data()

    def save(self):
        """
        save data to data base
        :return:
        """
        #deleta rows from data base for compative name
        session = Session()
        comat = session.query(Competitive).filter(
            Competitive.name.ilike(f'%{self.compative_name}%')).first()
        session.query(Data).filter_by(competitive_id=comat.id).delete()

        #read data from row and save to data base
        for row in range(self.sti.rowCount()):
            datas = []
            for col in range(self.sti.columnCount()):
                if col in (0, 1, 2, 20, 24):
                    try:
                        #tutaj poprawic nie chce wpisać
                        if self.sti.item(row, col) is not None:
                            datas.append(int(self.sti.item(row, col).text()))
                        else:
                            datas.append(None)
                    except ValueError:
                        datas.append(None)
                elif col in (25, 26, 28, 29):
                    try:
                        if self.sti.item(row, col) is not None:
                            datas.append(float(self.sti.item(row, col).text()))
                        else:
                            datas.append(None)
                    except ValueError:
                        datas.append(None)
                else:
                    if self.sti.item(row, col) is not None:
                        datas.append(self.sti.item(row, col).text())
                    else:
                        datas.append(None)

            comat.datas.append(Data(*datas))

        session.commit()
        session.close()
        QMessageBox.information(self, "Zapis",
                                "Zapis zakonczyl się powodzeniem.")

    def createActions(self):
        self.openAct = QAction(QIcon(':/images/open.png'),
                               "&Otwórz...",
                               self,
                               shortcut=QKeySequence.Open,
                               statusTip="Otwóż nowe pliki",
                               triggered=self.open)

        self.saveAct = QAction(QIcon(':/images/save.png'),
                               "&Zapisz...",
                               self,
                               shortcut=QKeySequence.Save,
                               statusTip="Zapisz plik",
                               triggered=self.save)

        self.exitAct = QAction("&Zamknij",
                               self,
                               shortcut="Ctrl+Q",
                               statusTip="Zamknij aplikacje",
                               triggered=self.close)

        self.runWordFilter = QAction("Filtry &Automatyczne",
                                     shortcut="Ctrl+A",
                                     statusTip="Urchom filtry automatyczne",
                                     triggered=self.run_filters)

        self.showExcelForm = QAction("Generuj plik excel",
                                     triggered=self.show_excel_form)

        self.ConnectRaports = QAction("Połącz raporty",
                                      triggered=self.show_connect_raports)

        self.FindDuplicate = QAction("Znajdz duplikaty",
                                     triggered=self.show_duplicate_form)

        self.FilterManager = QAction("Filtry Manualne",
                                     triggered=self.show_filter_manager)

    def createMenus(self):
        self.fileMenu = self.menuBar().addMenu("&Plik")
        self.fileMenu.addAction(self.openAct)
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.exitAct)

        self.filterMenu = self.menuBar().addMenu("&Filtry")
        self.filterMenu.addAction(self.runWordFilter)
        self.filterMenu.addAction(self.FilterManager)

        self.excelMenu = self.menuBar().addMenu("&Raporty")
        self.excelMenu.addAction(self.showExcelForm)
        self.excelMenu.addAction(self.ConnectRaports)
        self.excelMenu.addAction(self.FindDuplicate)

    def contextMenuEvent(self, event):
        contextMenu = QMenu(self)
        removeAction = contextMenu.addAction('Usuń')

        action = contextMenu.exec_(self.mapToGlobal(event.pos()))

        if action == removeAction:
            index_list = []
            for model_index in self.table.selectionModel().selectedRows():
                index = QPersistentModelIndex(model_index)
                index_list.append(index)

            for index in index_list:
                self.sti.removeRow(index.row())

    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def readSettings(self):
        settings = QSettings("Trolltech", "Application Example")
        pos = settings.value("pos", QPoint(200, 200))
        size = settings.value("size", QSize(800, 800))
        self.resize(size)
        self.move(pos)

    def get_data(self, paths, compative_name):
        """
        receives data from the filechose form
        :param paths: dictionary with paht to techege, adexpert
        :param compative_name: name of raport
        :return:
        """
        self.compative_name = compative_name
        if len(paths[0]) > 0:
            self.techegedata = Excel.get_data(paths[0])
        else:
            self.techegedata = None
        if len(paths[1]) > 0:
            self.adxpert = Excel.get_data(paths[1], False)
        else:
            self.adxpert = None

        #wczytanie arkusza z bazy danych
        session = Session()
        self.compativedata = session.query(Competitive).filter_by(
            name=compative_name).first()

        self.populate_row()
        session.close()

    def populate_row(self):
        """
        read data from compatiedate, techegedata, adxpert and past to rows
        :return:
        """
        # without this section data in column one don't show
        self.sti.setRowCount(0)
        self.sti.setRowCount(1)

        font = QFont()
        font.setPointSize(8)

        #add data from data base
        if self.compativedata:
            for row in self.compativedata.datas:
                rownr = self.sti.rowCount()
                rowvalue = row.values()
                for nr, value in enumerate(rowvalue):
                    item = QStandardItem(f'{value}')
                    item.setFont(font)
                    self.sti.setItem(rownr - 1, nr, item)
                    self.sti.setRowCount(rownr + 1)

        #add data from techegedata
        if self.techegedata:
            for rownr in range(len(self.techegedata[0])):
                self.sti.setRowCount(self.sti.rowCount() + 1)
                for colnr in range(len(self.techegedata)):
                    if len(self.techegedata[colnr]) == 0:
                        continue
                    item = QStandardItem(f'{self.techegedata[colnr][rownr]}')
                    item.setFont(font)
                    self.sti.setItem(self.sti.rowCount() - 2, colnr, item)

        #add data from adexpert
        if self.adxpert:
            for rownr in range(len(self.adxpert[0])):
                self.sti.setRowCount(self.sti.rowCount() + 1)
                for colnr in range(len(self.adxpert)):
                    if len(self.adxpert[colnr]) == 0:
                        continue
                    item = QStandardItem(f'{self.adxpert[colnr][rownr]}')
                    item.setFont(font)
                    self.sti.setItem(self.sti.rowCount() - 2, colnr, item)

        self.sti.removeRow(self.sti.rowCount() - 1)
        self.table.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)
        QMessageBox.information(self, "Dane", "Dane zostały wczytane")

    def showfilterforms(self, i):
        """
        Show filters for collumn nr"
        :param i:
        :return:
        """
        session = Session()
        filter_ = session.query(FilterF).filter_by(column_nr=i).one_or_none()
        if filter_ is not None and filter_.type == 'manual':
            columns = self.prapercolumns(filter_.columns)
            headersname = [self.headers[i] for i in filter_.columns]
            self.filter = FiltersForm(filter_.id, columns, headersname, self)
            self.filter.show()

        session.close()

    def show_excel_form(self):
        """
        Show excel form
        :return:
        """
        self.excel_form.set_compatives()
        self.excel_form.show()

    def show_connect_raports(self):
        """
        Show  connect rapot
        :return:
        """
        self.connect_form.set_raports()
        self.connect_form.show()

    def show_duplicate_form(self):
        """
        show duplicate form
        """
        self.for_find_duplicate.set_raports()
        self.for_find_duplicate.show()

    def show_filter_manager(self):
        """
        show filter manager form
        """
        self.filters_manager.show()

    def prapercolumns(self, columns):
        """
        get unic data from sending columns
        :param args:
        :return:
        """
        mainlist = []
        for col in columns:
            collist = []
            for row in range(self.sti.rowCount()):
                if self.sti.item(row, col) is not None:
                    collist.append(self.sti.item(row, col).text())
            mainlist.append(collist)

        return list(set(zip(*mainlist)))

    def replace_column(self, col_nr, assignded_column):
        """
        replace column with new data
        :param col_nr:
        :param assignded_column:
        :return:
        """
        self.sti.takeColumn(col_nr)
        self.sti.insertColumn(col_nr, assignded_column)
        self.sti.setHorizontalHeaderLabels(self.headers)
        self.set_color_on_header()

    """
    
    Filters
    
    """

    def assign_value_for_filter(self, filter_id, show=True):
        """
        preper list with value from main filter, send it to make_filter_list.
        Replace column for filter_id with column with assigned data
        :param filter_id:
        :return:
        """
        session = Session()
        filter_ = session.query(FilterF).get(filter_id)
        rows = []
        for row in range(self.sti.rowCount()):
            row_value = [
                self.sti.item(row, col).text() for col in filter_.columns
            ]
            rows.append(row_value)

        read_rows = self.make_filter_list(filter_id, rows)
        col_nr = filter_.column_nr
        self.sti.takeColumn(col_nr)
        self.sti.insertColumn(col_nr, read_rows)
        self.sti.setHorizontalHeaderLabels(self.headers)
        session.close()
        self.set_color_on_header()

        if show:
            QMessageBox.information(self, "Informacja", "Operacja zakończona.")

    @staticmethod
    def make_filter_list(filter_id, rows):
        """
        make list with assigned value
        :param filter_id:
        :param rows:
        :return:
        """
        session = Session()
        filter_ = session.query(FilterF).get(filter_id)

        ready_valus = []
        for row in rows:
            flag = False
            row = [i.strip().lower() for i in row]
            for category in filter_.categorys:
                items = [[b.strip().lower() for b in a]
                         for a in category.items]
                if row in items:
                    #make QStandardItem to make column in sti model
                    item = QStandardItem(str(category.name))
                    ready_valus.append(item)
                    flag = True
            if flag is False:
                item = QStandardItem('')
                ready_valus.append(item)

        session.close()
        return ready_valus

    """
    filters: words, cut
    """

    def run_filters(self):
        """
        make filters
        :return:
        """
        session = Session()
        # filters_ = session.query(FilterF).filter_by(type='words').all()
        filters_ = session.query(FilterF).all()
        for fil in filters_:

            if fil.type == 'words':
                rows = self.get_data_from_columns(fil.columns)
                assignded_column = self.make_words_list(fil.id, rows)
                self.replace_column(fil.column_nr, assignded_column)

            elif fil.type == 'cut':
                if fil.name == 'model':
                    rows = self.get_data_from_columns(fil.columns)
                    assignded_column = self.filter_cut_model(rows)
                    self.replace_column(fil.column_nr, assignded_column)

                elif fil.name == 'subbrand_brand_model':
                    rows = self.get_data_from_columns(fil.columns)
                    assignded_column = self.join_columns(rows)
                    self.replace_column(fil.column_nr, assignded_column)

        session.close()
        QMessageBox.information(self, "Informacja", "Operacja zakończona.")

    def get_data_from_columns(self, columns_nr):
        """
        get data for sending columns
        :param columns_nr:
        :return: return list of value from table
        """
        rows = []
        for row in range(self.sti.rowCount()):
            row_value = []
            for col in columns_nr:
                if self.sti.item(row, col) is not None:
                    row_value.append(self.sti.item(row, col).text())
                else:
                    row_value.append('')
            # row_value = [self.sti.item(row, col).text() for col in columns_nr]
            rows.append(row_value)
        return rows

    @staticmethod
    def make_words_list(filter_id, rows):
        """
        make words list for filters,
        if find word in list assigned name of category
        :param filter_id:
        :param rows:
        :return:
        """

        session = Session()
        filter_ = session.query(FilterF).get(filter_id)

        ready_valus = []
        for row in rows:
            flag = False
            row = [i.lower() for i in row]
            row = ' '.join(row)
            for category in filter_.categorys:
                words = [b.lower() for b in category.words]
                for word in words:
                    if word in row:
                        item = QStandardItem(str(category.name))
                        ready_valus.append(item)
                        flag = True
                        break
            if flag is False:
                item = QStandardItem('')
                ready_valus.append(item)

        session.close()
        return ready_valus

    def filter_cut_model(self, rows):
        """
        cut ferst word from string
        :param rows:
        :return:
        """
        ready_values = []
        for row in rows:
            item = QStandardItem((row[1].replace(row[0], '')).strip())
            ready_values.append(item)

        return ready_values

    def join_columns(self, rows):
        """
        join column in list rows
        """
        temp = [QStandardItem(' '.join(x)) for x in rows]
        return temp

    def set_color_on_header(self):
        """
        changes the color of the header
        :return:
        """

        session = Session()
        filtersf = session.query(FilterF).all()

        for filterf in filtersf:
            if filterf.type == 'manual':
                self.table.model().setHeaderData(filterf.column_nr,
                                                 Qt.Horizontal,
                                                 QBrush(QColor(121, 166, 210)),
                                                 Qt.BackgroundRole)
                self.table.model().setHeaderData(
                    filterf.column_nr, Qt.Horizontal,
                    self.headers[filterf.column_nr], Qt.DisplayRole)
            if filterf.type in ('words', 'cut'):
                self.table.model().setHeaderData(filterf.column_nr,
                                                 Qt.Horizontal,
                                                 QBrush(QColor(212, 214, 219)),
                                                 Qt.BackgroundRole)
                self.table.model().setHeaderData(
                    filterf.column_nr, Qt.Horizontal,
                    self.headers[filterf.column_nr], Qt.DisplayRole)
        session.close()
예제 #6
0
class QFlightWaypointList(QTableView):
    def __init__(self, package: Package, flight: Flight):
        super().__init__()
        self.package = package
        self.flight = flight

        self.model = QStandardItemModel(self)
        self.setModel(self.model)
        self.model.setHorizontalHeaderLabels(["Name", "Alt", "TOT/DEPART"])

        header = self.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
        self.update_list()

        self.selectionModel().setCurrentIndex(
            self.indexAt(QPoint(1, 1)), QItemSelectionModel.Select
        )

    def update_list(self):
        # We need to keep just the row and rebuild the index later because the
        # QModelIndex will not be valid after the model is cleared.
        current_index = self.currentIndex().row()
        self.model.clear()

        self.model.setHorizontalHeaderLabels(["Name", "Alt", "TOT/DEPART"])

        waypoints = self.flight.flight_plan.waypoints
        for row, waypoint in enumerate(waypoints):
            self.add_waypoint_row(row, self.flight, waypoint)
        self.selectionModel().setCurrentIndex(
            self.model.index(current_index, 0), QItemSelectionModel.Select
        )
        self.resizeColumnsToContents()
        total_column_width = self.verticalHeader().width() + self.lineWidth()
        for i in range(0, self.model.columnCount()):
            total_column_width += self.columnWidth(i) + self.lineWidth()
        self.setFixedWidth(total_column_width)

    def add_waypoint_row(
        self, row: int, flight: Flight, waypoint: FlightWaypoint
    ) -> None:
        self.model.insertRow(self.model.rowCount())

        self.model.setItem(row, 0, QWaypointItem(waypoint, row))

        altitude = int(waypoint.alt.feet)
        altitude_type = "AGL" if waypoint.alt_type == "RADIO" else "MSL"
        altitude_item = QStandardItem(f"{altitude} ft {altitude_type}")
        altitude_item.setEditable(False)
        self.model.setItem(row, 1, altitude_item)

        tot = self.tot_text(flight, waypoint)
        tot_item = QStandardItem(tot)
        tot_item.setEditable(False)
        self.model.setItem(row, 2, tot_item)

    def tot_text(self, flight: Flight, waypoint: FlightWaypoint) -> str:
        if waypoint.waypoint_type == FlightWaypointType.TAKEOFF:
            return self.takeoff_text(flight)
        prefix = ""
        time = flight.flight_plan.tot_for_waypoint(waypoint)
        if time is None:
            prefix = "Depart "
            time = flight.flight_plan.depart_time_for_waypoint(waypoint)
        if time is None:
            return ""
        time = timedelta(seconds=int(time.total_seconds()))
        return f"{prefix}T+{time}"

    @staticmethod
    def takeoff_text(flight: Flight) -> str:
        takeoff_time = flight.flight_plan.takeoff_time()
        # Handle custom flight plans where we can't estimate the takeoff time.
        if takeoff_time is None:
            takeoff_time = timedelta()
        start_time = timedelta(seconds=int(takeoff_time.total_seconds()))
        return f"T+{start_time}"
예제 #7
0
class StatusModel(BaseModel):
    def __init__(self, parent=None):
        super().__init__(parent)

        self._calculator = None

        # Create the status items
        chi_item = StatusItem('chiSq',
                              title='Current \u03c7\u00b2',
                              additionalData=1)
        chi_item.setReturn(True)
        chi_item.title = 'Previous \u03c7\u00b2'
        chi_item.setReturn(False)
        self._interestedList = StatusList([
            chi_item,
            StatusItem('numPars', title='Fit parameters', additionalData=1),
            StatusItem('numData', title='Experiments', additionalData=0),
            StatusItem('numPhases', title='Phases', additionalData=0)
        ])

        # minor properties
        self._first_role = Qt.UserRole + 1

        self._statusBarModel = QStandardItemModel()
        self._chartDisplayModel = QStandardItemModel()
        # set role names
        self._role_names_list = ['label', 'value']
        self._roles_list = []
        self._roles_dict = {'status': {}, 'plot': {}}
        self._setRolesListAndDict()
        self._statusBarModel.setItemRoleNames(self._roles_dict['status'])
        self._chartDisplayModel.setItemRoleNames(self._roles_dict['plot'])

        self._log = logger.getLogger(self.__class__.__module__)

    def _setRolesListAndDict(self):
        """..."""
        offset = 100
        for i, role_name in enumerate(self._role_names_list):
            display_role = self._first_role + i
            self._roles_dict['status'][display_role] = role_name.encode()
            self._roles_list.append(display_role)
            self._roles_dict['plot'][self._first_role + i +
                                     offset] = role_name.encode()

    def _setModelsFromProjectDict(self):
        """Create the initial data list with structure for GUI fitables table."""
        _ = self._statusBarModel.removeColumns(
            0, self._statusBarModel.columnCount())
        _ = self._chartDisplayModel.removeColumns(
            0, self._chartDisplayModel.columnCount())

        column_status_bar = []
        column_chart_display = []

        self._updateStatusList()

        for interest in self._interestedList:
            # Add the status bar item
            column_status_bar.append(
                self._makeItem(interest, self._roles_dict['status'].items()))
            # Does this need to added to the plot?
            if interest.additionalData == 1:
                column_chart_display.append(
                    self._makeItem(interest, self._roles_dict['plot'].items()))

            # Does this item also have previous values which need to be shown?
            if interest.hasPrevious:
                interest.setReturn(True)
                if interest.value is not None:
                    column_status_bar.append(
                        self._makeItem(interest,
                                       self._roles_dict['status'].items()))
                interest.setReturn(False)

        # Set the models
        self._statusBarModel.appendColumn(column_status_bar)
        self._chartDisplayModel.appendColumn(column_chart_display)

        self._statusBarModel.dataChanged.emit(
            self._statusBarModel.index(0, 0),
            self._statusBarModel.index(self._statusBarModel.rowCount() - 1,
                                       self._statusBarModel.columnCount() - 1),
            self._roles_list)

    def _updateStatusList(self):
        """Update the values of the Item List"""
        project_dict = self._project_dict

        # Set chi squared
        try:
            self._interestedList.setItemValue(
                'chiSq',
                round(float(project_dict['info']['chi_squared'].value), 2))
        except KeyError:
            self._interestedList.setItemValue('chiSq', 0)

        # Get number of parameters
        num_pars = get_num_refine_pars(project_dict.asDict())

        # Set the other parameters.
        self._interestedList.setItemValue('numPars', num_pars)
        self._interestedList.setItemValue('numPhases',
                                          len(project_dict['phases']))
        self._interestedList.setItemValue('numData',
                                          len(project_dict['experiments']))

    def returnStatusBarModel(self):
        """Return the status bar model."""
        return self._statusBarModel

    def onRefinementDone(self):
        """Define what to do when the refinement done is triggered"""
        self._setModelsFromProjectDict()
        self._chartDisplayModel.layoutChanged.emit()

    def returnChartModel(self):
        """Return the chart model"""
        return self._chartDisplayModel

    @staticmethod
    def _makeItem(this_interest, these_items):
        """Make an item. This can be a plot or status bar"""
        item = QStandardItem()
        for role, role_name_bytes in these_items:
            role_name = role_name_bytes.decode()
            if role_name == 'label':
                value = this_interest.title
            elif role_name == 'value':
                value = this_interest.value
            else:
                continue
            item.setData(value, role)
        return item
class ShowDataWidget(QWidget):
    pathSignal = Signal(list)
    _tr = QCoreApplication.translate

    def __init__(self, parent=None, items=None, graph=None, name=None):
        super().__init__(parent)
        self.setWindowFlag(Qt.Window, True)
        self.setWindowOpacity(0.9)
        self.ui = Ui_DataDetails()
        self.ui.setupUi(self)
        self.parent = parent
        self.scene: GraphicsScene = self.parent.scene()
        self.__graph: Graph = graph
        self.toolWidget = self.ui.toolWidget
        self.path = []

        self.layout = self.toolWidget.layout()
        self.items = items
        self.rowCount = 0
        self.columnCount = 0
        self.horizontalHeaderList = []
        self.verticalHeaderList = []

        source = self._tr("BezierShowDataWidget", '始点')
        dest = self._tr("BezierShowDataWidget", '终点')
        self.startLabel = QLabel(source)
        self.endLabel = QLabel(dest)

        self.startNodeEdit = QLineEdit(self)
        self.endNodeEdit = QLineEdit(self)
        btnStr = self._tr("BezierShowDataWidget", '搜索')
        self.searchBtn = QPushButton(btnStr, self)
        self.searchBtn.setVisible(False)
        self.startNodeEdit.setVisible(False)
        self.endNodeEdit.setVisible(False)

        self.scene.itemNode.connect(self.do_updateNode)

        self.toolWidget.setVisible(False)

        self.dataDetailView = self.ui.dataTable
        self.dataDetailView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.dataDetailView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.dataModel = QStandardItemModel(self.rowCount, self.columnCount,
                                            self)

        self.dataSelectionModel = QItemSelectionModel(self.dataModel)
        self.dataSelectionModel.currentChanged.connect(self.do_emitPathList)
        self.dataModel.clear()

        self.dataDetailView.setModel(self.dataModel)
        self.dataDetailView.setSelectionModel(self.dataSelectionModel)
        self.dataDetailView.verticalHeader().setSectionResizeMode(
            QHeaderView.Fixed)
        self.dataDetailView.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)
        self.dataDetailView.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)
        self.dataDetailView.setAlternatingRowColors(True)
        self.setWindowTitle(name)

    def updateToolWidget(self, mode=0, path=0):
        self.searchBtn.setVisible(True)
        self.startNodeEdit.setVisible(True)
        self.endNodeEdit.setVisible(True)
        rx = QRegExp(r'^[A-Z][\d+]{5}$')
        validator1 = QRegExpValidator(rx, self.startNodeEdit)
        validator2 = QRegExpValidator(rx, self.endNodeEdit)
        if mode == 1:
            self.endLabel.setVisible(False)
            self.endNodeEdit.setVisible(False)
            self.startNodeEdit.setValidator(validator1)
            self.startNodeEdit.setInputMask("A99")
            self.startNodeEdit.setMinimumWidth(40)
            self.startNodeEdit.setCursor(Qt.IBeamCursor)
            if path == 0:
                self.searchBtn.clicked.connect(self.do_searchBtnEasyLoop)
            elif path == 1:
                self.searchBtn.clicked.connect(self.do_searchBtnPrimaryLoop)
            elif path == 2:
                self.searchBtn.clicked.connect(self.do_searchBtnShortestPath)
        else:

            self.startNodeEdit.setValidator(validator1)
            self.endNodeEdit.setValidator(validator2)

            self.startNodeEdit.setInputMask("A99")
            self.endNodeEdit.setInputMask("A99")

            self.startNodeEdit.setMinimumWidth(40)
            self.endNodeEdit.setMinimumWidth(40)

            self.startNodeEdit.setCursor(Qt.IBeamCursor)
            self.endNodeEdit.setCursor(Qt.IBeamCursor)
            if path == 0:
                self.searchBtn.clicked.connect(self.do_searchBtnEasyPath)
            elif path == 1:
                self.searchBtn.clicked.connect(self.do_searchBtnPrimaryPath)

        self.toolWidget.setVisible(True)

        self.layout.addStretch()
        self.layout.addWidget(self.startLabel)
        self.layout.addWidget(self.startNodeEdit)
        self.layout.addStretch()
        self.layout.addWidget(self.endLabel)
        self.layout.addWidget(self.endNodeEdit)
        self.layout.addStretch()
        self.layout.addWidget(self.searchBtn)
        self.layout.addStretch()

    @classmethod
    def iniStartEnd(cls, nodeList):
        if nodeList[0][1] < nodeList[1][1]:
            start = nodeList[0][0].data(0)
            end = nodeList[1][0].data(0)
            return start, end
        else:
            start = nodeList[1][0].data(0)
            end = nodeList[0][0].data(0)
            return start, end

    def easyPath(self):

        if not self.startNodeEdit.text():
            startNode = self.iniStartEnd(self.items)[0]
        else:
            startNode = int(self.startNodeEdit.text().strip('V'))
        if not self.endNodeEdit.text():
            endNode = self.iniStartEnd(self.items)[1]
        else:
            endNode = int(self.endNodeEdit.text().strip('V'))
        paths = self.__graph.findSimplePathway(startNode, endNode)
        if len(paths) == 0:
            self.dataModel.clear()
            QMessageBox.information(
                None, "Sorry", self._tr("BezierShowDataWidget", "没有符合条件的通路"))
            return False
        self.rowCount = len(paths)
        self.dataModel.setRowCount(self.rowCount)
        self.dataModel.setColumnCount(self.columnCount)
        self.dataModel.clear()
        for i in range(self.rowCount):
            for j in range(len(paths[i])):
                if str(type(paths[i][j])).find("Edge") >= 0:
                    item = QStandardItem(f'e{paths[i][j].id()}')
                    item.setFlags(Qt.NoItemFlags)
                    self.dataModel.setItem(i, j, item)
                elif str(type(paths[i][j])).find("Vertex") >= 0:
                    item = QStandardItem(f'V{paths[i][j].id()}')
                    item.setFlags(Qt.NoItemFlags)
                    self.dataModel.setItem(i, j, item)

        return True

    def primaryPath(self):
        if not self.startNodeEdit.text():
            startNode = self.iniStartEnd(self.items)[0]
        else:
            startNode = int(self.startNodeEdit.text().strip('V'))
        if not self.endNodeEdit.text():
            endNode = self.iniStartEnd(self.items)[1]
        else:
            endNode = int(self.endNodeEdit.text().strip('V'))
        paths = self.__graph.findPrimaryPathway(startNode, endNode)
        if len(paths) == 0:
            self.dataModel.clear()
            QMessageBox.information(
                None, self._tr("BezierShowDataWidget", "对不起"),
                self._tr("BezierShowDataWidget", "没有符合条件的通路"))
            return False
        self.rowCount = len(paths)
        self.dataModel.setRowCount(self.rowCount)
        self.dataModel.setColumnCount(self.columnCount)
        self.dataModel.clear()
        for i in range(self.rowCount):
            for j in range(len(paths[i])):
                if str(type(paths[i][j])).find("Edge") >= 0:
                    item = QStandardItem(f'e{paths[i][j].id()}')
                    self.dataModel.setItem(i, j, item)
                    item.setFlags(Qt.NoItemFlags)
                elif str(type(paths[i][j])).find("Vertex") >= 0:
                    item = QStandardItem(f'V{paths[i][j].id()}')
                    item.setFlags(Qt.NoItemFlags)
                    self.dataModel.setItem(i, j, item)

        return True

    def easyLoop(self):
        if not self.startNodeEdit.text():
            startNode = self.items[0][0].data(0)
        else:
            startNode = int(self.startNodeEdit.text().strip('V'))
        paths = self.__graph.findSimpleLoop(startNode)
        if len(paths) == 0:
            self.dataModel.clear()
            QMessageBox.information(
                None, self._tr("BezierShowDataWidget", "对不起"),
                self._tr("BezierShowDataWidget", "没有符合条件的回路"))
            return False
        self.rowCount = len(paths)
        self.dataModel.setRowCount(self.rowCount)
        self.dataModel.setColumnCount(self.columnCount)
        self.dataModel.clear()
        for i in range(self.rowCount):
            for j in range(len(paths[i])):
                if str(type(paths[i][j])).find("Edge") >= 0:
                    item = QStandardItem(f'e{paths[i][j].id()}')
                    item.setFlags(Qt.NoItemFlags)
                    self.dataModel.setItem(i, j, item)
                elif str(type(paths[i][j])).find("Vertex") >= 0:
                    item = QStandardItem(f'V{paths[i][j].id()}')
                    item.setFlags(Qt.NoItemFlags)
                    self.dataModel.setItem(i, j, item)

        return True

    def primaryLoop(self):
        if not self.startNodeEdit.text():
            startNode = self.items[0][0].data(0)
        else:
            startNode = int(self.startNodeEdit.text().strip('V'))
        paths = self.__graph.findPrimaryLoop(startNode)
        if len(paths) == 0:
            self.dataModel.clear()
            QMessageBox.information(
                None, self._tr("BezierShowDataWidget", "对不起"),
                self._tr("BezierShowDataWidget", "没有符合条件的回路"))
            return False
        self.rowCount = len(paths)
        self.dataModel.setRowCount(self.rowCount)
        self.dataModel.setColumnCount(self.columnCount)
        self.dataModel.clear()
        for i in range(self.rowCount):
            for j in range(len(paths[i])):
                if str(type(paths[i][j])).find("Edge") >= 0:
                    item = QStandardItem(f'e{paths[i][j].id()}')
                    self.dataModel.setItem(i, j, item)
                    item.setFlags(Qt.NoItemFlags)
                elif str(type(paths[i][j])).find("Vertex") >= 0:
                    item = QStandardItem(f'V{paths[i][j].id()}')
                    item.setFlags(Qt.NoItemFlags)
                    self.dataModel.setItem(i, j, item)

        return True

    def multipleOrSimple(self):
        edges = self.items
        self.rowCount = len(edges)
        self.dataModel.setRowCount(self.rowCount)
        self.dataModel.setColumnCount(self.columnCount)
        self.dataModel.clear()
        for i in range(self.rowCount):
            for j in range(1):
                item = QStandardItem(f'e{edges[i]}')
                self.dataModel.setItem(i, j, item)
                item.setFlags(Qt.NoItemFlags)

    def shortestPath(self):
        if not self.startNodeEdit.text():
            startNode = self.items[0][0].data(0)
        else:
            startNode = int(self.startNodeEdit.text().strip('V'))
        paths = []
        for node in self.scene.singleItems(BezierNode):
            path = self.__graph.shortestPath(startNode, node.data(0))
            if path is not None and len(path) > 2 and path not in paths:
                paths.append(path)
        if len(paths) == 0:
            self.dataModel.clear()
            QMessageBox.information(
                None, self._tr("BezierShowDataWidget", "对不起"),
                self._tr("BezierShowDataWidget", "没有符合条件的路径"))
            return False
        self.rowCount = len(paths)
        self.dataModel.setRowCount(self.rowCount)
        self.dataModel.setColumnCount(self.columnCount)
        self.dataModel.clear()
        for i in range(self.rowCount):
            for j in range(len(paths[i])):
                if str(type(paths[i][j])).find("Edge") >= 0:
                    item = QStandardItem(f'e{paths[i][j].id()}')
                    item.setFlags(Qt.NoItemFlags)
                    self.dataModel.setItem(i, j, item)
                elif str(type(paths[i][j])).find("Vertex") >= 0:
                    item = QStandardItem(f'V{paths[i][j].id()}')
                    item.setFlags(Qt.NoItemFlags)
                    self.dataModel.setItem(i, j, item)

        return True

    def closeEvent(self, event: QCloseEvent):
        if self.__graph:
            self.parent.disconnectGraph()
        super().closeEvent(event)

    def leaveEvent(self, event: QEvent):
        self.parent.disconnectGraph()

    def enterEvent(self, event: QEvent):
        self.parent.disconnectGraph()
        self.parent.connectGraph()
        self.__graph = self.parent.graph()

    def do_searchBtnEasyPath(self):
        start = int(self.startNodeEdit.text().strip('V'))
        end = int(self.endNodeEdit.text().strip('V'))
        if start > self.__graph.nodeNumber() or end > self.__graph.nodeNumber(
        ):
            QMessageBox.information(None,
                                    self._tr("BezierShowDataWidget", "对不起"),
                                    self._tr("BezierShowDataWidget", "超出上限"))
            return
        self.easyPath()

    def do_searchBtnPrimaryPath(self):
        start = int(self.startNodeEdit.text().strip('V'))
        if start > self.__graph.nodeNumber() - 1:
            QMessageBox.information(None,
                                    self._tr("BezierShowDataWidget", "对不起"),
                                    self._tr("BezierShowDataWidget", "超出上限"))
            return
        self.primaryPath()

    def do_searchBtnEasyLoop(self):
        start = int(self.startNodeEdit.text().strip('V'))
        if start > self.__graph.nodeNumber() - 1:
            QMessageBox.information(None,
                                    self._tr("BezierShowDataWidget", "对不起"),
                                    self._tr("BezierShowDataWidget", "超出上限"))
            return
        self.easyLoop()

    def do_searchBtnPrimaryLoop(self):
        start = int(self.startNodeEdit.text().strip('V'))
        if start > self.__graph.nodeNumber() - 1:
            QMessageBox.information(None,
                                    self._tr("BezierShowDataWidget", "对不起"),
                                    self._tr("BezierShowDataWidget", "超出上限"))
            return
        self.easyLoop()

    def do_searchBtnShortestPath(self):
        start = int(self.startNodeEdit.text().strip('V'))
        if start > self.__graph.nodeNumber() - 1:
            QMessageBox.information(None,
                                    self._tr("BezierShowDataWidget", "对不起"),
                                    self._tr("BezierShowDataWidget", "超出上限"))
            return
        self.shortestPath()

    def do_updateNode(self, nodeList):
        if len(nodeList) == 1:
            start = nodeList[0][0].data(0)
            self.startNodeEdit.setText(f'V{start}')
        elif len(nodeList) == 2:
            if nodeList[0][1] < nodeList[1][1]:
                start = nodeList[0][0].data(0)
                end = nodeList[1][0].data(0)
                self.startNodeEdit.setText(f'V{start}')
                self.endNodeEdit.setText(f'V{end}')
                self.startNodeEdit.setText(f'V{start}')
                self.endNodeEdit.setText(f'V{end}')

            else:
                start = nodeList[1][0].data(0)
                end = nodeList[0][0].data(0)
                self.startNodeEdit.setText(f'{start}')
                self.endNodeEdit.setText(f'{end}')
                self.startNodeEdit.setText(f'{start}')
                self.endNodeEdit.setText(f'{end}')

    def do_emitPathList(self, current, previous):
        if current is not None:
            self.path.clear()
            item = self.dataModel.index(current.row(), current.column(),
                                        QModelIndex())
            for i in range(self.dataModel.columnCount()):
                item = self.dataModel.index(current.row(), i, QModelIndex())
                if item:
                    self.path.append(item.data())

            self.pathSignal.emit(self.path)