Example #1
0
    def __init__(self, parent, title='', msg = '', width=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle(title)
        self.setPalette(white_palette)

        sizer = QVBoxLayout()
        self.setLayout(sizer)

        texte = QTextEdit(self)
        texte.setPlainText(msg)
        texte.setMinimumHeight(500)
        texte.setReadOnly(True)
        if width is None:
            texte.setLineWrapMode(QTextEdit.NoWrap)
            doc = texte.document()
            width = doc.idealWidth() + 4*doc.documentMargin()
        texte.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        texte.setMinimumWidth(width)
        sizer.addWidget(texte)

        boutons = QHBoxLayout()
        boutons.addStretch()
        ok = QPushButton('OK', clicked=self.close)
        boutons.addWidget(ok)
        boutons.addStretch()
        sizer.addLayout(boutons)
class PastMessagesView(QWidget):
    def __init__(self, parent=None):
        super(PastMessagesView, self).__init__(parent)
        layout = QVBoxLayout(self)
        self.text = QTextEdit()
        self.text.setReadOnly(True)
        self.text.setLineWrapMode(QTextEdit.WidgetWidth)
        layout.addWidget(self.text)
        self.setLayout(layout)
        
    def AddMessageAsHtml(self, html):
        self.text.insertHtml(html)
 def on_pb_show_warnings_released(self):
     # show a dialog box with only the warnings from the conversion
     win = QDialog(self)
     win.resize(self.size() * 0.85)
     layout = QVBoxLayout()
     txt = QTextEdit(win)
     txt.setLineWrapMode(txt.NoWrap)
     txt.document().setPlainText('\n'.join(self.converter.warnings))
     pb = QPushButton('Close')
     self.connect(pb, SIGNAL('released()'), win.accept)
     layout.addWidget(txt)
     layout.addWidget(pb)
     win.setLayout(layout)
     win.exec_()
Example #4
0
 def on_pb_show_warnings_released(self):
     # show a dialog box with only the warnings from the conversion
     win = QDialog(self)
     win.resize(self.size() * 0.85)
     layout = QVBoxLayout()
     txt = QTextEdit(win)
     txt.setLineWrapMode(txt.NoWrap)
     txt.document().setPlainText('\n'.join(self.converter.warnings))
     pb = QPushButton('Close')
     self.connect(pb, SIGNAL('released()'), win.accept)
     layout.addWidget(txt)
     layout.addWidget(pb)
     win.setLayout(layout)
     win.exec_()
Example #5
0
 def window_msgCheckCreatePluginWidget(self,parent,plugin_object,p_name):
     sw = None
     try:
         sw = plugin_object.create_widget(parent)
     except:
         stringOut = StringIO()
         traceback.print_exc(None, stringOut)
         getCoreLogger().exception("while including plugin %s with options: %s  %s", p_name, str(plugin_object.options), str(sys.exc_info()))
         sw = QTextEdit(parent)
         #sw.set_size_request(400,200)
         sw.setLineWrapMode(QTextEdit.WidgetWidth)
         sw.setPlainText(stringOut.getvalue())
         stringOut.close() 
     return sw
Example #6
0
class lunch_menu(iface_gui_plugin):
    def __init__(self):
        super(lunch_menu, self).__init__()
        self.options = [(("no_proxy", "Don't use proxy server"),False),
                        (("url", "URL"),"http://lunchinator.de/files/menu_dummy.txt")]

    def activate(self):
        iface_gui_plugin.activate(self)
        
    def deactivate(self):
        iface_gui_plugin.deactivate(self)
    
    def create_widget(self, parent):
        from PyQt4.QtGui import QTextEdit, QSizePolicy
        from lunchinator.callables import AsyncCall
        self._textview = QTextEdit(parent)
        self._textview.setLineWrapMode(QTextEdit.WidgetWidth)
        self._textview.setReadOnly(True)
        self._textview.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        
        AsyncCall(getValidQtParent(), self.logger, self._downloadText, self._updateText, self._errorDownloadingText)()
        
        return self._textview
    
    def _downloadText(self):
        if self.options["no_proxy"]:
            hdr = {'User-Agent': 'Mozilla/5.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'}
            req = urllib2.Request(self.options["url"], headers=hdr)
            proxy_handler = urllib2.ProxyHandler({})
            opener = urllib2.build_opener(proxy_handler)   
            with contextlib.closing(opener.open(req)) as u:
                return u.read()
            
        resp = urllib2.urlopen(self.options["url"])
        return resp.read()
    
    @loggingFunc
    def _updateText(self, txt):
        self._textview.setPlainText(txt)
        
    @loggingFunc
    def _errorDownloadingText(self, msg):
        self._textview.setPlainText("Error downloading text: " + msg)
    
    def add_menu(self,menu):
        pass
class InfoDialog(QMainWindow):
    def __init__(self, parent=None, info_data=''):
        QMainWindow.__init__(self)

        self.info_data = info_data
        self.confirmed = False

        self.resize(700, 400)
        self.initUI()

    def initUI(self):
        cw = QWidget()
        self.setCentralWidget(cw)
        layout_main = QVBoxLayout()
        layout_main.setSpacing(5)

        self.setWindowTitle('New SSH logins to Localhost')

        ## Info
        self.info = QTextEdit()
        self.info.setReadOnly(True)
        self.info.setLineWrapMode(QTextEdit.NoWrap)
        self.info.append(self.info_data)

        layout_main.addWidget(self.info, 1)

        # confirm button
        self.btn_confirm = QPushButton('Confirm')
        self.btn_confirm.pressed.connect(self.confirm)
        layout_main.addWidget(self.btn_confirm)

        ## add stretch
        layout_main.addStretch()

        ## Setup layout
        cw.setLayout(layout_main)
        self.show()

    def confirm(self):
        self.confirmed = True
        self.close()

    def getConfirmed(self):
        return self.confirmed
Example #8
0
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        self.parent = parent

        sizer = QVBoxLayout()

        texte = QTextEdit(self)
        with open(path2("%/wxgeometrie/doc/license.txt"), "r") as f:
            msg = f.read().decode("utf8")
        texte.setPlainText(msg)
        texte.setMinimumHeight(500)
        texte.setReadOnly(True)
        texte.setLineWrapMode(QTextEdit.NoWrap)
        doc = texte.document()
        width = doc.idealWidth() + 4 * doc.documentMargin()
        texte.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        texte.setMinimumWidth(width)
        sizer.addWidget(texte)
        self.setLayout(sizer)
Example #9
0
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        self.parent = parent

        sizer = QVBoxLayout()

        texte = QTextEdit(self)
        with open(path2("%/wxgeometrie/doc/changelog.txt"), "r") as f:
            msg = f.read().decode("utf8").replace("\n", "<br>")
        titre = u"<b>Changements apportés par la version %s :</b>" % param.version
        msg = "<br>".join((titre, "", msg))
        texte.setHtml(msg)
        texte.setMinimumHeight(500)
        texte.setReadOnly(True)
        texte.setLineWrapMode(QTextEdit.NoWrap)
        doc = texte.document()
        width = doc.idealWidth() + 4 * doc.documentMargin()
        texte.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        texte.setMinimumWidth(width)
        sizer.addWidget(texte)
        self.setLayout(sizer)
Example #10
0
    def show(self, what, title=None, plain=False):

        try:
            from PyQt4.QtGui import QTextEdit, QTextCursor
        except ImportError:
            g.es("Need Qt for show command")
            return

        if not title:
            title = what.split('\n', 1)[0].strip()

        te = QTextEdit()
        te.setReadOnly(True)
        if plain:
            te.setText(what)
        else:
            te.setHtml("<pre>%s</pre>" % what)
        te.setLineWrapMode(QTextEdit.NoWrap)
        te.resize(800, 600)
        te.setWindowTitle(title)
        te.moveCursor(QTextCursor.End)
        te.show()
        self.popups.append(te)
Example #11
0
    def show(self, what, title=None, plain=False):

        try:
            from PyQt4.QtGui import QTextEdit, QTextCursor
        except ImportError:
            g.es("Need Qt for show command")
            return

        if not title:
            title = what.split('\n', 1)[0].strip()

        te = QTextEdit()
        te.setReadOnly(True)
        if plain:
            te.setText(what)
        else:
            te.setHtml("<pre>%s</pre>" % what)
        te.setLineWrapMode(QTextEdit.NoWrap)
        te.resize(800, 600)
        te.setWindowTitle(title)
        te.moveCursor(QTextCursor.End)
        te.show()
        self.popups.append(te)
Example #12
0
class MainWindow(QMainWindow):
    """
    class MainWindow for the gui of dokueddy
    """
    def __init__(self, config, parent=None):
        """
        Constructor for class MainWindow
        @param config: dokueddy configuration
        """
        QMainWindow.__init__(self)
        self.config = config
        self.setGeometry(
                         self.config.settings['app_x'], 
                         self.config.settings['app_y'], 
                         self.config.settings['app_w'],
                         self.config.settings['app_h']
                         )
        self.setWindowTitle(
                            self.config.settings['appname'] + 
                            ' - Version: ' +
                            self.config.settings['appversion']
                            )
        globalFont = QFont(
                           self.config.settings['fontfamily'], 
                           self.config.settings['pointsize']
                           )
        self.statusbar = self.statusBar()
        self.center()
    
        self.exit = QAction('Quit Dokueddy', self)
        self.menubar = QMenuBar(None)
        self.file = self.menubar.addMenu('&File')
        self.file.addAction(self.exit)
        self.setMenuBar(self.menubar)
        
        self.save = QAction(QIcon('../resources/icons/save_edit.gif'), 'Save current page', self)
        self.save.setShortcut('Ctrl+S')
        self.save.setDisabled(True)
        self.fontBold = QAction(QIcon('../resources/icons/tag_bold.png'), 'Bold text', self)
        self.fontItalic = QAction(QIcon('../resources/icons/tag_i.png'), 'Italic text', self)
        self.fontH1 = QAction(QIcon('../resources/icons/tag_h1.png'), 'Heading 1', self)
        self.fontH2 = QAction(QIcon('../resources/icons/tag_h2.png'), 'Heading 2', self)
        self.fontH3 = QAction(QIcon('../resources/icons/tag_h3.png'), 'Heading 3', self)
        self.fontH4 = QAction(QIcon('../resources/icons/tag_h4.png'), 'Heading 4', self)
        self.fontH5 = QAction(QIcon('../resources/icons/tag_h5.png'), 'Heading 5', self)
        self.search = QAction(QIcon('../resources/icons/magnify.png'), 'Search for', self)
        
        self.toolbar = self.addToolBar('Toolbar')
        self.toolbar.addAction(self.save)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.fontBold)
        self.toolbar.addAction(self.fontItalic)
        self.toolbar.addAction(self.fontH1)
        self.toolbar.addAction(self.fontH2)
        self.toolbar.addAction(self.fontH3)
        self.toolbar.addAction(self.fontH4)
        self.toolbar.addAction(self.fontH5)
        self.toolbar.addAction(self.search)
        self.toolbar.setMaximumHeight(24)
        
        self.serverLabel = QLabel()
        self.serverLabel.setText('Serveraddress:')
        self.userLabel = QLabel()
        self.userLabel.setText('Username:'******'Password:'******'serverAddress'])        
        self.userLineEdit = QLineEdit()
        self.userLineEdit.setMaximumSize(150, 35)
        self.userLineEdit.setText(self.config.settings['user'])        
        self.passwdLineEdit = QLineEdit()
        self.passwdLineEdit.setMaximumSize(150, 35)
        self.passwdLineEdit.setEchoMode(QLineEdit.Password)
        
        self.connectButton = QPushButton('Connect', self)
        self.connectButton.setMaximumSize(100, 35)
        self.quitButton = QPushButton('Quit', self)
        self.quitButton.setMaximumSize(100, 35)
    
        self.listView = QListView(self)
        self.listView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.listView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.listView.setMinimumWidth(200)
        self.listView.setMaximumWidth(400)
        self.listView.setFont(globalFont)
        
        self.textEdit = QTextEdit(self)
        self.textEdit.setMinimumWidth(400)
        self.textEdit.setFont(globalFont)
        self.textEdit.setLineWrapMode(QTextEdit.NoWrap)
    
        self.editLayout = QGridLayout()
        self.editLayout.addWidget(self.serverLabel, 0, 0, Qt.AlignLeft)
        self.editLayout.addWidget(self.serverLineEdit, 0, 1)
        self.editLayout.addWidget(self.userLabel, 0, 2, Qt.AlignLeft)
        self.editLayout.addWidget(self.userLineEdit, 0, 3)
        self.editLayout.addWidget(self.passwdLabel, 0, 4, Qt.AlignLeft)
        self.editLayout.addWidget(self.passwdLineEdit, 0, 5)
        
        self.gridLayout = QGridLayout()
        self.gridLayout.addLayout(self.editLayout, 0, 0, 1, 2)
        self.gridLayout.addWidget(self.listView, 1, 0, Qt.AlignLeft)
        self.gridLayout.addWidget(self.textEdit, 1, 1, Qt.AlignLeft)
        self.gridLayout.addWidget(self.connectButton, 2, 0, Qt.AlignLeft)
        self.gridLayout.addWidget(self.quitButton, 2, 1, Qt.AlignRight)
    
        self.mainWidget = QWidget(self)
        self.mainWidget.setLayout(self.gridLayout)
        self.setCentralWidget(self.mainWidget)

    def center(self):
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((screen.width() - size.width()) / 2,
                  (screen.height() - size.height()) / 2)
Example #13
0
class CompileWidget(QWidget):

    progress = pyqtSignal(int)

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self._options = None
        self._conf = None

        self._go = QPushButton('Go')
        self._go.setMaximumWidth(100)
        font = self._go.font()
        font.setPointSizeF(font.pointSizeF() * 2.0)
        font.setWeight(QFont.Bold)
        self._go.setFont(font)
        self._go.clicked.connect(self.go)

        self._saveLog = QPushButton('Save')
        saveLogLabel = QLabel('Log File:')
        saveLogBrowse = QPushButton('&Browse')
        saveLogBrowse.clicked.connect(self.browseSaveLog)
        self._saveLogEdit = QLineEdit('')

        gLayout = QGridLayout()
        gLayout.addWidget(saveLogLabel, 0, 0, 1, 1, Qt.AlignRight)
        gLayout.addWidget(self._saveLogEdit, 0, 1, 1, 6)
        gLayout.addWidget(saveLogBrowse, 0, 7, 1, 1)

        self._console = QTextEdit()
        self._console.setLineWrapMode(QTextEdit.NoWrap)
        self._console.setMinimumSize(800, 400)
        palette = self._console.palette()
        palette.setColor(QPalette.Base, QColor.fromRgb(255, 255,
                                                       221))  # ffffdd.
        self._console.setPalette(palette)
        font = QFont('Bitstream Vera Sans Mono',
                     self._console.font().pointSize())
        self._console.setFont(font)
        self._highlighter = Highlighter(self._console.document())

        self._progressBar = QProgressBar()
        self._progressBar.setRange(0, 100)
        self._progressBar.setTextVisible(True)

        hLayout = QHBoxLayout()
        hLayout.addStretch()
        hLayout.addWidget(self._go)
        hLayout.addStretch()
        hLayout.addWidget(self._saveLog)
        hLayout.addStretch()

        vLayout = QVBoxLayout()
        vLayout.addLayout(hLayout)
        vLayout.addLayout(gLayout)
        vLayout.addWidget(self._progressBar)
        vLayout.addWidget(self._console)
        self.setLayout(vLayout)

        self.progress.connect(self._progressBar.setValue)
        self._saveLog.clicked.connect(self.saveLog)

        self.readSettings()
        return

    def _setOptions(self, options):
        self._options = options

    def _setConf(self, conf):
        self._conf = conf

    def _getOptions(self):
        return self._options

    def _getConf(self):
        return self._conf

    options = property(_getOptions, _setOptions)
    conf = property(_getConf, _setConf)

    def browseSaveLog(self):
        self._saveLogEdit.setText(
            QFileDialog.getSaveFileName(self, 'Select Log File Report',
                                        self._saveLogEdit.text(),
                                        'Report Files (*.log *.txt)'))
        return

    def saveLog(self):
        if self._saveLogEdit.text():
            fd = open(self._saveLogEdit.text(), 'w+')
            fd.write(self._console.toPlainText())
            fd.close()
        return

    def shellCommand(self):
        command = [self.conf.bootstrapDir + '/ccb.py']
        for project in self.options.projects:
            for tool in project.actives:
                command += ['--tool=' + tool]
        toolsCount = len(command) - 1

        if self.conf.rootDir: command += ['--root=%s' % self.conf.rootDir]

        #if self.options.svnUpdate:   command += [ '--svn-update' ]
        #if self.options.svnStatus:   command += [ '--svn-update' ]
        if self.options.enableDoc: command += ['--doc']
        if self.options.devtoolset2: command += ['--devtoolset-2']
        if self.options.qt5: command += ['--qt5']
        if self.options.noCache: command += ['--no-cache']
        if self.options.rmBuild: command += ['--rm-build']
        if self.options.verbose: command += ['--verbose']
        if self.options.make:
            makeArguments = 'install ' + self.options.threads
            command += ['--make=%s' % makeArguments]

        if self.options.buildMode == 'Debug':
            command += ['--debug']
        return toolsCount, command

    def go(self):
        rePercentage = re.compile(r'^\[\s*(?P<percent>\d+)%\].*')
        reProcessTool = re.compile(r'^Processing tool:\s*"(?P<tool>.+)"')

        if not self.options or not self.conf: return

        toolsCount, command = self.shellCommand()
        if not toolsCount: return

        self._progressBar.reset()
        self._progressBar.setRange(0, toolsCount * 100)

        strCommand = command[0]
        for arg in command[1:]:
            strCommand += ' ' + arg
        strCommand += '\n\n'
        self._console.setFontItalic(True)
        self._console.insertPlainText(strCommand)
        self._console.setFontItalic(False)

        toolsDone = -1
        builderProcess = subprocess.Popen(command,
                                          stdout=subprocess.PIPE,
                                          stderr=subprocess.STDOUT)
        while True:
            line = builderProcess.stdout.readline()
            if line == '': break

            m = rePercentage.match(line)
            if m:
                self.progress.emit(toolsDone * 100 + int(m.group('percent')))
            else:
                m = reProcessTool.match(line)
                if m:
                    toolsDone += 1

            self._console.insertPlainText(line)

            scrollBar = self._console.verticalScrollBar()
            scrollBar.setValue(scrollBar.maximum())
            QApplication.processEvents()
        builderProcess.wait()
        if builderProcess.returncode == None:
            pass
        return

    def readSettings(self):
        settings = QSettings()
        self._saveLogEdit.setText(settings.value('compile/saveLog').toString())
        return

    def saveSettings(self):
        settings = QSettings()
        settings.setValue('compile/saveLog', self._saveLogEdit.text())
        return
Example #14
0
class LineTextWidget(QFrame):
 
    class NumberBar(QWidget):
 
        def __init__(self, *args):
            QWidget.__init__(self, *args)
            self.edit = None
            # This is used to update the width of the control.
            # It is the highest line that is currently visibile.
            self.highest_line = 0
 
        def setTextEdit(self, edit):
            self.edit = edit
 
        def update(self, *args):
            '''
            Updates the number bar to display the current set of numbers.
            Also, adjusts the width of the number bar if necessary.
            '''
            # The + 4 is used to compensate for the current line being bold.
            width = self.fontMetrics().width(str(self.highest_line)) + 4
            if self.width() != width:
                self.setFixedWidth(width)
            QWidget.update(self, *args)
 
        def paintEvent(self, event):
            contents_y = self.edit.verticalScrollBar().value()
            page_bottom = contents_y + self.edit.viewport().height()
            font_metrics = self.fontMetrics()
            current_block = self.edit.document().findBlock(self.edit.textCursor().position())
 
            painter = QPainter(self)
 
            line_count = 0
            # Iterate over all text blocks in the document.
            block = self.edit.document().begin()
            while block.isValid():
                line_count += 1
 
                # The top left position of the block in the document
                position = self.edit.document().documentLayout().blockBoundingRect(block).topLeft()
 
                # Check if the position of the block is out side of the visible
                # area.
                if position.y() > page_bottom:
                    break
 
                # We want the line number for the selected line to be bold.
                bold = False
                if block == current_block:
                    bold = True
                    font = painter.font()
                    font.setBold(True)
                    painter.setFont(font)
 
                # Draw the line number right justified at the y position of the
                # line. 3 is a magic padding number. drawText(x, y, text).
                painter.drawText(self.width() - font_metrics.width(str(line_count)) - 3, round(position.y()) - contents_y + font_metrics.ascent(), str(line_count))
 
                # Remove the bold style if it was set previously.
                if bold:
                    font = painter.font()
                    font.setBold(False)
                    painter.setFont(font)
 
                block = block.next()
 
            self.highest_line = line_count
            painter.end()
 
            QWidget.paintEvent(self, event)
 
 
    def __init__(self, *args):
        QFrame.__init__(self, *args)
 
        #self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
 
        self.edit = QTextEdit(*args)
        #self.edit.setFrameStyle(QFrame.NoFrame)
        self.edit.setLineWrapMode(QTextEdit.NoWrap)
        self.edit.setAcceptRichText(False)
        #self.edit.setReadOnly(True)
 
        self.number_bar = self.NumberBar()
        self.number_bar.setTextEdit(self.edit)
 
        hbox = QHBoxLayout(self)
        hbox.setSpacing(0)
        hbox.setMargin(0)
        hbox.addWidget(self.number_bar)
        hbox.addWidget(self.edit)

        self.edit.installEventFilter(self)
        self.edit.viewport().installEventFilter(self)
        
                    
    def setText(self, text):
        self.edit.setText(text)
        
    def toPlainText(self):
        return self.edit.toPlainText()
        
    def setFocus(self):
        self.edit.setFocus()
        
    def append(self, text):
        self.edit.append(text)
 
    def eventFilter(self, object, event):
        # Update the line numbers for all events on the text edit and the viewport.
        # This is easier than connecting all necessary singals.
        if object in (self.edit, self.edit.viewport()):
            self.number_bar.update()
            return False
        return QFrame.eventFilter(object, event)

 
    def getTextEdit(self):
        return self.edit
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        
        self._create_components()
        self._place_components()
        self._create_controller()
        
        self.setWindowTitle("Job Crawler")
    
    def _create_components(self):
        self.site_gb = QGroupBox(u"Choix des sites")
        self.param_gb = QGroupBox(u"Autres Paramètres")
        self.search_gb = QGroupBox(u"Mots-clé")
        self.log_gb = QGroupBox(u"Logs")

        self.apec_cb = QCheckBox(u"APEC")
        self.apec_cb.setDisabled(True)
        self.caoe_cb = QCheckBox(u"CAO Emploi")
        self.caoe_cb.setDisabled(True)
        self.inde_cb = QCheckBox(u"Indeed")
        self.mons_cb = QCheckBox(u"Monster Job")
        self.mons_cb.setDisabled(True)
        self.pole_cb = QCheckBox(u"Pole Enmploi")
        self.pole_cb.setDisabled(True)
        self.regi_cb = QCheckBox(u"Région Job")
        self.regi_cb.setDisabled(True)
        
        self.search_label = QLabel(u"Mots-clé de recherche")
        self.filter_label = QLabel(u"Critère de filtrage")
        self.region_label = QLabel(u"Région")
        self.daterange_label = QLabel(u"Plage de recherche")
        
        self.search_qle = QLineEdit()
        self.filter_qle = QLineEdit()
        
        self.start_button = QPushButton(u"Rechercher")
        self.stop_button = QPushButton(u"Stopper")
        self.stop_button.setDisabled(True)
        
        self.daterange_sb = QSpinBox()
        self.daterange_sb.setMaximum(40)
        self.daterange_sb.setProperty("value", 3)
        self.daterange_sb.setSuffix(u" Jours")
        
        self.region_cb = QComboBox()
        region_list = toolbox.getconfigvalue("STATIC", "regions").split(',')
        self.region_cb.addItems(region_list)
        
        self.log_te = QTextEdit()
        self.log_te.setReadOnly(True)
        self.log_te.setLineWrapMode(QTextEdit.NoWrap)
        
        self.file_menu = QMenu(u"Fichier")
        self.help_menu = QMenu(u"Aide")
        
    
    def _place_components(self):
        site_layout = QHBoxLayout()
        temp = QVBoxLayout()
        temp.addWidget(self.apec_cb)
        temp.addWidget(self.caoe_cb)
        temp.addWidget(self.inde_cb)
        site_layout.addLayout(temp)
        temp = QVBoxLayout()
        temp.addWidget(self.mons_cb)
        temp.addWidget(self.pole_cb)
        temp.addWidget(self.regi_cb)
        site_layout.addLayout(temp)
        self.site_gb.setLayout(site_layout)
        
        search_layout = QVBoxLayout()
        search_layout.addWidget(self.search_label)
        search_layout.addWidget(self.search_qle)
        search_layout.addWidget(self.filter_label)
        search_layout.addWidget(self.filter_qle)
        self.search_gb.setLayout(search_layout)
        
        param_layout = QVBoxLayout()
        param_layout.addWidget(self.daterange_label)
        param_layout.addWidget(self.daterange_sb)
        param_layout.addWidget(self.region_label)
        param_layout.addWidget(self.region_cb)
        self.param_gb.setLayout(param_layout)
        
        log_layout = QVBoxLayout()
        log_layout.addWidget(self.log_te)
        self.log_gb.setLayout(log_layout)
        
        command_layout = QHBoxLayout()
        command_layout.addWidget(self.start_button)
        command_layout.addWidget(self.stop_button)
        
        main_layout = QVBoxLayout()
        main_layout.addWidget(self.site_gb)
        main_layout.addWidget(self.search_gb)
        main_layout.addWidget(self.param_gb)
        main_layout.addWidget(self.log_gb)
        main_layout.addLayout(command_layout)
        
        centralwidget = QWidget(self)
        centralwidget.setLayout(main_layout)
        self.setCentralWidget(centralwidget)
        
        menubar = self.menuBar()
        menubar.addMenu(self.file_menu)
        menubar.addMenu(self.help_menu)
    
    def _create_controller(self):
        adminAction = QAction(u'Administration', self)        
        adminAction.setStatusTip(u'Régler les paramètres de l\'application')
        adminAction.triggered.connect(self.admin)
        
        exitAction = QAction(u'Quitter', self)        
        exitAction.setStatusTip(u'Quitter Job Crawler')
        exitAction.triggered.connect(qApp.quit)
        
        aboutAction = QAction(u'A propos', self)
        aboutAction.setStatusTip(u'Afficher la fenêtre à propos')
        aboutAction.triggered.connect(self.about)
        
        self.file_menu.addAction(adminAction)
        self.file_menu.addSeparator()
        self.file_menu.addAction(exitAction)
        
        self.help_menu.addAction(aboutAction)
        
        self.start_button.clicked.connect(self.start)
        self.stop_button.clicked.connect(self.stop)
        
        # Controller for logging
        XStream.stdout().messageWritten.connect( self.log_te.insertPlainText )
        XStream.stderr().messageWritten.connect( self.log_te.insertPlainText )
    
    def validate_fields(self):
        error = False
        error_list = u""
        
        inde = self.inde_cb.isChecked()
        apec = self.apec_cb.isChecked()
        caoe = self.caoe_cb.isChecked()
        mons = self.mons_cb.isChecked()
        pole = self.pole_cb.isChecked()
        regi = self.regi_cb.isChecked()
        
        if  not (inde or apec or caoe or mons or pole or regi):
            error = True
            error_list += u"<li>Site à requêter</li>"
            
        searchkeyword = unidecode(unicode(self.search_qle.text()))
        
        if searchkeyword == u"":
            error = True
            error_list += u"<li>Mots clé de recherche</li>"
        
        filterkeyword = unidecode(unicode(self.filter_qle.text()))
        
        if filterkeyword == u"":
            error = True
            error_list += u"<li>Critère de filtrage</li>"
        
        if error:
            message = u"Veuillez renseigner le(s) champ(s) suivant(s) :<ul>" + error_list + u"</ul>"
            QMessageBox.warning(self, u"Erreur", message)
        
        return not error
    
    def validate_admin(self):
        dbpath = toolbox.getconfigvalue("GENERAL", "dbfile")
        
        if not (dbpath != "" and os.access(os.path.dirname(dbpath), os.W_OK)):
            message = u"<p>Veuiller renseigner l'emplacement de la base de données dans l'administration (Fichier > Administration).</p>"\
                      u"<p>Si cela a déjà été fait, ce message signifie que vous n'avez pas les droits d'écriture dans ce répertoire. Veuillez déplacer la base de données et reconfigurer l'emplacement dans l'administration.</p>"
            QMessageBox.warning(self, u"Erreur", message)
            return False
        
        return True
        
    @pyqtSlot()
    def start(self):
        def run():
            self.start_button.setDisabled(True)
#             self.stop_button.setEnabled(True)
            
            logger.info(u"Début")
            
            inde = self.inde_cb.isChecked()
            apec = self.apec_cb.isChecked()
            caoe = self.caoe_cb.isChecked()
            mons = self.mons_cb.isChecked()
            pole = self.pole_cb.isChecked()
            regi = self.regi_cb.isChecked()
            
            searchkeyword = unidecode(unicode(self.search_qle.text())).split(",")
            filterkeyword = unidecode(unicode(self.filter_qle.text())).split(",")
            
            daterange = self.daterange_sb.value()
            region = str(self.region_cb.currentText())
            
            dbpath = toolbox.getconfigvalue("GENERAL", "dbfile")
            excludelist = unidecode(toolbox.getconfigvalue("GENERAL", "excludes")).split(",")
            
            c = core.core(dbpath)
            logger.info(u"Recherche d'annonces")
            c.found_annonce(searchkeyword, daterange, region, None, apec, caoe, inde, mons, pole, regi)
            logger.info(u"Tri des annonces par rapport aux mots-clé d'exclusion")
            c.exclude_annouces(excludelist)
            logger.info(u"Tri des annonces par rapport aux critères de filtrage")
            c.filter_announces(filterkeyword)
            
            logger.info(u"Fin")
            
#             self.stop_button.setDisabled(True)
            self.start_button.setEnabled(True)
        
        if self.validate_fields() and self.validate_admin():
            self.thread = threading.Thread(target=run)
            self.thread.start()
    
    @pyqtSlot()
    def stop(self):
        self.thread._Thread__stop()
        self.stop_button.setDisabled(True)
        self.start_button.setEnabled(True)
        
    @pyqtSlot()
    def about(self):
        self.aboutwindow = aboutdialog.AboutDialog(self).exec_()
    
    @pyqtSlot()
    def admin(self):
        admindialog.AdminDialog(self).exec_()
class SimpleViewWidget(QWidget):   
    # http://www.colourlovers.com/palette/1930/cheer_up_emo_kid
    colors = ["C44D58", "C7F464", "4ECDC4", "556270", "FF6B6B"]
    
    def __init__(self, parent, logger):
        super(SimpleViewWidget, self).__init__(parent)
        self.logger = logger
        self.colorMap = {}
        self.colorCounter = 0
        
        layout = QVBoxLayout(self)
        
        self.memberView = QLabel(self)
        self.memberView.setAlignment(Qt.AlignHCenter)
        
        self.addMemberWidget = QWidget(self)
        addMemberLayout = QHBoxLayout(self.addMemberWidget)
        addMemberLayout.setContentsMargins(0, 0, 0, 0)
        addMemberLayout.addWidget(QLabel(u"Add Member", self), 0)
        self.addMemberEdit = QLineEdit(self)
        if hasattr(self.addMemberEdit, "setPlaceholderText"):
            self.addMemberEdit.setPlaceholderText(u"IP or Hostname")
        self.addMemberEdit.returnPressed.connect(self._addMember)
        addMemberLayout.addWidget(self.addMemberEdit, 1)
        addMemberButton = QPushButton("Add", self)
        addMemberButton.clicked.connect(self._addMember)
        addMemberLayout.addWidget(addMemberButton, 0)
        
        sendLayout = QHBoxLayout()
        sendMessageField = QLineEdit(self)
        if hasattr(sendMessageField, "setPlaceholderText"):
            sendMessageField.setPlaceholderText("optional Message")
        lunchButton = LunchButton(parent, sendMessageField)
        
        sendLayout.addWidget(sendMessageField)
        sendLayout.addWidget(lunchButton)
        
        self.msgview = QTextEdit(self)
        self.msgview.setLineWrapMode(QTextEdit.WidgetWidth)
        self.msgview.setReadOnly(True)
        
        layout.addWidget(self.addMemberWidget)
        layout.addWidget(self.memberView)
        layout.addLayout(sendLayout)
        layout.addWidget(self.msgview)
        
        get_notification_center().connectMemberAppended(self._memberAppended)
        get_notification_center().connectMemberAppended(self.updateWidgets)
        get_notification_center().connectMemberUpdated(self.updateWidgets)
        get_notification_center().connectMemberRemoved(self.updateWidgets)
        get_notification_center().connectMessagePrepended(self.updateWidgets)
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.updateWidgets)
        self.timer.start(60000)
        
    def showEvent(self, showEvent):
        self.updateWidgets()
        
    @loggingSlot()
    def _addMember(self):
        hostn = convert_raw(self.addMemberEdit.text())
        if hostn:
            get_server().call_request_info([hostn])
        
    def getMemberColor(self, peerID):
        if not self.colorMap.has_key(peerID):
            self.colorMap[peerID] = self.colors[self.colorCounter]
            self.colorCounter = (self.colorCounter + 1) % len(self.colors)
        
        return self.colorMap[peerID]
            
    @loggingSlot(object, object)
    def _memberAppended(self, pID, _infoDict):
        if not get_peers().isMe(pID=pID):
            self.addMemberWidget.setVisible(False)
                
    @pyqtSlot(struct_time, object, object)
    @pyqtSlot(object, object)
    @pyqtSlot(object)
    @loggingSlot()
    def updateWidgets(self, _=None, __=None, ___=None):
        if not self.isVisible():
            return True        
        
        peers = get_peers()
        if peers is not None:
            members = peers.getMembers()
            readyMembers = peers.getReadyMembers()
            notReadyMembers = peers.getMembers() - readyMembers
        else:
            members = []
            readyMembers = []
            notReadyMembers = []
            
        memText = "%d group members online<br />" % len(members)
        memToolTip = ""
        
        # don't display members with unknown status as ready
        readyMembers = [pID for pID in readyMembers if peers.isPeerReadinessKnown(pID=pID)]
        
        readyText = ", ".join([peers.getDisplayedPeerName(pID=x) for x in readyMembers])
        notReadyText = ", ".join([peers.getDisplayedPeerName(pID=x) for x in notReadyMembers])
        memToolTip += "<span style='color:green'>%s</span><br />" % readyText if len(readyMembers) else ""
        memToolTip += "<span style='color:red'>%s</span>" % notReadyText if len(notReadyMembers) else ""
        
        memText += "<span style='color:green'>%d ready for lunch</span>" % len(readyMembers) if len(readyMembers) else "no one ready for lunch"
        self.memberView.setText(memText)
        self.memberView.setToolTip(memToolTip)
        
        msgTexts = ""
        with get_server().get_messages():
            messages = get_server().get_messages().getAll(time() - (180 * 60))
        for timest, peerID, msg in messages:
            member = peers.getDisplayedPeerName(pID=peerID)
            color = self.getMemberColor(peerID)
            msgTexts += "<span style='color:#%s'><b>%s</b> \
                        <i>[%s]</i>: %s</span><br />\n" % (color, member,strftime("%H:%M",timest), msg)
                        
        self.msgview.setHtml(msgTexts)
        
    def create_menu(self, menuBar):
        windowMenu = QMenu("Advanced", menuBar)
        windowMenu.addAction("Manually add an IP", self.addMemberByIP)
        return windowMenu
    
    def addMemberByIP(self):
        hostn, button = QInputDialog.getText(None, "Manually add a member", "In rare cases the lunchinator might not be available to find another user.\n" + 
                             "You can enter an IP/hostname here to explicitly look there. Make sure that the Lunchinator is running on\n" + 
                             "the other machine and that you are in the same group.")
        if button and len(hostn):
            get_server().call_request_info([str(hostn)])
        
    def finish(self):
        try:
            self.timer.timeout.disconnect()
            get_notification_center().disconnectMemberAppended(self.updateWidgets)
            get_notification_center().disconnectMemberUpdated(self.updateWidgets)
            get_notification_center().disconnectMemberRemoved(self.updateWidgets)
            get_notification_center().disconnectMessagePrepended(self.updateWidgets) 
        except:
            self.logger.info("Simple View: was not able to disconnect timer")
Example #17
0
class LineTextWidget(QFrame):
    class NumberBar(QWidget):
        def __init__(self, *args):
            QWidget.__init__(self, *args)
            self.edit = None
            # This is used to update the width of the control.
            # It is the highest line that is currently visibile.
            self.highest_line = 0

        def setTextEdit(self, edit):
            self.edit = edit

        def update(self, *args):
            '''
            Updates the number bar to display the current set of numbers.
            Also, adjusts the width of the number bar if necessary.
            '''
            # The + 4 is used to compensate for the current line being bold.
            width = self.fontMetrics().width(str(self.highest_line)) + 4
            if self.width() != width:
                self.setFixedWidth(width)
            QWidget.update(self, *args)

        def paintEvent(self, event):
            contents_y = self.edit.verticalScrollBar().value()
            page_bottom = contents_y + self.edit.viewport().height()
            font_metrics = self.fontMetrics()
            current_block = self.edit.document().findBlock(
                self.edit.textCursor().position())

            painter = QPainter(self)

            line_count = 0
            # Iterate over all text blocks in the document.
            block = self.edit.document().begin()
            while block.isValid():
                line_count += 1

                # The top left position of the block in the document
                position = self.edit.document().documentLayout(
                ).blockBoundingRect(block).topLeft()

                # Check if the position of the block is out side of the visible
                # area.
                if position.y() > page_bottom:
                    break

                # We want the line number for the selected line to be bold.
                bold = False
                if block == current_block:
                    bold = True
                    font = painter.font()
                    font.setBold(True)
                    painter.setFont(font)

                # Draw the line number right justified at the y position of the
                # line. 3 is a magic padding number. drawText(x, y, text).
                painter.drawText(
                    self.width() - font_metrics.width(str(line_count)) - 3,
                    round(position.y()) - contents_y + font_metrics.ascent(),
                    str(line_count))

                # Remove the bold style if it was set previously.
                if bold:
                    font = painter.font()
                    font.setBold(False)
                    painter.setFont(font)

                block = block.next()

            self.highest_line = line_count
            painter.end()

            QWidget.paintEvent(self, event)

    def __init__(self, *args):
        QFrame.__init__(self, *args)

        #self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)

        self.edit = QTextEdit(*args)
        #self.edit.setFrameStyle(QFrame.NoFrame)
        self.edit.setLineWrapMode(QTextEdit.NoWrap)
        self.edit.setAcceptRichText(False)
        #self.edit.setReadOnly(True)

        self.number_bar = self.NumberBar()
        self.number_bar.setTextEdit(self.edit)

        hbox = QHBoxLayout(self)
        hbox.setSpacing(0)
        hbox.setMargin(0)
        hbox.addWidget(self.number_bar)
        hbox.addWidget(self.edit)

        self.edit.installEventFilter(self)
        self.edit.viewport().installEventFilter(self)

    def setText(self, text):
        self.edit.setText(text)

    def toPlainText(self):
        return self.edit.toPlainText()

    def setFocus(self):
        self.edit.setFocus()

    def append(self, text):
        self.edit.append(text)

    def eventFilter(self, object, event):
        # Update the line numbers for all events on the text edit and the viewport.
        # This is easier than connecting all necessary singals.
        if object in (self.edit, self.edit.viewport()):
            self.number_bar.update()
            return False
        return QFrame.eventFilter(object, event)

    def getTextEdit(self):
        return self.edit
Example #18
0
class DownloaderWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.DownloadPath = os.path.expanduser("~") # get home dir
        self.pool = QThreadPool()
        self.pool.setMaxThreadCount(1)

        self.initVariables()

        self.resize(700, 400)
        self.initUI()

        self.line_downpath.setText(self.down_control.getDownloadPath())

    def initVariables(self):
        self.down_control = DownloadController(self.addInfo)
        self.down_control.setDownloadPath(self.DownloadPath)
        self.chapters = None
        self.chapters_filtered = None
        self.ch_from = None
        self.ch_to = None

    def initUI(self):
        cw = QWidget()
        self.setCentralWidget(cw)
        layout_main = QVBoxLayout()
        layout_main.setSpacing(5)

        ## Info
        self.info = QTextEdit()
        self.info.setReadOnly(True)
        self.info.setLineWrapMode(QTextEdit.NoWrap)

        layout_main.addWidget(self.info, 1)

        ## Line edit
        layout_url = QHBoxLayout()
        layout_url.setSpacing(5)

        self.line_url = QLineEdit()

        layout_url.addWidget(QLabel('<b>Series URL:</b>'))
        layout_url.addWidget(self.line_url, 1)
        layout_main.addLayout(layout_url)

        ## Comboboxes
        layout_combo = QHBoxLayout()
        layout_combo.setSpacing(5)

        self.combo_from = QComboBox()
        self.combo_from.setEnabled(False)
        self.combo_to = QComboBox()
        self.combo_to.setEnabled(False)

        layout_combo.addWidget(QLabel('<b>Download chapters: </b>'))
        layout_combo.addWidget(QLabel(' From:'))
        layout_combo.addWidget(self.combo_from, 1)
        layout_combo.addWidget(QLabel('To:'))
        layout_combo.addWidget(self.combo_to, 1)

        layout_main.addLayout(layout_combo)

        ## Download path
        layout_downpath = QHBoxLayout()
        layout_downpath.setSpacing(5)

        self.line_downpath = QLineEdit()
        self.line_downpath.setEnabled(False)
        self.btn_downpath = QPushButton('Change')
        self.btn_downpath.pressed.connect(self.selectDownloadPath)

        layout_downpath.addWidget(QLabel('<b>Download path:</b>'))
        layout_downpath.addWidget(self.line_downpath, 1)
        layout_downpath.addWidget(self.btn_downpath)
        layout_main.addLayout(layout_downpath)

        ## Buttons
        layout_btn = QHBoxLayout()
        layout_btn.setSpacing(5)

        self.btn_getlist = QPushButton('Get List of Chapters')
        self.btn_getlist.pressed.connect(self.getChaptersList)
        self.btn_download = QPushButton('Download chapters')
        self.btn_download.pressed.connect(self.downloadChapters)
        self.btn_download.setEnabled(False)
        self.btn_exit = QPushButton('Exit')
        self.btn_exit.pressed.connect(self.close)

        layout_btn.addStretch()
        layout_btn.addWidget(self.btn_getlist)
        layout_btn.addWidget(self.btn_download)
        layout_btn.addWidget(self.btn_exit)
        layout_btn.addStretch()
        layout_main.addLayout(layout_btn)

        # status bar
        self.statusBar().showMessage('Ready')

        # add layout to main window
        cw.setLayout(layout_main)
        self.setWindowTitle('OMAD - Online MAnga Downloader')
        self.show()

    def closeEvent(self, event):
        """
        Runs when user tryes to close main window.

        sys.exit(0) - to fix wierd bug, where process is not terminated.
        """
        sys.exit(0)

    def addInfo(self, s='Testing printing...', exception=False, downloadProgress=False, trace=[]):
        logger.info(s+', '+str(exception)+', '+str(downloadProgress)+', '+str(trace))

        if type(s)!=type("") and type(s)!=type(b"") and type(s) != type(QtCore.QString('')):
            s = str(s)

        if exception:
            s = "!!! Exception: "+s

        if downloadProgress:
            s = "Downloading progress: "+s
            self.setStatusBarText(s)

        self.info.append(s)

        if exception:
            for t in trace:
                self.info.append(str(t))

        sb = self.info.verticalScrollBar()
        sb.setValue(sb.maximum())

        QtCore.QCoreApplication.processEvents()

    def setStatusBarText(self, s='Testing...'):
        """
        Changes status bar text
        """
        self.statusBar().showMessage(s)
        QtCore.QCoreApplication.processEvents()

    def getChaptersList(self):
        self.addInfo('Getting list of chapters...')

        # reinit clean variables
        self.initVariables()

        # get series url
        url = str(self.line_url.text()).strip()

        if not self.down_control.setSeriesUrl(url):
            return # bad url

        self.chapters = self.down_control.getChaptersList()

        logger.debug('Setting up comboBoxes...')
        for i in range(0, self.combo_from.count()):
            self.combo_from.removeItem(0)
        for i in range(0, self.combo_to.count()):
            self.combo_to.removeItem(0)

        for c in self.chapters:
            self.combo_from.addItem(c[0])
            self.combo_to.addItem(c[0])

        self.combo_from.setCurrentIndex(0)
        self.combo_to.setCurrentIndex(len(self.chapters)-1)

        self.addInfo('Chapter list loaded')

        self.combo_from.setEnabled(True)
        self.combo_to.setEnabled(True)
        self.btn_download.setEnabled(True)

    def downloadChapters(self):
        self.addInfo('Checking chapter range')

        self.ch_from = self.combo_from.currentIndex()
        self.ch_to = self.combo_to.currentIndex()

        if self.ch_from>self.ch_to:
            self.addInfo('Bad range. Cant download backwards!')
            return
        else:
            self.addInfo('Range OK, starting download of '+str((self.ch_to-self.ch_from)+1)+' chapters...')

        self.gui_disable(True)

        worker = DownloadWorker(self.down_control, self.ch_from, self.ch_to)
        worker.signals.update.connect(self.addInfo)
        worker.signals.finished.connect(self.downloadChapters_finished)
        self.pool.start(worker)

    def downloadChapters_finished(self):
        self.gui_disable(False)
        self.setStatusBarText('Ready - Download Finished!!')

        # Finished
        self.addInfo('Download Finished!!')

        # Print failed downloads
        failed_chs = []
        for i, r in enumerate(self.down_control.results):
            if r is False:
                failed_chs.append(self.chapters[i+self.ch_from])

        if len(failed_chs)==0:
            self.addInfo('\nNo failed downloads')
        else:
            self.addInfo('\nChapters with failed downloads:')
            for c in failed_chs:
                self.addInfo(c[0])
        self.addInfo('')

    def selectDownloadPath(self):
        downdir = self._get_dir(directory=self.DownloadPath)
        self.down_control.setDownloadPath(downdir)
        self.DownloadPath = self.down_control.getDownloadPath()
        self.line_downpath.setText(self.DownloadPath)

    def _get_dir(self, directory=''):
        """
        Draw a dialog for directory selection.
        """

        downdir = QFileDialog.getExistingDirectory(
            caption='Select Folder',
            options=QFileDialog.ShowDirsOnly,
            directory=directory
        )

        if len(downdir) > 0:
            downdir = "%s" % (downdir)
        else:
            downdir = directory

        return downdir

    def gui_disable(self, downloading=True):
        self.line_url.setEnabled(not downloading)
        self.combo_from.setEnabled(not downloading)
        self.combo_to.setEnabled(not downloading)
        self.btn_getlist.setEnabled(not downloading)
        self.btn_download.setEnabled(not downloading)
        self.btn_downpath.setEnabled(not downloading)
class BugReportsWidget(QWidget):
    PREFERRED_WIDTH  = 400
    PREFERRED_HEIGHT = 150
    
    def __init__(self, parent, mt):
        super(BugReportsWidget, self).__init__(parent)
        self.mt = mt
        
        layout = QVBoxLayout(self)
#         layout.setContentsMargins(0, 0, 0, 0)
        
        self.entry = QTextEdit(self)
        
        self.issues = {}
        self.issuesComboModel = IssuesComboModel()
        
        self.dropdown_reports = QComboBox(self)
        self.dropdown_reports.setModel(self.issuesComboModel)
        self.display_report()
        self.details_btn = QPushButton("Details", self)
        self.details_btn.setEnabled(False)
        self.refresh_btn = QPushButton("Refresh", self)
        create_report_btn = QPushButton("New", self)
        
        topLayout = QHBoxLayout()
        topLayout.addWidget(self.dropdown_reports, 1)
        topLayout.addWidget(self.details_btn)
        topLayout.addWidget(self.refresh_btn)
        topLayout.addSpacing(20)
        topLayout.addWidget(create_report_btn)
        layout.addLayout(topLayout)

        layout.addWidget(QLabel("Description:", self))
        
        self.entry.setLineWrapMode(QTextEdit.WidgetWidth)
        self.entry.setReadOnly(True)
        layout.addWidget(self.entry)
                
        self.dropdown_reports.currentIndexChanged.connect(self.display_report)
        self.details_btn.clicked.connect(self.displayReportDetails)
        self.refresh_btn.clicked.connect(self.update_reports)
        create_report_btn.clicked.connect(self.createBugReport)
        
        self.update_reports()

    def repoChanged(self):
        self.update_reports()

    def displayReportDetails(self):
        selectedIssue = self.selectedIssue()
        if selectedIssue == None:
            return
        url = selectedIssue.issueUrl
        if url != None:
            webbrowser.open(url, new=2)
            
    def isRepoSpecified(self):
        repoUser = self.mt.options[u"repo_user"]
        repoName = self.mt.options[u"repo_name"]
        if repoUser and repoName:
            return True
        return False

    @pyqtSlot(QThread, unicode)
    def downloadedIssues(self, thread, _):
        self.refresh_btn.setEnabled(self.isRepoSpecified())
        j = json.loads(thread.getResult())
        
        newKeys = set()
        for i, issueDict in enumerate(j):
            issue = Issue(issueDict)
            newKeys.add(issue.id)
            self.issues[issue.id] = issue
            if not self.issuesComboModel.hasKey(issue.id):
                self.issuesComboModel.externalRowInserted(issue.id, issue, i)
            else:
                self.issuesComboModel.externalRowUpdated(issue.id, issue)
        
        oldKeys = set(self.issuesComboModel.keys)
        for removedKey in oldKeys - newKeys:
            self.issuesComboModel.externalRowRemoved(removedKey)
        self.details_btn.setEnabled(self.issuesComboModel.rowCount() > 0)
        
    @pyqtSlot(QThread, unicode)
    def errorDownloadingIssues(self, _thread, _url):
        self.refresh_btn.setEnabled(self.isRepoSpecified())
        log_error("Error fetching issues from github.")

    def update_reports(self):
        self.refresh_btn.setEnabled(False)
        repoUser = self.mt.options[u"repo_user"]
        repoName = self.mt.options[u"repo_name"]
        if repoUser and repoName:
            log_debug("Fetching issues from repository %s/%s" % (repoUser, repoName))
            thread = DownloadThread(self, "https://api.github.com/repos/%s/%s/issues?state=open" % (repoUser, repoName))
            thread.finished.connect(thread.deleteLater)
            thread.error.connect(self.errorDownloadingIssues)
            thread.success.connect(self.downloadedIssues)
            thread.start()
        else:
            log_warning("No Lunchinator GitHub repository specified.")
            
    def createBugReport(self):
        repoUser = self.mt.options[u"repo_user"]
        repoName = self.mt.options[u"repo_name"]
        if repoUser and repoName:
            url = "https://github.com/%s/%s/issues/new" % (repoUser, repoName)
            if url != None:
                webbrowser.open(url, new=2)
        else:
            log_warning("No Lunchinator GitHub repository specified.")
            QMessageBox.critical(self, "No Repository", "No Lunchinator GitHub repository specified.", buttons=QMessageBox.Ok, defaultButton=QMessageBox.Ok)
        
    def selectedIssue(self):
        issueID = self.dropdown_reports.itemData(self.dropdown_reports.currentIndex(), IssuesComboModel.KEY_ROLE).toInt()[0]
        if not issueID in self.issues:
            log_error("ID of selected issue is not in issues dictionary")
            return None
        return self.issues[issueID]
        
    def display_report(self):
        if self.dropdown_reports.currentIndex()>=0:
            self.entry.setText(self.selectedIssue().description)    

    def sizeHint(self):
        return QSize(self.PREFERRED_WIDTH, self.PREFERRED_HEIGHT)
Example #20
0
class MembersWidget(QWidget):
    def __init__(self, parent, logger):
        super(MembersWidget, self).__init__(parent)

        self.logger = logger
        layout = QVBoxLayout(self)
        layout.setSpacing(0)

        self.dropdown_members_dict = {}
        self.dropdown_members_model = DropdownModel(get_peers(), self.logger)
        self.dropdown_members = QComboBox(self)
        self.dropdown_members.setModel(self.dropdown_members_model)

        topLayout = QHBoxLayout()
        topLayout.setSpacing(10)
        topLayout.addWidget(self.dropdown_members, 1)
        self.requestLogsButton = QPushButton("Request Logfiles", self)
        topLayout.addWidget(self.requestLogsButton)
        layout.addLayout(topLayout)

        layout.addWidget(QLabel("Member Information:", self))
        self.memberInformationTable = QTreeWidget(self)
        self.memberInformationTable.setMaximumHeight(65)
        self.memberInformationTable.setSelectionMode(QTreeWidget.NoSelection)
        layout.addWidget(self.memberInformationTable, 0)

        layout.addWidget(QLabel("Send Message:", self))

        sendMessageLayout = QHBoxLayout()
        sendMessageLayout.setSpacing(10)
        messageInput = HistoryLineEdit(self, "Enter a message")
        self.sendMessageButton = QPushButton("Send", self)
        sendMessageLayout.addWidget(messageInput, 1)
        sendMessageLayout.addWidget(self.sendMessageButton)
        layout.addLayout(sendMessageLayout)

        layout.addWidget(QLabel("Log files:", self))
        logSplitter = QSplitter(Qt.Horizontal, self)

        logListWidget = QWidget(self)
        logListLayout = QVBoxLayout(logListWidget)
        logListLayout.setContentsMargins(0, 0, 0, 0)

        self.log_tree_view = QTreeWidget(logSplitter)
        self.log_tree_view.setAlternatingRowColors(True)
        self.log_tree_view.setColumnCount(1)
        self.log_tree_view.setHeaderHidden(True)
        self.log_tree_view.setItemsExpandable(False)
        self.log_tree_view.setIndentation(0)

        logListLayout.addWidget(self.log_tree_view, 1)

        logListBottomLayout = QHBoxLayout()
        self.logSizeLabel = QLabel(logListWidget)
        logListBottomLayout.addWidget(self.logSizeLabel, 1)

        self.clearLogsButton = QPushButton("Clear", logListWidget)
        self.clearLogsButton.setEnabled(False)
        self.clearLogsButton.clicked.connect(self.clearLogs)
        logListBottomLayout.addWidget(self.clearLogsButton, 0)

        logListLayout.addLayout(logListBottomLayout)

        logSplitter.addWidget(logListWidget)

        self.log_area = QTextEdit(logListWidget)
        self.log_area.setLineWrapMode(QTextEdit.WidgetWidth)
        self.log_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.log_area.setReadOnly(True)
        logSplitter.addWidget(self.log_area)

        logSplitter.setStretchFactor(0, 0)
        logSplitter.setStretchFactor(1, 1)

        layout.addWidget(logSplitter, 1)

        self.memberSelectionChanged()
        self.log_tree_view.selectionModel().selectionChanged.connect(self.displaySelectedLogfile)
        self.dropdown_members.currentIndexChanged.connect(self.memberSelectionChanged)
        self.requestLogsButton.clicked.connect(self.requestLogClicked)
        self.sendMessageButton.clicked.connect(partial(self.sendMessageToMember, messageInput))
        messageInput.returnPressed.connect(partial(self.sendMessageToMember, messageInput))

        get_notification_center().connectPeerAppended(self.dropdown_members_model.externalRowAppended)
        get_notification_center().connectPeerUpdated(self.dropdown_members_model.externalRowUpdated)
        get_notification_center().connectPeerRemoved(self.dropdown_members_model.externalRowRemoved)
        get_notification_center().connectPeerUpdated(self.updateMemberInformation)

    def destroy_widget(self):
        get_notification_center().disconnectPeerAppended(self.dropdown_members_model.externalRowAppended)
        get_notification_center().disconnectPeerUpdated(self.dropdown_members_model.externalRowUpdated)
        get_notification_center().disconnectPeerRemoved(self.dropdown_members_model.externalRowRemoved)
        get_notification_center().disconnectPeerUpdated(self.updateMemberInformation)

    def listLogfiles(self, basePath, sort=None):
        if sort is None:
            sort = lambda aFile: -self.getLogNumber(aFile)
        logList = [
            os.path.join(basePath, aFile)
            for aFile in os.listdir(basePath)
            if aFile.endswith(".log") and not os.path.isdir(os.path.join(basePath, aFile))
        ]
        return sorted(logList, key=sort)

    def getNumLogsToKeep(self, oldLogFiles, newLogFiles, logOffset):
        oldestNew = None
        for aLogFile in newLogFiles:
            oldestNew, _ = self.getLogDates(aLogFile)
            if oldestNew != None:
                break

        if oldestNew == None:
            # new new log file contains timestamps (they are probably all empty)
            return len(oldLogFiles)

        numToKeep = 0
        while numToKeep < len(oldLogFiles) - logOffset:
            curTime, _ = self.getLogDates(oldLogFiles[numToKeep])
            if curTime == None or curTime < oldestNew:
                # keep empty log files
                numToKeep = numToKeep + 1
            else:
                break
        return numToKeep

    def getLogDates(self, aLogFile):
        with codecs.open(aLogFile, "rb", "utf-8") as logContent:
            logLines = logContent.readlines()
            firstDate = None
            for aLine in logLines:
                firstDate = getLogLineTime(aLine)
                if firstDate != None:
                    break

            lastDate = None
            for aLine in reversed(logLines):
                lastDate = getLogLineTime(aLine)
                if lastDate != None:
                    break

            return firstDate, lastDate

    def getLogNumber(self, aLogFile):
        aLogFile = os.path.basename(aLogFile)
        try:
            return int(aLogFile[: aLogFile.rfind(".")])
        except:
            return -1

    def shiftLogFiles(self, oldLogFiles, numToKeep, shift, logOffset):
        renamedLogfiles = []
        for index, aFile in enumerate(oldLogFiles):
            logNum = self.getLogNumber(aFile)
            if logNum < logOffset:
                # don't touch up-to-date logs
                break
            if index < numToKeep:
                newName = os.path.join(os.path.dirname(aFile), "%d.log" % (logNum + shift))
                renamedLogfiles.append((len(oldLogFiles) - index - 1, aFile, newName))
                os.rename(aFile, newName)
            else:
                os.remove(aFile)
        return renamedLogfiles

    def handleNewLogFiles(self, basePath, tmpPath, logOffset=0):
        oldLogFiles = self.listLogfiles(basePath)
        newLogFiles = self.listLogfiles(tmpPath)

        # check how many log files are actually new
        numToKeep = self.getNumLogsToKeep(oldLogFiles, newLogFiles, logOffset)

        # rename / remove old log files to make room for the new ones
        numNew = len(newLogFiles) - (len(oldLogFiles) - logOffset - numToKeep)
        renamedLogfiles = self.shiftLogFiles(oldLogFiles, numToKeep, numNew, logOffset)

        # move new log files
        addedLogfiles = []
        for index, aLogFile in enumerate(reversed(newLogFiles)):
            shutil.move(aLogFile, basePath)
            if index < numNew:
                addedLogfiles.append((index + logOffset, os.path.join(basePath, os.path.basename(aLogFile))))
        shutil.rmtree(tmpPath, True)

        return numNew, addedLogfiles, renamedLogfiles

    def requestFinished(self):
        self.requestLogsButton.setEnabled(True)
        self.dropdown_members.setEnabled(True)

    @loggingSlot(QThread, object)
    def cb_log_transfer_success(self, thread, path):
        path = convert_string(path)

        basePath = os.path.dirname(path)
        tmpPath = os.path.join(basePath, "tmp")
        if not os.path.exists(tmpPath):
            os.makedirs(tmpPath)

        logsAdded = []
        if path.endswith(".tgz"):
            # extract received log files
            with contextlib.closing(tarfile.open(path, "r:gz")) as tarContent:
                tarContent.extractall(tmpPath)
            _, logsAdded, logsRenamed = self.handleNewLogFiles(basePath, tmpPath)
            self.requestFinished()
        else:
            # log comes from old version
            logNum = 0
            if thread.sender in self.logRequests:
                logNum, requestTime = self.logRequests[thread.sender]
                now = datetime.now()
                td = now - requestTime
                tdSeconds = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6) / 10 ** 6
                if tdSeconds > self.LOG_REQUEST_TIMEOUT:
                    # request timed out or was finished already
                    logNum = 0

            shutil.move(path, os.path.join(tmpPath, "%d.log" % logNum))

            numNew, logsAdded, logsRenamed = self.handleNewLogFiles(basePath, tmpPath, logNum)
            if numNew > 0 and logNum < 9:
                # there might be more new ones
                self.logRequests[thread.sender] = (logNum + 1, datetime.now())
                self.logger.debug("log seems to be new, another!!!")
                logsAdded.append((logNum + 1, None))
                self.request_log(thread.sender, logNum + 1)
            elif thread.sender in self.logRequests:
                # request finished
                del self.logRequests[thread.sender]
                self.requestFinished()
            else:
                self.requestFinished()

        if len(logsAdded) > 0 or len(logsRenamed) > 0:
            self.updateLogList(logsAdded, logsRenamed)

    @loggingSlot(QThread, object)
    def cb_log_transfer_error(self, _thread, message):
        if not self.isVisible():
            return False
        self.log_area.setText("Error while getting log (%s)" % message)
        self.requestFinished()

    def get_selected_log_member(self):
        member = convert_string(self.dropdown_members.currentText())
        if not member:
            return None

        if "(" in member:
            # member contains name, extract ID
            member = member[member.rfind("(") + 1 : member.rfind(")")]

        return member

    def request_log(self, member=None, logNum=0):
        if member == None:
            member = self.get_selected_log_member()
        if member != None:
            self.logger.debug("Requesting log %d from %s", logNum, member)
            get_server().call(
                "HELO_REQUEST_LOGFILE %s %d" % (DataReceiverThread.getOpenPort(category="log%s" % member), logNum),
                set([member]),
            )
        else:
            self.log_area.setText("No Member selected!")

    @loggingSlot()
    def requestLogClicked(self):
        self.requestLogsButton.setEnabled(False)
        self.dropdown_members.setEnabled(False)
        self.updateLogList([(0, None)])
        self.request_log()

    def listLogFilesForMember(self, member):
        if member is None:
            return []
        logDir = os.path.join(get_settings().get_main_config_dir(), "logs", member)
        if not os.path.exists(logDir):
            return []
        return self.listLogfiles(logDir)

    def numLogFilesForMember(self, member):
        return len(self.listLogFilesForMember(member))

    def requestTimedOut(self, item):
        if not sip.isdeleted(item) and item != None and item.data(0, Qt.UserRole) == None:
            self.log_tree_view.takeTopLevelItem(self.log_tree_view.indexFromItem(item).row())
            self.requestFinished()

    def formatFileSize(self, num):
        for x in ["Bytes", "KB", "MB", "GB", "TB"]:
            if num < 1024.0:
                return "%3.1f %s" % (num, x)
            num /= 1024.0

    def initializeLogItem(self, item, logFile):
        firstDate, lastDate = self.getLogDates(logFile)
        text = None
        tooltip = None
        if firstDate != None:
            text = firstDate.strftime("%Y-%m-%d %H:%M:%S")
            tooltip = u"File: %s\nFirst entry: %s\nLast entry: %s" % (
                logFile,
                firstDate.strftime("%Y-%m-%d %H:%M:%S"),
                lastDate.strftime("%Y-%m-%d %H:%M:%S"),
            )
        else:
            timestamp = datetime.fromtimestamp(os.path.getmtime(logFile)).strftime("%Y-%m-%d %H:%M:%S")
            text = u"%s" % os.path.basename(logFile)
            tooltip = u"File:%s\nModification Date: %s" % (logFile, timestamp)
        text = text + "\n%s" % self.formatFileSize(os.path.getsize(logFile))
        if tooltip != None:
            item.setData(0, Qt.ToolTipRole, QVariant(tooltip))
        item.setData(0, Qt.UserRole, logFile)
        item.setData(0, Qt.DisplayRole, QVariant(text))

    @loggingSlot()
    def clearLogs(self):
        for aLogFile in self.listLogFilesForMember(self.get_selected_log_member()):
            os.remove(aLogFile)
        self.updateLogList()

    def updateLogList(self, logsAdded=None, logsRenamed=None):
        selectedMember = self.get_selected_log_member()

        if logsAdded == None:
            self.log_tree_view.clear()
            logsAdded = []
            for index, logFile in enumerate(reversed(self.listLogFilesForMember(selectedMember))):
                logsAdded.append((index, logFile))
            if len(logsAdded) == 0:
                self.log_tree_view.clear()
                self.log_tree_view.addTopLevelItem(
                    QTreeWidgetItem(self.log_tree_view, QStringList("No logs available."))
                )
                self.log_tree_view.setSelectionMode(QTreeWidget.NoSelection)
                self.logSizeLabel.setText("No logs")
                self.clearLogsButton.setEnabled(False)
                return

        if logsRenamed != None:
            for index, oldName, newName in logsRenamed:
                # index + 1 because of the "requesting" item
                item = self.log_tree_view.topLevelItem(index + 1)
                if item != None:
                    itemLogFile = convert_string(item.data(0, Qt.UserRole).toString())
                    if itemLogFile != oldName:
                        self.logger.warning(
                            "index does not correspond to item in list:\n\t%s\n\t%s", itemLogFile, oldName
                        )
                    self.initializeLogItem(item, newName)

        if len(logsAdded) == 0:
            self.log_tree_view.takeTopLevelItem(0)
        else:
            for index, logFile in logsAdded:
                oldItem = self.log_tree_view.topLevelItem(index)
                item = None
                if oldItem != None and oldItem.data(0, Qt.UserRole) == None:
                    # requested item has been received
                    item = oldItem
                else:
                    item = QTreeWidgetItem()
                    oldItem = None

                if logFile == None:
                    item.setData(0, Qt.DisplayRole, QVariant("Requesting..."))
                    QTimer.singleShot(6000, partial(self.requestTimedOut, item))
                else:
                    self.initializeLogItem(item, logFile)

                if oldItem == None:
                    # else, the old item is being modified
                    self.log_tree_view.insertTopLevelItem(index, item)
                self.log_tree_view.setSelectionMode(QTreeWidget.SingleSelection)

        totalSize = 0
        for aLogFile in self.listLogFilesForMember(selectedMember):
            totalSize += os.path.getsize(aLogFile)

        self.logSizeLabel.setText("%s consumed" % self.formatFileSize(totalSize))
        self.clearLogsButton.setEnabled(True)
        # self.displaySelectedLogfile()

    def getSelectedLogContent(self):
        member = self.get_selected_log_member()
        if member == None:
            return "No Log selected."
        selection = self.log_tree_view.selectedIndexes()
        if len(selection) is 0:
            return "No Log selected."

        logPath = convert_string(selection[0].data(Qt.UserRole).toString())
        if logPath == None:
            return "ERROR: path is None"
        if not os.path.exists(logPath):
            return "File not found: " + logPath

        fcontent = ""
        try:
            with codecs.open(logPath, "r", "utf8") as fhandler:
                fcontent = fhandler.read()
        except Exception as e:
            self.logger.exception("Error reading file")
            fcontent = "Error reading file: %s" % str(e)
        return fcontent

    @loggingSlot(QItemSelection, QItemSelection)
    def displaySelectedLogfile(self, _new, _old):
        self.log_area.setText(self.getSelectedLogContent())

    @loggingSlot(int)
    def memberSelectionChanged(self, _new=None):
        self.updateLogList()
        isMemberSelected = self.get_selected_log_member() != None
        self.sendMessageButton.setEnabled(isMemberSelected)
        self.requestLogsButton.setEnabled(isMemberSelected)
        self.updateMemberInformation()

    @loggingSlot(object)
    def sendMessageToMember(self, lineEdit):
        selectedMember = self.get_selected_log_member()
        if selectedMember != None:
            get_server().call(convert_string(lineEdit.text()), set([selectedMember]))
            lineEdit.clear()

    @loggingSlot(object, object)
    def updateMemberInformation(self, peerID=None, peerInfo=None):
        if peerID != None and peerID != self.get_selected_log_member():
            # only update if selected member updated
            return

        self.memberInformationTable.clear()

        if self.get_selected_log_member() == None:
            self.memberInformationTable.setColumnCount(0)
            self.memberInformationTable.setHeaderLabel("No member selected.")
            return

        if peerInfo == None:
            peerInfo = get_peers().getPeerInfo(pID=self.get_selected_log_member())

        if peerInfo == None:
            self.memberInformationTable.setColumnCount(0)
            self.memberInformationTable.setHeaderLabel("No member information available.")
            return

        self.memberInformationTable.setColumnCount(len(peerInfo))
        headers = sorted(peerInfo.keys(), key=lambda s: s.lower())
        self.memberInformationTable.setHeaderLabels(QStringList(headers))
        item = QTreeWidgetItem(self.memberInformationTable)
        for col, header in enumerate(headers):
            item.setData(col, Qt.DisplayRole, QVariant(peerInfo[header]))
        for col in range(self.memberInformationTable.columnCount()):
            self.memberInformationTable.resizeColumnToContents(col)
Example #21
0
class EvtTableWidget(QTableWidget):
    def __init__(self, parent=None):
        QTableWidget.__init__(self, parent)
        self.setColumnCount(6)

        self.setHorizontalHeaderLabels(['level', 'id', 'date', 'source'])
        self.horizontalHeader().setStretchLastSection(True)
        self.verticalHeader().hide()
        self.setSortingEnabled(True)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.setShowGrid(False)
        self.setAlternatingRowColors(True)

        self.hideColumn(4)
        self.hideColumn(5)

        self.cellDoubleClicked.connect(self.dispSingleEvent)
        self.menu = EvtSelectorMenu(self)

    def selectedEvents(self):
        selected = []
        for itemId in range(self.rowCount()):
            item = self.item(itemId, 0)
            if item.checkState() != Qt.Unchecked:
                selected.append(self.itemRecord(itemId))

        if len(selected):
            return selected
        return None

    def mousePressEvent(self, e):
        index = self.indexAt(e.pos())
        if index.isValid():
            item = self.itemAt(e.pos())
            if e.button() == Qt.RightButton:
                self.menu.popup(QCursor.pos())
        QTableWidget.mousePressEvent(self, e)

    def select(self):
        for item in self.selectedItems():
            if item.column() == 0:
                item.setCheckState(Qt.Checked)

    def unselect(self):
        for item in self.selectedItems():
            if item.column() == 0:
                item.setCheckState(Qt.Unchecked)

    def selectAll(self):
        for itemId in range(self.rowCount()):
            item = self.item(itemId, 0)
            item.setCheckState(Qt.Checked)

    def unselectAll(self):
        for itemId in range(self.rowCount()):
            item = self.item(itemId, 0)
            item.setCheckState(Qt.Unchecked)

    def itemRecord(self, row):
        node_ptr = self.item(row, 4).text()
        index = int(self.item(row, 5).text())

        processus_manager = ModuleProcessusManager()
        evt = processus_manager.get('evt')
        record = evt.evts[long(node_ptr)][index]
        return record

    def dispSingleEvent(self, row, column):
        box = QDialog()

        main_layout = QHBoxLayout(box)
        main_widget = QWidget()
        main_layout.addWidget(main_widget)

        layout = QVBoxLayout(main_widget)
        node_ptr = self.item(row, 4).text()
        index = int(self.item(row, 5).text())

        processus_manager = ModuleProcessusManager()
        evt = processus_manager.get('evt')
        record = evt.evts[long(node_ptr)][index]

        self.label1 = QLabel("Date : " + record.getTimeGenerated())
        self.label2 = QLabel("Source : " + record.sourceName())
        self.label3 = QLabel("Type : " + record.getSingleType())
        self.lab_icon = QLabel()
        self.lab_icon.setPixmap(
            QPixmap(record.getIcon()).scaled(32, 32, Qt.KeepAspectRatio))

        weed = QWidget()
        l = QHBoxLayout(weed)
        l.addWidget(self.lab_icon)
        l.addWidget(self.label3)

        self.label4 = QLabel("Category : " + str(record.EventCategory))
        self.label5 = QLabel("EventId : " + str(record.EventID))
        self.label6 = QLabel("Computer : " + record.computerName())

        layout.addWidget(self.subWidget(self.label1, self.label2))
        layout.addWidget(self.subWidget(weed, self.label4))
        layout.addWidget(self.subWidget(self.label5, self.label6))

        layout.addWidget(QLabel('Messages :'))

        self.log_strings = QTextEdit('')
        self.log_strings.setReadOnly(True)
        self.log_strings.setLineWrapMode(QTextEdit.WidgetWidth)

        for log in record.getStrings():
            if log is not None:
                self.log_strings.setPlainText(self.log_strings.toPlainText() +
                                              log + "\n\n")

        layout.addWidget(self.log_strings)
        button_widget = QWidget()
        main_layout.addWidget(button_widget)

        self.next_evt = QPushButton(QIcon(":/next.png"), "")
        self.next_evt.setToolTip("Next record")
        self.prev_evt = QPushButton(QIcon(":/previous.png"), "")
        self.prev_evt.setToolTip("Previous record")
        self.next_evt.clicked.connect(self.dispNextEvent)
        self.prev_evt.clicked.connect(self.dispPrevEvent)

        if row == 0:
            self.prev_evt.setEnabled(False)
        elif row + 1 == self.rowCount():
            self.next_evt.setEnabled(False)
        else:
            self.hideOrDipsButton()

        button_layout = QVBoxLayout(button_widget)
        button_layout.addWidget(self.prev_evt)
        button_layout.addWidget(self.next_evt)

        spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        button_layout.addItem(spacerItem)

        close_button = QPushButton("Close")
        close_button.clicked.connect(box.done)
        button_layout.addWidget(close_button)

        box.exec_()

    def subWidget(self, label1, label2):
        widget = QWidget()
        layout = QHBoxLayout(widget)
        layout.addWidget(label1)
        layout.addWidget(label2)
        return widget

    def dispNextEvent(self, checked):
        row = self.currentRow() + 1
        while row + 1 != self.rowCount() and self.isRowHidden(row):
            row += 1
        self.display(row)

        # is there a next record ?
        while row + 1 != self.rowCount():
            row += 1
            if not self.isRowHidden(row): return
        self.next_evt.setEnabled(False)

    def dispPrevEvent(self, checked):
        row = self.currentRow() - 1
        while row != 0 and self.isRowHidden(row):
            row -= 1
        self.display(row)

        # is there a previous record ?
        while row != 0:
            row -= 1
            if not self.isRowHidden(row): return

        self.prev_evt.setEnabled(False)

    def display(self, row):

        self.setCurrentCell(row, 0)

        node_ptr = self.item(row, 4).text()
        index = int(self.item(row, 5).text())

        processus_manager = ModuleProcessusManager()
        evt = processus_manager.get('evt')
        record = evt.evts[long(node_ptr)][index]

        self.label1.setText("Date : " + record.getTimeGenerated())
        self.label2.setText("Source : " + record.sourceName())
        self.lab_icon.setPixmap(
            QPixmap(record.getIcon()).scaled(32, 32, Qt.KeepAspectRatio))
        self.label3.setText("Type : " + record.getSingleType())
        self.label4.setText("Category : " + str(record.EventCategory))
        self.label5.setText("EventId : " + str(record.EventID))
        self.label6.setText("Computer : " + record.computerName())

        self.log_strings.setPlainText('')
        for log in record.getStrings():
            if log is not None:
                self.log_strings.setPlainText(self.log_strings.toPlainText() +
                                              log + "\n")
        self.hideOrDipsButton()

    def hideOrDipsButton(self):
        row = self.currentRow()
        if row == 0:
            self.prev_evt.setEnabled(False)
        else:
            self.prev_evt.setEnabled(True)

        if row + 1 == self.rowCount():
            self.next_evt.setEnabled(False)
        else:
            self.next_evt.setEnabled(True)

        # is there a next record ?
        row = self.currentRow()
        next_e = False
        while row + 1 != self.rowCount():
            row += 1
            if not self.isRowHidden(row):
                next_e = True
                break
        if next_e == False:
            self.next_evt.setEnabled(False)

        row = self.currentRow()
        # is there a previous record ?
        prev_e = False
        while row != 0:
            row -= 1
            if not self.isRowHidden(row):
                prev_e = True
                break
        if prev_e == False:
            self.prev_evt.setEnabled(False)

    def setItemFlags(self, item):
        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable
                      | Qt.ItemIsEnabled)
        item.setCheckState(Qt.Checked)

    def addItemToTable(self, record, widget, rows, node_ptr, count):
        if count == -1:
            count = rows

        item = QTableWidgetItem(QIcon(record.getIcon()),
                                str(record.getSingleType()))
        self.setItemFlags(item)
        widget.setItem(rows, 0, item)

        item = QTableWidgetItem(str(record.EventID))
        widget.setItem(rows, 1, item)

        item = QTableWidgetItem(str(record.getTimeGenerated()))
        widget.setItem(rows, 2, item)

        item = QTableWidgetItem(str(record.sourceName()))
        widget.setItem(rows, 3, item)

        item = QTableWidgetItem(str(long(node_ptr)))
        widget.setItem(rows, 4, item)

        item = QTableWidgetItem(str(count))
        widget.setItem(rows, 5, item)