示例#1
0
    def initUI(self):      
        # bottom left frame (hosts)
        hostsArea = QFrame(self)
        self.hostTable = hostsTable.hostsTable()
 
        # bottom right frame (KPIs)
        self.kpisTable = kpiTable.kpiTable()
        kpisTable = self.kpisTable


        # top (main chart area)
        self.chartArea = chartArea.chartArea()

        # establish hard links:
        kpisTable.kpiScales = self.chartArea.widget.nscales
        self.chartArea.widget.hosts = self.hostTable.hosts
        
        kpisTable.hosts = self.chartArea.widget.hosts #why do we have hosts inside widget? because we have all data there...
        kpisTable.hostKPIs = self.chartArea.hostKPIs
        kpisTable.srvcKPIs = self.chartArea.srvcKPIs
        kpisTable.nkpis = self.chartArea.widget.nkpis
        
        # bottm part left+right
        kpiSplitter = QSplitter(Qt.Horizontal)
        kpiSplitter.addWidget(self.hostTable)
        kpiSplitter.addWidget(kpisTable)
        kpiSplitter.setSizes([200, 380])
        
        
        self.tabs = QTabWidget()
        
        console = sqlConsole.sqlConsole()
        
        # main window splitter
        mainSplitter = QSplitter(Qt.Vertical)
        
        kpisWidget = QWidget()
        lo = QVBoxLayout(kpisWidget)
        lo.addWidget(kpiSplitter)
        
        mainSplitter.addWidget(self.chartArea)
        mainSplitter.addWidget(kpisWidget)
        mainSplitter.setSizes([300, 90])
        
        mainSplitter.setAutoFillBackground(True)

        # central widget
        #self.setCentralWidget(mainSplitter)
        
        kpisWidget.autoFillBackground = True
        
        self.tabs.addTab(mainSplitter, 'Chart')
        
        if cfg('experimental-notnow'):
            self.tabs.addTab(console, 'Sql')
        
        self.setCentralWidget(self.tabs)
        
        # service stuff
        self.statusbar = self.statusBar()

        #menu
        iconPath = resourcePath('ico\\favicon.ico')

        exitAct = QAction('&Exit', self)        
        exitAct.setShortcut('Alt+Q')
        exitAct.setStatusTip('Exit application')
        exitAct.triggered.connect(self.menuQuit)


        aboutAct = QAction(QIcon(iconPath), '&About', self)
        aboutAct.setStatusTip('About this app')
        aboutAct.triggered.connect(self.menuAbout)

        dummyAct = QAction('&Dummy', self)
        dummyAct.setShortcut('Alt+D')
        dummyAct.setStatusTip('Dummy Data provider')
        dummyAct.triggered.connect(self.menuDummy)

        configAct = QAction('&Connect', self)
        configAct.setShortcut('Alt+C')
        configAct.setStatusTip('Configure connection')
        configAct.triggered.connect(self.menuConfig)

        importAct = QAction('&Import', self)
        importAct.setShortcut('Ctrl+I')
        importAct.setStatusTip('Import nameserver.trc')
        importAct.triggered.connect(self.menuImport)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(aboutAct)
        fileMenu.addAction(configAct)

        if cfg('experimental'):
            fileMenu.addAction(importAct)
            fileMenu.addAction(dummyAct)

        fileMenu.addAction(exitAct)
        
        if cfg('experimental'):
            actionsMenu = menubar.addMenu('&Actions')
            fileMenu.addAction(aboutAct)

            fontAct = QAction('&Adjust Fonts', self)
            fontAct.setStatusTip('Adjust margins after font change (for example after move to secondary screen)')
            fontAct.triggered.connect(self.menuFont)

            reloadConfigAct = QAction('Reload &Config', self)
            reloadConfigAct.setStatusTip('Reload configuration file. Note: some values used during the connect or other one-time-actions')
            reloadConfigAct.triggered.connect(self.menuReloadConfig)
            
            actionsMenu.addAction(fontAct)
            
            actionsMenu.addAction(reloadConfigAct)

            reloadCustomKPIsAct = QAction('Reload Custom &KPIs', self)
            reloadCustomKPIsAct.setStatusTip('Reload definition of custom KPIs')
            reloadCustomKPIsAct.triggered.connect(self.menuReloadCustomKPIs)

            actionsMenu.addAction(reloadCustomKPIsAct)

        # finalization
        self.setGeometry(200, 200, 1400, 800)
        #self.setWindowTitle('SAP HANA Studio Light')
        # self.setWindowTitle('HANA Army Knife')
        self.setWindowTitle('Ryba Fish Charts')
        
        self.setWindowIcon(QIcon(iconPath))
        
        self.show()

        '''
            set up some interactions
        '''
        # bind kpi checkbox signal
        kpisTable.checkboxToggle.connect(self.chartArea.checkboxToggle)
        
        # bind change scales signal
        kpisTable.adjustScale.connect(self.chartArea.adjustScale)
        kpisTable.setScale.connect(self.chartArea.setScale)

        # host table row change signal
        self.hostTable.hostChanged.connect(kpisTable.refill)

        # to fill hosts
        self.chartArea.hostsUpdated.connect(self.hostTable.hostsUpdated)

        # refresh
        self.chartArea.kpiToggled.connect(kpisTable.refill)
        # update scales signal
        self.chartArea.scalesUpdated.connect(kpisTable.updateScales)
        self.chartArea.scalesUpdated.emit() # it really not supposed to have any to update here

        #bind statusbox updating signals
        self.chartArea.statusMessage_.connect(self.statusMessage)
        self.chartArea.widget.statusMessage_.connect(self.statusMessage)

        self.chartArea.connected.connect(self.setTabName)
        log('init finish()')
        
        if self.chartArea.dp:
            self.chartArea.initDP()
示例#2
0
class UI_mainWindow(QMainWindow):
    __tlvInfoGB_ = None
    __tlvPkgListGB_ = None
    __videoGB_ = None
    __videoLabel_ = None
    __audioGB_ = None
    __audioLabel_ = None
    __menubar_ = None
    __winResolution_ = (1280, 720)

    def __init__(self):
        super().__init__()
        # self.setWindowFlag(Qt.FramelessWindowHint)
        self.__vsplitter_ = QSplitter(Qt.Vertical)
        self.__vsplitter_.setChildrenCollapsible(False)  # 拉动分割器至最小,被分割部分不会消失
        self.__vsplitter_.setAutoFillBackground(True)  # 分割器随主窗口大小自适应变化
        self.__hsplitter_ = QSplitter(Qt.Horizontal)
        self.__hsplitter_.setChildrenCollapsible(False)
        self.__hsplitter_.setAutoFillBackground(True)
        self.__initTlvInfoLayout()
        self.__initVideoLayout()
        self.__initAudioLayout()
        self.__initTlvPkgListLayout()
        self.__initMainWindow()

    def __initMainWindow(self):
        availGeometry = QDesktopWidget().availableGeometry()
        self.resize(availGeometry.width() * 0.7, availGeometry.height() * 0.7)
        self.__center()

        self.__menubar_ = UIMenuBar()
        self.setMenuBar(self.__menubar_)
        self.setCentralWidget(self.__hsplitter_)
        self.setWindowTitle('tlv分析工具')

    def __center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def __initTlvInfoLayout(self):
        tlvinfo = UITlvInfo('TLV INFO')
        tlvinfo.setMinimumWidth(250)
        self.__hsplitter_.addWidget(tlvinfo)

    def __initTlvPkgListLayout(self):
        self.__tlvpkglist_ = UITlvPkgList('Tlv Pkg List')
        for i in range(30):
            pkg_level = UITlvPkgList.PKG_LEVEL.NORMAL
            if i % 10 == 0:
                pkg_level = UITlvPkgList.PKG_LEVEL.LOSS
            elif i % 11 == 0:
                pkg_level = UITlvPkgList.PKG_LEVEL.ORDER
            self.__tlvpkglist_.insertTlvPkgItem(
                "H264 RTP Header #{:<10d}".format(i), '''this is an example!
        this is an apple!
        this is a banana!
        this is a pen!
        end''', pkg_level)
        self.__hsplitter_.addWidget(self.__tlvpkglist_)

    def __initVideoLayout(self):
        label = UIVideoLabel()
        label.setMinimumSize(640, 480)
        hlayout = QHBoxLayout()
        hlayout.addStretch(1)
        hlayout.addWidget(label)
        hlayout.addStretch(1)
        vlayout = QVBoxLayout()
        # vlayout.addStretch(1)
        vlayout.addLayout(hlayout)
        # vlayout.addStretch(1)
        video = QGroupBox("Video Replay")
        video.setLayout(vlayout)
        self.__vsplitter_.addWidget(video)

    def __initAudioLayout(self):
        hlayout = QHBoxLayout()
        hlayout.addStretch(1)
        hlayout.addWidget(QLabel('Audio Replay'))
        hlayout.addStretch(1)

        audio = QGroupBox("Audio Replay")
        audio.setLayout(hlayout)
        self.__vsplitter_.addWidget(audio)
        self.__vsplitter_.setSizes([420, 300])
        self.__hsplitter_.addWidget(self.__vsplitter_)
示例#3
0
class ChartWidget(QWidget):
    def __init__(self, *args, **kwargs):
        super(ChartWidget, self).__init__(*args, **kwargs)
        self.resize(800, 600)
        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        self.splitter = QSplitter(self)
        layout.addWidget(self.splitter)
        self.splitter.setOrientation(Qt.Horizontal)
        self.splitter.setStretchFactor(0, 2)
        self.splitter.setStretchFactor(1, 3)
        self.splitter.setStretchFactor(2, 5)
        self.splitter.setAutoFillBackground(True)
        self.splitter.setChildrenCollapsible(False)
        self.splitter.setHandleWidth(2)
        # 分类
        self.classifyWidget = ClassifyWidget(self)
        self.splitter.addWidget(self.classifyWidget)
        # 代码
        self.codeWidget = CodeWidget(self)
        self.splitter.addWidget(self.codeWidget)

        # 等待界面
        self.loadingWidget = LoadingWidget(self, visible=False)
        self.loadingWidget.resize(self.size())

        # 绑定信号槽
        self.classifyWidget.fileSelected.connect(self.codeWidget.openFile)
        self.codeWidget.runSignal.connect(self.onRun)

    def onRun(self, text):
        self.setEnabled(False)
        self.loadingWidget.show()
        # 解析json生成view并添加
        if hasattr(self, "previewView"):
            # 删除旧view
            self.previewView.setParent(None)
            self.previewView.setVisible(False)
            self.previewView.hide()
            self.previewView.deleteLater()
            del self.previewView
        self.previewView = self.getChartView(text)
        if isinstance(self.previewView, QChartView):
            self.splitter.addWidget(self.previewView)
        else:
            QMessageBox.warning(self, "提示", self.previewView)
            del self.previewView
        self.setEnabled(True)
        self.loadingWidget.close()

    def getChartView(self, text):
        try:
            return ChartView(text)
        except Exception as e:
            return str(e)

    def resizeEvent(self, event):
        super(ChartWidget, self).resizeEvent(event)
        self.loadingWidget.resize(self.size())

    def closeEvent(self, event):
        self.loadingWidget.close()
        self.loadingWidget.deleteLater()
        del self.loadingWidget
        super(ChartWidget, self).closeEvent(event)
示例#4
0
class hslWindow(QMainWindow):

    statusbar = None
    connectionConf = None

    kpisTable = None

    def __init__(self):

        self.layoutDumped = False

        self.sqlTabCounter = 0  #static tab counter

        self.tabs = None

        super().__init__()
        self.initUI()

    # def tabChanged(self, newidx):

    def closeTab(self):
        indx = self.tabs.currentIndex()

        if indx > 0:  #print need a better way to identify sql consoles...
            cons = self.tabs.currentWidget()

            cons.delayBackup()

            status = cons.close()

            if status == True:
                self.statusbar.removeWidget(cons.indicator)
                self.tabs.removeTab(indx)

    def keyPressEvent(self, event):
        #log('window keypress: %s' % (str(event.key())))

        modifiers = event.modifiers()

        if (modifiers == Qt.ControlModifier
                and event.key() == 82) or event.key() == Qt.Key_F5:
            log('reload request!')
            self.chartArea.reloadChart()

        elif modifiers == Qt.ControlModifier and event.key() == Qt.Key_W:
            self.closeTab()
        else:
            super().keyPressEvent(event)

    def statusMessage(self, message, repaint):
        if not self.statusbar:
            log('self.statusbar.showMessage(' '%s' ')' % (message))
        else:
            self.statusbar.showMessage(message)

            if repaint:
                self.repaint()

    def closeEvent(self, event):
        log('Exiting...')

        if cfg('saveLayout', True):
            self.dumpLayout()
        '''
        for i in range(self.tabs.count() -1, 0, -1):

            w = self.tabs.widget(i)
            
            if isinstance(w, sqlConsole.sqlConsole):
                w.delayBackup()
                status = w.close(False) # can not abort
        
        clipboard = QApplication.clipboard()
        event = QEvent(QEvent.Clipboard)
        QApplication.sendEvent(clipboard, event)
        '''

    def dumpLayout(self):

        if self.layoutDumped:
            return

        if self.layout is None:
            return

        self.layoutDumped = True

        kpis = {}
        for i in range(len(self.chartArea.widget.hosts)):
            host = self.chartArea.widget.hosts[i]
            hst = '%s:%s' % (host['host'], host['port'])

            if i < len(self.chartArea.widget.nkpis
                       ) and self.chartArea.widget.nkpis[i]:
                kpis[hst] = self.chartArea.widget.nkpis[i]

        if kpis:
            self.layout['kpis'] = kpis
        else:
            if 'kpis' in self.layout.lo:
                del self.layout.lo['kpis']

        self.layout['pos'] = [self.pos().x(), self.pos().y()]
        self.layout['size'] = [self.size().width(), self.size().height()]

        self.layout['mainSplitter'] = self.mainSplitter.sizes()
        self.layout['kpiSplitter'] = self.kpiSplitter.sizes()

        hostTableWidth = []
        KPIsTableWidth = []

        for i in range(self.hostTable.columnCount()):
            hostTableWidth.append(self.hostTable.columnWidth(i))

        for i in range(self.kpisTable.columnCount()):
            KPIsTableWidth.append(self.kpisTable.columnWidth(i))

        self.layout['hostTableWidth'] = hostTableWidth
        self.layout['KPIsTableWidth'] = KPIsTableWidth

        # print(self.pos().x(), self.pos().y())

        tabs = []

        self.layout['currentTab'] = self.tabs.currentIndex()

        if cfg('saveOpenTabs', True):
            for i in range(self.tabs.count() - 1, 0, -1):
                w = self.tabs.widget(i)

                if isinstance(w, sqlConsole.sqlConsole):
                    w.delayBackup()

                    if w.fileName is not None or w.backup is not None:
                        pos = w.cons.textCursor().position()
                        block = w.cons.edit.verticalScrollBar().value()
                        #print('scroll position:', block)
                        #block = w.cons.firstVisibleBlock().position()

                        if w.backup:
                            bkp = os.path.abspath(w.backup)
                        else:
                            bkp = None

                        tabs.append([w.fileName, bkp, pos, block])
                        #tabs.append([w.fileName, bkp, pos])

                    w.close(None)  # can not abort (and dont need to any more!)

                    self.tabs.removeTab(i)

            tabs.reverse()

            if len(tabs) > 0:
                self.layout['tabs'] = tabs
            else:
                if 'tabs' in self.layout.lo:
                    self.layout.lo.pop('tabs')

        if 'running' in self.layout.lo:
            self.layout.lo.pop('running')

        self.layout.dump()

    def menuQuit(self):
        '''
        for i in range(self.tabs.count() -1, 0, -1):
            w = self.tabs.widget(i)
            if isinstance(w, sqlConsole.sqlConsole):
                
                status = w.close(True) # can abort
                
                if status == True:
                    self.tabs.removeTab(i)
                
                if status == False:
                    return
        '''

        if cfg('saveLayout', True):
            self.dumpLayout()

        self.close()

    def menuReloadCustomKPIs(self):

        kpiStylesNN = kpiDescriptions.kpiStylesNN

        for type in ('host', 'service'):
            for kpiName in list(kpiStylesNN[type]):

                kpi = kpiStylesNN[type][kpiName]

                if kpi['sql'] is not None:
                    del (kpiStylesNN[type][kpiName])

                    if type == 'host':
                        self.chartArea.hostKPIs.remove(kpiName)
                    else:
                        self.chartArea.srvcKPIs.remove(kpiName)

        # del host custom groups
        kpis_len = len(self.chartArea.hostKPIs)
        i = 0

        while i < kpis_len:
            if self.chartArea.hostKPIs[i][:1] == '.' and (
                    i == len(self.chartArea.hostKPIs) - 1
                    or self.chartArea.hostKPIs[i + 1][:1] == '.'):
                del (self.chartArea.hostKPIs[i])
                kpis_len -= 1
            else:
                i += 1

        # del service custom groups
        kpis_len = len(self.chartArea.srvcKPIs)
        i = 0

        while i < kpis_len:
            if self.chartArea.srvcKPIs[i][:1] == '.' and (
                    i == len(self.chartArea.srvcKPIs) - 1
                    or self.chartArea.srvcKPIs[i + 1][:1] == '.'):
                del (self.chartArea.srvcKPIs[i])
                kpis_len -= 1
            else:
                i += 1

        try:
            dpDBCustom.scanKPIsN(self.chartArea.hostKPIs,
                                 self.chartArea.srvcKPIs, kpiStylesNN)
        except Exception as e:
            self.chartArea.disableDeadKPIs()
            msgDialog(
                'Custom KPIs Error',
                'There were errors during custom KPIs load. Load of the custom KPIs STOPPED because of that.\n\n'
                + str(e))

        self.chartArea.widget.initPens()
        self.chartArea.widget.update()

        #really unsure if this one can be called twice...
        kpiDescriptions.clarifyGroups()

        #trigger refill
        self.kpisTable.refill(self.hostTable.currentRow())

        self.statusMessage('Custom KPIs reload finish', False)

    def menuReloadConfig(self):
        loadConfig()
        self.statusMessage('Configuration file reloaded.', False)

    def menuFont(self):
        id = QInputDialog

        sf = cfg('fontScale', 1)

        sf, ok = id.getDouble(self, 'Input the scaling factor',
                              'Scaling Factor', sf, 0, 5, 2)

        if ok:
            self.chartArea.widget.calculateMargins(sf)
            self.chartArea.adjustScale(sf)

    def menuAbout(self):
        abt = aboutDialog.About()
        abt.exec_()

    def menuConfHelp(self):
        QDesktopServices.openUrl(QUrl('https://www.rybafish.net/config'))

    def menuCustomConfHelp(self):
        QDesktopServices.openUrl(QUrl('https://www.rybafish.net/customKPI'))

    def menuTips(self):
        QDesktopServices.openUrl(QUrl('https://www.rybafish.net/tips'))

    def menuDummy(self):
        self.chartArea.dp = dpDummy.dataProvider()  # generated data

        if cfg('saveKPIs', True):
            self.chartArea.initDP(self.layout['kpis'])
        else:
            self.chartArea.initDP()

    def menuConfig(self):

        if self.connectionConf is None:
            connConf = cfg('server')
        else:
            connConf = self.connectionConf

        conf, ok = configDialog.Config.getConfig(connConf, self)

        if ok:
            self.connectionConf = conf

        if ok and conf['ok']:

            try:

                # need to disconnect open consoles first...
                self.statusMessage('Disconnecing open consoles...', False)

                for i in range(self.tabs.count()):

                    w = self.tabs.widget(i)

                    if isinstance(
                            w, sqlConsole.sqlConsole) and w.conn is not None:
                        log('closing connection...')
                        w.disconnectDB()
                        w.indicator.status = 'disconnected'
                        w.indicator.repaint()
                        log('disconnected...')

                self.statusMessage('Connecting...', False)
                self.repaint()

                self.chartArea.setStatus('sync', True)
                self.chartArea.dp = dpDB.dataProvider(conf)  # db data provider
                self.chartArea.setStatus('idle')

                for i in range(self.tabs.count()):

                    w = self.tabs.widget(i)

                    if isinstance(w, sqlConsole.sqlConsole):
                        w.config = conf

                if cfg('saveKPIs', True):
                    if self.layout and 'kpis' in self.layout.lo:
                        self.chartArea.initDP(self.layout['kpis'])
                    else:
                        self.chartArea.initDP()

                    starttime = datetime.datetime.now() - datetime.timedelta(
                        seconds=12 * 3600)
                    starttime -= datetime.timedelta(
                        seconds=starttime.timestamp() % 3600)

                    self.chartArea.fromEdit.setText(
                        starttime.strftime('%Y-%m-%d %H:%M:%S'))
                    self.chartArea.toEdit.setText('')

                else:
                    self.chartArea.initDP()

                if hasattr(self.chartArea.dp, 'dbProperties'):
                    self.chartArea.widget.timeZoneDelta = self.chartArea.dp.dbProperties[
                        'timeZoneDelta']
                    self.chartArea.reloadChart()

                propStr = conf['user'] + '@' + self.chartArea.dp.dbProperties[
                    'sid']

                self.tabs.setTabText(0, propStr)
                self.setWindowTitle('RybaFish Charts [%s]' % propStr)

                #setup keep alives

                if cfg('keepalive'):
                    try:
                        keepalive = int(cfg('keepalive'))
                        self.chartArea.dp.enableKeepAlive(self, keepalive)
                    except:
                        log('wrong keepalive setting: %s' % (cfg('keepalive')))

            except dbException as e:
                log('Connect or init error:')
                if hasattr(e, 'message'):
                    log(e.message)
                else:
                    log(e)

                msgBox = QMessageBox()
                msgBox.setWindowTitle('Connection error')
                msgBox.setText('Connection failed: %s ' % (str(e)))
                iconPath = resourcePath('ico\\favicon.ico')
                msgBox.setWindowIcon(QIcon(iconPath))
                msgBox.setIcon(QMessageBox.Warning)
                msgBox.exec_()

                self.statusMessage('', False)

            except Exception as e:
                log('Init exception not related to DB')
                log(str(e))

                msgBox = QMessageBox()
                msgBox.setWindowTitle('Error')
                msgBox.setText(
                    'Init failed: %s \n\nSee more deteails in the log file.' %
                    (str(e)))
                iconPath = resourcePath('ico\\favicon.ico')
                msgBox.setWindowIcon(QIcon(iconPath))
                msgBox.setIcon(QMessageBox.Warning)
                msgBox.exec_()

                self.statusMessage('', False)

        else:
            # cancel or parsing error

            if ok and conf[
                    'ok'] == False:  #it's connection string dict in case of [Cancel]
                msgBox = QMessageBox()
                msgBox.setWindowTitle('Connection string')
                msgBox.setText(
                    'Could not start the connection. Please check the connection string: host, port, etc.'
                )
                iconPath = resourcePath('ico\\favicon.ico')
                msgBox.setWindowIcon(QIcon(iconPath))
                msgBox.setIcon(QMessageBox.Warning)
                msgBox.exec_()

                self.statusMessage('', False)

    def changeActiveTabName(self, name):

        i = self.tabs.currentIndex()

        # must be a better way verity if we attempt to update chart tab name
        if i == 0:
            return

        self.tabs.setTabText(i, name)

    def menuSave(self):

        indx = self.tabs.currentIndex()

        w = self.tabs.widget(indx)

        if not isinstance(w, sqlConsole.sqlConsole):
            return

        w.delayBackup()
        w.saveFile()

    def menuOpen(self):
        '''
            so much duplicate code with menuSqlConsole
            and with dumpLayout!
        '''
        fname = QFileDialog.getOpenFileNames(self, 'Open file', '', '*.sql')

        openfiles = {}

        for i in range(self.tabs.count()):

            w = self.tabs.widget(i)

            if isinstance(w, sqlConsole.sqlConsole):

                fn = w.fileName

                if fn is not None:
                    openfiles[fn] = i

        for filename in fname[0]:

            if filename in openfiles:
                # the file is already open
                idx = openfiles[filename]

                self.tabs.setCurrentIndex(idx)
                continue

            conf = self.connectionConf

            self.statusMessage('Connecting console...', True)

            try:
                console = sqlConsole.sqlConsole(self, conf, 'sqlopen')
            except:
                self.statusMessage('Failed', True)
                log('[!] error creating console for the file')
                return

            self.statusMessage('', False)

            console.nameChanged.connect(self.changeActiveTabName)
            console.cons.closeSignal.connect(self.closeTab)

            self.tabs.addTab(console, console.tabname)

            console.selfRaise.connect(self.raiseTab)

            ind = indicator()
            console.indicator = ind

            ind.iClicked.connect(console.reportRuntime)

            self.statusbar.addPermanentWidget(ind)

            self.tabs.setCurrentIndex(self.tabs.count() - 1)

            console.openFile(filename)

            if self.layout == None:
                # no backups to avoid conflicts...
                console.noBackup = True

    #def populateConsoleTab(self):

    def menuSQLConsole(self):

        conf = self.connectionConf

        if conf is None:
            self.statusMessage('No configuration...', False)
            return

        self.statusMessage('Connecting...', True)

        ind = indicator()
        self.statusbar.addPermanentWidget(ind)

        ind.status = 'sync'
        ind.repaint()

        log('menuSQLConsole...')

        noname = True

        while noname:
            self.sqlTabCounter += 1
            idx = self.sqlTabCounter

            if idx > 1:
                tname = 'sql' + str(idx)
            else:
                tname = 'sql'

            for i in range(self.tabs.count() - 1, 0, -1):
                w = self.tabs.widget(i)
                if isinstance(w, sqlConsole.sqlConsole):
                    if w.tabname == tname or w.tabname == tname + ' *':  # so not nice...
                        break
            else:
                noname = False

        # console = sqlConsole.sqlConsole(self, conf, tname) # self = window

        try:
            console = sqlConsole.sqlConsole(self, conf, tname)  # self = window
            log('seems connected...')
        except dbException as e:
            log('[!] failed to open console expectedly')
            self.statusMessage('Connection error', True)

            self.statusbar.removeWidget(ind)
            return
        '''
        except Exception as e:
            log('[!] failed to open console unexpectedly: ' + str(e))
            self.statusMessage('Connection error?', True)
            return
        '''

        console.indicator = ind
        ind.iClicked.connect(console.reportRuntime)

        console.nameChanged.connect(self.changeActiveTabName)
        console.cons.closeSignal.connect(self.closeTab)
        self.tabs.addTab(console, tname)

        console.selfRaise.connect(self.raiseTab)

        self.tabs.setCurrentIndex(self.tabs.count() - 1)

        if console.unsavedChanges:
            # if autoloaded from backup
            # cannot be triggered from inside as signal not connected on __init__
            self.changeActiveTabName(console.tabname + ' *')

        if self.layout == None:
            # no backups to avoid conflicts...
            console.noBackup = True

        self.statusMessage('', False)
        console.indicator.status = 'idle'
        console.indicator.repaint()

    def menuImport(self):
        fname = QFileDialog.getOpenFileNames(
            self, 'Import nameserver_history.trc...', None,
            'Import nameserver history trace (*.trc)')
        log(fname[0])

        if len(fname[0]) > 0:
            self.chartArea.dp = dpTrace.dataProvider(
                fname[0])  # db data provider

            self.chartArea.initDP(
                message='Parsing the trace file, will take a minute or so...')

            toTime = self.chartArea.widget.hosts[0]['to']
            fromTime = toTime - datetime.timedelta(hours=10)

            self.chartArea.toEdit.setText(toTime.strftime('%Y-%m-%d %H:%M:%S'))
            self.chartArea.fromEdit.setText(
                fromTime.strftime('%Y-%m-%d %H:%M:%S'))

            self.chartArea.reloadChart()

    def raiseTab(self, tab):
        for i in range(self.tabs.count()):
            w = self.tabs.widget(i)

            if w is tab:
                self.tabs.setCurrentIndex(i)
                break

    def setTabName(self, str):
        self.tabs.setTabText(0, str)

    def initUI(self):

        if cfg('saveLayout', True):
            self.layout = Layout(True)

            if self.layout['running']:
                answer = utils.yesNoDialog(
                    'Warning',
                    'Another RybaFish is already running, all the layout and autosave features will be disabled.\n\nExit now?',
                    ignore=True)
                #answer = utils.yesNoDialog('Warning', 'RybaFish is already running or crashed last time, all the layout and autosave features will be disabled.\n\nExit now?', ignore = True)

                if answer == True or answer is None:
                    exit(0)

                if answer == 'ignore':
                    log('Ignoring the layout')
                else:
                    self.layout = None
            else:
                self.layout['running'] = True
                self.layout.dump()
        else:
            self.layout = Layout()

        # bottom left frame (hosts)
        hostsArea = QFrame(self)
        self.hostTable = hostsTable.hostsTable()

        # bottom right frame (KPIs)
        self.kpisTable = kpiTable.kpiTable()
        kpisTable = self.kpisTable

        # top (main chart area)
        self.chartArea = chartArea.chartArea()

        ind = indicator()
        self.chartArea.indicator = ind

        # establish hard links:
        kpisTable.kpiScales = self.chartArea.widget.nscales
        self.chartArea.widget.hosts = self.hostTable.hosts

        kpisTable.hosts = self.chartArea.widget.hosts  #why do we have hosts inside widget? because we have all data there...
        kpisTable.hostKPIs = self.chartArea.hostKPIs
        kpisTable.srvcKPIs = self.chartArea.srvcKPIs
        kpisTable.nkpis = self.chartArea.widget.nkpis

        # bottm part left+right
        self.kpiSplitter = QSplitter(Qt.Horizontal)
        self.kpiSplitter.addWidget(self.hostTable)
        self.kpiSplitter.addWidget(kpisTable)
        self.kpiSplitter.setSizes([200, 380])

        self.tabs = QTabWidget()

        # self.tabs.currentChanged.connect(self.tabChanged)

        # main window splitter
        self.mainSplitter = QSplitter(Qt.Vertical)

        kpisWidget = QWidget()
        lo = QVBoxLayout(kpisWidget)
        lo.addWidget(self.kpiSplitter)

        self.mainSplitter.addWidget(self.chartArea)
        self.mainSplitter.addWidget(kpisWidget)

        if self.layout is not None:
            if self.layout['mainSplitter']:
                self.mainSplitter.setSizes(self.layout['mainSplitter'])
            else:
                self.mainSplitter.setSizes([300, 90])

            if self.layout['kpiSplitter']:
                self.kpiSplitter.setSizes(self.layout['kpiSplitter'])
            else:
                self.kpiSplitter.setSizes([200, 380])

            if self.layout['hostTableWidth']:
                hostTableWidth = self.layout['hostTableWidth']

                for i in range(self.hostTable.columnCount()):
                    if i > len(hostTableWidth) - 1:
                        break
                    self.hostTable.setColumnWidth(i, hostTableWidth[i])

            if self.layout['KPIsTableWidth']:
                KPIsTableWidth = self.layout['KPIsTableWidth']

                for i in range(self.kpisTable.columnCount()):
                    if i > len(KPIsTableWidth) - 1:
                        break
                    self.kpisTable.setColumnWidth(i, KPIsTableWidth[i])
        else:
            self.mainSplitter.setSizes([300, 90])
            self.kpiSplitter.setSizes([200, 380])

        self.mainSplitter.setAutoFillBackground(True)

        # central widget
        #self.setCentralWidget(mainSplitter)

        kpisWidget.autoFillBackground = True

        self.tabs.addTab(self.mainSplitter, 'Chart')

        self.chartArea.selfRaise.connect(self.raiseTab)
        ind.iClicked.connect(self.chartArea.indicatorSignal)

        self.setCentralWidget(self.tabs)

        # service stuff
        self.statusbar = self.statusBar()
        self.statusbar.addPermanentWidget(ind)

        #menu
        iconPath = resourcePath('ico\\favicon.ico')

        exitAct = QAction('&Exit', self)
        exitAct.setShortcut('Alt+Q')
        exitAct.setStatusTip('Exit application')
        exitAct.triggered.connect(self.menuQuit)

        dummyAct = QAction('&Dummy', self)
        dummyAct.setShortcut('Alt+D')
        dummyAct.setStatusTip('Dummy Data provider')
        dummyAct.triggered.connect(self.menuDummy)

        configAct = QAction('&Connect', self)
        configAct.setShortcut('Alt+C')
        configAct.setStatusTip('Configure connection')
        configAct.triggered.connect(self.menuConfig)

        importAct = QAction('&Import nameserver history trace', self)
        importAct.setShortcut('Ctrl+I')
        importAct.setStatusTip('Import nameserver.trc')
        importAct.triggered.connect(self.menuImport)

        sqlConsAct = QAction('New &SQL Console', self)
        sqlConsAct.setShortcut('Alt+S')
        sqlConsAct.setStatusTip('Create SQL Console')
        sqlConsAct.triggered.connect(self.menuSQLConsole)

        openAct = QAction('&Open file in new sql console', self)
        openAct.setShortcut('Ctrl+O')
        openAct.setStatusTip('Open new console with the file')
        openAct.triggered.connect(self.menuOpen)

        saveAct = QAction('&Save sql to a file', self)
        saveAct.setShortcut('Ctrl+S')
        saveAct.setStatusTip('Saves sql from current console to a file')
        saveAct.triggered.connect(self.menuSave)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(configAct)

        fileMenu.addAction(importAct)
        fileMenu.addAction(sqlConsAct)
        fileMenu.addAction(openAct)
        fileMenu.addAction(saveAct)

        if cfg('experimental'):
            fileMenu.addAction(dummyAct)

        fileMenu.addAction(exitAct)

        actionsMenu = menubar.addMenu('&Actions')

        if cfg('experimental'):
            # fileMenu.addAction(aboutAct) -- print not sure why its here

            fontAct = QAction('&Adjust Fonts', self)
            fontAct.setStatusTip(
                'Adjust margins after font change (for example after move to secondary screen)'
            )
            fontAct.triggered.connect(self.menuFont)

            actionsMenu.addAction(fontAct)

        # issue #255
        reloadConfigAct = QAction('Reload &Config', self)
        reloadConfigAct.setStatusTip(
            'Reload configuration file. Note: some values used during the connect or other one-time-actions (restart required).'
        )
        reloadConfigAct.triggered.connect(self.menuReloadConfig)
        actionsMenu.addAction(reloadConfigAct)

        reloadCustomKPIsAct = QAction('Reload Custom &KPIs', self)
        reloadCustomKPIsAct.setStatusTip('Reload definition of custom KPIs')
        reloadCustomKPIsAct.triggered.connect(self.menuReloadCustomKPIs)

        actionsMenu.addAction(reloadCustomKPIsAct)

        # help menu part
        aboutAct = QAction(QIcon(iconPath), '&About', self)
        aboutAct.setStatusTip('About this app')
        aboutAct.triggered.connect(self.menuAbout)

        confHelpAct = QAction('Configuration', self)
        confHelpAct.setStatusTip('Configuration options description')
        confHelpAct.triggered.connect(self.menuConfHelp)

        confCustomHelpAct = QAction('Custom KPIs', self)
        confCustomHelpAct.setStatusTip('Short manual on custom KPIs')
        confCustomHelpAct.triggered.connect(self.menuCustomConfHelp)

        confTipsAct = QAction('Tips and tricks', self)
        confTipsAct.setStatusTip('Tips and tricks description')
        confTipsAct.triggered.connect(self.menuTips)

        helpMenu = menubar.addMenu('&Help')
        helpMenu.addAction(confHelpAct)

        helpMenu.addAction(confCustomHelpAct)
        helpMenu.addAction(confTipsAct)

        helpMenu.addAction(aboutAct)

        # finalization

        if self.layout is not None and self.layout['pos'] and self.layout[
                'size']:
            pos = self.layout['pos']
            size = self.layout['size']

            #print('screen number', QApplication.desktop().screenNumber())
            #print('number of screens', QApplication.desktop().screenCount())
            #print('available geometry:', QApplication.desktop().availableGeometry())
            #print('screen geometry:', QApplication.desktop().screenGeometry())

            r = QRect(pos[0], pos[1], size[0], size[1])

            if QApplication.desktop().screenCount() == 1:
                # only when just one screen is available...
                if not QApplication.desktop().screenGeometry().contains(
                        r) and not cfg('dontAutodetectScreen'):
                    #the window will not be visible so jump to the main screen:
                    (pos[0], pos[1]) = (100, 50)

            #self.setGeometry(pos[0] + 8, pos[1] + 31, size[0], size[1])
            #self.setGeometry(pos[0], pos[1], size[0], size[1])

            self.move(pos[0], pos[1])
            self.resize(size[0], size[1])
        else:
            self.setGeometry(200, 200, 1400, 800)

        self.setWindowTitle('RybaFish Charts')

        self.setWindowIcon(QIcon(iconPath))

        scrollPosition = []

        if cfg('saveOpenTabs',
               True) and self.layout is not None and self.layout['tabs']:
            for t in self.layout['tabs']:
                if len(t) != 4:
                    continue

                console = sqlConsole.sqlConsole(self, None, '?')

                console.nameChanged.connect(self.changeActiveTabName)
                console.cons.closeSignal.connect(self.closeTab)

                self.tabs.addTab(console, console.tabname)

                ind = indicator()
                console.indicator = ind

                console.selfRaise.connect(self.raiseTab)
                ind.iClicked.connect(console.reportRuntime)

                self.statusbar.addPermanentWidget(ind)

                self.tabs.setCurrentIndex(self.tabs.count() - 1)

                if t[0] is not None or t[1] is not None:
                    # such a tab should not ever be saved (this call will just open fileOpen dialog), anyway...
                    # should we even create such a tab?
                    console.openFile(t[0], t[1])

                    pos = t[2]
                    block = t[3]

                    scrollPosition.append(block)

                    if isinstance(pos, int) and isinstance(block, int):
                        cursor = console.cons.textCursor()
                        cursor.setPosition(pos, cursor.MoveAnchor)
                        console.cons.setTextCursor(cursor)

            indx = self.layout['currentTab']

            if isinstance(indx, int):
                self.tabs.setCurrentIndex(indx)

                w = self.tabs.widget(indx)

                if isinstance(w, sqlConsole.sqlConsole):
                    w.cons.setFocus()

            else:
                self.tabs.setCurrentIndex(0)

        self.show()

        #scroll everything to stored position
        for i in range(self.tabs.count() - 1, 0, -1):
            w = self.tabs.widget(i)
            if isinstance(w, sqlConsole.sqlConsole):

                if i - 1 < len(scrollPosition):
                    block = scrollPosition[i - 1]
                    w.cons.edit.verticalScrollBar().setValue(block)
                else:
                    log('[w] scroll position list out of range, ignoring scrollback...'
                        )
        '''
            set up some interactions
        '''
        # bind kpi checkbox signal
        kpisTable.checkboxToggle.connect(self.chartArea.checkboxToggle)

        # bind change scales signal
        kpisTable.adjustScale.connect(self.chartArea.adjustScale)
        kpisTable.setScale.connect(self.chartArea.setScale)

        # host table row change signal
        self.hostTable.hostChanged.connect(kpisTable.refill)

        # to fill hosts
        self.chartArea.hostsUpdated.connect(self.hostTable.hostsUpdated)

        # refresh
        self.chartArea.kpiToggled.connect(kpisTable.refill)
        # update scales signal
        self.chartArea.scalesUpdated.connect(kpisTable.updateScales)

        log('self.scalesUpdated.emit() #0', 5)
        self.chartArea.scalesUpdated.emit(
        )  # it really not supposed to have any to update here

        #bind statusbox updating signals
        self.chartArea.statusMessage_.connect(self.statusMessage)
        self.chartArea.widget.statusMessage_.connect(self.statusMessage)

        self.chartArea.connected.connect(self.setTabName)
        log('init finish()')

        # offline console tests

        if cfg('developmentMode'):

            #tname = sqlConsole.generateTabName()

            #idx = self.tabs.count()
            self.sqlTabCounter += 1
            idx = self.sqlTabCounter

            if idx > 1:
                tname = 'sql' + str(idx)
            else:
                tname = 'sql'

            console = sqlConsole.sqlConsole(self, None, tname)
            console.nameChanged.connect(self.changeActiveTabName)

            from SQLSyntaxHighlighter import SQLSyntaxHighlighter

            self.tabs.addTab(console, tname)

            console.selfRaise.connect(self.raiseTab)

            self.tabs.setCurrentIndex(self.tabs.count() - 1)

            self.SQLSyntax = SQLSyntaxHighlighter(console.cons.document())
            #console.cons.setPlainText('select * from dummy;\n\nselect \n    *\n    from dummy;\n\nselect * from m_host_information;');

            ind = indicator()
            console.indicator = ind
            self.statusbar.addPermanentWidget(ind)

            ind.iClicked.connect(console.reportRuntime)

            if cfg('developmentMode'):
                console.cons.setPlainText('''select 0 from dummy;
create procedure ...
(
(as begin)
select * from dummy);
end;

where timestamp between '2020-02-10 00:00:00' and '2020-02-16 23:59:59' -- test comment

where not "NAME1" = '' and "DOKST" in ('D0', 'D2') and (1 = 2)

select 1 from dummy;
select 2 from dummy;
select 3 from dummy;''')

            console.dummyResultTable()

        self.statusMessage('', False)

        if self.chartArea.dp:
            self.chartArea.initDP()
示例#5
0
 def initWin(self):
     iptGrid = QGridLayout()
     title = Text("TSP", (255, 0, 0), 16, "center")
     pic = QPixmap("C:\\tsp.png")
     picLbl = QLabel()
     picLbl.setPixmap(pic)
     picLbl.setScaledContents(True)
     titleLayout = QVBoxLayout()
     titleLayout.addWidget(title)
     titleLayout.addWidget(picLbl)
     titleFrame = QFrame()
     titleFrame.setFrameShape(QFrame.StyledPanel)
     titleFrame.setAutoFillBackground(True)
     p5 = titleFrame.palette()
     p5.setColor(titleFrame.backgroundRole(), QColor(255, 255, 255))
     titleFrame.setPalette(p5)
     titleFrame.setLayout(titleLayout)
     iptTitle = Text("Program Input", (255, 0, 0), 12, "center")
     iptTxt1 = QLabel("Cities No:")
     iptTxt1.setFont(QFont("Decorative", 12))
     iptTxt2 = QLabel("start:")
     iptTxt2.setFont(QFont("Decorative", 12))
     self.iptEdt1 = QLineEdit()
     self.iptEdt1.textChanged[str].connect(self.get_input)
     self.iptEdt2 = QLineEdit()
     self.iptEdt2.textChanged[str].connect(self.get_input)
     self.iptBtn1 = QPushButton("Build")
     self.iptBtn1.clicked.connect(self.bulid_map)
     self.iptBtn2 = QPushButton("Rturn")
     self.iptBtn2.clicked.connect(self.get_initial)
     iptH = QHBoxLayout()
     iptH.addWidget(self.iptBtn1)
     iptH.addWidget(self.iptBtn2)
     iptGrid.addWidget(iptTitle, 1, 0, 1, 5)
     iptGrid.addWidget(iptTxt1, 2, 0)
     iptGrid.addWidget(self.iptEdt1, 2, 1)
     iptGrid.addWidget(iptTxt2, 3, 0)
     iptGrid.addWidget(self.iptEdt2, 3, 1)
     iptGrid.setVerticalSpacing(10)
     iptV = QVBoxLayout()
     iptV.addLayout(iptGrid)
     iptV.addLayout(iptH)
     iptFrame = QFrame()
     iptFrame.setAutoFillBackground(True)
     p6 = iptFrame.palette()
     p6.setColor(iptFrame.backgroundRole(), QColor(220, 225, 255))
     iptFrame.setPalette(p6)
     iptFrame.setFrameShape(QFrame.StyledPanel)
     iptFrame.setLayout(iptV)
     srgGrid = QGridLayout()
     #srgGrid.setVerticalSpacing(10)
     srgTitle = Text("Algorithms", (255, 0, 0), 12, "center")
     self.srgBtn1 = QPushButton("Genetic")
     self.srgBtn1.clicked.connect(self.run_algorithm)
     self.srgBtn2 = QPushButton("Simulated")
     self.srgBtn2.clicked.connect(self.run_algorithm)
     self.srgBtn3 = QPushButton("Tabu")
     self.srgBtn3.clicked.connect(self.run_algorithm)
     self.srgBtn4 = QPushButton("reset")
     self.srgBtn4.clicked.connect(self.reset)
     srgGrid.addWidget(srgTitle, 1, 0, 1, 6)
     srgGrid.addWidget(self.srgBtn1, 2, 1, 2, 4)
     srgGrid.addWidget(self.srgBtn2, 3, 1, 3, 4)
     srgGrid.addWidget(self.srgBtn3, 4, 1, 4, 4)
     srgGrid.addWidget(self.srgBtn4, 5, 1, 5, 4)
     srgFrame = QFrame()
     srgFrame.setFrameShape(QFrame.StyledPanel)
     srgFrame.setAutoFillBackground(True)
     p7 = srgFrame.palette()
     p7.setColor(srgFrame.backgroundRole(), QColor(255, 255, 255))
     srgFrame.setPalette(p7)
     srgFrame.setLayout(srgGrid)
     otpGrid = QGridLayout()
     otpTitle = Text("Program Output", (255, 0, 0), 12, "center")
     otpTxt1 = QLabel("The Cost")
     otpTxt1.setFont(QFont("Decorative", 12))
     self.lcd1 = QLCDNumber()
     otpGrid.addWidget(otpTitle, 1, 0, 1, 2)
     otpGrid.addWidget(otpTxt1, 2, 0)
     otpGrid.addWidget(self.lcd1, 2, 1)
     otpFrame = QFrame()
     otpFrame.setFrameShape(QFrame.StyledPanel)
     otpFrame.setAutoFillBackground(True)
     p8 = otpFrame.palette()
     p8.setColor(otpFrame.backgroundRole(), QColor(220, 225, 255))
     otpFrame.setPalette(p8)
     otpFrame.setLayout(otpGrid)
     splitter1 = QSplitter(Qt.Vertical)
     splitter1.addWidget(titleFrame)
     splitter1.addWidget(iptFrame)
     splitter1.setSizes([240, 135])
     splitter2 = QSplitter(Qt.Vertical)
     splitter2.addWidget(srgFrame)
     splitter2.addWidget(otpFrame)
     splitter2.setSizes([200, 92])
     splitter3 = QSplitter(Qt.Vertical)
     splitter3.addWidget(splitter1)
     splitter3.addWidget(splitter2)
     splitter3.setSizes([382, 291])
     splitter3.resize(260, 685)
     splitter3.move(1100, 5)
     splitter3.setParent(self)
     splitter3.setAutoFillBackground(True)
     p3 = splitter3.palette()
     p3.setColor(splitter3.backgroundRole(), QColor(255, 255, 255))
     splitter3.setPalette(p3)
     self.mapFrame = QFrame()
     self.mapFrame.setFrameShape(QFrame.StyledPanel)
     self.mapFrame.move(5, 5)
     self.mapFrame.resize(1090, 685)
     self.mapFrame.setParent(self)
     self.setAutoFillBackground(True)
     p2 = self.palette()
     p2.setColor(self.backgroundRole(), QColor(0, 0, 0))
     self.setPalette(p2)
     self.mapFrame.setParent(self)
     self.hint = Text("Click the bulid button to bulid a random map",
                      (255, 0, 0), 23, "center")
     self.hint.move(230, 100)
     self.hint.setParent(self)
     self.setWindowTitle("TSP")
     self.width = QDesktopWidget().availableGeometry().width()
     self.height = QDesktopWidget().availableGeometry().height() - 40
     self.resize(self.width, self.height)
     self.show()
     self.nodes = {}
     self.points = {}
     self.flag = True