示例#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)
class DataSourceWidget(_AbstractCtrlWidget):
    """DataSourceWidget class.

    Widgets provide data source management and monitoring.
    """

    _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_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_device_delegate)
        self._src_view.setItemDelegateForColumn(1, self._src_ppt_delegate)
        self._src_view.setItemDelegateForColumn(2, self._src_slicer_delegate)
        self._src_view.setItemDelegateForColumn(3, 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._avail_src_timer = QTimer()
        self._avail_src_timer.timeout.connect(self.updateSourceList)
        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, "Available sources")
        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.expandToDepth(1)
        self._src_view.resizeColumnToContents(0)
        self._src_view.resizeColumnToContents(1)

    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 updateSourceList(self):
        available_sources = self._mon.get_available_sources()
        if available_sources is not None:  # for unittest
            self._avail_src_model.setupModelData(list(
                available_sources.keys()))

    def updateProcessInfo(self):
        info = []
        for p in list_foam_processes():
            info.append(list(p))
        self._process_mon_model.setupModelData(info)
示例#3
0
class DanaBrowseWindow(QMainWindow):
    def __init__(self, args):
        super(DanaBrowseWindow, self).__init__()
        #Leeo la configuracion
        self.configFile = args.configFile
        self.secure = args.secure
        self.cubeFile = args.cubeFile
        self.sysExclude = args.sysExclude

        self.maxLevel = 1  #para poder modificarlo luego
        self.dictionary = DataDict(defFile=args.configFile,
                                   secure=args.secure,
                                   sysExclude=args.sysExclude)
        #TODO variables asociadas del diccionario. Reevaluar al limpiar

        self.baseModel = self.dictionary.baseModel
        self.configData = self.dictionary.configData
        self.conn = self.dictionary.conn
        if self.dictionary.isEmpty:
            self.newConfigData()
            #self.dictionary._cargaModelo(self.dictionary.baseModel)
        self.setupView()
        self.cubeMgr = None  # necesito mas adelante que este definida
        if config.DEBUG:
            print('inicializacion completa')
        #CHANGE here

        self.queryView = TableBrowse(None)

        self.dictMenu = self.menuBar().addMenu("&Conexiones")
        self.dictMenu.addAction("&New ...", self.newConnection, "Ctrl+N")
        self.dictMenu.addAction("&Modify ...", self.modConnection, "Ctrl+M")
        self.dictMenu.addAction("&Delete ...", self.delConnection, "Ctrl+D")
        self.dictMenu.addAction("&Save Config File", self.saveConfigFile,
                                "Ctrl+S")
        self.dictMenu.addAction("E&xit", self.close, "Ctrl+Q")

        self.queryMenu = self.menuBar().addMenu('Consulta de &datos')
        self.queryMenu.addAction("Cerrar", self.hideDatabrowse)
        self.queryMenu.setEnabled(False)

        self.cubeMenu = self.menuBar().addMenu("C&ubo")
        self.cubeMenu.addAction("&Salvar", self.saveCubeFile, "Ctrl+S")
        #self.cubeMenu.addAction("&Restaurar", self.restoreCubeFile, "Ctrl+M")
        self.cubeMenu.addAction("S&alir", self.hideCube, "Ctrl+C")
        self.cubeMenu.addSeparator()
        self.cubeMenu.addAction("Ver &ejemplo de datos del cubo",
                                self.previewCube, "Ctrl+E")
        self.cubeMenu.setEnabled(False)

        #self.queryModel = self.queryView.baseModel

        self.querySplitter = QSplitter(Qt.Vertical)
        self.querySplitter.addWidget(self.view)
        #self.querySplitter.addWidget(self.queryView)

        self.configSplitter = QSplitter(Qt.Horizontal)
        self.configSplitter.addWidget(self.querySplitter)

        self.setCentralWidget(self.configSplitter)

        self.setWindowTitle("Visualizador de base de datos")
        """
            estas funciones son para soportar para los decoradores keep position y tal
        """

    def model(self):
        return self.baseModel

    def isExpanded(self, idx):
        return self.view.isExpanded(idx)

    def setExpanded(self, idx, state):
        return self.view.setExpanded(idx, state)

    def setupView(self):
        self.view = QTreeView(self)
        self.view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.view.customContextMenuRequested.connect(self.openContextMenu)
        self.view.doubleClicked.connect(self.test)
        self.view.setModel(self.baseModel)
        #self.view.resizeColumnToContents(0)
        self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.view.expandAll()
        for m in range(self.baseModel.columnCount()):
            self.view.resizeColumnToContents(m)
        self.view.collapseAll()
        self.view.expandToDepth(0)
        #self.view.setHeaderHidden(True)
        #self.view.setSortingEnabled(True)
        #self.view.setRootIsDecorated(False)
        self.view.setAlternatingRowColors(True)
        #self.view.sortByColumn(0, Qt.AscendingOrder)

    def newConfigData(self):
        self.configData = dict()
        self.configData['Conexiones'] = dict()
        self.editConnection(None)
        if self.configData['Conexiones']:
            self.saveConfigFile()
            print(self.configData)
            self.dictionary._cargaModelo(confData=self.configData['Conexiones']
                                         )  #self.dictionary.baseModel)
        else:
            QMessageBox.critical(
                self, "Error Fatal",
                "No se ha encontrado una conexión valida.\nFin de proceso")
            self.close()

    def saveConfigFile(self):
        dump_config(self.configData,
                    getConfigFileName(self.configFile),
                    secure=self.secure)  #TODO de momento

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

    def close(self):

        if self.cubeMgr:
            self.saveConfigFile()

        for conid in self.conn:
            if self.conn[conid] is None:
                continue
            if self.conn[conid].closed:
                self.conn[conid].close()
        self.saveConfigFile()

        sys.exit()

    def newConnection(self):
        confName = self.editConnection(None)
        # esta claro que sobran parametros
        self.dictionary.appendConnection(confName)

    def modConnection(self, nombre=None):
        if nombre is None:
            selDialog = SelectConnectionDlg(self.configData['Conexiones'])
            if selDialog.exec_():
                confName = selDialog.conexion
            else:
                return
        else:
            confName = nombre
        self.editConnection(confName)
        self.updateModel(confName)

    @waiting_effects
    def updateModel(self, nombre=None):
        self.dictionary.updateModel(nombre)

    def delConnection(self, nombre=None):
        if nombre is None:
            selDialog = SelectConnectionDlg(self.configData['Conexiones'])
            if selDialog.exec_():
                confName = selDialog.conexion
            else:
                return
        else:
            confName = nombre
        self.dictionary.dropConnection(confName)

    def editConnection(self, nombre=None):
        attr_list = ('driver', 'dbname', 'dbhost', 'dbuser', 'dbpass',
                     'dbport', 'debug')
        if nombre is None:
            datos = [None for k in range(len(attr_list) + 1)]
        else:
            datos = [
                nombre,
            ] + dict2row(self.configData['Conexiones'][nombre], attr_list)
            datos[1] = DRIVERS.index(datos[1])
        #contexto
        context = (
            (
                'Nombre',
                QLineEdit,
                {
                    'setReadOnly': True
                } if nombre is not None else None,
                None,
            ),
            # driver
            (
                "Driver ",
                QComboBox,
                None,
                DRIVERS,
            ),
            (
                "DataBase Name",
                QLineEdit,
                None,
                None,
            ),
            (
                "Host",
                QLineEdit,
                None,
                None,
            ),
            (
                "User",
                QLineEdit,
                None,
                None,
            ),
            (
                "Password",
                QLineEdit,
                {
                    'setEchoMode': QLineEdit.Password
                },
                None,
            ),
            (
                "Port",
                QLineEdit,
                None,
                None,
            ),
            (
                "Debug",
                QCheckBox,
                None,
                None,
            ))
        parmDialog = ConnectionSheetDlg('Edite la conexion', context, datos,
                                        self)
        if parmDialog.exec_():
            #TODO deberia verificar que se han cambiado los datos
            #datos[1]=DRIVERS[datos[1]]
            self.configData['Conexiones'][datos[0]] = row2dict(
                datos[1:], attr_list)
            return datos[0]

    @keep_tree_layout()
    def openContextMenu(self, position):
        """
        """
        item = None
        indexes = self.view.selectedIndexes()
        if len(indexes) > 0:
            index = indexes[0]
            item = self.baseModel.itemFromIndex(index)
        menu = QMenu()
        if item:
            item.setMenuActions(menu, self)
            action = menu.exec_(self.view.viewport().mapToGlobal(position))
        #getContextMenu(item,action,self)

    @waiting_effects
    def databrowse(self, confName, schema, table, iters=0):
        #print(confName,schema,table,self.dictionary.conn[confName])
        self.queryView.reconnect(
            self.queryView.getConnection(self.dictionary, confName, schema,
                                         table, iters))
        self.queryView.executeNewScript(
            self.queryView.generateSQL(confName,
                                       schema,
                                       table,
                                       iters,
                                       pFilter=None))
        if self.queryView.isHidden():
            self.queryView.show()
        self.queryMenu.setEnabled(True)
        if self.querySplitter.count(
        ) == 1:  #de momento parece un modo sencillo de no multiplicar en exceso
            self.querySplitter.addWidget(self.queryView)

    def hideDatabrowse(self):
        self.queryView.hide()
        self.queryMenu.setEnabled(False)

    def prepareNewCube(self, confName, schema, table):
        # aqui tiene que venir un dialogo para seleccionar nombre del cubo
        maxLevel = self.maxLevel
        parmDlg = GenerationSheetDlg('Parámetros de generación', table,
                                     maxLevel)
        if parmDlg.exec_():
            kname = parmDlg.data[0]
            maxLevel = parmDlg.data[1]
        infox = info2cube(self.dictionary, confName, schema, table, maxLevel)
        if kname != table:
            infox[kname] = infox.pop(table)
        return infox

    def cubebrowse(self, confName, schema, table):

        infox = self.prepareNewCube(confName, schema, table)
        if self.cubeMgr and not self.cubeMgr.isHidden():
            self.hideCube()
        self.cubeMgr = CubeMgr(self,
                               confName,
                               schema,
                               table,
                               self.dictionary,
                               rawCube=infox,
                               cubeFile=self.cubeFile)
        self.cubeMgr.expandToDepth(1)
        #if self.configSplitter.count() == 1:  #de momento parece un modo sencillo de no multiplicar en exceso
        self.configSplitter.addWidget(self.cubeMgr)

        self.cubeMgr.show()
        self.cubeMenu.setEnabled(True)

    def saveCubeFile(self):
        self.cubeMgr.saveCubeFile()

    def restoreCubeFile(self):
        self.cubeMgr.restoreConfigFile()

    def hideCube(self):
        self.cubeMgr.saveCubeFile()
        self.cubeMgr.hide()
        self.cubeMenu.setEnabled(False)

    def test(self, index):
        return
        print(index.row(), index.column())
        item = self.baseModel.itemFromIndex(index)
        print(item.text(), item.model())

    def refreshTable(self):
        self.baseModel.emitModelReset()

    def previewCube(self):
        startItem = self.cubeMgr.model().item(0, 0)
        conName = self.cubeMgr.defaultConnection
        self.queryView.reconnect(
            self.queryView.getConnection(self.dictionary, confName=conName))
        query = self.cubeMgr.getPreviewQuery(startItem)
        self.queryView.executeNewScript(query)
        if self.queryView.isHidden():
            self.queryView.show()
        self.queryMenu.setEnabled(True)
        if self.querySplitter.count(
        ) == 1:  #de momento parece un modo sencillo de no multiplicar en exceso
            self.querySplitter.addWidget(self.queryView)