예제 #1
0
class DataSourceWidget(_AbstractCtrlWidget):
    """DataSourceWidget class.

    Widgets provide data source management and monitoring.
    """

    class AvailStateDelegate(QStyledItemDelegate):
        def __init__(self, parent=None):
            super().__init__(parent=parent)
            self._brush = FColor.mkBrush('g')

        def paint(self, painter, option, index):
            """Override."""
            v = index.data()
            painter.setPen(Qt.NoPen)
            if v:
                painter.setBrush(self._brush)
            else:
                painter.setBrush(Qt.NoBrush)

            rect = option.rect
            h = rect.height()
            painter.drawRect(rect.x() + 2, rect.y() + 2, h - 4, h - 4)

    class DataTypeDelegate(QStyledItemDelegate):
        def __init__(self, parent=None):
            super().__init__(parent=parent)

            self._c_brush = FColor.mkBrush('c')
            self._p_brush = FColor.mkBrush('p')

        def paint(self, painter, option, index):
            """Override."""
            v = index.data()
            if isinstance(v, int):
                painter.setPen(Qt.NoPen)

                if v == 0:
                    # control data
                    painter.setBrush(self._c_brush)
                elif v == 1:
                    # pipeline data
                    painter.setBrush(self._p_brush)
                else:
                    raise ValueError(f"Unknown data type: {v}")

                rect = option.rect
                h = rect.height()
                painter.drawRect(rect.x() + 2, rect.y() + 2, h - 4, h - 4)
            else:
                super().paint(painter, option, index)

    _source_types = {
        "Run directory": DataSource.FILE,
        "ZeroMQ bridge": DataSource.BRIDGE,
    }

    SPLITTER_HANDLE_WIDTH = 9

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self._con_view = QTableView()
        self._con_model = ConnectionTableModel(self._source_types)
        self._con_view.setModel(self._con_model)
        self._con_src_type_delegate = ComboBoxDelegate(self._source_types)
        self._con_addr_delegate = LineEditItemDelegateN(self)
        self._con_port_delegate = LineEditItemDelegateN(
            self, validator=QIntValidator(0, 65535))
        self._con_view.setItemDelegateForColumn(1, self._con_src_type_delegate)
        self._con_view.setItemDelegateForColumn(2, self._con_addr_delegate)
        self._con_view.setItemDelegateForColumn(3, self._con_port_delegate)

        self._src_view = QTreeView()
        self._src_tree_model = DataSourceItemModel(self)
        self._src_avail_delegate = self.AvailStateDelegate(self)
        self._src_data_type_delegate = self.DataTypeDelegate(self)
        self._src_device_delegate = LineEditItemDelegate(self)
        self._src_ppt_delegate = LineEditItemDelegate(self)
        self._src_slicer_delegate = SliceItemDelegate(self)
        self._src_boundary_delegate = BoundaryItemDelegate(self)
        self._src_view.setModel(self._src_tree_model)
        self._src_view.setItemDelegateForColumn(0, self._src_avail_delegate)
        self._src_view.setItemDelegateForColumn(1, self._src_data_type_delegate)
        self._src_view.setItemDelegateForColumn(2, self._src_device_delegate)
        self._src_view.setItemDelegateForColumn(3, self._src_ppt_delegate)
        self._src_view.setItemDelegateForColumn(4, self._src_slicer_delegate)
        self._src_view.setItemDelegateForColumn(5, self._src_boundary_delegate)

        self._monitor_tb = QTabWidget()

        self._avail_src_view = QListView()
        self._avail_src_model = DataSourceListModel()
        self._avail_src_view.setModel(self._avail_src_model)

        self._process_mon_view = QTableView()
        self._process_mon_model = ProcessMonitorTableModel()
        self._process_mon_view.setModel(self._process_mon_model)
        self._process_mon_view.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)

        self.initUI()
        self.initConnections()

        self._non_reconfigurable_widgets = [
            self._con_view,
        ]

        self._mon = MonProxy()

        self._raw_srcs = dict()
        self._matched_srcs = dict()
        self._avail_src_timer = QTimer()
        self._avail_src_timer.timeout.connect(self.updateAvailableSources)
        self._avail_src_timer.start(config["SOURCE_AVAIL_UPDATE_TIMER"])

        self._process_mon_timer = QTimer()
        self._process_mon_timer.timeout.connect(self.updateProcessInfo)
        self._process_mon_timer.start(config["PROCESS_MONITOR_UPDATE_TIMER"])

    def initUI(self):
        """Override."""
        self._monitor_tb.setTabPosition(QTabWidget.TabPosition.South)
        self._monitor_tb.addTab(self._avail_src_view, "Source monitor")
        self._monitor_tb.addTab(self._process_mon_view, "Process monitor")

        splitter = QSplitter(Qt.Vertical)
        splitter.setHandleWidth(self.SPLITTER_HANDLE_WIDTH)
        splitter.setChildrenCollapsible(False)
        splitter.addWidget(self._con_view)
        splitter.addWidget(self._src_view)
        splitter.addWidget(self._monitor_tb)
        splitter.setStretchFactor(0, 3)
        splitter.setStretchFactor(1, 1)
        h = splitter.sizeHint().height()
        splitter.setSizes([0.1 * h, 0.6 * h, 0.3 * h])

        layout = QVBoxLayout()
        layout.addWidget(splitter)
        self.setLayout(layout)

        self._con_view.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)

        self._src_view.setIndentation(self._src_view.indentation()/2)
        self._src_view.expandToDepth(1)
        for i in range(4):
            self._src_view.resizeColumnToContents(i)
        for i in range(2):
            self._src_view.header().setSectionResizeMode(
                i, QHeaderView.Fixed)

    def initConnections(self):
        """Override."""
        mediator = self._mediator

        mediator.file_stream_initialized_sgn.connect(self.updateMetaData)

    def updateMetaData(self):
        """Override."""
        try:
            cons = self._con_model.connections()
            self._mediator.onBridgeConnectionsChange(cons)
        except ValueError as e:
            logger.error(e)
            return False

        return True

    def loadMetaData(self):
        """Override."""
        pass

    def updateAvailableSources(self):
        ret = self._mon.get_available_sources()
        if ret is not None:
            raw, matched = ret
            self._avail_src_model.setupModelData(raw)
            self._src_tree_model.updateMatchedSources(matched)

    def updateProcessInfo(self):
        info = []
        for p in list_foam_processes():
            info.append(list(p))
        self._process_mon_model.setupModelData(info)
예제 #2
0
class TreeView(QWidget):
    def __init__(self, table, parent):
        QWidget.__init__(self, parent)
        self.window = parent
        self.tree = QTreeView(self)
        indent = self.tree.indentation()
        self.tree.setIndentation(indent / 2)

        self.model = DataModel(table)
        self.sorter = sorter = FilterModel(self)
        sorter.setSourceModel(self.model)
        self.tree.setModel(sorter)
        for col in range(3, 9):
            self.tree.setItemDelegateForColumn(col, PercentDelegate(self))
        self.tree.header().setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.tree.header().customContextMenuRequested.connect(
            self._on_header_menu)
        self.tree.setSortingEnabled(True)
        self.tree.setAutoExpandDelay(0)
        self.tree.resizeColumnToContents(0)
        self.tree.resizeColumnToContents(NAME_COLUMN)
        self.tree.expand(self.sorter.index(0, 0))
        #self.tree.expandAll()

        self.tree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.tree.customContextMenuRequested.connect(self._on_tree_menu)

        searchbox = QHBoxLayout()
        self.search = QLineEdit(self)

        searchbox.addWidget(self.search)

        self.search_type = QComboBox(self)
        self.search_type.addItem("Contains", SEARCH_CONTAINS)
        self.search_type.addItem("Exact", SEARCH_EXACT)
        self.search_type.addItem("Reg.Exp", SEARCH_REGEXP)
        searchbox.addWidget(self.search_type)

        btn = QPushButton("&Search", self)
        searchbox.addWidget(btn)
        btn.clicked.connect(self._on_search)

        btn = QPushButton("&Next", self)
        searchbox.addWidget(btn)
        btn.clicked.connect(self._on_search_next)

        filterbox = QHBoxLayout()

        label = QLabel("Time Individual", self)
        filterbox.addWidget(label)
        self.individual_time = QSpinBox(self)
        self.individual_time.setMinimum(0)
        self.individual_time.setMaximum(100)
        self.individual_time.setSuffix(" %")
        filterbox.addWidget(self.individual_time)

        label = QLabel("Alloc Individual", self)
        filterbox.addWidget(label)
        self.individual_alloc = QSpinBox(self)
        self.individual_alloc.setMinimum(0)
        self.individual_alloc.setMaximum(100)
        self.individual_alloc.setSuffix(" %")
        filterbox.addWidget(self.individual_alloc)

        label = QLabel("Time Inherited", self)
        filterbox.addWidget(label)
        self.inherited_time = QSpinBox(self)
        self.inherited_time.setMinimum(0)
        self.inherited_time.setMaximum(100)
        self.inherited_time.setSuffix(" %")
        filterbox.addWidget(self.inherited_time)

        label = QLabel("Alloc Inherited", self)
        filterbox.addWidget(label)
        self.inherited_alloc = QSpinBox(self)
        self.inherited_alloc.setMinimum(0)
        self.inherited_alloc.setMaximum(100)
        self.inherited_alloc.setSuffix(" %")
        filterbox.addWidget(self.inherited_alloc)

        btn = QPushButton("&Filter", self)
        btn.clicked.connect(self._on_filter)
        filterbox.addWidget(btn)
        btn = QPushButton("&Reset", self)
        filterbox.addWidget(btn)
        btn.clicked.connect(self._on_reset_filter)

        vbox = QVBoxLayout()
        vbox.addLayout(searchbox)
        vbox.addLayout(filterbox)
        vbox.addWidget(self.tree)
        self.setLayout(vbox)

        self._search_idxs = None
        self._search_idx_no = 0

    def _expand_to(self, idx):
        idxs = [idx]
        parent = idx
        while parent and parent.isValid():
            parent = self.sorter.parent(parent)
            idxs.append(parent)
        #print(idxs)
        for idx in reversed(idxs[:-1]):
            data = self.sorter.data(idx, QtCore.Qt.DisplayRole)
            #print(data)
            self.tree.expand(idx)

    def _on_search(self):
        text = self.search.text()
        selected = self.tree.selectedIndexes()
        #         if selected:
        #             start = selected[0]
        #         else:
        start = self.sorter.index(0, NAME_COLUMN)
        search_type = self.search_type.currentData()
        if search_type == SEARCH_EXACT:
            method = QtCore.Qt.MatchFixedString
        elif search_type == SEARCH_CONTAINS:
            method = QtCore.Qt.MatchContains
        else:
            method = QtCore.Qt.MatchRegExp

        self._search_idxs = idxs = self.sorter.search(start, text, search_type)
        if idxs:
            self.window.statusBar().showMessage(
                "Found: {} occurence(s)".format(len(idxs)))
            self._search_idx_no = 0
            idx = idxs[0]
            self._locate(idx)
        else:
            self.window.statusBar().showMessage("Not found")

    def _locate(self, idx):
        self.tree.resizeColumnToContents(0)
        self.tree.resizeColumnToContents(NAME_COLUMN)
        self._expand_to(idx)
        self.tree.setCurrentIndex(idx)
        #self.tree.selectionModel().select(idx, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Current | QItemSelectionModel.Rows)
        #self.tree.scrollTo(idx, QAbstractItemView.PositionAtCenter)

    def _on_search_next(self):
        if self._search_idxs:
            n = len(self._search_idxs)
            self._search_idx_no = (self._search_idx_no + 1) % n
            idx = self._search_idxs[self._search_idx_no]
            self.window.statusBar().showMessage("Occurence {} of {}".format(
                self._search_idx_no, n))
            self._locate(idx)
        else:
            self.window.statusBar().showMessage("No search results")

    def _on_filter(self):
        self.sorter.setFilter(self.search.text(), self.individual_time.value(),
                              self.individual_alloc.value(),
                              self.inherited_time.value(),
                              self.inherited_alloc.value())

    def _on_reset_filter(self):
        self.sorter.reset()

    def _on_header_menu(self, pos):
        menu = make_header_menu(self.tree)
        menu.exec_(self.mapToGlobal(pos))

    def _on_tree_menu(self, pos):
        index = self.tree.indexAt(pos)
        #print("index: {}".format(index))
        if index.isValid():
            record = self.sorter.data(index, QtCore.Qt.UserRole + 1)
            #print("okay?..")
            #print("context: {}".format(record))
            menu = self.window.make_item_menu(self.model, record)
            menu.exec_(self.tree.viewport().mapToGlobal(pos))