class SummarySection(QTabWidget):
  """
  Represents the summary section.
  Takes reply data from main ui and updates it's tabs
  Keeps track of cumulative summary data.
  """
  def __init__(self, parent=None):
    super(SummarySection, self).__init__(parent)
    self.text_edit_summary = QTextEdit()
    self.text_edit_summary.setReadOnly(True)
    self.addTab(self.text_edit_summary, "Output")
    self.ball_grid = BallGrid(30, 30, 2)
    self.addTab(self.ball_grid, "Led View")
    self.tab_summary = SummaryTab()
    self.addTab(self.tab_summary, "Summary")
    #some private fields, keep track of accumulated summary data
    self.current_ip = 0 #we take reply data for ips in order
    self.sent_packets = 0
    self.received_packets = 0
    self.average_delay = 0
    
  def setIPs(self, ips):
    #this indicates the start of a new ping, could be treated
    #as a pingStarted signal
    self.current_ip = 0
    self.sent_packets = 0
    self.received_packets = 0
    self.average_delay = 0
    self.text_edit_summary.clear()
    self.ball_grid.layoutForIps(ips)
    self.tab_summary.zeroOut()
  
  def takeReplyData(self, replyData, sentPackets): #sent packets is passed in as extra
    """
    Update the output text area with the replyData string representation
    Set proper widget states on the BallGrid
    Calculate summaries cumulatively and set them for display on the summary tab 
    """
    self.text_edit_summary.append(str(replyData))
    packets_lost = replyData.packets_lost
    if packets_lost:
      self.ball_grid.setStateAt(self.current_ip, BallWidget.UNREACHABLE)
    else:
      self.ball_grid.setStateAt(self.current_ip, BallWidget.REACHABLE)
    self.current_ip += 1
    self.sent_packets += sentPackets 
    self.received_packets = self.sent_packets - replyData.packets_lost
    self.average_delay += (replyData.rtt / self.current_ip) #the current_ip reflects the overall number of replies
    summary_data = SummaryData(self.sent_packets, self.received_packets, self.average_delay)
    self.tab_summary.setSummaryData(summary_data)
    
  def pingingStoppedHandler(self):
    self.ball_grid.pingingCancelledHandler()
Пример #2
0
class Console():
    def __init__(self, targetLayoutContainer):
        self.textarea = QTextEdit()
        self.commits = QListWidget()
        
        self.commits.addAction(QAction('Rollback to this revision', self.commits, triggered=self.rollback))
        self.commits.setContextMenuPolicy(Qt.ActionsContextMenu)
        
        self.widget = QTabWidget()
        self.widget.addTab(self.textarea, 'Log')
        self.widget.addTab(self.commits, 'Commits')
        
        targetLayoutContainer.addWidget(self.widget)
        
    def color(self, module, function, color,  *args):
        print module, function, args
        
        prettyString = '<font color="' + color + '"><b>', module, '</b><i>::', function, '</i> --> ', ''.join(args), '</font>'
        self.textarea.append(''.join(prettyString))    
        
    def info(self, module, function, *args):
        print module, function, args
        
        prettyString = '<font color="black"><b>', module, '</b><i>::', function, '</i> --> ', ''.join(args), '</font>'
        self.textarea.append(''.join(prettyString))
        
    def error(self, module, function, *args):
        print module, function, args
        
        prettyString = '<font color="red"><b>', module, '</b><i>::', function, '</i> --> ', ''.join(args), '</font>'
        self.textarea.append(''.join(prettyString))
        
    def warn(self, module, function, *args):
        print module, function, args
        
        prettyString = '<font color="#BE9900"><b>', module, '</b><i>::', function, '</i> --> ', ''.join(args), '</font>'
        self.textarea.append(''.join(prettyString))
        
    def set_commits(self, commits):
        self.commits.clear()
        
        for commit in commits:
            self.commits.addItem(commit)
            
    def clear(self):
        self.textarea.clear()
        
    def rollback(self):
        targetCommit = self.commits.currentItem().text().split(' ')[0]
        if QMessageBox.warning(None, 'Rollback to commit?', 'All commits after ' + targetCommit + ' will be lost, proceed?', QMessageBox.Yes, QMessageBox.No) == QMessageBox.Yes:
            rollback(targetCommit)
Пример #3
0
class CardBordAIApp(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("CardBord AI Demo ver0.10")
        self.operator = Operator()

        self.setupUi()

        self.operator.speach.connect(self.speak_ai)

        self.init()

    def setupUi(self):
        self.mainlayout = QVBoxLayout(self)

        self.title = QLabel("CardBord Operator", self)
        self.mainlayout.addWidget(self.title)

        self.user_txtarea = QTextEdit(self)
        self.ai_txtarea = QTextEdit(self)

        self.users_edit_title = QLabel("質問に答えてください")
        self.users_edit = QLineEdit("", self)

        self.txtarea_layout = QHBoxLayout()

        self.txtarea_layout.addWidget(self.user_txtarea)
        self.txtarea_layout.addWidget(self.ai_txtarea)

        self.mainlayout.addLayout(self.txtarea_layout)
        self.mainlayout.addWidget(self.users_edit_title)
        self.mainlayout.addWidget(self.users_edit)

        self.send_btn = QPushButton("send", self)
        self.send_btn.setObjectName("send_btn")
        self.mainlayout.addWidget(self.send_btn)

        QMetaObject.connectSlotsByName(self)

    def init(self):
        # Talkエリアの初期化
        self.user_txtarea.clear()
        self.ai_txtarea.clear()
        # オペレータ初期化、初期ワード取得
        self.operator.init()

    @Slot()
    def on_send_btn_clicked(self):
        # UI処理
        user_word = self.users_edit.text()
        if user_word == "":
            return None
        self.users_edit.clear()
        self.user_txtarea.append(user_word)

        # サーバー(エンジン)へユーザワードを送信
        self.operator.send(user_word)

    @Slot()
    def speak_ai(self, word):
        # AIのトークを表示
        # ディレイを使ってテンポを整える
        def wrapper():
            self.ai_txtarea.append(word)

        QTimer.singleShot(TALK_DELAY, wrapper)
Пример #4
0
class CustomWidget(QtGui.QMainWindow):
    def __init__(self):
        """
        Constructor
        """
        QtGui.QMainWindow.__init__(self)
        self.name = "Custom widget"
        self.central_widget = QtGui.QWidget()
        self.setCentralWidget(self.central_widget)

        # TODO: This is ugly, improve it
        self.iconp = JConfig().icons_path

        self._createLayout()

    def _createGui(self):
        """
        Subclasses must override this
        depending on the elements they want to add
        self._createOutputTree(),
        self._createOutputTable(),
        self._createOutputWindow() and add them to
        the corresponding layouts.
        """
        raise NotImplementedError

    def _createToolBar(self, name):
        """
        Subclasses need to define the
        specific Actions
        """
        self.toolbar = self.addToolBar(name)
        self.toolbar.setMovable(False)

    def _createLayout(self):
        """
        This creates the basic layout:
        Buttons & Outputs
        """

        # Layouts (This is a common disposition)
        main_layout = QtGui.QVBoxLayout()
        self.button_layout = QtGui.QHBoxLayout()
        output_layout = QtGui.QVBoxLayout()

        # You will need to create your buttons
        # and add them to your layout like this:
        # self.button_layout.addWidget(button_1)

        # Output Layout Inner (QSplitter)
        # Add as many widgets as you please
        # They will be ordered vertically and
        # be resizable by the user
        # self.splitter.addWidget(self.table_label)
        # self.splitter.addWidget(...)
        self.splitter = QSplitter(QtCore.Qt.Vertical)

        # Nested layouts
        main_layout.addLayout(self.button_layout)
        output_layout.addWidget(self.splitter)
        main_layout.addLayout(output_layout)
        self.central_widget.setLayout(main_layout)

    def _createOutputWindow(self):
        """
        Some binary analysis commands will output to this.
        """

        self.output_label = QtGui.QLabel('Output')

        self.output_window = QTextEdit()
        self.output_window.setFontPointSize(10)
        self.output_window.setReadOnly(True)
        # Save it for later use
        self.output_window.original_textcolor = self.output_window.textColor()

    def _createOutputTable(self):
        """
        A vanilla QTableWidget. Callbacks modify
        its properties, like number of columns, etc.
        """
        self.table_label = QtGui.QLabel('Table Output')

        self.table = QTableWidget()
        self.table.setColumnCount(3)
        self.table.setColumnWidth(0, 100)
        self.table.setColumnWidth(1, 300)
        self.table.setColumnWidth(2, 300)

        self.table.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)

        # Connect signals to slots
        self.table.customContextMenuRequested.connect(self._tablePopup)
        self.table.horizontalHeader().sectionDoubleClicked.connect(
            self._tableHeaderDoubleClicked)
        self.table.cellDoubleClicked.connect(self._tableCellDoubleClicked)

    def _createOutputTree(self):
        """
        A QtreeWidget. Initially used to display those pesky
        dword comparison to immediate values.
        """
        self.tree_label = QtGui.QLabel('Tree Output')

        self.tree = QTreeWidget()
        self.tree.setColumnCount(3)
        self.tree.setColumnWidth(0, 150)
        self.tree.setColumnWidth(1, 150)
        self.tree.setColumnWidth(2, 50)

        # Connect signals to slots
        self.tree.itemDoubleClicked.connect(self._treeElementDoubleClicked)

    #################################################################
    # GUI Callbacks
    #################################################################
    def _console_output(self, s="", err=False):
        """
        Convenience wrapper
        """
        if err:
            # Error message
            err_color = QColor('red')
            self.output_window.setTextColor(err_color)
            self.output_window.append(s)
            # restore original color
            self.output_window.setTextColor(
                self.output_window.original_textcolor)

        else:
            self.output_window.append(s)

    def _tableCellDoubleClicked(self, row, col):
        """
        Most of the info displayed in QTableWidgets represent addresses.
        Default action: try to jump to it.
        """
        it = self.table.item(row, col).text()

        try:
            addr = int(it, 16)
            jump_to_address(addr)

        except ValueError:
            self._console_output("[!] That does not look like an address...",
                                 err=True)
            return

    def _tablePopup(self, pos):
        """
        Popup menu activated clicking the secondary
        button on the table
        """
        menu = QtGui.QMenu()

        # Add menu entries
        delRow = menu.addAction(QIcon(self.iconp + "close.png"), "Delete Row")
        selItem = menu.addAction(QIcon(self.iconp + "bookmark.png"),
                                 "Mark entry")
        menu.addSeparator()
        origFunc = menu.addAction(QIcon(self.iconp + "lightning.png"),
                                  "Select origin function")
        destFunc = menu.addAction(QIcon(self.iconp + "flag.png"),
                                  "Select destination function")

        # Get entry clicked
        action = menu.exec_(self.mapToGlobal(pos))

        # Dispatch :)
        if action == delRow:
            self.table.removeRow(self.table.currentRow())

        elif action == selItem:
            self.table.currentItem().setBackground(QtGui.QColor('red'))

        elif action == origFunc:
            try:
                addr = self.table.currentItem().text()
                InfoUI.function_orig_ea = int(addr, 16)

            except:
                self._console_output("This does not look like an address...",
                                     err=True)

        elif action == destFunc:
            try:
                addr = self.table.currentItem().text()
                InfoUI.function_dest_ea = int(addr, 16)

            except:
                self._console_output("This does not look like an address...",
                                     err=True)

    def _tableHeaderDoubleClicked(self, index):
        """
        Used to sort the contents
        """
        self.table.sortItems(index, order=QtCore.Qt.AscendingOrder)

    def _treeElementDoubleClicked(self, item, column):
        """
        QTreeWidgetElement callback. Basically it jumps to
        the selected address in IDA disassembly window.
        """
        try:
            # Only interested in addresses
            addr_int = int(item.text(column), 16)
            jump_to_address(addr_int)
            # Paint some color
            item.setBackground(column, QtGui.QColor('green'))

        except:
            self._console_output("[!] That does not look like an address...",
                                 err=True)
Пример #5
0
class Dialog(QWidget):

    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)
        self.setupUI()
        self.setupConnection()
        self.threadPool = []
        self.totalUids = 0
        self.finishedThreadNum = 0
        self.realThreadNum = 0
        self.excel = Excel()
        #self.initSearchDb()

    def setupUI(self):

        self.pushButton = QPushButton(u"Search", self)
        #self.testButton = QPushButton(u"Test", self)
        self.lineEdit = QLineEdit(self)
        self.textEdit = QTextEdit(self)
        self.comboBox = QComboBox(self)
        self.label = QLabel(u"DB:", self)
        self.progressBar = QProgressBar(self)
        self.progressBar.setRange(0,1)
        
        self.textEdit.setReadOnly(True)

        self.layout = QVBoxLayout()
        self.topLayout = QHBoxLayout()
        
        self.topLayout.addWidget(self.label)
        self.topLayout.addWidget(self.comboBox)
        self.topLayout.addWidget(self.lineEdit)
        self.topLayout.addWidget(self.pushButton)
        #self.topLayout.addWidget(self.testButton)

        #self.testButton.clicked.connect(self.onTestButtonClicked)

        self.layout.addLayout(self.topLayout)
        self.layout.addWidget(self.textEdit)
        self.layout.addWidget(self.progressBar)

        self.setLayout(self.layout)

        self.resize(600, 700)
        self.setWindowTitle(u"Search Data for NCBI")

    def setupConnection(self):
        self.pushButton.clicked.connect(self.onButtonClicked)

    def onButtonClicked(self):
        if not self.lineEdit.text() or not self.comboBox.count():
            QtGui.QMessageBox.information(self, u"Warning", u"Please Set the Search Field")
            return
        # disable button
        self.pushButton.setDisabled(True)
        dbName = self.comboBox.currentText()
        fieldName = self.lineEdit.text()
        self.log("Start searching db: %s and field: %s" % (dbName, fieldName))
        # add use history to add all uids to the history server
        handle = self.entrez.esearch(db=dbName, term=fieldName, usehistory='y')
        record = self.entrez.read(handle)
        self.log("All result count %s" % record['Count'])
        self.totalUids = int(record['Count'])
        # to get onnly data less than the MAX_COUNT
        if self.totalUids > MAX_COUNT:
            ret = QtGui.QMessageBox.question(
                    self,
                    u'Warning',
                    u'result count %s is too large, will only get the %s result \
                            continue?' % (self.totalUids, MAX_COUNT),
                            QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel
                            )
            if ret == QtGui.QMessageBox.Ok:
                self.totalUids = MAX_COUNT
            else:
                return
        #handle = self.entrez.efetch(db=dbName, id=record['IdList'], rettype='gb')
        self.finishedThreadNum = 0
        WebEnv = record['WebEnv']
        QueryKey = record['QueryKey']
        global FINISHED_COUNT
        FINISHED_COUNT = 0
        self.progressBar.setValue(0)
        self.progressBar.setMaximum(self.totalUids)
        if self.totalUids / RET_MAX_SUMMARY >= MAX_THREAD:
            self.realThreadNum = MAX_THREAD
            each_count = self.totalUids/MAX_THREAD
            startIndex = 0
            for i in range(MAX_THREAD - 1):
                thread = MyThread(startIndex, each_count, dbName, fieldName, WebEnv, QueryKey)
                thread.finished.connect(self.onThreadFinished)
                thread.finishedCountChanged.connect(self.onFinishedCountChange)
                thread.start()
                self.threadPool.append(thread)
                startIndex = startIndex + each_count
            thread = MyThread(startIndex, (self.totalUids-startIndex+1), dbName, fieldName, WebEnv, QueryKey)
            thread.finished.connect(self.onThreadFinished)
            thread.finishedCountChanged.connect(self.onFinishedCountChange)
            self.threadPool.append(thread)
            thread.start()
        else:
            if self.totalUids == RET_MAX_SUMMARY:
                self.realThreadNum = 1
            else:
                self.realThreadNum = self.totalUids/RET_MAX_SUMMARY + 1
            startIndex = 0
            for i in range(self.realThreadNum):
                thread = MyThread(startIndex, RET_MAX_SUMMARY, dbName, fieldName, WebEnv, QueryKey)
                thread.finished.connect(self.onThreadFinished)
                thread.finishedCountChanged.connect(self.onFinishedCountChange)
                self.threadPool.append(thread)
                thread.start()
                startIndex = startIndex + RET_MAX_SUMMARY
        self.log("thread num: %s" % self.realThreadNum)
        self.log('reading data')
        self.filename = '%s_%s_output.xls' % (dbName, fieldName)
        self.excel.setFilename(self.filename)

    def log(self, context):
        self.textEdit.append(context)

    def initSearchDb(self):
        self.entrez = Entrez 
        self.entrez.email = email
        self.log("Connect to NCBI")
        try:
            handle = self.entrez.einfo()
        except:
            QtGui.QMessageBox.warning(self, u"Error", u"Error Connect the WebSite")
            self.close()
        record = self.entrez.read(handle)
        self.log("Get NCBI DataBases:")
        for name in record['DbList']:
            self.log('DBName:\t%s' % name)
        self.comboBox.addItems(record['DbList'])

    def onThreadFinished(self):
        self.finishedThreadNum = self.finishedThreadNum + 1
        self.log('finished thread %s ' % self.finishedThreadNum)
        if(self.finishedThreadNum == self.realThreadNum):
            global all_output
            heads = all_output[0][0].keys()
            self.excel.setHead(heads)
            for values in all_output:
                for value in values:
                    self.excel.addValues(value)
            self.excel.save()
            self.progressBar.setValue(int(self.totalUids))
            # clear all thread
            self.threadPool = []
            all_output = []
            self.excel.clearValues()
            self.pushButton.setDisabled(False)
            self.log("output to file: %s" % self.filename)

    def onFinishedCountChange(self, num):
        self.progressBar.setValue(num)

    def onTestButtonClicked(self):
        self.finishedThreadNum = 0
        self.realThreadNum = 1
        self.thread = MyThread(0, 10,"abd","123")
        self.thread.finished.connect(self.onThreadFinished)
        self.thread.startIndex()
Пример #6
0
class TransferPanel(QWidget):
    '''
    Transfer Panel
    
    This Panel is the main dialog box for the Dive Computer Transfer GUI
    '''
    def __init__(self, parent=None):
        super(TransferPanel, self).__init__(parent)
        
        self._logbook = None
        self._logbookName = 'None'
        self._logbookPath = None
        
        self._createLayout()
        
        self._readSettings()
        self.setWindowTitle(self.tr('DC Transfer - %s') % self._logbookName)
        
    def _createLayout(self):
        'Create the Widget Layout'
        
        self._txtLogbook = QLineEdit()
        self._txtLogbook.setReadOnly(True)
        self._lblLogbook = QLabel(self.tr('&Logbook File:'))
        self._lblLogbook.setBuddy(self._txtLogbook)
        self._btnBrowse = QPushButton('...')
        self._btnBrowse.clicked.connect(self._btnBrowseClicked)
        self._btnBrowse.setStyleSheet('QPushButton { min-width: 24px; max-width: 24px; }')
        self._btnBrowse.setToolTip(self.tr('Browse for a Logbook'))
        
        self._cbxComputer = QComboBox()
        self._lblComputer = QLabel(self.tr('Dive &Computer:'))
        self._lblComputer.setBuddy(self._cbxComputer)
        self._btnAddComputer = QPushButton(QPixmap(':/icons/list-add.png'), self.tr(''))
        self._btnAddComputer.setStyleSheet('QPushButton { min-width: 24px; min-height: 24; max-width: 24px; max-height: 24; }')
        self._btnAddComputer.clicked.connect(self._btnAddComputerClicked)
        self._btnRemoveComputer = QPushButton(QPixmap(':/icons/list-remove.png'), self.tr(''))
        self._btnRemoveComputer.setStyleSheet('QPushButton { min-width: 24px; min-height: 24; max-width: 24px; max-height: 24; }')
        self._btnRemoveComputer.clicked.connect(self._btnRemoveComputerClicked)
        
        hbox = QHBoxLayout()
        hbox.addWidget(self._btnAddComputer)
        hbox.addWidget(self._btnRemoveComputer)
        
        gbox = QGridLayout()
        gbox.addWidget(self._lblLogbook, 0, 0)
        gbox.addWidget(self._txtLogbook, 0, 1)
        gbox.addWidget(self._btnBrowse, 0, 2)
        gbox.addWidget(self._lblComputer, 1, 0)
        gbox.addWidget(self._cbxComputer, 1, 1)
        gbox.addLayout(hbox, 1, 2)
        gbox.setColumnStretch(1, 1)
        
        self._pbTransfer = QProgressBar()
        self._pbTransfer.reset()
        self._txtStatus = QTextEdit()
        self._txtStatus.setReadOnly(True)
        
        self._btnTransfer = QPushButton(self.tr('&Transfer Dives'))
        self._btnTransfer.clicked.connect(self._btnTransferClicked)
        
        self._btnExit = QPushButton(self.tr('E&xit'))
        self._btnExit.clicked.connect(self.close)
        
        hbox = QHBoxLayout()
        hbox.addWidget(self._btnTransfer)
        hbox.addStretch()
        hbox.addWidget(self._btnExit)
        
        vbox = QVBoxLayout()
        vbox.addLayout(gbox)
        vbox.addWidget(self._pbTransfer)
        vbox.addWidget(self._txtStatus)
        vbox.addLayout(hbox)
        
        self.setLayout(vbox)
        
    def _closeLogbook(self):
        'Close the current Logbook'
        if self._logbook is None:
            return
        
        self._logbook = None
        self._logbookName = 'None'
        self._logbookPath = None
        
        self._txtLogbook.clear()
        self._cbxComputer.setModel(None)
        
        self._writeSettings()
        self.setWindowTitle(self.tr('DC Transfer - %s') % self._logbookName)
        
    def _openLogbook(self, path):
        'Open an existing Logbook'
        if self._logbook is not None:
            self._closeLogbook()
            
        if not os.path.exists(path):
            QMessageBox.critical(self, self.tr('Missing Logbook'), 
                self.tr('Logbook File "%s" does not exist.') % path)
            return
        
        #TODO: Handle a Schema Upgrade in a user-friendly manner
        self._logbook = Logbook(path, auto_update=False)
        self._logbookName = os.path.basename(path)
        self._logbookPath = path
        
        self._txtLogbook.setText(self._logbookPath)
        self._cbxComputer.setModel(DiveComputersModel(self._logbook))
        
        self._writeSettings()
        self.setWindowTitle(self.tr('DC Transfer - %s') % self._logbookName)
        
    def _readSettings(self):
        'Read main window settings from the configuration'
        settings = QSettings()
        settings.beginGroup('MainWindow')
        max = settings.value('max')
        size = settings.value('size')
        pos = settings.value('pos')
        file = settings.value('file')
        settings.endGroup()
        
        # Size and Position the Main Window
        if size is not None:
            self.resize(size)
        if pos is not None:
            self.move(pos)
            
        # HAX because QVariant is not exposed in PySide and the default
        # coercion to string is just stupid
        if max is not None and (max == 'true'):
            self.showMaximized()
        
        # Open the Logbook
        if file is not None:
            self._openLogbook(file)
        
    def _writeSettings(self):
        'Write settings to the configuration'
        settings = QSettings()
        settings.beginGroup('MainWindow')
        settings.setValue('pos', self.pos())
        settings.setValue('size', self.size())
        settings.setValue('max', self.isMaximized())
        settings.setValue('file', self._logbookPath)
        settings.endGroup()
        
    def closeEvent(self, e):
        'Intercept an OnClose event'
        self._writeSettings()
        e.accept()
        
    #--------------------------------------------------------------------------
    # Slots
    
    @QtCore.Slot()
    def _btnAddComputerClicked(self):
        'Add a Dive Computer'
        dc = AddDiveComputerWizard.RunWizard(self)
        
        if dc is not None:
            self._logbook.session.add(dc)
            self._logbook.session.commit()
            self._cbxComputer.model().reload()
            self._cbxComputer.setCurrentIndex(self._cbxComputer.findText(dc.name))
    
    @QtCore.Slot()
    def _btnRemoveComputerClicked(self):
        'Remove a Dive Computer'
        idx = self._cbxComputer.currentIndex()
        dc = self._cbxComputer.itemData(idx, Qt.UserRole+0)
        if QMessageBox.question(self, self.tr('Delete Dive Computer?'), 
                    self.tr('Are you sure you want to delete "%s"?') % dc.name,
                    QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) == QMessageBox.Yes:
            self._logbook.session.delete(dc)
            self._logbook.session.commit()
            self._cbxComputer.model().reload()
    
    @QtCore.Slot()
    def _btnBrowseClicked(self):
        'Browse for a Logbook File'
        if self._logbook is not None:
            dir = os.path.dirname(self._logbookPath)
        else:
            dir = os.path.expanduser('~')
        
        fn = QFileDialog.getOpenFileName(self,
            caption=self.tr('Select a Logbook file'), dir=dir,
            filter='Logbook Files (*.lbk);;All Files(*.*)')[0]    
        if fn == '':
            return
        if not os.path.exists(fn):
            if QMessageBox.question(self, self.tr('Create new Logbook?'), 
                    self.tr('Logbook "%s" does not exist. Would you like to create it?') % os.path.basename(fn),
                    QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) != QMessageBox.Yes:
                return
            Logbook.Create(fn)
        self._openLogbook(fn)
        
    @QtCore.Slot()
    def _btnTransferClicked(self):
        'Transfer Dives'
        idx = self._cbxComputer.currentIndex()
        dc = self._cbxComputer.itemData(idx, Qt.UserRole+0)
        
        if self._logbook.session.dirty:
            print "Flushing dirty session"
            self._logbook.rollback()
        
        self._txtLogbook.setEnabled(False)
        self._btnBrowse.setEnabled(False)
        self._cbxComputer.setEnabled(False)
        self._btnAddComputer.setEnabled(False)
        self._btnRemoveComputer.setEnabled(False)
        self._btnTransfer.setEnabled(False)
        self._btnExit.setEnabled(False)
        
        self._txtStatus.clear()
        
        thread = QThread(self)
        
        #FIXME: ZOMG HAX: Garbage Collector will eat TransferWorker when moveToThread is called
        #NOTE: Qt.QueuedConnection is important...
        self.worker = None
        self.worker = TransferWorker(dc)
        thread.started.connect(self.worker.start, Qt.QueuedConnection)
        self.worker.moveToThread(thread)
        self.worker.finished.connect(self._transferFinished, Qt.QueuedConnection)
        self.worker.finished.connect(self.worker.deleteLater, Qt.QueuedConnection)
        self.worker.finished.connect(thread.deleteLater, Qt.QueuedConnection)
        self.worker.progress.connect(self._transferProgress, Qt.QueuedConnection)
        self.worker.started.connect(self._transferStart, Qt.QueuedConnection)
        self.worker.status.connect(self._transferStatus, Qt.QueuedConnection)
        
        thread.start()
        
    @QtCore.Slot(str)
    def _transferStatus(self, msg):
        'Transfer Status Message'
        self._txtStatus.append(msg)
        
    @QtCore.Slot(int)
    def _transferStart(self, nBytes):
        'Transfer Thread Stated'
        if nBytes > 0:
            self._pbTransfer.setMaximum(nBytes)
        else:
            self._pbTransfer.setMaximum(100)
        self._pbTransfer.reset()
        
    @QtCore.Slot(int)
    def _transferProgress(self, nTransferred):
        'Transfer Thread Progress Event'
        self._pbTransfer.setValue(nTransferred)
        
    @QtCore.Slot(models.Dive)
    def _transferParsed(self, dive):
        'Transfer Thread Parsed Dive'
        self._logbook.session.add(dive)
        
    @QtCore.Slot()
    def _transferFinished(self):
        'Transfer Thread Finished'
        self._logbook.session.commit()
        
        self._txtLogbook.setEnabled(True)
        self._btnBrowse.setEnabled(True)
        self._cbxComputer.setEnabled(True)
        self._btnAddComputer.setEnabled(True)
        self._btnRemoveComputer.setEnabled(True)
        self._btnTransfer.setEnabled(True)
        self._btnExit.setEnabled(True)
Пример #7
0
class QLogger(logging.Handler):
    '''Code from:
  https://stackoverflow.com/questions/28655198/best-way-to-display-logs-in-pyqt
  '''
    def __init__(self,
                 parent=None,
                 format=settings.log_fmt,
                 level=logging.INFO):
        logging.Handler.__init__(self)
        # Initialize a log handler as the super class
        self.setFormatter(logging.Formatter(format))
        # Set the formatter for the logger
        self.setLevel(level)
        # Set the logging level
        self.frame = QFrame(parent)
        # Initialize a QFrame to place other widgets in

        self.frame2 = QFrame(parent)
        # Initialize frame2 for the label and checkbox
        self.label = QLabel('Logs')
        # Define a label for the frame
        self.check = QCheckBox('Debugging')
        # Checkbox to enable debugging logging
        self.check.clicked.connect(self.__changeLevel)
        # Connect checkbox clicked to the __changeLevel method

        self.log_widget = QTextEdit()
        # Initialize a QPlainTextWidget to write logs to
        self.log_widget.verticalScrollBar().minimum()
        # Set a vertical scroll bar on the log widget
        self.log_widget.horizontalScrollBar().minimum()
        # Set a horizontal scroll bar on the log widget
        self.log_widget.setLineWrapMode(self.log_widget.NoWrap)
        # Set line wrap mode to no wrapping
        self.log_widget.setFont(QFont("Courier", 12))
        # Set the font to a monospaced font
        self.log_widget.setReadOnly(True)
        # Set log widget to read only

        layout = QHBoxLayout()
        # Initialize a horizontal layout scheme for the label and checkbox frame
        layout.addWidget(self.label)
        # Add the label to the layout scheme
        layout.addWidget(self.check)
        # Add the checkbox to the layout scheme
        self.frame2.setLayout(layout)
        # Set the layout for frame to the horizontal layout

        layout = QVBoxLayout()
        # Initialize a layout scheme for the widgets
        layout.addWidget(self.frame2)
        # Add the label/checkbox frame to the layout scheme
        layout.addWidget(self.log_widget)
        # Add the text widget to the layout scheme

        self.frame.setLayout(layout)
        # Set the layout of the fram to the layout scheme defined

    ##############################################################################
    def emit(self, record):
        '''
    Overload the emit method so that it prints to the text widget
    '''
        msg = self.format(record)
        # Format the message for logging
        if record.levelno >= logging.CRITICAL:  # If the log level is critical
            self.log_widget.setTextColor(Qt.red)
            # Set text color to red
        elif record.levelno >= logging.ERROR:  # Elif level is error
            self.log_widget.setTextColor(Qt.darkMagenta)
            # Set text color to darkMagenta
        elif record.levelno >= logging.WARNING:  # Elif level is warning
            self.log_widget.setTextColor(Qt.darkCyan)
            # Set text color to darkCyan
        else:  # Else
            self.log_widget.setTextColor(Qt.black)
            # Set text color to black
        self.log_widget.append(msg)
        # Add the log to the text widget

    ##############################################################################
    def write(self, m):
        '''
    Overload the write method so that it does nothing
    '''
        pass

    ##############################################################################
    def __changeLevel(self, *args):
        '''
    Private method to change logging level
    '''
        if self.check.isChecked():
            self.setLevel(logging.DEBUG)
            # Get the Meso1819 root logger and add the handler to it
        else:
            self.setLevel(logging.INFO)
Пример #8
0
class qNotebook(QVBoxLayout):
    def __init__(self):
        QVBoxLayout.__init__(self)
        self._teditor = QTextEdit()
        self._teditor.setMinimumWidth(500)
        self._teditor.setStyleSheet("font: 12pt \"Courier\";")
        button_layout = QHBoxLayout()
        self.addLayout(button_layout)
        self.clear_but = qmy_button(button_layout, self.clear_all, "clear")
        self.copy_but = qmy_button(button_layout, self._teditor.copy, "copy")
        qmy_button(button_layout, self._teditor.selectAll, "select all")
        qmy_button(button_layout, self._teditor.undo, "undo")
        qmy_button(button_layout, self._teditor.redo, "redo")
        search_button = qButtonWithArgumentsClass("search", self.search_for_text, {"search_text": ""})
        button_layout.addWidget(search_button)
        qmy_button(button_layout, self.save_as_html, "save notebook")
        
        self.addWidget(self._teditor)
        self._teditor.document().setUndoRedoEnabled(True)
        self.image_counter = 0
        self.image_dict = {}
        self.image_data_dict = {}
        
    def append_text(self, text):
        self._teditor.append(str(text))
        
    def search_for_text(self, search_text = " "):
        self._teditor.find(search_text)
        
    def clear_all(self):
        self._teditor.clear()
        self.image_dict = {}
        self.image_counter = 0
#        newdoc = QTextDocument()
#        self._teditor.setDocument(newdoc)
        
    def append_image(self, fig=None):
        #This assumes that an image is there waiting to be saved from matplotlib
        self.imgdata = StringIO.StringIO()
        if fig is None:
            pyplot.savefig(self.imgdata, transparent = False, format = img_format)
        else:
            fig.savefig(self.imgdata, transparent = False, format = img_format)
        self.abuffer = QBuffer()
        self.abuffer.open(QBuffer.ReadWrite)
        self.abuffer.write(self.imgdata.getvalue())
        self.abuffer.close()
        
        self.abuffer.open(QBuffer.ReadOnly)
        iReader = QImageReader(self.abuffer, img_format )
        the_image = iReader.read()
        # the_image = the_image0.scaledToWidth(figure_width)
        
        # save the image in a file
        imageFileName = "image" + str(self.image_counter) + "." + img_format
        self.image_data_dict[imageFileName] = self.imgdata
        
        self.image_counter +=1
        imageFormat = QTextImageFormat()
        imageFormat.setName(imageFileName)
        imageFormat.setWidth(image_width)
        self.image_dict[imageFileName] = the_image
        
        #insert the image in the text document
        text_doc = self._teditor.document()
        text_doc.addResource(QTextDocument.ImageResource, QUrl(imageFileName), the_image)
        cursor = self._teditor.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertImage(imageFormat)
        
    def add_image_data_resource(self, imgdata, imageFileName):
        
        self.abuffer = QBuffer()
        self.abuffer.open(QBuffer.ReadWrite)
        self.abuffer.write(imgdata.getvalue())
        self.abuffer.close()
        
        self.abuffer.open(QBuffer.ReadOnly)
        iReader = QImageReader(self.abuffer, img_format )
        the_image = iReader.read()
        # the_image = the_image0.scaledToWidth(figure_width)
        
        # save the image in a file
        # imageFileName = "image" + str(self.image_counter) + "." + img_format
        self.image_data_dict[imageFileName] = imgdata
        
        # self.image_counter +=1
        imageFormat = QTextImageFormat()
        imageFormat.setName(imageFileName)
        imageFormat.setWidth(image_width)
        self.image_dict[imageFileName] = the_image
        
        #insert the image in the text document
        text_doc = self._teditor.document()
        text_doc.addResource(QTextDocument.ImageResource, QUrl(imageFileName), the_image)
        
    
    def append_html_table_from_array(self, a, header_rows=0, precision = 3, caption = None, cmap = None):
        nrows = len(a)
        ncols = len(a[0])
        result_string = "<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n"
        if caption != None:
            result_string += "<caption>%s</caption>\n"  % caption
        r = 0
        while r < header_rows:
            result_string += "<tr>"
            for c in range(ncols):
                if a[r][c] != "":
                    # count following blank columns
                    count = 1
                    while ((c+count) < len(a[r])) and (a[r][c+count] == "") :
                        count += 1
                    val = a[r][c]
                    if (type(val) == numpy.float64) or (type(val) == float):  # @UndefinedVariable
                        if precision != 999:
                            val = round(val, precision)
                    if count > 1:
                        result_string +="<th colspan=%s>%s</th>"  % (count, val)
                    else:
                        result_string += "<th>%s</th>"  % val
            result_string +="</tr>\n"
            r += 1
        while r < nrows:
            result_string += "<tr>"
            for c in range(ncols):
                val = a[r][c]
                if (cmap == None):
                    fcolor = "#ffffff"
                elif (type(val) == int) or (type(val) == float) or (type(val) == numpy.float64):  # @UndefinedVariable
                    fcolor = cmap.color_from_val(val)
                else:
                    fcolor = "#ffffff"
      
                if (val != "") or (c == 0):
                    if (type(val) == numpy.float64) or (type(val) == float): # @UndefinedVariable
                        if precision != 999:
                            val = round(val, precision)
                    count = 1
                    while ((c+count) < len(a[r])) and (a[r][c+count] == "") :
                        count += 1
                    if count > 1:
                        result_string +="<td colspan=%s bgcolor=%s>%s</td>"  % (count, fcolor, val)
                    else:
                        result_string += "<td bgcolor=%s>%s</td>" % (fcolor, val)
            result_string +="</tr>\n"
            r += 1
        result_string += "</table>\n"
        self.append_text(result_string)
        
    def create_empty_string_array(self, rows, cols):
        table_array = []
        for r in range(rows): #@UnusedVariable
            the_row = []
            for c in range(cols): #@UnusedVariable
                the_row.append("")
            table_array.append(the_row)
        return table_array
    
    def recurse_on_dict_headers(self, sdict, r, c, sorted_headers = None):
        if ((type(sdict) != dict) and (type(sdict) != OrderedDict)):
            return c + 1
        else:
            if sorted_headers != None:
                sheaders = sorted_headers
            else:
                sheaders = sorted(sdict.keys())
            for k in sheaders:
                self.table_array[r][c] = k
                c = self.recurse_on_dict_headers(sdict[k], r + 1, c)
            return c
        
    def recurse_to_find_size(self, sdict, r, c):
        
        if ((type(sdict) != dict) and (type(sdict) != OrderedDict)):
            return r, c + 1
        else:
            rbiggest = r
            for k in sorted(sdict.keys()):
                rnew, c = self.recurse_to_find_size(sdict[k], r + 1, c)
                if rnew > rbiggest:
                    rbiggest = rnew
            return rbiggest, c
                
    def recurse_on_dict(self, sdict, r, c, sorted_headers = None):
        if ((type(sdict) != dict) and (type(sdict) != OrderedDict)):
            self.table_array[r][c] = sdict
            return c + 1
        else:
            if sorted_headers != None:
                sheaders = sorted_headers
            else:
                sheaders = sorted(sdict.keys())
            for k in sheaders:
                c = self.recurse_on_dict(sdict[k], r, c)
            return c

    def convert_structured_dicts_to_array(self, sdict, sorted_keys = None, sorted_headers = None):
        header_levels, ncols = self.recurse_to_find_size(sdict[sdict.keys()[0]], 0, 0)
        nrows = header_levels + len(sdict.keys())
        self.table_array = self.create_empty_string_array(nrows, ncols)
        self.recurse_on_dict_headers(sdict[sdict.keys()[0]], 0, 0, sorted_headers)
        if sorted_keys != None:
            key_list = sorted_keys
        else:
            key_list = sdict.keys()
        r = header_levels
        for entry in key_list:
            c = 0
            self.table_array[r][0] = entry
            self.recurse_on_dict(sdict[entry], r, c, sorted_headers = sorted_headers)
            r += 1
        return self.table_array
            
    def append_html_table_from_dicts(self, sdict, header_rows = 1, title = None, sorted_keys = None, precision = 3, cmap = None, sorted_headers = None):
        the_array = self.convert_structured_dicts_to_array(sdict, sorted_keys, sorted_headers = sorted_headers)
        self.append_html_table_from_array(the_array, header_rows, caption = title, precision = precision, cmap = cmap)
    
    def append_table(self, rows, cols, border_style = QTextFrameFormat.BorderStyle_Solid):
        tformat = QTextTableFormat()
        tformat.setBorderStyle(border_style)
        cursor= self._teditor.textCursor()
        cursor.movePosition(QTextCursor.End)
        table = cursor.insertTable(rows, cols, tformat)
        return table
    
    def fill_table_cell(self, row, col, table, text):
        cptr = table.cellAt(row, col).firstCursorPosition()
        cptr.insertText(text)
        
    def save_as_html(self):
        fname = QFileDialog.getSaveFileName()[0]
        fdirectoryname = os.path.dirname(fname)
        # fdirectoryname = QFileDialog.getExistingDirectory()
        # print fdirectoryname
        # fname = fdirectoryname + "/report.html"
        text_doc = self._teditor.document()
        f = open(fname, 'w')
        f.write(text_doc.toHtml())
        f.close()
        for imageFileName in self.image_dict.keys():
            full_image_path = fdirectoryname + "/" + imageFileName
            iWriter = QImageWriter(full_image_path, img_format)
            iWriter.write(self.image_dict[imageFileName])
Пример #9
0
class CustomWidget(QtGui.QMainWindow):

    def __init__(self):
        """
        Constructor
        """
        QtGui.QMainWindow.__init__(self)
        self.name = "Custom widget"
        self.central_widget = QtGui.QWidget()
        self.setCentralWidget(self.central_widget)

        # TODO: This is ugly, improve it
        self.iconp = JConfig().icons_path

        self._createLayout()


    def _createGui(self):
        """
        Subclasses must override this
        depending on the elements they want to add
        self._createOutputTree(),
        self._createOutputTable(),
        self._createOutputWindow() and add them to
        the corresponding layouts.
        """
        raise NotImplementedError


    def _createToolBar(self, name):
        """
        Subclasses need to define the
        specific Actions
        """
        self.toolbar = self.addToolBar(name)
        self.toolbar.setMovable(False)


    def _createLayout(self):
        """
        This creates the basic layout:
        Buttons & Outputs
        """

        # Layouts (This is a common disposition)
        main_layout = QtGui.QVBoxLayout()
        self.button_layout = QtGui.QHBoxLayout()
        output_layout = QtGui.QVBoxLayout()

        # You will need to create your buttons
        # and add them to your layout like this:
        # self.button_layout.addWidget(button_1)

        # Output Layout Inner (QSplitter)
        # Add as many widgets as you please
        # They will be ordered vertically and
        # be resizable by the user
        # self.splitter.addWidget(self.table_label)
        # self.splitter.addWidget(...)
        self.splitter = QSplitter(QtCore.Qt.Vertical)

        # Nested layouts
        main_layout.addLayout(self.button_layout)
        output_layout.addWidget(self.splitter)
        main_layout.addLayout(output_layout)
        self.central_widget.setLayout(main_layout)


    def _createOutputWindow(self):
        """
        Some binary analysis commands will output to this.
        """

        self.output_label = QtGui.QLabel('Output')

        self.output_window = QTextEdit()
        self.output_window.setFontPointSize(10)
        self.output_window.setReadOnly(True)
        # Save it for later use
        self.output_window.original_textcolor = self.output_window.textColor()


    def _createOutputTable(self):
        """
        A vanilla QTableWidget. Callbacks modify
        its properties, like number of columns, etc.
        """
        self.table_label = QtGui.QLabel('Table Output')

        self.table = QTableWidget()
        self.table.setColumnCount(3)
        self.table.setColumnWidth(0, 100)
        self.table.setColumnWidth(1, 300)
        self.table.setColumnWidth(2, 300)

        self.table.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)

        # Connect signals to slots
        self.table.customContextMenuRequested.connect(self._tablePopup)
        self.table.horizontalHeader().sectionDoubleClicked.connect(self._tableHeaderDoubleClicked)
        self.table.cellDoubleClicked.connect(self._tableCellDoubleClicked)


    def _createOutputTree(self):
        """
        A QtreeWidget. Initially used to display those pesky
        dword comparison to immediate values.
        """
        self.tree_label = QtGui.QLabel('Tree Output')

        self.tree = QTreeWidget()
        self.tree.setColumnCount(3)
        self.tree.setColumnWidth(0, 150)
        self.tree.setColumnWidth(1, 150)
        self.tree.setColumnWidth(2, 50)

        # Connect signals to slots
        self.tree.itemDoubleClicked.connect(self._treeElementDoubleClicked)



    #################################################################
    # GUI Callbacks
    #################################################################
    def _console_output(self, s = "", err = False):
        """
        Convenience wrapper
        """
        if err:
            # Error message
            err_color = QColor('red')
            self.output_window.setTextColor(err_color)
            self.output_window.append(s)
            # restore original color
            self.output_window.setTextColor(self.output_window.original_textcolor)

        else:
            self.output_window.append(s)


    def _tableCellDoubleClicked(self, row, col):
        """
        Most of the info displayed in QTableWidgets represent addresses.
        Default action: try to jump to it.
        """
        it = self.table.item(row, col).text()

        try:
            addr = int(it, 16)
            jump_to_address(addr)

        except ValueError:
            self._console_output("[!] That does not look like an address...", err = True)
            return


    def _tablePopup(self, pos):
        """
        Popup menu activated clicking the secondary
        button on the table
        """
        menu = QtGui.QMenu()

        # Add menu entries
        delRow = menu.addAction(QIcon(self.iconp + "close.png"), "Delete Row")
        selItem = menu.addAction(QIcon(self.iconp + "bookmark.png"), "Mark entry")
        menu.addSeparator()
        origFunc = menu.addAction(QIcon(self.iconp + "lightning.png"), "Select origin function")
        destFunc = menu.addAction(QIcon(self.iconp + "flag.png"), "Select destination function")

        # Get entry clicked
        action = menu.exec_(self.mapToGlobal(pos))

        # Dispatch :)
        if action == delRow:
            self.table.removeRow(self.table.currentRow())

        elif action == selItem:
            self.table.currentItem().setBackground(QtGui.QColor('red'))

        elif action == origFunc:
            try:
                addr = self.table.currentItem().text()
                InfoUI.function_orig_ea = int(addr, 16)

            except:
                self._console_output("This does not look like an address...", err = True)

        elif action == destFunc:
            try:
                addr = self.table.currentItem().text()
                InfoUI.function_dest_ea = int(addr, 16)

            except:
                self._console_output("This does not look like an address...", err = True)


    def _tableHeaderDoubleClicked(self, index):
        """
        Used to sort the contents
        """
        self.table.sortItems(index, order = QtCore.Qt.AscendingOrder)


    def _treeElementDoubleClicked(self, item, column):
        """
        QTreeWidgetElement callback. Basically it jumps to
        the selected address in IDA disassembly window.
        """
        try:
            # Only interested in addresses
            addr_int = int(item.text(column), 16)
            jump_to_address(addr_int)
            # Paint some color
            item.setBackground(column, QtGui.QColor('green'))

        except:
            self._console_output("[!] That does not look like an address...", err = True)