コード例 #1
0
ファイル: nuitka-gui.py プロジェクト: GaelicGrime/nuitka-gui
class MyMainWindow(QMainWindow):
    ' Main Window '

    def __init__(self, parent=None):
        ' Initialize QWidget inside MyMainWindow '
        super(MyMainWindow, self).__init__(parent)
        self.statusBar().showMessage(__doc__.title())
        self.setWindowTitle(__doc__)
        self.setMinimumSize(600, 800)
        self.setMaximumSize(2048, 1024)
        self.resize(1024, 800)
        self.setWindowIcon(QIcon.fromTheme("face-monkey"))
        if not A11Y:
            self.setStyleSheet('''QWidget{color:#fff;font-family:Oxygen}
            QWidget:item:hover, QWidget:item:selected {
                background-color: cyan; color: #000
            }
            QWidget:disabled { color: #404040; background-color: #323232 }
            QWidget:focus { border: 1px solid cyan }
            QPushButton {
                background-color: gray;
                padding: 3px; border: 1px solid gray; border-radius: 9px;
                margin: 0;font-size: 12px;
                padding-left: 5px; padding-right: 5px
            }
            QLineEdit, QTextEdit {
                background-color: #4a4a4a; border: 1px solid gray;
                border-radius: 0; font-size: 12px;
            }
            QPushButton:pressed { background-color: #323232 }
            QComboBox {
                background-color: #4a4a4a; padding-left: 9px;
                border: 1px solid gray; border-radius: 5px;
            }
            QComboBox:pressed { background-color: gray }
            QComboBox QAbstractItemView, QMenu {
                border: 1px solid #4a4a4a; background:grey;
                selection-background-color: cyan;
                selection-color: #000;
            }
            QSlider {
                padding: 3px; font-size: 8px; padding-left: 2px;
                padding-right: 2px; border: 5px solid #1e1e1e
            }
            QSlider::sub-page:vertical {
                background-color: QLinearGradient(spread:pad, x1:0, y1:0, x2:1,
                    y2:0.27, stop:0 rgba(255, 0, 0, 255),
                    stop:1 rgba(50, 0, 0, 200));
                border: 4px solid #1e1e1e; border-radius: 5px
            }
            QSlider::add-page:vertical {
                background-color: QLinearGradient(spread:pad, x1:0, y1:0, x2:1,
                    y2:0.27, stop:0 rgba(0, 255, 0, 255),
                    stop:1 rgba(0, 99, 0, 255));
                border: 4px solid #1e1e1e; border-radius: 5px;
            }
            QSlider::handle:vertical {
                background-color: QLinearGradient(spread:pad, x1:0, y1:0, x2:1,
                    y2:0.273, stop:0 rgba(0, 0, 0, 255), stop:1 gray);
                height: 5px; border: 1px dotted #fff; text-align: center;
                border-top-left-radius: 2px; border-bottom-left-radius: 2px;
                border-top-right-radius: 2px; border-bottom-right-radius 2px;
                margin-left: 2px; margin-right: 2px;
            }
            QSlider::handle:vertical:hover { border: 1px solid cyan }
            QSlider::sub-page:vertical:disabled {
                background: #bbb; border-color: #999;
            }
            QSlider::add-page:vertical:disabled {
                background: #eee; border-color: #999;
            }
            QSlider::handle:vertical:disabled {
                background: #eee; border: 1px solid #aaa; border-radius: 4px;
            }
            QToolBar, QStatusBar, QDockWidget::title{background-color:#323232;}
            QToolBar::handle,
            QToolBar::handle:vertical, QToolBar::handle:horizontal {
                border: 1px solid gray; border-radius: 9px; width: 19px;
                height: 19px; margin: 0.5px
            }
            QGroupBox {
                border: 1px solid gray; border-radius: 9px; padding-top: 9px;
            }
            QStatusBar, QToolBar::separator:horizontal,
            QToolBar::separator:vertical {color:gray}
            QScrollBar:vertical{
                background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,
                    stop: 0 #212121,stop: 1.0 #323232);
                width: 10px;
            }
            QScrollBar:horizontal{
                background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                    stop: 0 #212121,stop: 1.0 #323232);
                height: 10px;
            }
            QScrollBar::handle:vertical{
                padding: 2px;
                min-height: 50px;
                background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,
                    stop: 0 #585858,stop: 1.0 #404040);
                border-radius: 5px;
                border: 1px solid #191919;
            }
            QScrollBar::handle:horizontal{
                padding: 2px;
                min-width: 50px;
                background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                    stop: 0 #585858,stop: 1.0 #404040);
                border-radius: 5px;
                border: 1px solid #191919;
            }
            QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical,
            QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical,
            QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal,
            QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
                background: none; border: none;
            }
            QDockWidget::close-button, QDockWidget::float-button {
                border: 1px solid gray;
                border-radius: 3px;
                background: darkgray;
            }''')

        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.read_output)
        self.process.readyReadStandardError.connect(self.read_errors)
        self.process.finished.connect(self._process_finished)
        self.process.error.connect(self._process_finished)

        self.group0, self.group1 = QGroupBox("Options"), QGroupBox("Paths")
        self.group2 = QGroupBox("Nodes")
        self.group3 = QGroupBox("Python Code")
        self.group4, self.group5 = QGroupBox("Logs"), QGroupBox("Backend")
        g0grid, g1vlay = QGridLayout(self.group0), QVBoxLayout(self.group1)
        g5vlay = QVBoxLayout(self.group5)

        self.treeview_nodes, self.textedit_source = QTextEdit(), QTextEdit()
        self.dock1, self.dock2 = QDockWidget(), QDockWidget()
        self.output, self.dock3 = QTextEdit(), QDockWidget()
        self.treeview_nodes.setAutoFormatting(QTextEdit.AutoAll)
        self.treeview_nodes.setWordWrapMode(QTextOption.NoWrap)
        self.dock1.setWidget(self.treeview_nodes)
        self.dock2.setWidget(self.textedit_source)
        self.dock3.setWidget(self.output)
        self.dock1.setWindowTitle("Tree")
        self.dock2.setWindowTitle("Sources")
        self.dock3.setWindowTitle("STDOutput")
        featur = QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable
        self.dock1.setFeatures(featur)
        self.dock2.setFeatures(featur)
        self.dock3.setFeatures(featur)
        QVBoxLayout(self.group2).addWidget(self.dock1)
        QVBoxLayout(self.group3).addWidget(self.dock2)
        QVBoxLayout(self.group4).addWidget(self.dock3)
        self.slider1, self.slider2 = QSlider(), QSlider()
        g0grid.addWidget(self.slider1, 0, 0)
        g0grid.addWidget(QLabel('Use Debug'), 0, 1)
        self.slider2.setValue(1)
        g0grid.addWidget(self.slider2, 1, 0)
        g0grid.addWidget(QLabel('Use verbose'), 1, 1)

        self.slider3, self.slider4 = QSlider(), QSlider()
        self.slider3.setValue(1)
        g0grid.addWidget(self.slider3, 2, 0)
        g0grid.addWidget(QLabel('Show compiling progress'), 2, 1)
        self.slider4.setValue(1)
        g0grid.addWidget(self.slider4, 3, 0)
        g0grid.addWidget(QLabel('Show Scons building debug'), 3, 1)

        self.slider5, self.slider6 = QSlider(), QSlider()
        g0grid.addWidget(self.slider5, 4, 0)
        g0grid.addWidget(QLabel('Keep debug unstriped binary'), 4, 1)
        g0grid.addWidget(self.slider6, 5, 0)
        g0grid.addWidget(QLabel('Traced execution outputs'), 5, 1)

        self.slider7, self.slider8 = QSlider(), QSlider()
        self.slider7.setValue(1)
        g0grid.addWidget(self.slider7, 6, 0)
        g0grid.addWidget(QLabel('Remove the build folder'), 6, 1)
        g0grid.addWidget(self.slider8, 7, 0)
        g0grid.addWidget(QLabel('No Python Optimizations'), 7, 1)

        self.slider9, self.slider10 = QSlider(), QSlider()
        g0grid.addWidget(self.slider9, 8, 0)
        g0grid.addWidget(QLabel('No Statements line numbers'), 8, 1)
        g0grid.addWidget(self.slider10, 9, 0)
        g0grid.addWidget(QLabel('Execute the output binary'), 9, 1)

        self.slider11, self.slider12 = QSlider(), QSlider()
        g0grid.addWidget(self.slider11, 10, 0)
        g0grid.addWidget(QLabel('Warning detected implicit exceptions'), 10, 1)
        g0grid.addWidget(self.slider12, 11, 0)
        g0grid.addWidget(QLabel('Keep the PYTHONPATH, do not Reset it'), 11, 1)

        self.slider13 = QSlider()
        g0grid.addWidget(self.slider13, 12, 0)
        g0grid.addWidget(QLabel('Enhance compile, CPython incompatible'), 12,
                         1)

        self.slider1a, self.slider2a = QSlider(), QSlider()
        g0grid.addWidget(self.slider1a, 0, 2)
        g0grid.addWidget(QLabel('Descendent Recursive Compile'), 0, 3)
        self.slider2a.setValue(1)
        g0grid.addWidget(self.slider2a, 1, 2)
        g0grid.addWidget(QLabel('Force non recursive compile'), 1, 3)

        self.slider3a, self.slider4a = QSlider(), QSlider()
        g0grid.addWidget(self.slider3a, 2, 2)
        g0grid.addWidget(QLabel('STD Lib Recursive Compile'), 2, 3)
        g0grid.addWidget(self.slider4a, 3, 2)
        g0grid.addWidget(QLabel('Enforce the use of Clang'), 3, 3)

        self.slider5a, self.slider6a = QSlider(), QSlider()
        self.slider5a.setValue(1)
        g0grid.addWidget(self.slider5a, 4, 2)
        g0grid.addWidget(QLabel('Use G++ link time optimizations'), 4, 3)
        g0grid.addWidget(self.slider6a, 5, 2)
        g0grid.addWidget(QLabel('Disable the console window'), 5, 3)

        self.slider7a, self.slider8a = QSlider(), QSlider()
        g0grid.addWidget(self.slider7a, 6, 2)
        g0grid.addWidget(QLabel('Force compile for MS Windows'), 6, 3)
        g0grid.addWidget(self.slider8a, 7, 2)
        g0grid.addWidget(QLabel('Use Python Debug versions'), 7, 3)

        self.slider9a, self.slider10a = QSlider(), QSlider()
        self.slider9a.setValue(1)
        g0grid.addWidget(self.slider9a, 8, 2)
        g0grid.addWidget(QLabel('Create standalone executable'), 8, 3)
        g0grid.addWidget(self.slider10a, 9, 2)
        g0grid.addWidget(QLabel('Enable Standalone mode build'), 9, 3)

        self.slider11a, self.slider12a = QSlider(), QSlider()
        g0grid.addWidget(self.slider11a, 10, 2)
        g0grid.addWidget(QLabel('Make module executable instead of app'), 10,
                         3)
        g0grid.addWidget(self.slider12a, 11, 2)
        g0grid.addWidget(QLabel('No froze module of stdlib as bytecode'), 11,
                         3)

        self.slider13a = QSlider()
        g0grid.addWidget(self.slider13a, 12, 2)
        g0grid.addWidget(QLabel('Force use of MinGW on MS Windows'), 12, 3)

        for each_widget in (self.slider1, self.slider2, self.slider3,
                            self.slider4, self.slider5, self.slider6,
                            self.slider7, self.slider8, self.slider9,
                            self.slider10, self.slider11, self.slider12,
                            self.slider13, self.slider1a, self.slider2a,
                            self.slider3a, self.slider4a, self.slider5a,
                            self.slider6a, self.slider7a, self.slider8a,
                            self.slider9a, self.slider10a, self.slider11a,
                            self.slider12a, self.slider13a):
            each_widget.setRange(0, 1)
            each_widget.setCursor(QCursor(Qt.OpenHandCursor))
            each_widget.setTickInterval(1)
            each_widget.TickPosition(QSlider.TicksBothSides)

        self.combo1 = QComboBox()
        self.combo1.addItems(('2.7', '2.6', '3.2', '3.3'))
        g5vlay.addWidget(QLabel('Python Version'))
        g5vlay.addWidget(self.combo1)
        self.combo2 = QComboBox()
        self.combo2.addItems(('Default', 'Low', 'High'))
        g5vlay.addWidget(QLabel('CPU priority'))
        g5vlay.addWidget(self.combo2)
        self.combo3 = QComboBox()
        self.combo3.addItems(('1', '2', '3', '4', '5', '6', '7', '8', '9'))
        g5vlay.addWidget(QLabel('MultiProcessing Workers'))
        g5vlay.addWidget(self.combo3)

        self.outdir = QLineEdit()
        self.outdir.setStyleSheet("QLineEdit{margin-left:25px}")
        self.clearButton = QToolButton(self.outdir)
        self.clearButton.setIcon(QIcon.fromTheme("edit-clear"))
        self.clearButton.setIconSize(QSize(25, 25))
        self.clearButton.setStyleSheet("QToolButton{border:none}")
        self.clearButton.hide()
        self.clearButton.clicked.connect(self.outdir.clear)
        self.outdir.textChanged.connect(
            lambda: self.clearButton.setVisible(True))
        self.clearButton.clicked.connect(
            lambda: self.clearButton.setVisible(False))
        self.outdir.setPlaceholderText('Output Directory')
        if path.isfile('.nuitka-output-dir.txt'):
            self.outdir.setText(open('.nuitka-output-dir.txt', 'r').read())
        else:
            self.outdir.setText(path.expanduser("~"))
        self.completer, self.dirs = QCompleter(self), QDirModel(self)
        self.dirs.setFilter(QDir.Dirs | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        self.completer.popup().setStyleSheet(
            """border:1px solid #4a4a4a;background:grey;
            selection-background-color:cyan;selection-color:#000""")
        self.completer.popup().setVerticalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff)
        self.outdir.setCompleter(self.completer)

        self.btn1 = QPushButton(QIcon.fromTheme("document-open"),
                                'Open' if IS_WIN else '')
        self.btn1.clicked.connect(
            lambda: open('.nuitka-output-dir.txt', 'w').write(
                str(
                    QFileDialog.getExistingDirectory(
                        None, 'Open Output Directory', path.expanduser("~")))))
        self.btn1.released.connect(lambda: self.outdir.setText(
            open('.nuitka-output-dir.txt', 'r').read()))
        g1vlay.addWidget(QLabel('Output Directory'))
        g1vlay.addWidget(self.outdir)
        g1vlay.addWidget(self.btn1)

        self.target = QLineEdit()
        self.target.setStyleSheet("QLineEdit{margin-left:25px}")
        self.clearButton2 = QToolButton(self.target)
        self.clearButton2.setIcon(QIcon.fromTheme("edit-clear"))
        self.clearButton2.setIconSize(QSize(25, 25))
        self.clearButton2.setStyleSheet("QToolButton{border:none}")
        self.clearButton2.hide()
        self.clearButton2.clicked.connect(self.target.clear)
        self.target.textChanged.connect(
            lambda: self.clearButton2.setVisible(True))
        self.clearButton2.clicked.connect(
            lambda: self.clearButton2.setVisible(False))
        self.target.setPlaceholderText('Target Python App to Binary Compile')
        self.target.setCompleter(self.completer)
        self.btn2 = QPushButton(QIcon.fromTheme("document-open"),
                                'Open' if IS_WIN else '')
        self.btn2.clicked.connect(lambda: self.target.setText(
            str(
                QFileDialog.getOpenFileName(
                    None, "Open", path.expanduser("~"), ';;'.join([
                        '{}(*.{})'.format(e.upper(), e)
                        for e in ('py', 'pyw', '*')
                    ])))))
        g1vlay.addWidget(QLabel('Input File'))
        g1vlay.addWidget(self.target)
        g1vlay.addWidget(self.btn2)

        self.icon, self.icon_label = QLineEdit(), QLabel('Icon File')
        self.icon.setStyleSheet("QLineEdit{margin-left:25px}")
        self.clearButton3 = QToolButton(self.icon)
        self.clearButton3.setIcon(QIcon.fromTheme("edit-clear"))
        self.clearButton3.setIconSize(QSize(25, 25))
        self.clearButton3.setStyleSheet("QToolButton{border:none}")
        self.clearButton3.hide()
        self.clearButton3.clicked.connect(self.icon.clear)
        self.icon.textChanged.connect(
            lambda: self.clearButton3.setVisible(True))
        self.clearButton3.clicked.connect(
            lambda: self.clearButton3.setVisible(False))
        self.icon.setPlaceholderText('Path to Icon file for your App')
        self.icon.setCompleter(self.completer)
        self.btn3 = QPushButton(QIcon.fromTheme("document-open"),
                                'Open' if IS_WIN else '')
        self.btn3.clicked.connect(lambda: self.icon.setText(
            str(
                QFileDialog.getOpenFileName(
                    None, "Open", path.expanduser("~"), ';;'.join([
                        '{}(*.{})'.format(e.upper(), e)
                        for e in ('ico', 'png', 'bmp', 'svg', '*')
                    ])))))
        g1vlay.addWidget(self.icon_label)
        g1vlay.addWidget(self.icon)
        g1vlay.addWidget(self.btn3)

        # Menu Bar inicialization and detail definitions
        menu_salir = QAction(QIcon.fromTheme("application-exit"), 'Quit', self)
        menu_salir.setStatusTip('Quit')
        menu_salir.triggered.connect(exit)
        menu_minimize = QAction(QIcon.fromTheme("go-down"), 'Minimize', self)
        menu_minimize.setStatusTip('Minimize')
        menu_minimize.triggered.connect(lambda: self.showMinimized())
        menu_qt = QAction(QIcon.fromTheme("help-about"), 'About Qt', self)
        menu_qt.setStatusTip('About Qt...')
        menu_qt.triggered.connect(lambda: QMessageBox.aboutQt(self))
        menu_dev = QAction(QIcon.fromTheme("applications-development"),
                           'Developer Manual PDF', self)
        menu_dev.setStatusTip('Open Nuitka Developer Manual PDF...')
        menu_dev.triggered.connect(lambda: call(
            OPEN + '/usr/share/doc/nuitka/Developer_Manual.pdf.gz', shell=True)
                                   )
        menu_usr = QAction(QIcon.fromTheme("help-contents"), 'User Docs', self)
        menu_usr.setStatusTip('Open Nuitka End User Manual PDF...')
        menu_usr.triggered.connect(lambda: call(
            OPEN + '/usr/share/doc/nuitka/README.pdf.gz', shell=True))
        menu_odoc = QAction(QIcon.fromTheme("help-browser"), 'OnLine Doc',
                            self)
        menu_odoc.setStatusTip('Open Nuitka on line Documentation pages...')
        menu_odoc.triggered.connect(
            lambda: open_new_tab('http://nuitka.net/doc/user-manual.html'))
        menu_man = QAction(QIcon.fromTheme("utilities-terminal"), 'Man', self)
        menu_man.setStatusTip('Open Nuitka technical command line Man Pages..')
        menu_man.triggered.connect(
            lambda: call('xterm -e "man nuitka"', shell=True))
        menu_tra = QAction(QIcon.fromTheme("applications-development"),
                           'View Nuitka-GUI Source Code', self)
        menu_tra.setStatusTip('View, study, edit Nuitka-GUI Libre Source Code')
        menu_tra.triggered.connect(lambda: call(OPEN + __file__, shell=True))
        menu_foo = QAction(QIcon.fromTheme("folder"), 'Open Output Dir', self)
        menu_foo.setStatusTip('Open the actual Output Directory location...')
        menu_foo.triggered.connect(
            lambda: call(OPEN + str(self.outdir.text()), shell=True))
        menu_pic = QAction(QIcon.fromTheme("camera-photo"), 'Screenshot', self)
        menu_pic.setStatusTip('Take a Screenshot for Documentation purposes..')
        menu_pic.triggered.connect(
            lambda: QPixmap.grabWindow(QApplication.desktop().winId()).save(
                QFileDialog.getSaveFileName(None, "Save", path.expanduser("~"),
                                            'PNG(*.png)', 'png')))
        menu_don = QAction(QIcon.fromTheme("emblem-favorite"), 'Help Nuitka',
                           self)
        menu_don.setStatusTip('Help the Nuitka Open Source Libre Free Project')
        menu_don.triggered.connect(
            lambda: open_new_tab('http://nuitka.net/pages/donations.html'))

        # movable draggable toolbar
        self.toolbar = QToolBar(self)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.toggleViewAction().setText("Show/Hide Toolbar")
        l_spacer, r_spacer = QWidget(self), QWidget(self)
        l_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        r_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.toolbar.addWidget(l_spacer)
        self.toolbar.addSeparator()
        self.toolbar.addActions((menu_salir, menu_minimize, menu_qt, menu_odoc,
                                 menu_foo, menu_pic, menu_don))
        if not IS_WIN:
            self.toolbar.addActions((menu_man, menu_dev, menu_tra, menu_usr))
        self.toolbar.addSeparator()
        self.toolbar.addWidget(r_spacer)
        self.addToolBar(Qt.BottomToolBarArea, self.toolbar)

        # Bottom Buttons Bar
        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Close)
        self.buttonBox.rejected.connect(exit)
        self.buttonBox.accepted.connect(self.run)

        self.guimode = QComboBox()
        self.guimode.addItems(('Full UX / UI', 'Simple UX / UI'))
        self.guimode.setStyleSheet(
            """QComboBox{background:transparent;border:0;
            margin-left:25px;color:gray;text-decoration:underline}""")
        self.guimode.currentIndexChanged.connect(self.set_guimode)

        container = QWidget()
        container_layout = QGridLayout(container)  # Y, X
        container_layout.addWidget(self.guimode, 0, 1)
        container_layout.addWidget(self.group2, 1, 0)
        container_layout.addWidget(self.group3, 2, 0)
        container_layout.addWidget(self.group0, 1, 1)
        container_layout.addWidget(self.group1, 2, 1)
        container_layout.addWidget(self.group4, 1, 2)
        container_layout.addWidget(self.group5, 2, 2)
        container_layout.addWidget(self.buttonBox, 3, 1)
        self.setCentralWidget(container)
        # Paleta de colores para pintar transparente
        if not A11Y:
            palette = self.palette()
            palette.setBrush(QPalette.Base, Qt.transparent)
            self.setPalette(palette)
            self.setAttribute(Qt.WA_OpaquePaintEvent, False)

    def get_fake_tree(self, target):
        """Return the fake tree."""
        try:
            fake_tree = check_output(NUITKA + ' --dump-xml ' + target,
                                     shell=True)
        except:
            fake_tree = "ERROR: Failed to get Tree Dump."
        finally:
            return fake_tree.strip()

    def run(self):
        ' run the actual backend process '
        self.treeview_nodes.clear()
        self.textedit_source.clear()
        self.output.clear()
        self.statusBar().showMessage('WAIT!, Working...')
        target = str(self.target.text()).strip()
        self.treeview_nodes.setText(self.get_fake_tree(target))
        self.textedit_source.setText(open(target, "r").read().strip())
        conditional_1 = sys.platform.startswith('linux')
        conditional_2 = self.combo3.currentIndex() != 2
        command_to_run_nuitka = " ".join(
            ('chrt -i 0' if conditional_1 and conditional_2 else '', NUITKA,
             '--debug' if self.slider1.value() else '',
             '--verbose' if self.slider2.value() else '',
             '--show-progress' if self.slider3.value() else '',
             '--show-scons --show-modules' if self.slider4.value() else '',
             '--unstriped' if self.slider5.value() else '',
             '--trace-execution' if self.slider6.value() else '',
             '--remove-output' if self.slider7.value() else '',
             '--no-optimization' if self.slider8.value() else '',
             '--code-gen-no-statement-lines' if self.slider9.value() else '',
             '--execute' if self.slider10.value() else '',
             '--recurse-all' if self.slider1a.value() else '',
             '--recurse-none' if self.slider2a.value() else '',
             '--recurse-stdlib' if self.slider3a.value() else '',
             '--clang' if self.slider4a.value() else '',
             '--lto' if self.slider5a.value() else '',
             '--windows-disable-console' if self.slider6a.value() else '',
             '--windows-target' if self.slider7a.value() else '',
             '--python-debug' if self.slider8a.value() else '',
             '--exe' if self.slider9a.value() else '',
             '--standalone' if self.slider10a.value() else '',
             '--module' if self.slider11a.value() else '',
             '--nofreeze-stdlib' if self.slider12a.value() else '',
             '--mingw' if self.slider13a.value() else '',
             '--warn-implicit-exceptions' if self.slider11.value() else '',
             '--execute-with-pythonpath' if self.slider12.value() else '',
             '--enhanced' if self.slider13.value() else '',
             '--icon="{}"'.format(self.icon.text())
             if self.icon.text() else '', '--python-version={}'.format(
                 self.combo1.currentText()), '--jobs={}'.format(
                     self.combo3.currentText()), '--output-dir="{}"'.format(
                         self.outdir.text()), "{}".format(target)))
        if DEBUG:
            print(command_to_run_nuitka)
        self.process.start(command_to_run_nuitka)
        if not self.process.waitForStarted() and not IS_WIN:
            return  # ERROR !
        self.statusBar().showMessage(__doc__.title())

    def _process_finished(self):
        """finished sucessfully"""
        self.output.setFocus()
        self.output.selectAll()

    def read_output(self):
        """Read and append output to the log"""
        self.output.append(str(self.process.readAllStandardOutput()))

    def read_errors(self):
        """Read and append errors to the log"""
        self.output.append(str(self.process.readAllStandardError()))

    def paintEvent(self, event):
        """Paint semi-transparent background,animated pattern,background text"""
        if not A11Y:
            p = QPainter(self)
            p.setRenderHint(QPainter.Antialiasing)
            p.setRenderHint(QPainter.TextAntialiasing)
            p.setRenderHint(QPainter.HighQualityAntialiasing)
            p.fillRect(event.rect(), Qt.transparent)
            # animated random dots background pattern
            for i in range(4096):
                x = randint(25, self.size().width() - 25)
                y = randint(25, self.size().height() - 25)
                # p.setPen(QPen(QColor(randint(9, 255), 255, 255), 1))
                p.drawPoint(x, y)
            p.setPen(QPen(Qt.white, 1))
            p.rotate(40)
            p.setFont(QFont('Ubuntu', 250))
            p.drawText(200, 99, "Nuitka")
            p.rotate(-40)
            p.setPen(Qt.NoPen)
            p.setBrush(QColor(0, 0, 0))
            p.setOpacity(0.8)
            p.drawRoundedRect(self.rect(), 9, 9)
            p.end()

    def set_guimode(self):
        """Switch between simple and full UX"""
        for widget in (self.group2, self.group3, self.group4, self.group5,
                       self.icon, self.icon_label, self.btn3, self.toolbar,
                       self.statusBar()):
            widget.hide() if self.guimode.currentIndex() else widget.show()
コード例 #2
0
class PylintWidget(QWidget):
    """
    Pylint widget
    """
    DATAPATH = get_conf_path('.pylint.results')
    VERSION = '1.0.2'

    def __init__(self, parent, max_entries=100):
        QWidget.__init__(self, parent)

        self.output = None
        self.error_output = None

        self.max_entries = max_entries
        self.data = [self.VERSION]
        if osp.isfile(self.DATAPATH):
            try:
                data = cPickle.load(file(self.DATAPATH))
                if data[0] == self.VERSION:
                    self.data = data
            except EOFError:
                pass

        self.filecombo = PythonModulesComboBox(self)
        if self.data:
            self.remove_obsolete_items()
            self.filecombo.addItems(self.get_filenames())

        self.start_button = create_toolbutton(self,
                                              get_icon('run.png'),
                                              translate('Pylint', "Analyze"),
                                              tip=translate(
                                                  'Pylint', "Run analysis"),
                                              triggered=self.start)
        self.stop_button = create_toolbutton(self,
                                             get_icon('terminate.png'),
                                             translate('Pylint', "Stop"),
                                             tip=translate(
                                                 'Pylint',
                                                 "Stop current analysis"))
        self.connect(self.filecombo, SIGNAL('valid(bool)'),
                     self.start_button.setEnabled)
        self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)

        browse_button = create_toolbutton(self,
                                          get_icon('fileopen.png'),
                                          tip=translate(
                                              'Pylint',
                                              'Select Python script'),
                                          triggered=self.select_file)

        self.ratelabel = QLabel()
        self.datelabel = QLabel()
        self.log_button = create_toolbutton(self,
                                            get_icon('log.png'),
                                            translate('Pylint', "Output"),
                                            tip=translate(
                                                'Pylint',
                                                "Complete Pylint output"),
                                            triggered=self.show_log)
        self.treewidget = ResultsTree(self)

        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.filecombo)
        hlayout1.addWidget(browse_button)
        hlayout1.addWidget(self.start_button)
        hlayout1.addWidget(self.stop_button)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self.ratelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.datelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.log_button)

        layout = QVBoxLayout()
        layout.addLayout(hlayout1)
        layout.addLayout(hlayout2)
        layout.addWidget(self.treewidget)
        self.setLayout(layout)

        self.process = None
        self.set_running_state(False)

        if not is_pylint_installed():
            for widget in (self.treewidget, self.filecombo, self.start_button,
                           self.stop_button):
                widget.setDisabled(True)
            text = translate('Pylint', 'Please install <b>pylint</b>:')
            url = 'http://www.logilab.fr'
            text += ' <a href=%s>%s</a>' % (url, url)
            self.ratelabel.setText(text)
        else:
            self.show_data()

    def analyze(self, filename):
        if not is_pylint_installed():
            return
        filename = unicode(filename)  # filename is a QString instance
        self.kill_if_running()
        index, _data = self.get_data(filename)
        if index is None:
            self.filecombo.addItem(filename)
            self.filecombo.setCurrentIndex(self.filecombo.count() - 1)
        else:
            self.filecombo.setCurrentIndex(index)
        self.filecombo.selected()
        if self.filecombo.is_valid():
            self.start()

    def select_file(self):
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        filename = QFileDialog.getOpenFileName(
            self, translate('Pylint', "Select Python script"), os.getcwdu(),
            translate('Pylint', "Python scripts") + " (*.py ; *.pyw)")
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        if filename:
            self.analyze(filename)

    def remove_obsolete_items(self):
        """Removing obsolete items"""
        self.data = [self.VERSION] + \
                    [(filename, data) for filename, data in self.data[1:]
                     if is_module_or_package(filename)]

    def get_filenames(self):
        return [filename for filename, _data in self.data[1:]]

    def get_data(self, filename):
        filename = osp.abspath(filename)
        for index, (fname, data) in enumerate(self.data[1:]):
            if fname == filename:
                return index, data
        else:
            return None, None

    def set_data(self, filename, data):
        filename = osp.abspath(filename)
        index, _data = self.get_data(filename)
        if index is not None:
            self.data.pop(index)
        self.data.append((filename, data))
        self.save()

    def set_max_entries(self, max_entries):
        self.max_entries = max_entries
        self.save()

    def save(self):
        while len(self.data) > self.max_entries + 1:
            self.data.pop(1)
        cPickle.dump(self.data, file(self.DATAPATH, 'w'))

    def show_log(self):
        if self.output:
            TextEditor(self.output,
                       title=translate('Pylint', "Pylint output"),
                       readonly=True,
                       size=(700, 500)).exec_()

    def start(self):
        filename = unicode(self.filecombo.currentText())

        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.SeparateChannels)
        self.process.setWorkingDirectory(osp.dirname(filename))
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.read_output)
        self.connect(self.process, SIGNAL("readyReadStandardError()"),
                     lambda: self.read_output(error=True))
        self.connect(self.process,
                     SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)
        self.connect(self.stop_button, SIGNAL("clicked()"), self.process.kill)

        self.output = ''
        self.error_output = ''
        p_args = [osp.basename(filename)]
        self.process.start(PYLINT_PATH, p_args)

        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(
                self, translate('Pylint', "Error"),
                translate('Pylint', "Process failed to start"))

    def set_running_state(self, state=True):
        self.start_button.setEnabled(not state)
        self.stop_button.setEnabled(state)

    def read_output(self, error=False):
        if error:
            self.process.setReadChannel(QProcess.StandardError)
        else:
            self.process.setReadChannel(QProcess.StandardOutput)
        bytes = QByteArray()
        while self.process.bytesAvailable():
            if error:
                bytes += self.process.readAllStandardError()
            else:
                bytes += self.process.readAllStandardOutput()
        text = unicode(QString.fromLocal8Bit(bytes.data()))
        if error:
            self.error_output += text
        else:
            self.output += text

    def finished(self):
        self.set_running_state(False)
        if not self.output:
            return

        # Convention, Refactor, Warning, Error
        results = {'C:': [], 'R:': [], 'W:': [], 'E:': []}
        txt_module = '************* Module '

        module = ''  # Should not be needed - just in case something goes wrong
        for line in self.output.splitlines():
            if line.startswith(txt_module):
                # New module
                module = line[len(txt_module):]
                continue
            for prefix in results:
                if line.startswith(prefix):
                    break
            else:
                continue
            i1 = line.find(':')
            if i1 == -1:
                continue
            i2 = line.find(':', i1 + 1)
            if i2 == -1:
                continue
            line_nb = line[i1 + 1:i2].strip()
            if not line_nb:
                continue
            line_nb = int(line_nb)
            message = line[i2 + 1:]
            item = (module, line_nb, message)
            results[line[:i1 + 1]].append(item)

        # Rate
        rate = None
        txt_rate = 'Your code has been rated at '
        i_rate = self.output.find(txt_rate)
        if i_rate > 0:
            i_rate_end = self.output.find('/10', i_rate)
            if i_rate_end > 0:
                rate = self.output[i_rate + len(txt_rate):i_rate_end]

        # Previous run
        previous = ''
        if rate is not None:
            txt_prun = 'previous run: '
            i_prun = self.output.find(txt_prun, i_rate_end)
            if i_prun > 0:
                i_prun_end = self.output.find('/10', i_prun)
                previous = self.output[i_prun + len(txt_prun):i_prun_end]

        filename = unicode(self.filecombo.currentText())
        self.set_data(filename, (time.localtime(), rate, previous, results))
        self.output = self.error_output + self.output
        self.show_data(justanalyzed=True)

    def kill_if_running(self):
        if self.process is not None:
            if self.process.state() == QProcess.Running:
                self.process.kill()
                self.process.waitForFinished()

    def show_data(self, justanalyzed=False):
        if not justanalyzed:
            self.output = None
        self.log_button.setEnabled(self.output is not None \
                                   and len(self.output) > 0)
        self.kill_if_running()
        filename = unicode(self.filecombo.currentText())
        if not filename:
            return

        _index, data = self.get_data(filename)
        if data is None:
            text = translate('Pylint', 'Source code has not been rated yet.')
            self.treewidget.clear()
            date_text = ''
        else:
            datetime, rate, previous_rate, results = data
            if rate is None:
                text = translate(
                    'Pylint', 'Analysis did not succeed '
                    '(see output for more details).')
                self.treewidget.clear()
                date_text = ''
            else:
                text_style = "<span style=\'color: #444444\'><b>%s </b></span>"
                rate_style = "<span style=\'color: %s\'><b>%s</b></span>"
                prevrate_style = "<span style=\'color: #666666\'>%s</span>"
                color = "#FF0000"
                if float(rate) > 5.:
                    color = "#22AA22"
                elif float(rate) > 3.:
                    color = "#EE5500"
                text = translate('Pylint', 'Global evaluation:')
                text = (text_style % text) + (rate_style % (color,
                                                            ('%s/10' % rate)))
                if previous_rate:
                    text_prun = translate('Pylint', 'previous run:')
                    text_prun = ' (%s %s/10)' % (text_prun, previous_rate)
                    text += prevrate_style % text_prun
                self.treewidget.set_results(filename, results)
                date_text = text_style % time.strftime("%d %b %Y %H:%M",
                                                       datetime)

        self.ratelabel.setText(text)
        self.datelabel.setText(date_text)
コード例 #3
0
ファイル: pylint.py プロジェクト: tonal/KhtEditor
class PyLint(Plugin, QObject):
    """ PyLint Plugin """
    capabilities = ['toolbarHook']
    __version__ = '0.5'
    thread = None

    def do_toolbarHook(self, widget):
        """ Hook to install the pylint toolbar button"""
        widget.addAction('PyLint', self.do_pylint)

    @pyqtSlot()
    def do_pylint(self):
        """ Launch the lint process and create the result window """
        print 'do_pylint'

        self.pylint_pross = QProcess()
        self.pylint_pross.setProcessChannelMode(QProcess.MergedChannels)
        self.pylint_pross.setWorkingDirectory( \
            os.path.dirname(str(self.parent.editor.filename)))
        self.pylint_pross.setReadChannel(QProcess.StandardOutput)

        self.connect(self.pylint_pross, \
            SIGNAL('finished(int)'), \
            self.finished)
        self.connect(self.pylint_pross, \
            SIGNAL('readyReadStandardOutput()'), \
            self.handle_stdout)
        self.connect(self.pylint_pross, \
            SIGNAL('readyReadStandardError()'), \
            self.handle_stderr)
        if (self.pylint_pross.start("pylint", \
                [self.parent.editor.filename,])):
            print 'Cannot start process'

        self.win = ResultWin()
        self.win.setWindowTitle("PyLint Results :" \
            + os.path.basename(str(self.parent.editor.filename)))
        self.win.show()
        if isMAEMO:
            self.win.setAttribute(Qt.WA_Maemo5ShowProgressIndicator, True)

        self.win.connect(self.win.list_view, \
            SIGNAL('doubleClicked(const QModelIndex&)'), \
            self.goto_line)

        self.pylint_pross.waitForStarted()

    def finished(self, _):
        """ Call back called when lint end """
        if isMAEMO:
            self.win.setAttribute(Qt.WA_Maemo5ShowProgressIndicator, False)

    def handle_stdout(self):
        """
        Private slot to handle the readyReadStdout
        signal of the pylint process.
        """
        result_list = []
        #regex = QRegExp('(\w)\S*:\S*(\d*):.*: (.*)')
        regex = QRegExp('(\w)\s*:\s*(\d*):(.*)')
        regex_score = \
            QRegExp('.*at.(\d.\d*)/10.*')
        while self.pylint_pross and self.pylint_pross.canReadLine():
            result = unicode(self.pylint_pross.readLine())
            if result != None:
                pos = 0
                while True:
                    pos = regex.indexIn(result, pos)
                    if pos < 0:
                        if regex_score.indexIn(result, 0) >= 0:
                            self.win.setWindowTitle( \
                                "PyLint Results :" \
                                + str(regex_score.cap(1)) \
                                + ':'
                                + os.path.basename(str(self.parent.editor.filename)))
                        break
                    result_list.append(
                        (regex.cap(1), regex.cap(2), regex.cap(3)))
                    #print 'Append : ',(regex.cap(1), regex.cap(2), regex.cap(3))
                    pos = pos + regex.matchedLength()

        if len(result_list) > 0:
            self.win.append_results(result_list)

    def goto_line(self, index):
        """ Callback called when a lint result is double clicked """
        line = int(self.win.list_model.items[index.row()][1])
        self.parent.do_gotoLine(line)

    def handle_stderr(self):
        """
        Private slot to handle the readyReadStderr
        signal of the pylint process. Currently not
        managed
        """
        print 'error stderr'
コード例 #4
0
 def _performMonitor(self):
     """
     Protected method implementing the monitoring action.
     
     This method populates the statusList member variable
     with a list of strings giving the status in the first column and the
     path relative to the project directory starting with the third column.
     The allowed status flags are:
     <ul>
         <li>"A" path was added but not yet comitted</li>
         <li>"M" path has local changes</li>
         <li>"O" path was removed</li>
         <li>"R" path was deleted and then re-added</li>
         <li>"U" path needs an update</li>
         <li>"Z" path contains a conflict</li>
         <li>" " path is back at normal</li>
     </ul>
     
     @return tuple of flag indicating successful operation (boolean) and 
         a status message in case of non successful operation (QString)
     """
     self.shouldUpdate = False
     
     process = QProcess()
     args = QStringList()
     args.append('status')
     if not Preferences.getVCS("MonitorLocalStatus"):
         args.append('--show-updates')
     args.append('--non-interactive')
     args.append('.')
     process.setWorkingDirectory(self.projectDir)
     process.start('svn', args)
     procStarted = process.waitForStarted()
     if procStarted:
         finished = process.waitForFinished(300000)
         if finished and process.exitCode() == 0:
             output = \
                 unicode(process.readAllStandardOutput(), self.__ioEncoding, 'replace')
             states = {}
             for line in output.splitlines():
                 if self.rx_status1.exactMatch(line):
                     flags = str(self.rx_status1.cap(1))
                     path = self.rx_status1.cap(3).trimmed()
                 elif self.rx_status2.exactMatch(line):
                     flags = str(self.rx_status2.cap(1))
                     path = self.rx_status2.cap(5).trimmed()
                 else:
                     continue
                 if flags[0] in "ACDMR" or \
                    (flags[0] == " " and flags[-1] == "*"):
                     if flags[-1] == "*":
                         status = "U"
                     else:
                         status = flags[0]
                     if status == "C":
                         status = "Z"    # give it highest priority
                     elif status == "D":
                         status = "O"
                     if status == "U":
                         self.shouldUpdate = True
                     name = unicode(path)
                     states[name] = status
                     try:
                         if self.reportedStates[name] != status:
                             self.statusList.append("%s %s" % (status, name))
                     except KeyError:
                         self.statusList.append("%s %s" % (status, name))
             for name in self.reportedStates.keys():
                 if name not in states:
                     self.statusList.append("  %s" % name)
             self.reportedStates = states
             return True, \
                    self.trUtf8("Subversion status checked successfully (using svn)")
         else:
             process.kill()
             process.waitForFinished()
             return False, QString(process.readAllStandardError())
     else:
         process.kill()
         process.waitForFinished()
         return False, self.trUtf8("Could not start the Subversion process.")
コード例 #5
0
ファイル: pythonshell.py プロジェクト: Brainsciences/luminoso
class ExternalPythonShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = ExtPyQsciShell
    def __init__(self, parent=None, fname=None, wdir=None, commands=[],
                 interact=False, debug=False, path=[]):
        ExternalShellBase.__init__(self, parent, wdir,
                                   history_filename='.history_ec.py')
        
        self.shell.set_externalshell(self)

        self.toggle_globals_explorer(False)
        self.interact_check.setChecked(interact)
        self.debug_check.setChecked(debug)
        
        self.monitor_socket = None
        self.interpreter = fname is None
        self.fname = startup.__file__ if fname is None else fname
        
        if self.interpreter:
            self.interact_check.hide()
            self.debug_check.hide()
            self.terminate_button.hide()
        
        self.commands = ["import sys", "sys.path.insert(0, '')"] + commands
        
        # Additional python path list
        self.path = path
        
    def get_toolbar_buttons(self):
        ExternalShellBase.get_toolbar_buttons(self)
        self.globalsexplorer_button = create_toolbutton(self,
                          get_icon('dictedit.png'), self.tr("Variables"),
                          tip=self.tr("Show/hide global variables explorer"),
                          toggled=self.toggle_globals_explorer)
        self.terminate_button = create_toolbutton(self,
              get_icon('terminate.png'), self.tr("Terminate"),
              tip=self.tr("Attempts to terminate the process.\n"
                          "The process may not exit as a result of clicking "
                          "this button\n(it is given the chance to prompt "
                          "the user for any unsaved files, etc)."))        
        self.interact_check = QCheckBox(self.tr("Interact"), self)
        self.debug_check = QCheckBox(self.tr("Debug"), self)
        return [self.interact_check, self.debug_check,
                self.globalsexplorer_button, self.run_button,
                self.terminate_button, self.kill_button]
        
    def get_shell_widget(self):
        # Globals explorer
        self.globalsexplorer = GlobalsExplorer(self)
        self.connect(self.globalsexplorer, SIGNAL('collapse()'),
                     lambda: self.toggle_globals_explorer(False))
        
        # Shell splitter
        self.splitter = splitter = QSplitter(Qt.Vertical, self)
        self.connect(self.splitter, SIGNAL('splitterMoved(int, int)'),
                     self.splitter_moved)
        splitter.addWidget(self.shell)
        splitter.setCollapsible(0, False)
        splitter.addWidget(self.globalsexplorer)
        splitter.setStretchFactor(0, 2)
        splitter.setStretchFactor(1, 1)
        return splitter
    
    def get_icon(self):
        return get_icon('python.png')

    def set_buttons_runnning_state(self, state):
        ExternalShellBase.set_buttons_runnning_state(self, state)
        self.interact_check.setEnabled(not state)
        self.debug_check.setEnabled(not state)
        self.terminate_button.setEnabled(state)
        if not state:
            self.toggle_globals_explorer(False)
        self.globalsexplorer_button.setEnabled(state)
    
    def create_process(self):
        self.shell.clear()
            
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        self.connect(self.shell, SIGNAL("wait_for_ready_read()"),
                     lambda: self.process.waitForReadyRead(250))
        
        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)

        #-------------------------Python specific-------------------------------
        # Python arguments
        p_args = ['-u']
        if self.interact_check.isChecked():
            p_args.append('-i')
        if self.debug_check.isChecked():
            p_args.extend(['-m', 'pdb'])
        p_args.append(self.fname)
        
        env = self.process.systemEnvironment()
        
        # Monitor
        env.append('SHELL_ID=%s' % id(self))
        from spyderlib.widgets.externalshell.monitor import start_server
        server, port = start_server()
        self.notification_thread = server.register(str(id(self)), self)
        self.connect(self.notification_thread, SIGNAL('refresh()'),
                     self.globalsexplorer.refresh_table)
        env.append('SPYDER_PORT=%d' % port)
        
        # Python init commands (interpreter only)
        if self.commands and self.interpreter:
            env.append('PYTHONINITCOMMANDS=%s' % ';'.join(self.commands))
            self.process.setEnvironment(env)
            
        pathlist = []

        # Fix encoding with custom "sitecustomize.py"
        scpath = osp.dirname(osp.abspath(__file__))
        pathlist.append(scpath)
        
        # Adding Spyder path
        pathlist += self.path
        
        # Adding path list to PYTHONPATH environment variable
        pypath = "PYTHONPATH"
        pathstr = os.pathsep.join(pathlist)
        if os.environ.get(pypath) is not None:
            env.replaceInStrings(pypath+'=', pypath+'='+pathstr+os.pathsep,
                                 Qt.CaseSensitive)
        else:
            env.append(pypath+'='+pathstr)
        self.process.setEnvironment(env)
        #-------------------------Python specific-------------------------------
            
        if self.arguments:
            p_args.extend( self.arguments.split(' ') )
                        
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)

        self.connect(self.terminate_button, SIGNAL("clicked()"),
                     self.process.terminate)
        self.connect(self.kill_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        #-------------------------Python specific-------------------------------
        self.process.start(sys.executable, p_args)
        #-------------------------Python specific-------------------------------
            
        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, self.tr("Error"),
                                 self.tr("Process failed to start"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))
            
        return self.process
    
#===============================================================================
#    Input/Output
#===============================================================================
    def _write_error(self, text, findstr):
        pos = text.find(findstr)
        if pos != -1:
            self.shell.write(text[:pos])
            if text.endswith(">>> "):
                self.shell.write_error(text[pos:-5])
                self.shell.write(text[-5:], flush=True)
            else:
                self.shell.write_error(text[pos:])
            return True
        return False
    
    def write_output(self):
        text = self.get_stdout()
        if not self._write_error(text, 'Traceback (most recent call last):') \
           and not self._write_error(text, 'File "<stdin>", line 1'):
            self.shell.write(text)
        QApplication.processEvents()
        
    def send_to_process(self, qstr):
        if not isinstance(qstr, QString):
            qstr = QString(qstr)
        if not qstr.endsWith('\n'):
            qstr.append('\n')
        self.process.write(qstr.toLocal8Bit())
        self.process.waitForBytesWritten(-1)
        
    def keyboard_interrupt(self):
        communicate(self.monitor_socket, "thread.interrupt_main()")
            
#===============================================================================
#    Globals explorer
#===============================================================================
    def toggle_globals_explorer(self, state):
        self.splitter.setSizes([1, 1 if state else 0])
        self.globalsexplorer_button.setChecked(state)
        if state:
            self.globalsexplorer.refresh_table()
        
    def splitter_moved(self, pos, index):
        self.globalsexplorer_button.setChecked( self.splitter.sizes()[1] )
コード例 #6
0
ファイル: freshexample.py プロジェクト: hlamer/fresh
 def interpret(self, command):
     """Interprets command
     Returns turple (output, exitCode)
     """
     print '~~~~~~~~~ interpret'
     ec = pConsoleCommand.NotFound
     output, ec = pConsoleCommand.interpret( command)
     parts = self.parseCommands( command )
     if parts:
         cmd = parts.takeFirst()
     else:
         cmd = ''
     
     if ec != pConsoleCommand.NotFound :            # nothing to do
         pass
     elif  cmd == "ls" :
         if sys.platform.startswith('win'):
             cmd = "dir %s" % \
             " ".join(pConsoleCommand.quotedStringList(parts)).trim()
         else:
             cmd = "dir %s" % " ".join( \
                 pConsoleCommand.quotedStringList(parts)).trimmed()
         
         process = QProcess()
         process.setProcessChannelMode( QProcess.MergedChannels )
         process.start( cmd )
         process.waitForStarted()
         process.waitForFinished()
         
         output = process.readAll().trimmed()
         ec = process.exitCode()
     elif  cmd == "echo" :
         if parts:
             output = "\n".join(parts)
             ec = pConsoleCommand.Error
         else:
             output = pConsole.tr(console, "No argument given" )
             ec = pConsoleCommand.Success
     elif  cmd == "quit":
         output = pConsole.tr(console, "Quitting the application..." )
         ec = pConsoleCommand.Success
         
         QTimer.singleShot(1000, qApp.quit() )
     elif  cmd == "style" :
         if  parts.count() != 1 :
             output = pConsole.tr(console, "%s take only 1 parameter, %d given"  %
                                     (cmd, len(parts)) )
             ec = pConsoleCommand.Error
         elif  parts[-1] == "list" :
             output = pConsole.tr(console, "Available styles:\n%s" % 
                                     '\n'.join(QStyleFactory.keys()) )
             ec = pConsoleCommand.Success
         else:
             styleExists = parts[-1].lower() in \
                         [key.lower() for key in QStyleFactory.keys()]
             if styleExists:
                 output = pConsole.tr(console, "Setting style to %s..." % parts[-1])
                 self.mMainWindow.setCurrentStyle( parts[-1] )
                 ec = pConsoleCommand.Success
             else:
                 output = pConsole.tr(console, "This style does not exists" )
                 ec = pConsoleCommand.Error
     
     return (output, ec)
コード例 #7
0
ファイル: main.py プロジェクト: juancarlospaco/testrunner
class Main(plugin.Plugin):
    " Main Class "
    def initialize(self, *args, **kwargs):
        " Init Main Class "
        super(Main, self).initialize(*args, **kwargs)
        self.completer, self.dirs = QCompleter(self), QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        self.process, self.mainwidget = QProcess(), QTabWidget()
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self.process.readyReadStandardError.connect(self.readErrors)
        self.process.finished.connect(self._process_finished)
        self.process.error.connect(self._process_finished)
        self.mainwidget.tabCloseRequested.connect(lambda:
            self.mainwidget.setTabPosition(1)
            if self.mainwidget.tabPosition() == 0
            else self.mainwidget.setTabPosition(0))
        self.mainwidget.setStyleSheet('QTabBar{font-weight:bold;}')
        self.mainwidget.setMovable(True)
        self.mainwidget.setTabsClosable(True)
        self.dock, self.scrollable = QDockWidget(), QScrollArea()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(self.mainwidget)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)
        self.locator.get_service('misc').add_widget(self.dock,
                                 QIcon.fromTheme("face-sad"), __doc__)
        self.tab1, self.tab2, self.tab3 = QGroupBox(), QGroupBox(), QGroupBox()
        self.tab4, self.tab5, self.tab6 = QGroupBox(), QGroupBox(), QGroupBox()
        for a, b in ((self.tab1, 'Basics'), (self.tab2, 'Coverage'),
            (self.tab3, 'Extensions'), (self.tab5, 'Regex'),
             (self.tab4, 'Paths'), (self.tab6, 'Run')):
            a.setTitle(b)
            a.setToolTip(b)
            self.mainwidget.addTab(a, QIcon.fromTheme("face-sad"), b)
        QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock
          ).clicked.connect(lambda: QMessageBox.information(self.dock, __doc__,
          ''.join((__doc__, __version__, __license__, 'by', __author__))))

        groupl, groupr, co = QWidget(), QWidget(), QGroupBox()
        self.qckb1 = QCheckBox('Open target directory later')
        self.qckb2 = QCheckBox('Save a LOG file to target later')
        self.qckb3 = QCheckBox('Verbose operation')
        self.qckb4 = QCheckBox('Force Stop on Error')
        self.qckb5 = QCheckBox('Scan Executable files for Tests')
        vboxgl, vboxgr = QVBoxLayout(groupl), QVBoxLayout(groupr)
        for a in (self.qckb1, self.qckb2, self.qckb3, self.qckb4, self.qckb5):
            vboxgl.addWidget(a)
            a.setToolTip(a.text())
        self.qckb6 = QCheckBox('No Byte Compile to .PYC or Delete .PYC later')
        self.qckb7 = QCheckBox('Dont touch sys.path when running tests')
        self.qckb8 = QCheckBox('Traverse all paths of a package')
        self.qckb9 = QCheckBox('Dont capture STDOUT, print STDOUT on the fly')
        self.qckb10 = QCheckBox('Clear all Logging handlers')
        for a in (self.qckb6, self.qckb7, self.qckb8, self.qckb9, self.qckb10):
            vboxgr.addWidget(a)
            a.setToolTip(a.text())
        vboxcon, self.framew = QHBoxLayout(co), QComboBox()
        [vboxcon.addWidget(a) for a in (groupl, groupr)]
        self.chrt = QCheckBox('LOW CPU priority for Backend Process')
        self.framew.addItems(['nosetests', 'PyTest', 'DocTest', 'Unittest',
                              'Django_Test', 'Django-Nose', 'None'])
        self.framew.currentIndexChanged.connect(lambda:  #FIXME refactor for 3
            QMessageBox.information(self.dock, __doc__, '<b>Only Nose for now'))
        self.framew.currentIndexChanged.connect(lambda:  #FIXME refactor for 3
            self.framew.setCurrentIndex(0))
        vboxg1 = QVBoxLayout(self.tab1)
        for each_widget in (QLabel('<b>Framework'), self.framew, self.chrt, co):
            vboxg1.addWidget(each_widget)

        self.t2ck1, self.t2sp1 = QCheckBox('Activate Coverage'), QSpinBox()
        self.t2ck2 = QCheckBox('Erase previously collected Coverage before run')
        self.t2ck3 = QCheckBox('Include all tests modules in Coverage reports')
        self.t2ck4 = QCheckBox('Include all python files on working directory')
        self.t2ck5 = QCheckBox('Produce HTML Coverage reports information')
        self.t2ck6 = QCheckBox('Include Branch Coverage in Coverage reports')
        self.t2sp1.setRange(10, 90)
        self.t2sp1.setValue(75)
        vboxg2 = QVBoxLayout(self.tab2)
        for each_widget in (QLabel('<b>Min Percentage'), self.t2sp1, self.t2ck1,
            self.t2ck2, self.t2ck3, self.t2ck4, self.t2ck5, self.t2ck6):
            vboxg2.addWidget(each_widget)

        groupi, groupd, vbxg3 = QGroupBox(), QGroupBox(), QHBoxLayout(self.tab3)
        vboxgi, vboxgd = QVBoxLayout(groupi), QVBoxLayout(groupd)
        self.t3ck1 = QCheckBox('Activate DocTest to find and run doctests')
        self.t3ck2 = QCheckBox('Look for any doctests in tests modules too')
        self.t3ck3 = QCheckBox('Activate isolation (Do Not use with Coverage!)')
        self.t3ck4 = QCheckBox('Use Detailed Errors, evaluate failed asserts')
        for a in (self.t3ck1, self.t3ck2, self.t3ck3, self.t3ck4):
            vboxgi.addWidget(a)
            a.setToolTip(a.text())
        self.t3ck5 = QCheckBox('Disable special handling of SkipTest exception')
        self.t3ck6 = QCheckBox('Run the tests that failed in the last test run')
        self.t3ck7 = QCheckBox('Use AllModules, Collect tests from all modules')
        self.t3ck8 = QCheckBox('Collect tests names only, do Not run any tests')
        for a in (self.t3ck5, self.t3ck6, self.t3ck7, self.t3ck8):
            vboxgd.addWidget(a)
            a.setToolTip(a.text())
        [vbxg3.addWidget(a) for a in (groupi, groupd)]

        self.t4le1, self.t4le2 = QLineEdit(), QLineEdit(path.expanduser("~"))
        self.t4le1.setCompleter(self.completer)
        self.t4le2.setCompleter(self.completer)
        self.t4le1.setPlaceholderText(' /full/path/to/a/folder/ ')
        self.t4le2.setPlaceholderText(' /full/path/to/a/folder/ ')
        le1b = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        le1b.setMinimumSize(50, 50)
        le1b.clicked.connect(lambda: self.t4le1.setText(
            QFileDialog.getExistingDirectory(None, '', path.expanduser("~"))))
        le2b = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        le2b.clicked.connect(lambda: self.t4le2.setText(
            QFileDialog.getExistingDirectory(None, '', path.expanduser("~"))))
        vboxg4 = QVBoxLayout(self.tab4)
        for a in (QLabel('<b>Directory to look for Tests'), self.t4le1, le1b,
            QLabel('<b>Directory to generate HTML Coverage'), self.t4le2, le2b):
            vboxg4.addWidget(a)
            a.setToolTip(a.text())

        self.t5le1 = QLineEdit(r'(?:^|[\b_\./-])[Tt]est')
        self.t5le2 = QLineEdit()
        self.t5le3, vboxg5 = QLineEdit(), QVBoxLayout(self.tab5)
        r = QPushButton('Reset')
        r.clicked.connect(lambda: self.t5le1.setText(r'(?:^|[\b_\./-])[Tt]est'))
        for a in (QLabel('<b>Matching Name Regex to be test'), self.t5le1, r,
            QLabel('<b>Force Include Regex Tests'), self.t5le2,
            QLabel('<b>Force Exclude Regex Tests'), self.t5le3):
            vboxg5.addWidget(a)
            a.setToolTip(a.text())

        self.output = QTextEdit(''' Engineering is the art of making what you
            want from things you can get.    -Dhobi''')
        self.runbtn = QPushButton(QIcon.fromTheme("face-sad"), 'Start Testing!')
        self.runbtn.setMinimumSize(75, 50)
        self.runbtn.clicked.connect(self.run)
        glow = QGraphicsDropShadowEffect(self)
        glow.setOffset(0)
        glow.setBlurRadius(99)
        glow.setColor(QColor(99, 255, 255))
        self.runbtn.setGraphicsEffect(glow)
        self.kbt = QPushButton(QIcon.fromTheme("application-exit"), 'Kill')
        self.kbt.clicked.connect(lambda: self.process.kill())
        vboxg6 = QVBoxLayout(self.tab6)
        for each_widget in (QLabel('Logs'), self.output, self.runbtn, self.kbt):
            vboxg6.addWidget(each_widget)
        [a.setChecked(True) for a in (self.chrt, self.qckb2, self.qckb3,
                                      self.qckb10, self.t2ck1, self.t2ck2,
                                      self.t2ck5, self.t3ck1, self.t3ck4)]
        self.mainwidget.setCurrentIndex(4)

    def readOutput(self):
        """Read and append output to the logBrowser"""
        self.output.append(str(self.process.readAllStandardOutput()))

    def readErrors(self):
        """Read and append errors to the logBrowser"""
        self.output.append(str(self.process.readAllStandardError()))

    def run(self):
        """Main function calling vagrant to generate the vm"""
        if not len(self.t4le1.text()):
            QMessageBox.information(self.dock, __doc__,
                '<b style="color:red">ERROR: Target Folder can not be Empty !')
            return
        self.output.clear()
        self.output.append('INFO: OK: Starting at {}'.format(datetime.now()))
        self.runbtn.setDisabled(True)
        #nose = True if self.framew.currentText() in 'nosetests' else False
        cmd = ' '.join(('chrt -i 0' if self.chrt.isChecked() else '',
            # tab 1
            self.framew.currentText(),
            '--verbose' if self.qckb3.isChecked() else '--quiet',
            '--stop' if self.qckb4.isChecked() else '',
            '--exe' if self.qckb5.isChecked() else '--noexe',
            '--no-byte-compile' if self.qckb6.isChecked() else '',
            '--no-path-adjustment' if self.qckb7.isChecked() else '',
            '--traverse-namespace' if self.qckb8.isChecked() else '',
            '--nocapture' if self.qckb9.isChecked() else '',
            '--logging-clear-handlers' if self.qckb10.isChecked() else '',
            # tab 2
            '--with-coverage' if self.t2ck1.isChecked() else '',
            '--cover-erase' if self.t2ck2.isChecked() else '',
            '--cover-tests' if self.t2ck3.isChecked() else '',
            '--cover-inclusive' if self.t2ck4.isChecked() else '',
            '--cover-html' if self.t2ck5.isChecked() else '--cover-xml',
            '--cover-branches' if self.t2ck6.isChecked() else '',
            '--cover-min-percentage={}'.format(self.t2sp1.value()),
            # tab 3
            '--with-doctest' if self.t3ck1.isChecked() else '',
            '--doctest-tests' if self.t3ck2.isChecked() else '',
            '--with-isolation' if self.t3ck3.isChecked() else '',
            '--detailed-errors' if self.t3ck4.isChecked() else '',
            '--no-skip' if self.t3ck5.isChecked() else '',
            '--failed' if self.t3ck6.isChecked() else '',
            '--all-modules' if self.t3ck7.isChecked() else '',
            '--collect-only' if self.t3ck8.isChecked() else '',
            # tab 4
            '--where="{}"'.format(self.t4le1.text()),
            '--cover-html-dir="{}"'.format(self.t4le2.text()) if self.t2ck5.isChecked() else '--cover-xml-file={}'.format(path.join(self.t4le2.text(), 'coverage_ninja.xml')),
            # tab 5
            '--match="{}"'.format(self.t5le1.text().encode('utf-8')) if len(self.t5le1.text()) else '',
            '--include="{}"'.format(self.t5le2.text()) if len(self.t5le2.text()) else '',
            '--exclude="{}"'.format(self.t5le3.text()) if len(self.t5le3.text()) else '',
        ))
        self.output.append('INFO: OK: Command: {}'.format(cmd))
        with open(path.join(self.t4le2.text(), 'tests_run_ninja.sh'), 'w') as f:
            self.output.append('INFO: OK : Writing tests_run_ninja.sh')
            f.write('#!/usr/bin/env bash\n# -*- coding: utf-8 -*-\n\n' + cmd)
        try:
            chmod(path.join(self.t4le2.text(), 'tests_run_ninja.sh'), 0775)
        except:
            chmod(path.join(self.t4le2.text(), 'tests_run_ninja.sh'), 0o775)
        self.output.append('INFO: OK: Running Tests !')
        self.process.start(cmd)
        if not self.process.waitForStarted():
            self.output.append('ERROR: FAIL: Unkown Error !')
            self.runbtn.setEnabled(True)
            return
        self.runbtn.setEnabled(True)

    def _process_finished(self):
        """finished sucessfully"""
        self.output.append('INFO: OK: Finished at {}'.format(datetime.now()))
        if self.qckb2.isChecked() is True:
            with open(path.join(self.t4le2.text(), 'test_ninja.log'), 'w') as f:
                self.output.append('INFO: OK: Writing .LOG')
                f.write(self.output.toPlainText())
        if self.qckb1.isChecked() is True:
            self.output.append('INFO:Opening Target Folder')
            try:
                startfile(self.t4le2.text())
            except:
                Popen(["xdg-open", self.t4le2.text()])

    def finish(self):
        ' clear when finish '
        self.process.kill()
コード例 #8
0
ファイル: systemshell.py プロジェクト: koll00/Gui_SM
class ExternalSystemShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = TerminalWidget
    def __init__(self, parent=None, wdir=None, path=[], light_background=True,
                 menu_actions=None, show_buttons_inside=True,
                 show_elapsed_time=True):
        ExternalShellBase.__init__(self, parent=parent, fname=None, wdir=wdir,
                                   history_filename='.history',
                                   light_background=light_background,
                                   menu_actions=menu_actions,
                                   show_buttons_inside=show_buttons_inside,
                                   show_elapsed_time=show_elapsed_time)
        
        # Additional python path list
        self.path = path
        
        # For compatibility with the other shells that can live in the external
        # console
        self.is_ipykernel = False
        self.connection_file = None

    def get_icon(self):
        return get_icon('cmdprompt.png')
    
    def create_process(self):
        self.shell.clear()
            
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        
        # PYTHONPATH (in case we use Python in this terminal, e.g. py2exe)
        env = [unicode(_path) for _path in self.process.systemEnvironment()]
        add_pathlist_to_PYTHONPATH(env, self.path)
        self.process.setEnvironment(env)
        
        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)
            
        # Shell arguments
        if os.name == 'nt':
            p_args = ['/Q']
        else:
            p_args = ['-i']
            
        if self.arguments:
            p_args.extend( shell_split(self.arguments) )
                        
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)
        
        self.connect(self.kill_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        if os.name == 'nt':
            self.process.start('cmd.exe', p_args)
        else:
            # Using bash:
            self.process.start('bash', p_args)
            self.send_to_process("""PS1="\u@\h:\w> "\n""")
            
        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, _("Error"),
                                 _("Process failed to start"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))
            
        return self.process
    
#===============================================================================
#    Input/Output
#===============================================================================
    def transcode(self, bytes):
        if os.name == 'nt':
            return encoding.transcode(str(bytes.data()), 'cp850')
        else:
            return ExternalShellBase.transcode(self, bytes)
    
    def send_to_process(self, text):
        if not isinstance(text, basestring):
            text = unicode(text)
        if text[:-1] in ["clear", "cls", "CLS"]:
            self.shell.clear()
            self.send_to_process(os.linesep)
            return
        if not text.endswith('\n'):
            text += '\n'
        if os.name == 'nt':
            self.process.write(text.encode('cp850'))
        else:
            self.process.write(locale_codec.fromUnicode(text))
        self.process.waitForBytesWritten(-1)
        
    def keyboard_interrupt(self):
        # This does not work on Windows:
        # (unfortunately there is no easy way to send a Ctrl+C to cmd.exe)
        self.send_ctrl_to_process('c')

#        # The following code will soon be removed:
#        # (last attempt to send a Ctrl+C on Windows)
#        if os.name == 'nt':
#            pid = int(self.process.pid())
#            import ctypes, win32api, win32con
#            class _PROCESS_INFORMATION(ctypes.Structure):
#                _fields_ = [("hProcess", ctypes.c_int),
#                            ("hThread", ctypes.c_int),
#                            ("dwProcessID", ctypes.c_int),
#                            ("dwThreadID", ctypes.c_int)]
#            x = ctypes.cast( ctypes.c_void_p(pid),
#                             ctypes.POINTER(_PROCESS_INFORMATION) )
#            win32api.GenerateConsoleCtrlEvent(win32con.CTRL_C_EVENT,
#                                              x.dwProcessID)
#        else:
#            self.send_ctrl_to_process('c')
                
コード例 #9
0
ファイル: render.py プロジェクト: kayosiii/Cadence
class RenderW(QDialog, ui_render.Ui_RenderW):
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.setupUi(self)

        # -------------------------------------------------------------
        # Get JACK client and base information

        global jack_client
        if jack_client:
            self.m_jack_client = jack_client
            self.m_closeClient = False
        else:
            self.m_jack_client = jacklib.client_open("Render-Dialog", jacklib.JackNoStartServer, None)
            self.m_closeClient = True

        self.m_buffer_size = jacklib.get_buffer_size(self.m_jack_client)
        for i in range(self.cb_buffer_size.count()):
            if int(self.cb_buffer_size.itemText(i)) == self.m_buffer_size:
                self.cb_buffer_size.setCurrentIndex(i)

        self.m_sample_rate = jacklib.get_sample_rate(self.m_jack_client)

        # -------------------------------------------------------------
        # Internal stuff

        self.m_max_time = 180
        self.m_last_time = 0
        self.m_freewheel = False

        self.m_timer = QTimer(self)
        self.m_process = QProcess(self)

        # -------------------------------------------------------------
        # Set-up GUI stuff

        # Get List of formats
        self.m_process.start("jack_capture", ["-pf"])
        self.m_process.waitForFinished()

        formats = str(self.m_process.readAllStandardOutput(), encoding="utf-8").split(" ")
        for i in range(len(formats) - 1):
            self.cb_format.addItem(formats[i])
            if formats[i] == "wav":
                self.cb_format.setCurrentIndex(i)

        self.cb_depth.setCurrentIndex(4)  # Float
        self.rb_stereo.setChecked(True)

        self.te_end.setTime(QTime(0, 3, 0))
        self.progressBar.setMinimum(0)
        self.progressBar.setMaximum(0)
        self.progressBar.setValue(0)

        self.b_render.setIcon(getIcon("media-record"))
        self.b_stop.setIcon(getIcon("media-playback-stop"))
        self.b_close.setIcon(getIcon("window-close"))
        self.b_open.setIcon(getIcon("document-open"))
        self.b_stop.setVisible(False)
        self.le_folder.setText(HOME)

        # -------------------------------------------------------------
        # Set-up connections

        self.connect(self.b_render, SIGNAL("clicked()"), SLOT("slot_renderStart()"))
        self.connect(self.b_stop, SIGNAL("clicked()"), SLOT("slot_renderStop()"))
        self.connect(self.b_open, SIGNAL("clicked()"), SLOT("slot_getAndSetPath()"))
        self.connect(self.b_now_start, SIGNAL("clicked()"), SLOT("slot_setStartNow()"))
        self.connect(self.b_now_end, SIGNAL("clicked()"), SLOT("slot_setEndNow()"))
        self.connect(self.te_start, SIGNAL("timeChanged(const QTime)"), SLOT("slot_updateStartTime(const QTime)"))
        self.connect(self.te_end, SIGNAL("timeChanged(const QTime)"), SLOT("slot_updateEndTime(const QTime)"))
        self.connect(self.m_timer, SIGNAL("timeout()"), SLOT("slot_updateProgressbar()"))

    @pyqtSlot()
    def slot_renderStart(self):
        if not os.path.exists(self.le_folder.text()):
            QMessageBox.warning(
                self, self.tr("Warning"), self.tr("The selected directory does not exist. Please choose a valid one.")
            )
            return

        self.group_render.setEnabled(False)
        self.group_time.setEnabled(False)
        self.group_encoding.setEnabled(False)
        self.b_render.setVisible(False)
        self.b_stop.setVisible(True)
        self.b_close.setEnabled(False)

        self.m_freewheel = bool(self.cb_render_mode.currentIndex() == 1)
        new_buffer_size = int(self.cb_buffer_size.currentText())

        time_start = self.te_start.time()
        time_end = self.te_end.time()
        min_time = (time_start.hour() * 3600) + (time_start.minute() * 60) + (time_start.second())
        max_time = (time_end.hour() * 3600) + (time_end.minute() * 60) + (time_end.second())
        self.m_max_time = max_time

        self.progressBar.setMinimum(min_time)
        self.progressBar.setMaximum(max_time)
        self.progressBar.setValue(min_time)
        self.progressBar.update()

        if self.m_freewheel:
            self.m_timer.setInterval(100)
        else:
            self.m_timer.setInterval(500)

        arguments = []

        # Bit depth
        arguments.append("-b")
        arguments.append(self.cb_depth.currentText())

        # Channels
        arguments.append("-c")
        if self.rb_mono.isChecked():
            arguments.append("1")
        elif self.rb_stereo.isChecked():
            arguments.append("2")
        else:
            arguments.append(str(self.sb_channels.value()))

        # Format
        arguments.append("-f")
        arguments.append(self.cb_format.currentText())

        # Controlled by transport
        arguments.append("-jt")

        # Silent mode
        arguments.append("-dc")
        arguments.append("-s")

        # Change current directory
        os.chdir(self.le_folder.text())

        if new_buffer_size != jacklib.get_buffer_size(self.m_jack_client):
            print("NOTICE: buffer size changed before render")
            jacklib.set_buffer_size(self.m_jack_client, new_buffer_size)

        if (
            jacklib.transport_query(self.m_jack_client, None) > jacklib.JackTransportStopped
        ):  # >TransportStopped is rolling/starting
            jacklib.transport_stop(self.m_jack_client)

        jacklib.transport_locate(self.m_jack_client, min_time * self.m_sample_rate)
        self.m_last_time = -1

        self.m_process.start("jack_capture", arguments)
        self.m_process.waitForStarted()

        if self.m_freewheel:
            print("NOTICE: rendering in freewheel mode")
            sleep(1)
            jacklib.set_freewheel(self.m_jack_client, 1)

        self.m_timer.start()
        jacklib.transport_start(self.m_jack_client)

    @pyqtSlot()
    def slot_renderStop(self):
        jacklib.transport_stop(self.m_jack_client)

        if self.m_freewheel:
            jacklib.set_freewheel(self.m_jack_client, 0)

        sleep(1)

        self.m_process.close()
        self.m_timer.stop()

        self.group_render.setEnabled(True)
        self.group_time.setEnabled(True)
        self.group_encoding.setEnabled(True)
        self.b_render.setVisible(True)
        self.b_stop.setVisible(False)
        self.b_close.setEnabled(True)

        self.progressBar.setMinimum(0)
        self.progressBar.setMaximum(0)
        self.progressBar.setValue(0)
        self.progressBar.update()

        # Restore buffer size
        new_buffer_size = jacklib.get_buffer_size(self.m_jack_client)
        if new_buffer_size != self.m_buffer_size:
            jacklib.set_buffer_size(self.m_jack_client, new_buffer_size)

    @pyqtSlot()
    def slot_getAndSetPath(self):
        getAndSetPath(self, self.le_folder.text(), self.le_folder)

    @pyqtSlot()
    def slot_setStartNow(self):
        time = jacklib.get_current_transport_frame(self.m_jack_client) / self.m_sample_rate
        secs = time % 60
        mins = (time / 60) % 60
        hrs = (time / 3600) % 60
        self.te_start.setTime(QTime(hrs, mins, secs))

    @pyqtSlot()
    def slot_setEndNow(self):
        time = jacklib.get_current_transport_frame(self.m_jack_client) / self.m_sample_rate
        secs = time % 60
        mins = (time / 60) % 60
        hrs = (time / 3600) % 60
        self.te_end.setTime(QTime(hrs, mins, secs))

    @pyqtSlot(QTime)
    def slot_updateStartTime(self, time):
        if time >= self.te_end.time():
            self.te_end.setTime(time)
            self.b_render.setEnabled(False)
        else:
            self.b_render.setEnabled(True)

    @pyqtSlot(QTime)
    def slot_updateEndTime(self, time):
        if time <= self.te_start.time():
            self.te_start.setTime(time)
            self.b_render.setEnabled(False)
        else:
            self.b_render.setEnabled(True)

    @pyqtSlot()
    def slot_updateProgressbar(self):
        time = jacklib.get_current_transport_frame(self.m_jack_client) / self.m_sample_rate
        self.progressBar.setValue(time)

        if time > self.m_max_time or (self.m_last_time > time and not self.m_freewheel):
            self.slot_renderStop()

        self.m_last_time = time

    def closeEvent(self, event):
        if self.m_closeClient:
            jacklib.client_close(self.m_jack_client)
        QDialog.closeEvent(self, event)

    def done(self, r):
        QDialog.done(self, r)
        self.close()
コード例 #10
0
def run_process(fused_command, read_output=False):
    #     print "run process", fused_command
    #     qprocess = QProcess()
    #     set_process_env(qprocess)
    #     code_de_retour = qprocess.execute(fused_command)
    #     print "code de retour", code_de_retour
    #     logger.info("command: ")
    #     logger.info(fused_command)
    #     logger.info("code de retour" + str(code_de_retour))
    #
    # #     if not qprocess.waitForStarted():
    # #         # handle a failed command here
    # #         print "qprocess.waitForStarted()"
    # #         return
    # #
    # #     if not qprocess.waitForReadyRead():
    # #         # handle a timeout or error here
    # #         print "qprocess.waitForReadyRead()"
    # #         return
    # #     #if not qprocess.waitForFinished(1):
    # #     #    qprocess.kill()
    # #     #    qprocess.waitForFinished(1)
    #
    # #     if read_output:
    #
    #     # logger.info("Erreur")
    #     code_d_erreur = qprocess.error()
    #     dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError" }
    #     logger.info("Code de retour: " + str(code_d_erreur))
    #     logger.info(dic_err[code_d_erreur])
    #
    #     print "get output"
    #     output = str(qprocess.readAllStandardOutput())
    #     # print "output", output
    #     print 'end output'
    process = QProcess()
    process.start(fused_command)
    if process.waitForStarted():
        process.waitForFinished(-1)
        exit_code = process.exitCode()
        logger.info("Code de sortie : " + str(exit_code))
        if exit_code < 0:
            code_d_erreur = process.error().data
            dic_err = {
                0: "QProcess::FailedToStart",
                1: "QProcess::Crashed",
                2: "QProcess::TimedOut",
                3: "QProcess::WriteError",
                4: "QProcess::ReadError",
                5: "QProcess::UnknownError"
            }
            logger.info("Code erreur : " + str(code_d_erreur))
            logger.info(dic_err[code_d_erreur])

        result = process.readAllStandardOutput()
        # print type(result), result
        error = process.readAllStandardError().data()
        # print repr(error)
        if not error == "\n":
            logger.info("error : " + "\'" + str(error) + "\'")
        logger.info("output : " + result.data() + "fin output")
        return result
    else:
        code_d_erreur = process.error()
        dic_err = {
            0: "QProcess::FailedToStart",
            1: "QProcess::Crashed",
            2: "QProcess::TimedOut",
            3: "QProcess::WriteError",
            4: "QProcess::ReadError",
            5: "QProcess::UnknownError"
        }
        logger.info("Code erreur : " + str(code_d_erreur))
        logger.info(dic_err[code_d_erreur])
    return None
コード例 #11
0
ファイル: PluginBase.py プロジェクト: eaglexmw/seascope
class PluginProcessBase(QObject):
	proc_list = []

	def __init__(self, wdir):
		QObject.__init__(self)
		
		PluginProcess.proc_list.append(self)
		self.is_rebuild = False
		self.is_query_fl = False

		self.sig = QuerySignal()

		self.proc = QProcess()
		self.proc.finished.connect(self._finished_cb)
		self.proc.error.connect(self._error_cb)

		self.proc.setWorkingDirectory(wdir)
		self.wdir = wdir

	def _cleanup(self):
		PluginProcess.proc_list.remove(self)
		if self.err_str != '':
			s = '<b>' + self.p_cmd + '</b><p>' + '<p>'.join(self.err_str.splitlines())
			QMessageBox.warning(None, "Seascope", s, QMessageBox.Ok)
		if self.res != '':
			s = '<b>' + self.p_cmd + '</b><p>Summary<p>' + self.res
			QMessageBox.information(None, "Seascope", s, QMessageBox.Ok)

	def _error_cb(self, err):
		err_dict = { 
			QProcess.FailedToStart:	'FailedToStart',
			QProcess.Crashed:	'Crashed',
			QProcess.Timedout:	'The last waitFor...() function timed out',
			QProcess.WriteError:	'An error occurred when attempting to write to the process',
			QProcess.ReadError:	'An error occurred when attempting to read from the process',
			QProcess.UnknownError:	'An unknown error occurred',
		}
		self.err_str = '<b>' + self.p_cmd + '</b><p>' + err_dict[err]
		self._cleanup()

	def _finished_cb(self, ret):
		res = str(self.proc.readAllStandardOutput())
		self.err_str = str(self.proc.readAllStandardError())
		
		#print 'output', res
		#print 'cmd:', self.p_cmd
		if self.is_rebuild:
			self.res = res
			self.sig.sig_rebuild.emit()
		elif self.is_query_fl:
			self.res = ''
			res = self.parse_query_fl(res)
			self.sig.sig_query_fl.emit(res)
		else:
			self.res = ''
			self.sig.sig_result_dbg.emit(self.p_cmd, res, self.err_str)
			try:
				res = self.parse_result(res, self.sig)
			except Exception as e:
				print e
				res = [['', '', '', 'error while parsing output of: ' + self.p_cmd]]
			if res != None:
				self.sig.emit_result(res)

		self._cleanup()

	def run_query_process(self, pargs, sym, rquery=None):
		self.sig.sym = sym
		self.sig.rquery = rquery
		self.p_cmd = ' '.join(pargs)
		if os.getenv('SEASCOPE_DEBUG'):
			print self.p_cmd
		self.proc.start(pargs[0], pargs[1:])
		if self.proc.waitForStarted() == False:
			return None
		self.proc.closeWriteChannel()
		return [self.sig.sig_result, self.sig.sig_result_dbg]

	def run_rebuild_process(self, pargs):
		self.is_rebuild = True
		self.p_cmd = ' '.join(pargs)
		self.proc.start(pargs[0], pargs[1:])
		if self.proc.waitForStarted() == False:
			return None
		#print 'cmd:', pargs
		self.sig.sig_rebuild.connect(CtagsCache.flush)
		return self.sig.sig_rebuild

	def run_query_fl(self, pargs):
		self.is_query_fl = True
		self.p_cmd = ' '.join(pargs)
		self.proc.start(pargs[0], pargs[1:])
		if self.proc.waitForStarted() == False:
			return None
		return self.sig.sig_query_fl

	def parse_query_fl(self, text):
		fl = []
		for f in re.split('\r?\n', text.strip()):
			if f == '':
				continue
			fl.append(os.path.join(self.wdir, f))
		return fl
コード例 #12
0
ファイル: main.py プロジェクト: juancarlospaco/nuitka-ninja
class Main(plugin.Plugin):
    " Main Class "
    def initialize(self, *args, **kwargs):
        " Init Main Class "
        super(Main, self).initialize(*args, **kwargs)
        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self.process.readyReadStandardError.connect(self.readErrors)
        self.process.finished.connect(self._process_finished)
        self.process.error.connect(self._process_finished)
        self.editor_s = self.locator.get_service('editor')
        self.completer, self.dirs = QCompleter(self), QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        self.group0 = QGroupBox()
        self.group0.setTitle(' Source ')
        self.infile = QLineEdit(path.expanduser("~"))
        self.infile.setPlaceholderText(' /full/path/to/file.html ')
        self.infile.setCompleter(self.completer)
        self.open = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.open.setCursor(QCursor(Qt.PointingHandCursor))
        self.open.clicked.connect(lambda: self.infile.setText(str(
            QFileDialog.getOpenFileName(self.dock, "Open a File to read from",
            path.expanduser("~"), ';;'.join(['{}(*.{})'.format(e.upper(), e)
            for e in ['py', 'pyw', 'txt', '*']])))))
        self.output = QTextEdit()
        vboxg0 = QVBoxLayout(self.group0)
        for each_widget in (self.infile, self.open, self.output):
            vboxg0.addWidget(each_widget)

        self.group1 = QGroupBox()
        self.group1.setTitle(' General ')
        self.group1.setCheckable(True)
        self.group1.setGraphicsEffect(QGraphicsBlurEffect(self))
        self.group1.graphicsEffect().setEnabled(False)
        self.group1.toggled.connect(self.toggle_gral_group)
        self.ckgrl1 = QCheckBox('Create standalone executable')
        self.ckgrl2 = QCheckBox('Use Python debug')
        self.ckgrl3 = QCheckBox('Force compilation for MS Windows')
        self.ckgrl4 = QCheckBox('When compiling, disable the console window')
        self.ckgrl5 = QCheckBox('Use link time optimizations if available')
        self.ckgrl6 = QCheckBox('Force the use of clang')
        self.ckgrl7 = QCheckBox('Allow minor devitations from Python behaviour')
        self.ckgrl8 = QCheckBox('Warnings implicit exceptions at compile time')
        self.pyver, self.jobs = QComboBox(), QSpinBox()
        self.pyver.addItems(['2.7', '2.6', '3.2', '3.3'])
        self.jobs.setValue(1)
        self.jobs.setMaximum(12)
        self.jobs.setMinimum(1)
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (self.ckgrl1, self.ckgrl2, self.ckgrl3, self.ckgrl4,
            self.ckgrl5, self.ckgrl6, self.ckgrl7, self.ckgrl8,
            QLabel('Python Version to Target'), self.pyver,
            QLabel('Multi-Processing Parallel Workers'), self.jobs):
            vboxg1.addWidget(each_widget)
            try:
                each_widget.setToolTip(each_widget.text())
            except:
                pass

        self.group2 = QGroupBox()
        self.group2.setTitle(' Recursion Control ')
        self.ckrec0 = QCheckBox('Descend to imported modules from standard lib')
        self.ckrec1 = QCheckBox('Force not descend to any imported modules')
        self.ckrec2 = QCheckBox('Try to descend into all imported modules')
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (self.ckrec0, self.ckrec1, self.ckrec2):
            vboxg2.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        self.group3 = QGroupBox()
        self.group3.setTitle(' Execution after compilation ')
        self.ckexe0 = QCheckBox('Execute created binary (or import the module)')
        self.ckexe1 = QCheckBox('When executing binary dont reset PYTHONPATH')
        vboxg2 = QVBoxLayout(self.group3)
        for each_widget in (self.ckexe0, self.ckexe1):
            vboxg2.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        self.group4, self.dumptree = QGroupBox(), QTextEdit()
        self.group4.setTitle(' Dump of internal tree ')
        QVBoxLayout(self.group4).addWidget(self.dumptree)

        self.group5 = QGroupBox()
        self.group5.setTitle(' Code generation ')
        self.chdmp1 = QCheckBox('Statements shall have their line numbers set')
        self.chdmp2 = QCheckBox('Disable all unnecessary Python optimization')
        vboxg5 = QVBoxLayout(self.group5)
        for each_widget in (self.chdmp1, self.chdmp2):
            vboxg5.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        self.group6 = QGroupBox()
        self.group6.setTitle(' Output ')
        self.outdir = QLineEdit(path.expanduser("~"))
        self.outdir.setPlaceholderText(' /full/path/to/target/directory ')
        self.outdir.setCompleter(self.completer)
        self.open2 = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.open2.setCursor(QCursor(Qt.PointingHandCursor))
        self.open2.clicked.connect(lambda: self.outdir.setText(str(
            QFileDialog.getExistingDirectory(self.dock, "Open Target Folder",
            path.expanduser("~")))))
        self.ckcgn2 = QCheckBox('Remove build dir after compile module or exe')
        vboxg6 = QVBoxLayout(self.group6)
        for each_widget in (QLabel('Target Output Directory'), self.outdir,
                            self.open2, self.ckcgn2):
            vboxg6.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        self.group7 = QGroupBox()
        self.group7.setTitle(' Debug ')
        self.ckdbg1 = QCheckBox('Execute self checks to find errors in Nuitka')
        self.ckdbg2 = QCheckBox('Keep debug info in resulting file')
        self.ckdbg3 = QCheckBox('Traced execution output')
        self.ckdbg4 = QCheckBox('Allow compile edited C++ file, debug changes')
        self.ckdbg5 = QCheckBox('Use experimental features')
        vboxg7 = QVBoxLayout(self.group7)
        for each_widget in (self.ckdbg1, self.ckdbg2, self.ckdbg3,
                            self.ckdbg4, self.ckdbg5):
            vboxg7.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        self.group8 = QGroupBox()
        self.group8.setTitle(' Tracing ')
        self.cktrc1 = QCheckBox('Show Scons in non-quiet mode, showing command')
        self.cktrc2 = QCheckBox('Show Progress information and statistics')
        self.cktrc3 = QCheckBox('Show Verbose output details')
        vboxg8 = QVBoxLayout(self.group8)
        for each_widget in (self.cktrc1, self.cktrc2, self.cktrc3):
            vboxg8.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        self.group9 = QGroupBox()
        self.group9.setTitle(' Extras ')
        self.group9.setCheckable(True)
        self.group9.toggled.connect(self.group9.hide)
        self.nice = QSpinBox()
        self.nice.setValue(20)
        self.nice.setMaximum(20)
        self.nice.setMinimum(0)
        self.ckxtr1 = QCheckBox('Open Target Directory later')
        self.ckxtr2 = QCheckBox('Save a LOG file to target later')
        self.ckxtr3 = QCheckBox('Save SH Bash script to reproduce Nuitka build')
        try:
            self.vinfo = QLabel('<center> <b> Nuitka Backend Version: </b>' +
                            getoutput('nuitka --version',).strip())
        except:
            self.vinfo = QLabel('<b>Warning: Failed to query Nuitka Backend!')
        vboxg9 = QVBoxLayout(self.group9)
        for each_widget in (QLabel('Backend CPU Priority'), self.nice,
                            self.ckxtr1, self.ckxtr2, self.ckxtr3, self.vinfo):
            vboxg9.addWidget(each_widget)

        self.group10 = QGroupBox()
        self.group10.setTitle(' Documentation ')
        self.group10.setCheckable(True)
        self.group10.toggled.connect(self.group10.hide)
        vboxg10 = QVBoxLayout(self.group10)
        for each_widget in (QLabel('''<a href=
            "file:///usr/share/doc/nuitka/README.pdf.gz">
            <small><center> Nuitka User Documentation Local PDF </a>'''),
            QLabel('''<a href=
            "file:///usr/share/doc/nuitka/Developer_Manual.pdf.gz">
            <small><center> Nuitka Developer Documentation Local PDF </a>'''),
            QLabel('''<a href="http://nuitka.net/doc/user-manual.html">
            <small><center> Nuitka User Documentation On Line HTML </a>'''),
            QLabel('''<a href="http://nuitka.net/doc/developer-manual.html">
            <small><center> Nuitka Developer Documentation On Line HTML </a>''')
             ):
            vboxg10.addWidget(each_widget)
            each_widget.setOpenExternalLinks(True)
            each_widget.setTextInteractionFlags(Qt.LinksAccessibleByMouse)

        [a.setChecked(True) for a in (self.ckgrl1, self.ckgrl2, self.ckgrl4,
            self.ckgrl5, self.ckgrl6, self.ckgrl7, self.ckgrl8, self.ckrec0,
            self.ckrec1, self.ckrec2, self.ckexe1, self.ckcgn2, self.ckdbg1,
            self.ckdbg3, self.ckdbg4, self.ckdbg5, self.cktrc1, self.cktrc2,
            self.cktrc3, self.ckxtr1, self.ckxtr2, self.ckxtr3,)]

        self.button = QPushButton(QIcon.fromTheme("face-cool"),
                                  'Compile Python')
        self.button.setCursor(QCursor(Qt.PointingHandCursor))
        self.button.setMinimumSize(100, 50)
        self.button.clicked.connect(self.run)
        glow = QGraphicsDropShadowEffect(self)
        glow.setOffset(0)
        glow.setBlurRadius(99)
        glow.setColor(QColor(99, 255, 255))
        self.button.setGraphicsEffect(glow)

        class TransientWidget(QWidget):
            ' persistant widget thingy '
            def __init__(self, widget_list):
                ' init sub class '
                super(TransientWidget, self).__init__()
                vbox = QVBoxLayout(self)
                for each_widget in widget_list:
                    vbox.addWidget(each_widget)

        tw = TransientWidget((
            QLabel('<b>Python Code to Binary Executable Compiler'), self.group0,
            self.group6, self.group1, self.group2, self.group3, self.group4,
            self.group5, self.group7, self.group8, self.group9, self.group10,
            self.button, ))
        self.scrollable, self.dock = QScrollArea(), QDockWidget()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(tw)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)
        ExplorerContainer().addTab(self.dock, "Nuitka")
        QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock
          ).clicked.connect(lambda: QMessageBox.information(self.dock, __doc__,
            HELPMSG))

    def run(self):
        ' run the compile '
        target = path.abspath(str(self.infile.text()).strip())
        self.button.setDisabled(True)
        self.output.clear()
        self.output.show()
        self.output.setFocus()
        self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now())))
        self.output.append(self.formatInfoMsg(' INFO: Dumping Internal Tree'))
        try:
            self.dumptree.setPlainText(
                getoutput('nuitka --dump-tree {}'.format(target)))
            self.dumptree.setMinimumSize(100, 500)
        except:
            self.output.append(self.formatErrorMsg('ERROR:FAIL: Internal Tree'))
        self.output.append(self.formatInfoMsg(' INFO: OK: Parsing Arguments'))
        cmd = ' '.join(('nice --adjustment={} nuitka'.format(self.nice.value()),

            # output
            '--remove-output' if self.ckcgn2.isChecked() is True else '',

            # general
            '--exe' if self.ckgrl1.isChecked() is True else '',
            '--python-debug' if self.ckgrl2.isChecked() is True else '',
            '--verbose' if self.cktrc3.isChecked() is True else '',
            '--windows-target' if self.ckgrl3.isChecked() is True else '',
            '--windows-disable-console' if self.ckgrl4.isChecked() is True else '',
            '--lto' if self.ckgrl5.isChecked() is True else '',
            '--clang' if self.ckgrl6.isChecked() is True else '',
            '--improved' if self.ckgrl7.isChecked() is True else '',
            '--warn-implicit-exceptions' if self.ckgrl8.isChecked() is True else '',

            # recursion control
            '--recurse-stdlib' if self.ckrec0.isChecked() is True else '',
            '--recurse-none' if self.ckrec1.isChecked() is True else '',
            '--recurse-all' if self.ckrec2.isChecked() is True else '',

            # execution after compilation
            '--execute' if self.ckexe0.isChecked() is True else '',
            '--keep-pythonpath' if self.ckexe1.isChecked() is True else '',

            # code generation
            '--code-gen-no-statement-lines' if self.chdmp1.isChecked() is True else '',
            '--no-optimization' if self.chdmp2.isChecked() is True else '',

            # debug
            '--debug' if self.ckdbg1.isChecked() is True else '',
            '--unstripped' if self.ckdbg2.isChecked() is True else '',
            '--trace-execution' if self.ckdbg3.isChecked() is True else '',
            '--c++-only' if self.ckdbg4.isChecked() is True else '',
            '--experimental' if self.ckdbg5.isChecked() is True else '',

            # tracing
            '--show-scons' if self.cktrc1.isChecked() is True else '',
            '--show-progress' if self.cktrc2.isChecked() is True else '',
            '--verbose' if self.cktrc3.isChecked() is True else '',

            # non boolean parametrization
            '--python-version={}'.format(self.pyver.currentText()),
            '--jobs={}'.format(self.jobs.value()),
            '--output-dir="{}"'.format(self.outdir.text()),
            target))
        self.output.append(self.formatInfoMsg(' INFO: Command: {}'.format(cmd)))
        self.output.append(self.formatInfoMsg(' INFO: OK: Starting to Compile'))
        self.process.start(cmd)
        if not self.process.waitForStarted():
            self.output.append(self.formatErrorMsg('ERROR: FAIL: Compile Fail'))
            self.output.append(self.formatErrorMsg('ERROR:FAIL:{}'.format(cmd)))
            self.button.setEnabled(True)
            return
        # write a .sh bash script file on target
        if self.ckxtr3.isChecked() is True:
            sh_file = 'nuitka_compile_python_to_cpp.sh'
            with open(path.join(str(self.outdir.text()), sh_file), 'w') as _sh:
                self.output.append(self.formatInfoMsg('''INFO: OK: Writing Bash:
                    {}'''.format(sh_file)))
                _sh.write('#!/usr/bin/env bash {}{}'.format(linesep, cmd))
                _sh.close()
            self.output.append(self.formatInfoMsg('INFO: OK: Bash chmod: 775'))
            try:
                chmod(path.join(str(self.outdir.text()), sh_file), 0775)  # Py2
            except:
                chmod(path.join(str(self.outdir.text()), sh_file), 0o775)  # Py3

    def _process_finished(self):
        """sphinx-build finished sucessfully"""
        self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now())))
        if self.ckxtr2.isChecked() is True:
            log_file = 'nuitka_ninja.log'
            with open(path.join(str(self.outdir.text()), log_file), 'w') as log:
                self.output.append(self.formatInfoMsg('''INFO: OK: Writing LOG:
                    {}'''.format(log_file)))
                log.write(self.output.toPlainText())
        if self.ckxtr1.isChecked() is True:
            try:
                startfile(path.abspath(str(self.outdir.text())))
            except:
                Popen(["xdg-open", path.abspath(str(self.outdir.text()))])
        self.button.setDisabled(False)
        self.output.show()
        self.output.setFocus()
        self.output.selectAll()

    def toggle_gral_group(self):
        ' toggle on or off the checkboxes '
        if self.group1.isChecked() is True:
            [a.setChecked(True) for a in (self.ckgrl1, self.ckgrl2, self.ckgrl4,
            self.ckgrl5, self.ckgrl6, self.ckgrl7, self.ckgrl8)]
            self.group1.graphicsEffect().setEnabled(False)
        else:
            [a.setChecked(False) for a in (self.ckgrl1, self.ckgrl2,
            self.ckgrl4, self.ckgrl5, self.ckgrl6, self.ckgrl7, self.ckgrl8)]
            self.group1.graphicsEffect().setEnabled(True)

    def readOutput(self):
        """Read and append sphinx-build output to the logBrowser"""
        self.output.append(str(self.process.readAllStandardOutput()))

    def readErrors(self):
        """Read and append sphinx-build errors to the logBrowser"""
        self.output.append(self.formatErrorMsg(str(
                                        self.process.readAllStandardError())))

    def formatErrorMsg(self, msg):
        """Format error messages in red color"""
        return self.formatMsg(msg, 'red')

    def formatInfoMsg(self, msg):
        """Format informative messages in blue color"""
        return self.formatMsg(msg, 'green')

    def formatMsg(self, msg, color):
        """Format message with the given color"""
        return '<font color="{}">{}</font>'.format(color, msg)
コード例 #13
0
ファイル: profilergui.py プロジェクト: sjara/spyder-profiler
class ProfilerWidget(QWidget):
    """
    Profiler widget
    """
    DATAPATH = get_conf_path('.profiler.results')
    VERSION = '0.0.1'
    
    def __init__(self, parent, max_entries=100):
        QWidget.__init__(self, parent)
        
        self.setWindowTitle("Profiler")
        
        self.output = None
        self.error_output = None
        
        self.filecombo = PythonModulesComboBox(self)
        
        self.start_button = create_toolbutton(self, icon=get_icon('run.png'),
                                    text=translate('Profiler', "Profile"),
                                    tip=translate('Profiler', "Run profiler"),
                                    triggered=self.start, text_beside_icon=True)
        self.stop_button = create_toolbutton(self,
                                    icon=get_icon('terminate.png'),
                                    text=translate('Profiler', "Stop"),
                                    tip=translate('Profiler',
                                                  "Stop current profiling"),
                                    text_beside_icon=True)
        self.connect(self.filecombo, SIGNAL('valid(bool)'),
                     self.start_button.setEnabled)
        #self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)
        # FIXME: The combobox emits this signal on almost any event
        #        triggering show_data() too early, too often. 

        browse_button = create_toolbutton(self, icon=get_icon('fileopen.png'),
                               tip=translate('Profiler', 'Select Python script'),
                               triggered=self.select_file)

        self.datelabel = QLabel()

        self.log_button = create_toolbutton(self, icon=get_icon('log.png'),
                                    text=translate('Profiler', "Output"),
                                    text_beside_icon=True,
                                    tip=translate('Profiler',
                                                  "Show program's output"),
                                    triggered=self.show_log)

        self.datatree = ProfilerDataTree(self)

        self.collapse_button = create_toolbutton(self, icon=get_icon('collapse.png'),
                                    triggered=lambda dD=-1:self.datatree.change_view(dD),
                                    tip='Collapse one level up')
        self.expand_button = create_toolbutton(self, icon=get_icon('expand.png'),
                                    triggered=lambda dD=1:self.datatree.change_view(dD),
                                    tip='Expand one level down')

        
        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.filecombo)
        hlayout1.addWidget(browse_button)
        hlayout1.addWidget(self.start_button)
        hlayout1.addWidget(self.stop_button)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self.collapse_button)
        hlayout2.addWidget(self.expand_button)
        hlayout2.addStretch()
        hlayout2.addWidget(self.datelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.log_button)
        
        layout = QVBoxLayout()
        layout.addLayout(hlayout1)
        layout.addLayout(hlayout2)
        layout.addWidget(self.datatree)
        self.setLayout(layout)
        
        self.process = None
        self.set_running_state(False)
        
        if not is_profiler_installed():
            for widget in (self.datatree, self.filecombo,
                           self.start_button, self.stop_button):
                widget.setDisabled(True)
            if os.name == 'nt' \
               and programs.is_module_installed("profile"):
                # The following is a comment from the pylint plugin:
                # Module is installed but script is not in PATH
                # (AFAIK, could happen only on Windows)
                text = translate('Profiler',
                     'Profiler script was not found. Please add "%s" to PATH.')
                text = unicode(text) % os.path.join(sys.prefix, "Scripts")
            else:
                text = translate('Profiler',
                    ('Please install the modules '+
                     '<b>profile</b> and <b>pstats</b>:'))
                # FIXME: need the actual website
                url = 'http://www.python.org'
                text += ' <a href=%s>%s</a>' % (url, url)
            self.datelabel.setText(text)
        else:
            pass # self.show_data()
                
    def analyze(self, filename):
        if not is_profiler_installed():
            return
        filename = unicode(filename) # filename is a QString instance
        self.kill_if_running()
        #index, _data = self.get_data(filename)
        index=None # FIXME: storing data is not implemented yet
        if index is None:
            self.filecombo.addItem(filename)
            self.filecombo.setCurrentIndex(self.filecombo.count()-1)
        else:
            self.filecombo.setCurrentIndex(self.filecombo.findText(filename))
        self.filecombo.selected()
        if self.filecombo.is_valid():
            self.start()
            
    def select_file(self):
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        filename = QFileDialog.getOpenFileName(self,
                      translate('Profiler', "Select Python script"), os.getcwdu(),
                      translate('Profiler', "Python scripts")+" (*.py ; *.pyw)")
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        if filename:
            self.analyze(filename)
        
    def show_log(self):
        if self.output:
            TextEditor(self.output, title=translate('Profiler', "Profiler output"),
                       readonly=True, size=(700, 500)).exec_()
    
    def show_errorlog(self):
        if self.error_output:
            TextEditor(self.error_output, title=translate('Profiler', "Profiler output"),
                       readonly=True, size=(700, 500)).exec_()
        
    def start(self):
        self.datelabel.setText('Profiling, please wait...')
        filename = unicode(self.filecombo.currentText())
        
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.SeparateChannels)
        self.process.setWorkingDirectory(os.path.dirname(filename))
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.read_output)
        self.connect(self.process, SIGNAL("readyReadStandardError()"),
                     lambda: self.read_output(error=True))
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)
        self.connect(self.stop_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        self.output = ''
        self.error_output = ''
        p_args = [os.path.basename(filename)]
        
        # FIXME: Use the system path to 'python' as opposed to hardwired
        p_args = ['-m', PROFILER_PATH, '-o', self.DATAPATH, os.path.basename(filename)]
        self.process.start('python', p_args)
        
        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, translate('Profiler', "Error"),
                                 translate('Profiler', "Process failed to start"))
    
    def set_running_state(self, state=True):
        self.start_button.setEnabled(not state)
        self.stop_button.setEnabled(state)
        
    def read_output(self, error=False):
        if error:
            self.process.setReadChannel(QProcess.StandardError)
        else:
            self.process.setReadChannel(QProcess.StandardOutput)
        bytes = QByteArray()
        while self.process.bytesAvailable():
            if error:
                bytes += self.process.readAllStandardError()
            else:
                bytes += self.process.readAllStandardOutput()
        text = unicode( QString.fromLocal8Bit(bytes.data()) )
        if error:
            self.error_output += text
        else:
            self.output += text
        
    def finished(self):
        self.set_running_state(False)
        self.show_errorlog()  # If errors occurred, show them.
        self.output = self.error_output + self.output
        # FIXME: figure out if show_data should be called here or
        #        as a signal from the combobox
        self.show_data(justanalyzed=True)
                
    def kill_if_running(self):
        if self.process is not None:
            if self.process.state() == QProcess.Running:
                self.process.kill()
                self.process.waitForFinished()
        
    def show_data(self, justanalyzed=False):
        if not justanalyzed:
            self.output = None
        self.log_button.setEnabled(self.output is not None \
                                   and len(self.output) > 0)
        self.kill_if_running()
        filename = unicode(self.filecombo.currentText())
        if not filename:
            return

        self.datatree.load_data(self.DATAPATH)
        self.datatree.show_tree()
            
        text_style = "<span style=\'color: #444444\'><b>%s </b></span>"
        date_text = text_style % time.strftime("%d %b %Y %H:%M",time.localtime())
        self.datelabel.setText(date_text)
コード例 #14
0
ファイル: main.py プロジェクト: juancarlospaco/clones
class Main(plugin.Plugin):
    ' main class for plugin '
    def initialize(self, *args, **kwargs):
        ' class init '
        super(Main, self).initialize(*args, **kwargs)
        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self.process.readyReadStandardError.connect(self.readErrors)
        self.process.finished.connect(self._process_finished)
        self.process.error.connect(self._process_finished)
        # directory auto completer
        self.completer, self.dirs = QCompleter(self), QDirModel(self)
        self.dirs.setFilter(QDir.Dirs | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        menu = QMenu('Clones')
        menu.addAction('Analyze for Code Clones here', lambda: self.make_clon())
        self.locator.get_service('explorer').add_project_menu(menu, lang='all')

        self.group1 = QGroupBox()
        self.group1.setTitle(' Target ')
        self.outdir, self.igndir = QLineEdit(path.expanduser("~")), QLineEdit()
        self.outdir.setCompleter(self.completer)
        self.btn1 = QPushButton(QIcon.fromTheme("document-open"), ' Open ')
        self.btn1.clicked.connect(lambda: self.outdir.setText(str(
            QFileDialog.getExistingDirectory(self.dock,
            'Please, Open a Target Directory...', path.expanduser("~")))))
        self.btn1a = QPushButton(QIcon.fromTheme("face-smile"),
                                 'Get from Ninja active project')
        self.btn1a.clicked.connect(lambda: self.outdir.setText(
          self.locator.get_service('explorer').get_current_project_item().path))

        self.ignckb, self.ignmor = QComboBox(), QTextEdit()
        self.ignckb.addItems(['Single Directory', 'Multiple Directories CSV'])
        self.ignckb.currentIndexChanged.connect(self.on_ignore_changed)
        self.ignmor.hide()
        self.igndir.setPlaceholderText('Exclude directory')
        self.igndir.setCompleter(self.completer)
        self.btn2 = QPushButton(QIcon.fromTheme("document-open"), ' Open ')
        self.btn2.clicked.connect(lambda: self.igndir.setText(str(
            QFileDialog.getExistingDirectory(self.dock,
            'Please, Open a Ignore Directory...', path.expanduser("~")))))
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (QLabel('<b>Target directory path: '), self.outdir,
            self.btn1, self.btn1a, QLabel('<b>Ignore directory path: '),
            self.ignckb, self.ignmor, self.igndir, self.btn2, ):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle(' Output ')
        self.outfle = QLineEdit(path.join(path.expanduser("~"), 'output.html'))
        self.outfle.setPlaceholderText('Exclude directory')
        self.outfle.setCompleter(self.completer)
        self.btn3 = QPushButton(QIcon.fromTheme("document-save"), ' Save ')
        self.btn3.clicked.connect(lambda: self.outfle.setText(
            QFileDialog.getSaveFileName(self.dock, 'Save', path.expanduser("~"),
            'XML(*.xml)' if self.xmlo.isChecked() is True else 'HTML(*.html)')))
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (QLabel('<b>Output report file path:'),
            self.outfle, self.btn3):
            vboxg2.addWidget(each_widget)

        self.group3 = QGroupBox()
        self.group3.setTitle(' Options ')
        self.group3.setCheckable(True)
        self.group3.setGraphicsEffect(QGraphicsBlurEffect(self))
        self.group3.graphicsEffect().setEnabled(False)
        self.group3.toggled.connect(self.toggle_options_group)
        self.qckb1, self.qckb2 = QCheckBox('Recursive'), QCheckBox('Time-less')
        self.qckb3, self.qckb4 = QCheckBox('Force Diff'), QCheckBox('Fast Mode')
        self.qckb5, self.tm = QCheckBox('Save a LOG file to target'), QLabel('')
        self.xmlo = QCheckBox('XML Output instead of HTML')
        self.opeo = QCheckBox('Open Clones Report when done')
        self.chrt = QCheckBox('LOW CPU priority for Backend Process')
        self.mdist, self.hdep, self.output = QSpinBox(), QSpinBox(), QTextEdit()
        self.ign_func = QLineEdit('test, forward, backward, Migration')
        self.mdist.setValue(5)
        self.hdep.setValue(1)
        self.mdist.setToolTip('''<b>Maximum amount of difference between pair of
        sequences in clone pair (5 default).Larger value more false positive''')
        self.hdep.setToolTip('''<b>Computation can be speeded up by increasing
                       this value, but some clones can be missed (1 default)''')
        [a.setChecked(True) for a in (self.qckb1, self.qckb3, self.qckb5,
                                      self.chrt, self.opeo)]
        vboxg3 = QVBoxLayout(self.group3)
        for each_widget in (self.qckb1, self.qckb2, self.qckb3, self.qckb4,
            self.qckb5, self.chrt, self.xmlo, self.opeo,
            QLabel('<b>Max Distance Threshold:'), self.mdist,
            QLabel('<b>Max Hashing Depth:'), self.hdep,
            QLabel('<b>Ignore code block prefix:'), self.ign_func):
            vboxg3.addWidget(each_widget)

        self.group4, self.auto = QGroupBox(), QComboBox()
        self.group4.setTitle(' Automation ')
        self.group4.setCheckable(True)
        self.group4.setToolTip('<font color="red"><b>WARNING:Advanced Setting!')
        self.group4.toggled.connect(lambda: self.group4.hide())
        self.auto.addItems(['Never run automatically', 'Run when File Saved',
            'Run when File Executed', 'Run when Tab Changed',
            'Run when File Opened', 'Run before File Saved'])
        self.auto.currentIndexChanged.connect(self.on_auto_changed)
        QVBoxLayout(self.group4).addWidget(self.auto)

        self.button = QPushButton(' Analyze for Clones ')
        self.button.setMinimumSize(75, 50)
        self.button.clicked.connect(self.run)
        glow = QGraphicsDropShadowEffect(self)
        glow.setOffset(0)
        glow.setBlurRadius(99)
        glow.setColor(QColor(99, 255, 255))
        self.button.setGraphicsEffect(glow)

        self.butkil = QPushButton(' Force Kill Clones ')
        self.butkil.clicked.connect(lambda: self.process.kill())

        class TransientWidget(QWidget):
            ' persistant widget thingy '
            def __init__(self, widget_list):
                ' init sub class '
                super(TransientWidget, self).__init__()
                vbox = QVBoxLayout(self)
                for each_widget in widget_list:
                    vbox.addWidget(each_widget)

        tw = TransientWidget((QLabel('<i>D.R.Y. principle analyzer'),
            self.group1, self.group2, self.group3, self.group4,
            QLabel('<b>Backend Logs'), self.output, self.tm, self.button,
            self.butkil))
        self.scrollable, self.dock = QScrollArea(), QDockWidget()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(tw)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)
        ExplorerContainer().addTab(self.dock, "Clones")
        QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock
            ).clicked.connect(lambda:
            QMessageBox.information(self.dock, __doc__, HELPMSG))

    def readOutput(self):
        """Read and append output to the logBrowser"""
        self.output.append(str(self.process.readAllStandardOutput()).strip())

    def readErrors(self):
        """Read and append errors to the logBrowser"""
        self.output.append(self.formatErrorMsg(str(
                                        self.process.readAllStandardError())))

    def formatErrorMsg(self, msg):
        """Format error messages in red color"""
        return self.formatMsg(msg, 'red')

    def formatInfoMsg(self, msg):
        """Format informative messages in blue color"""
        return self.formatMsg(msg, 'green')

    def formatMsg(self, msg, color):
        """Format message with the given color"""
        return '<font color="{}">{}</font>'.format(color, msg)

    def make_clon(self):
        ' make clones analyze from contextual sub menu '
        self.outdir.setText(
          self.locator.get_service('explorer').get_current_project_item().path)
        self.run()

    def run(self):
        ' run the actions '
        self.output.clear()
        self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now())))
        self.tm.setText('<center><b>Last Clone: </b>' +
                        datetime.now().isoformat().split('.')[0])
        self.button.setDisabled(True)
        if not len(self.outdir.text()) and not len(self.outfle.text()):
            self.output.append(self.formatErrorMsg('ERROR: FAIL: Target empty'))
            self.button.setEnabled(True)
            return
        # run the subprocesses
        cmd = ' '.join((
            'chrt -i 0' if self.chrt.isChecked() is True else '', 'clonedigger',
            '' if self.qckb1.isChecked() is True else '--no-recursion',
            '--dont-print-time' if self.qckb2.isChecked() is True else '',
            '--force' if self.qckb3.isChecked() is True else '',
            '--fast' if self.qckb4.isChecked() is True else '',
            '--cpd-output' if self.xmlo.isChecked() is True else '',
            '' if self.xmlo.isChecked() is True else '--report-unifiers',
            '--distance-threshold={}'.format(self.mdist.value()),
            '--hashing-depth={}'.format(self.hdep.value()),
            '--ignore-dir="{}"'.format(self.igndir.text()
                if self.ignckb.currentIndex() is 0
                else self.ignmor.toPlainText()),
            '--func-prefixes="{}"'.format(self.ign_func.text()),
            '--output="{}"'.format(self.outfle.text()),
            '--language=python', path.abspath(self.outdir.text()),
        ))
        self.output.append(self.formatInfoMsg('INFO:OK:Command:{}'.format(cmd)))
        self.process.start(cmd)
        if not self.process.waitForStarted():
            self.output.append(self.formatErrorMsg(' ERROR: FAIL: Meh. '))
            self.output.append(self.formatErrorMsg('ERROR:FAIL:{}'.format(cmd)))
            self.button.setEnabled(True)
            return
        self.readOutput()
        self.readErrors()
        self.button.setEnabled(True)

    def _process_finished(self):
        """ finished sucessfully """
        self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now())))
        # write a .log file on target
        if self.qckb5.isChecked() is True:
            log_file = 'ninja_clones.log'
            with open(path.join(str(self.outdir.text()), log_file), 'w') as log:
                self.output.append(self.formatInfoMsg('''INFO: OK: Writing Logs:
                    {}'''.format(path.join(str(self.outdir.text()), log_file))))
                log.write(self.output.toPlainText())
                log.close()
        # open target output
        if self.opeo.isChecked() is True and self.xmlo.isChecked() is False:
            try:
                startfile(self.outfle.text())
            except:
                Popen(["xdg-open", self.outfle.text()])
        self.output.selectAll()
        self.output.setFocus()

    def toggle_options_group(self):
        ' toggle on off the options group '
        if self.group3.isChecked() is True:
            [a.setChecked(True) for a in (self.qckb1, self.qckb3, self.qckb5,
                                          self.chrt, self.opeo)]
            self.mdist.setValue(5)
            self.hdep.setValue(1)
            self.group3.graphicsEffect().setEnabled(False)
        else:
            [a.setChecked(False) for a in (self.qckb1, self.qckb3, self.qckb5,
                                           self.chrt, self.opeo)]
            self.group3.graphicsEffect().setEnabled(True)

    def on_ignore_changed(self):
        'hide or show one widget or another depending what kind of input need'
        if self.ignckb.currentIndex() is 0:
            self.igndir.show()
            self.btn2.show()
            self.ignmor.hide()
        else:
            self.igndir.hide()
            self.btn2.hide()
            self.ignmor.show()

    def on_auto_changed(self):
        ' automation connects '
        if self.auto.currentIndex() is 1:
            self.locator.get_service('editor').fileSaved.connect(lambda:
                self.run())
            QMessageBox.information(self.dock, __doc__,
            '<b>Now Actions will Run Automatically when any File is Saved !')
        elif self.auto.currentIndex() is 2:
            self.locator.get_service('editor').fileExecuted.connect(lambda:
                self.run())
            QMessageBox.information(self.dock, __doc__,
            '<b>Now Actions will Run Automatically when any File is Executed !')
        elif self.auto.currentIndex() is 3:
            self.locator.get_service('editor').currentTabChanged.connect(lambda:
                self.run())
            QMessageBox.information(self.dock, __doc__,
            '<b>Now Actions will Run Automatically when current Tab is Changed')
        elif self.auto.currentIndex() is 4:
            self.locator.get_service('editor').fileOpened.connect(lambda:
                self.run())
            QMessageBox.information(self.dock, __doc__,
            '<b>Now Actions will Run Automatically when any File is Opened !')
        elif self.auto.currentIndex() is 5:
            self.locator.get_service('editor').beforeFileSaved.connect(lambda:
                self.run())
            QMessageBox.information(self.dock, __doc__,
            '<b>Now Actions will Run Automatically before any File is Saved !')
        self.group4.setDisabled(True)

    def finish(self):
        ' clear when finish '
        self.process.kill()
コード例 #15
0
ファイル: main.py プロジェクト: juancarlospaco/mobile
class Main(plugin.Plugin):
    " Main Class "
    def initialize(self, *args, **kwargs):
        " Init Main Class "
        super(Main, self).initialize(*args, **kwargs)
        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self.process.readyReadStandardError.connect(self.readErrors)
        self.process.finished.connect(self._process_finished)
        self.process.error.connect(self._process_finished)
        # directory auto completer
        self.completer, self.dirs = QCompleter(self), QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        self.group0 = QGroupBox()
        self.group0.setTitle(' Source ')
        self.source, self.infile = QComboBox(), QLineEdit(path.expanduser("~"))
        self.source.addItems(['Local File', 'Remote URL'])
        self.source.currentIndexChanged.connect(self.on_source_changed)
        self.infile.setPlaceholderText(' /full/path/to/file.html ')
        self.infile.setCompleter(self.completer)
        self.open = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.open.setCursor(QCursor(Qt.PointingHandCursor))
        self.open.clicked.connect(lambda: self.infile.setText(str(
            QFileDialog.getOpenFileName(self.dock, "Open a File to read from",
            path.expanduser("~"), ';;'.join(['{}(*.{})'.format(e.upper(), e)
            for e in ['html', 'webp', 'webm', 'svg', 'css', 'js', '*']])))))
        self.inurl, self.output = QLineEdit('http://www.'), QTextEdit()
        self.inurl.setPlaceholderText('http://www.full/url/to/remote/file.html')
        self.inurl.hide()
        vboxg0 = QVBoxLayout(self.group0)
        for each_widget in (self.source, self.infile, self.open, self.inurl):
            vboxg0.addWidget(each_widget)

        self.group1 = QGroupBox()
        self.group1.setTitle(' Mobile ')
        self.ckcss1 = QCheckBox('Run in full screen using current resolution')
        self.ckcss2 = QCheckBox('Disable touch mode and use keypad mode')
        self.ckcss3 = QCheckBox('Disable touch mode but allow to use the mouse')
        self.ckcss4 = QCheckBox('Enable mouse,disable pointer & zoom emulation')
        self.ckcss5 = QCheckBox('Start the Mobile version of the browser')
        self.ckcss6 = QCheckBox('Start the Tablet version of the browser')
        self.ckcss7 = QCheckBox('Emulate hardware with Menu and Back keys')
        self.ckcss8 = QCheckBox('Start the browser in Kiosk mode')
        self.width, self.height = QSpinBox(), QSpinBox()
        self.zoom, self.ram, self.dpi = QSpinBox(), QSpinBox(), QSpinBox()
        self.cpulag, self.gpulag = QSpinBox(), QSpinBox()
        self.lang, self.agent = QComboBox(), QComboBox()
        self.lang.addItems(['EN', 'ES', 'PT', 'JA', 'ZH', 'DE', 'RU', 'FR'])
        self.agent.addItems(['Default', 'Android', 'MeeGo', 'Desktop'])
        self.fonts = QLineEdit()
        self.width.setMaximum(9999)
        self.width.setMinimum(100)
        self.width.setValue(480)
        self.height.setMaximum(9999)
        self.height.setMinimum(100)
        self.height.setValue(800)
        self.zoom.setMaximum(999)
        self.zoom.setMinimum(1)
        self.zoom.setValue(100)
        self.ram.setMaximum(999)
        self.ram.setMinimum(1)
        self.ram.setValue(100)
        self.dpi.setMaximum(200)
        self.dpi.setMinimum(50)
        self.dpi.setValue(96)
        self.cpulag.setMaximum(9999)
        self.cpulag.setMinimum(0)
        self.cpulag.setValue(1)
        self.gpulag.setMaximum(9999)
        self.gpulag.setMinimum(0)
        self.gpulag.setValue(1)
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (self.ckcss1, self.ckcss2, self.ckcss3, self.ckcss4,
            self.ckcss5, self.ckcss6, self.ckcss7, self.ckcss8,
            QLabel('Width Pixels of the emulated device screen'), self.width,
            QLabel('Height Pixels of the emulated device screen'), self.height,
            QLabel('Zoom Percentage of emulated screen'), self.zoom,
            QLabel('RAM MegaBytes of the emulated device'), self.ram,
            QLabel('Language of the emulated device'), self.lang,
            QLabel('D.P.I. of the emulated device'), self.dpi,
            QLabel('User-Agent of the emulated device'), self.agent,
            QLabel('CPU Core Lag Miliseconds of emulated device'), self.cpulag,
            QLabel('GPU Video Lag Miliseconds of emulated device'), self.gpulag,
            QLabel('Extra Fonts Directory Full Path'), self.fonts):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle(' General ')
        self.nice, self.opera = QSpinBox(), QLineEdit(path.expanduser("~"))
        self.nice.setValue(20)
        self.nice.setMaximum(20)
        self.nice.setMinimum(0)
        self.opera.setCompleter(self.completer)
        if path.exists(CONFIG_FILE):
            with codecs.open(CONFIG_FILE, encoding='utf-8') as fp:
                self.opera.setText(fp.read())
        self.open2 = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.open2.setCursor(QCursor(Qt.PointingHandCursor))
        self.open2.clicked.connect(lambda: self.opera.setText(str(
            QFileDialog.getOpenFileName(self.dock, "Open Opera Mobile Emulator",
            path.expanduser("~"),
            'Opera Mobile Emulator Executable(opera-mobile-emulator)'))))
        self.help1 = QLabel('''<a href=
            "http://www.opera.com/developer/mobile-emulator">
            <small><center>Download Opera Mobile Emulator !</a>''')
        self.help1.setTextInteractionFlags(Qt.LinksAccessibleByMouse)
        self.help1.setOpenExternalLinks(True)
        vboxg4 = QVBoxLayout(self.group2)
        for each_widget in (QLabel(' Backend CPU priority: '), self.nice,
            QLabel(' Opera Mobile Emulator Full Path: '), self.opera,
            self.open2, self.help1):
            vboxg4.addWidget(each_widget)

        self.button = QPushButton('Preview on Mobile')
        self.button.setCursor(QCursor(Qt.PointingHandCursor))
        self.button.setMinimumSize(100, 50)
        self.button.clicked.connect(self.run)
        glow = QGraphicsDropShadowEffect(self)
        glow.setOffset(0)
        glow.setBlurRadius(99)
        glow.setColor(QColor(99, 255, 255))
        self.button.setGraphicsEffect(glow)
        glow.setEnabled(True)

        class TransientWidget(QWidget):
            ' persistant widget thingy '
            def __init__(self, widget_list):
                ' init sub class '
                super(TransientWidget, self).__init__()
                vbox = QVBoxLayout(self)
                for each_widget in widget_list:
                    vbox.addWidget(each_widget)

        tw = TransientWidget((QLabel('<b>Mobile Browser Emulator'),
            self.group0, self.group1, self.group2, self.output, self.button, ))
        self.scrollable, self.dock = QScrollArea(), QDockWidget()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(tw)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)
        ExplorerContainer().addTab(self.dock, "Mobile")
        QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock
          ).clicked.connect(lambda: QMessageBox.information(self.dock, __doc__,
            HELPMSG))

    def run(self):
        ' run the string replacing '
        self.output.clear()
        self.button.setEnabled(False)
        self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now())))
        if self.source.currentText() == 'Local File':
            target = 'file://' + str(self.infile.text()).strip()
        else:
            target = self.inurl.text()
        self.output.append(self.formatInfoMsg(' INFO: OK: Parsing Arguments'))
        cmd = ' '.join(('nice --adjustment={}'.format(self.nice.value()),
            '"{}"'.format(self.opera.text()),
            '-fullscreen' if self.ckcss1.isChecked() is True else '',
            '-notouch' if self.ckcss2.isChecked() is True else '',
            '-notouchwithtouchevents' if self.ckcss3.isChecked() is True else '',
            '-usemouse' if self.ckcss4.isChecked() is True else '',
            '-mobileui' if self.ckcss5.isChecked() is True else '',
            '-tabletui' if self.ckcss6.isChecked() is True else '',
            '-hasmenuandback' if self.ckcss7.isChecked() is True else '',
            '-k' if self.ckcss8.isChecked() is True else '',
            '-displaysize {}x{}'.format(self.width.value(), self.height.value()),
            '-displayzoom {}'.format(self.zoom.value()),
            '-mem {}M'.format(self.ram.value()),
            '-lang {}'.format(self.lang.currentText()),
            '-ppi {}'.format(self.dpi.value()),
            '-extra-fonts {}'.format(self.fonts.text()) if str(self.fonts.text()).strip() is not '' else '',
            '-user-agent-string {}'.format(self.agent.currentText()),
            '-delaycorethread {}'.format(self.cpulag.value()),
            '-delayuithread {}'.format(self.gpulag.value()),
            '-url "{}"'.format(target)
        ))
        self.output.append(self.formatInfoMsg('INFO:OK:Command:{}'.format(cmd)))
        self.process.start(cmd)
        if not self.process.waitForStarted():
            self.output.append(self.formatErrorMsg(' ERROR: FAIL: Meh. '))
            self.output.append(self.formatErrorMsg(
                'ERROR: FAIL: Failed with Arguments: {} '.format(cmd)))
            self.button.setEnabled(True)
            return
        self.output.setFocus()
        self.output.selectAll()
        self.button.setEnabled(True)

    def on_source_changed(self):
        ' do something when the desired source has changed '
        if self.source.currentText() == 'Local File':
            self.open.show()
            self.infile.show()
            self.inurl.hide()
        else:
            self.inurl.show()
            self.open.hide()
            self.infile.hide()

    def _process_finished(self):
        """ finished sucessfully """
        self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now())))
        self.output.selectAll()
        self.output.setFocus()

    def readOutput(self):
        """Read and append output to the logBrowser"""
        self.output.append(str(self.process.readAllStandardOutput()).strip())

    def readErrors(self):
        """Read and append errors to the logBrowser"""
        self.output.append(self.formatErrorMsg(str(
                                        self.process.readAllStandardError())))

    def formatErrorMsg(self, msg):
        """Format error messages in red color"""
        return self.formatMsg(msg, 'red')

    def formatInfoMsg(self, msg):
        """Format informative messages in blue color"""
        return self.formatMsg(msg, 'green')

    def formatMsg(self, msg, color):
        """Format message with the given color"""
        return '<font color="{}">{}</font>'.format(color, msg)

    def finish(self):
        ' save when finish '
        with codecs.open(CONFIG_FILE, "w", encoding='utf-8') as fp:
            fp.write(self.opera.text())
コード例 #16
0
ファイル: pythonshell.py プロジェクト: cheesinglee/spyder
class ExternalPythonShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = ExtPythonShellWidget
    def __init__(self, parent=None, fname=None, wdir=None, commands=[],
                 interact=False, debug=False, path=[],
                 ipython=False, arguments=None, stand_alone=True,
                 umd_enabled=True, umd_namelist=[], umd_verbose=True):
        self.namespacebrowser = None # namespace browser widget!
        
        self.fname = startup.__file__ if fname is None else fname
        
        self.stand_alone = stand_alone
        
        self.umd_enabled = umd_enabled
        self.umd_namelist = umd_namelist
        self.umd_verbose = umd_verbose
        
        self.namespacebrowser_button = None
        self.cwd_button = None
        self.terminate_button = None
        
        ExternalShellBase.__init__(self, parent, wdir,
                                   history_filename='.history.py')

        self.nsb_timer = QTimer(self) # Namespace browser auto-refresh timer
        self.nsb_timer.setInterval(3000)
        
        if arguments is not None:
            assert isinstance(arguments, basestring)
            self.arguments = arguments
        
        self.ipython = ipython
        if self.ipython:
            interact = False
        
        self.shell.set_externalshell(self)

        self.toggle_globals_explorer(False)
        self.interact_action.setChecked(interact)
        self.debug_action.setChecked(debug)
        
        self.monitor_socket = None
        self.interpreter = fname is None
        
        if self.interpreter:
            self.terminate_button.hide()
        
        self.commands = ["import sys", "sys.path.insert(0, '')"] + commands
        
        # Additional python path list
        self.path = path
        
    def closeEvent(self, event):
        ExternalShellBase.closeEvent(self, event)
        self.disconnect(self.nsb_timer, SIGNAL("timeout()"),
                        self.namespacebrowser.refresh_table)
        
    def get_toolbar_buttons(self):
        ExternalShellBase.get_toolbar_buttons(self)
        if self.namespacebrowser_button is None and self.stand_alone:
            self.namespacebrowser_button = create_toolbutton(self,
                          get_icon('dictedit.png'), self.tr("Variables"),
                          tip=self.tr("Show/hide global variables explorer"),
                          toggled=self.toggle_globals_explorer)
        if self.cwd_button is None:
            self.cwd_button = create_toolbutton(self,
                          get_std_icon('DirOpenIcon'), self.tr("Working directory"),
                          tip=self.tr("Set current working directory"),
                          triggered=self.set_current_working_directory)
        if self.terminate_button is None:
            self.terminate_button = create_toolbutton(self,
                          get_icon('terminate.png'), self.tr("Terminate"),
                          tip=self.tr("Attempts to terminate the process.\n"
                                      "The process may not exit as a result of "
                                      "clicking this button\n"
                                      "(it is given the chance to prompt "
                                      "the user for any unsaved files, etc)."))        
        buttons = [self.cwd_button]
        if self.namespacebrowser_button is not None:
            buttons.append(self.namespacebrowser_button)
        buttons += [self.run_button, self.options_button,
                    self.terminate_button, self.kill_button]
        return buttons

    def get_options_menu(self):
        self.interact_action = create_action(self, self.tr("Interact"))
        self.interact_action.setCheckable(True)
        self.debug_action = create_action(self, self.tr("Debug"))
        self.debug_action.setCheckable(True)
        self.args_action = create_action(self, self.tr("Arguments..."),
                                         triggered=self.get_arguments)
        return [self.interact_action, self.debug_action, self.args_action]

    def is_interpreter(self):
        """Return True if shellwidget is a Python/IPython interpreter"""
        return self.interpreter
        
    def set_namespacebrowser(self, namespacebrowser):
        """Set namespace browser *widget*"""
        self.namespacebrowser = namespacebrowser
        
    def get_shell_widget(self):
        if self.stand_alone:
            self.namespacebrowser = NamespaceBrowser(self)
            self.namespacebrowser.set_shellwidget(self)
            self.connect(self.namespacebrowser, SIGNAL('collapse()'),
                         lambda: self.toggle_globals_explorer(False))
            # Shell splitter
            self.splitter = splitter = QSplitter(Qt.Vertical, self)
            self.connect(self.splitter, SIGNAL('splitterMoved(int, int)'),
                         self.splitter_moved)
            splitter.addWidget(self.shell)
            splitter.setCollapsible(0, False)
            splitter.addWidget(self.namespacebrowser)
            splitter.setStretchFactor(0, 1)
            splitter.setStretchFactor(1, 0)
            splitter.setHandleWidth(5)
            splitter.setSizes([2, 1])
            return splitter
        else:
            return self.shell
    
    def get_icon(self):
        return get_icon('python.png')

    def set_buttons_runnning_state(self, state):
        ExternalShellBase.set_buttons_runnning_state(self, state)
        self.interact_action.setEnabled(not state and not self.interpreter)
        self.debug_action.setEnabled(not state and not self.interpreter)
        self.args_action.setEnabled(not state and
                                    (not self.interpreter or self.ipython))
        if state:
            if self.arguments:
                argstr = self.tr("Arguments: %1").arg(self.arguments)
            else:
                argstr = self.tr("No argument")
        else:
            argstr = self.tr("Arguments...")
        self.args_action.setText(argstr)
        self.terminate_button.setEnabled(state)
        if not state:
            self.toggle_globals_explorer(False)
        self.cwd_button.setEnabled(state)
        if self.namespacebrowser_button is not None:
            self.namespacebrowser_button.setEnabled(state)
    
    def create_process(self):
        self.shell.clear()
            
        self.process = QProcess(self)
        if self.ipython:
            self.process.setProcessChannelMode(QProcess.MergedChannels)
        else:
            self.process.setProcessChannelMode(QProcess.SeparateChannels)
        self.connect(self.shell, SIGNAL("wait_for_ready_read()"),
                     lambda: self.process.waitForReadyRead(250))
        
        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)

        #-------------------------Python specific-------------------------------
        # Python arguments
        p_args = ['-u']
        if self.interact_action.isChecked():
            p_args.append('-i')
        if self.debug_action.isChecked():
            p_args.extend(['-m', 'pdb'])
        if os.name == 'nt':
            # When calling pdb on Windows, one has to double the backslashes 
            # to help Python escaping these characters (otherwise, for example,
            # '\t' will be interpreted as a tabulation):
            p_args.append(self.fname.replace(os.sep, os.sep*2))
        else:
            p_args.append(self.fname)
        
        env = self.process.systemEnvironment()
        
        # Monitor
        env.append('SHELL_ID=%s' % id(self))
        from spyderlib.widgets.externalshell.monitor import start_server
        server, port = start_server()
        self.notification_thread = server.register(str(id(self)), self)
        self.connect(self.notification_thread, SIGNAL('refresh()'),
                     self.namespacebrowser.refresh_table)
        env.append('SPYDER_PORT=%d' % port)
        
        # Python init commands (interpreter only)
        if self.commands and self.interpreter:
            env.append('PYTHONINITCOMMANDS=%s' % ';'.join(self.commands))
            self.process.setEnvironment(env)
        
        # User Module Deleter
        if self.interpreter:
            env.append('UMD_ENABLED=%r' % self.umd_enabled)
            env.append('UMD_NAMELIST=%s' % ','.join(self.umd_namelist))
            env.append('UMD_VERBOSE=%r' % self.umd_verbose)
        
        # IPython related configuration
        if self.ipython:
            env.append('IPYTHON=True')
            # Do not call msvcrt.getch in IPython.genutils.page_more:
            env.append('TERM=emacs')
            
        pathlist = []

        # Fix encoding with custom "sitecustomize.py"
        scpath = osp.dirname(osp.abspath(__file__))
        pathlist.append(scpath)
        
        # Adding Spyder path
        pathlist += self.path
        
        # Adding path list to PYTHONPATH environment variable
        add_pathlist_to_PYTHONPATH(env, pathlist)
        
        self.process.setEnvironment(env)
        #-------------------------Python specific-------------------------------
            
        if self.arguments:
            p_args.extend( self.arguments.split(' ') )
                        
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process, SIGNAL("readyReadStandardError()"),
                     self.write_error)
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)

        self.connect(self.terminate_button, SIGNAL("clicked()"),
                     self.process.terminate)
        self.connect(self.kill_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        #-------------------------Python specific-------------------------------
        self.process.start(sys.executable, p_args)
        #-------------------------Python specific-------------------------------
            
        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, self.tr("Error"),
                                 self.tr("Process failed to start"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))
            self.connect(self.nsb_timer, SIGNAL("timeout()"),
                         self.namespacebrowser.auto_refresh)
            self.nsb_timer.start()
            
        return self.process
    
#===============================================================================
#    Input/Output
#===============================================================================
    def write_error(self):
        #---This is apparently necessary only on Windows (not sure though):
        #   emptying standard output buffer before writing error output
        self.process.setReadChannel(QProcess.StandardOutput)
        if self.process.waitForReadyRead(1):
            self.write_output()
            
        self.shell.write_error(self.get_stderr())
        QApplication.processEvents()
        
    def send_to_process(self, qstr):
        if not isinstance(qstr, QString):
            qstr = QString(qstr)
        if not qstr.endsWith('\n'):
            qstr.append('\n')
        self.process.write(qstr.toLocal8Bit())
        self.process.waitForBytesWritten(-1)
        
        # Eventually write prompt faster (when hitting Enter continuously)
        # -- necessary/working on Windows only:
        if os.name == 'nt':
            self.write_error()
        
    def keyboard_interrupt(self):
        communicate(self.monitor_socket, "thread.interrupt_main()")
            
#===============================================================================
#    Globals explorer
#===============================================================================
    def toggle_globals_explorer(self, state):
        if self.stand_alone:
            self.splitter.setSizes([1, 1 if state else 0])
            self.namespacebrowser_button.setChecked(state)
            if state:
                self.namespacebrowser.refresh_table()
        
    def splitter_moved(self, pos, index):
        self.namespacebrowser_button.setChecked( self.splitter.sizes()[1] )

#===============================================================================
#    Current working directory
#===============================================================================
    def set_current_working_directory(self):
        cwd = self.shell.get_cwd()
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        directory = QFileDialog.getExistingDirectory(self,
                                             self.tr("Select directory"), cwd)
        if not directory.isEmpty():
            self.shell.set_cwd(unicode(directory))
        self.emit(SIGNAL('redirect_stdio(bool)'), True)
コード例 #17
0
ファイル: pythonshell.py プロジェクト: koll00/Gui_SM
class ExternalPythonShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = ExtPythonShellWidget

    def __init__(self,
                 parent=None,
                 fname=None,
                 wdir=None,
                 interact=False,
                 debug=False,
                 path=[],
                 python_args='',
                 ipykernel=False,
                 arguments='',
                 stand_alone=None,
                 umd_enabled=True,
                 umd_namelist=[],
                 umd_verbose=True,
                 pythonstartup=None,
                 pythonexecutable=None,
                 monitor_enabled=True,
                 mpl_patch_enabled=True,
                 mpl_backend=None,
                 ets_backend='qt4',
                 qt_api=None,
                 pyqt_api=0,
                 install_qt_inputhook=True,
                 ignore_sip_setapi_errors=False,
                 merge_output_channels=False,
                 colorize_sys_stderr=False,
                 autorefresh_timeout=3000,
                 autorefresh_state=True,
                 light_background=True,
                 menu_actions=None,
                 show_buttons_inside=True,
                 show_elapsed_time=True):

        assert qt_api in (None, 'pyqt', 'pyside')

        self.namespacebrowser = None  # namespace browser widget!

        self.dialog_manager = DialogManager()

        self.stand_alone = stand_alone  # stand alone settings (None: plugin)
        self.pythonstartup = pythonstartup
        self.pythonexecutable = pythonexecutable
        self.monitor_enabled = monitor_enabled
        self.mpl_patch_enabled = mpl_patch_enabled
        self.mpl_backend = mpl_backend
        self.ets_backend = ets_backend
        self.qt_api = qt_api
        self.pyqt_api = pyqt_api
        self.install_qt_inputhook = install_qt_inputhook
        self.ignore_sip_setapi_errors = ignore_sip_setapi_errors
        self.merge_output_channels = merge_output_channels
        self.colorize_sys_stderr = colorize_sys_stderr
        self.umd_enabled = umd_enabled
        self.umd_namelist = umd_namelist
        self.umd_verbose = umd_verbose
        self.autorefresh_timeout = autorefresh_timeout
        self.autorefresh_state = autorefresh_state

        self.namespacebrowser_button = None
        self.cwd_button = None
        self.env_button = None
        self.syspath_button = None
        self.terminate_button = None

        self.notification_thread = None

        ExternalShellBase.__init__(self,
                                   parent=parent,
                                   fname=fname,
                                   wdir=wdir,
                                   history_filename='.history.py',
                                   light_background=light_background,
                                   menu_actions=menu_actions,
                                   show_buttons_inside=show_buttons_inside,
                                   show_elapsed_time=show_elapsed_time)

        if self.pythonexecutable is None:
            self.pythonexecutable = get_python_executable()

        self.python_args = None
        if python_args:
            assert isinstance(python_args, basestring)
            self.python_args = python_args

        assert isinstance(arguments, basestring)
        self.arguments = arguments

        self.connection_file = None
        self.is_ipykernel = ipykernel
        if self.is_ipykernel:
            interact = False
            # Running our custom startup script for IPython kernels:
            # (see spyderlib/widgets/externalshell/start_ipython_kernel.py)
            self.fname = get_module_source_path('SMlib.widgets.externalshell',
                                                'start_ipython_kernel.py')

        self.shell.set_externalshell(self)

        self.toggle_globals_explorer(False)
        self.interact_action.setChecked(interact)
        self.debug_action.setChecked(debug)

        self.introspection_socket = None
        self.is_interpreter = fname is None

        if self.is_interpreter:
            self.terminate_button.hide()

        # Additional python path list
        self.path = path
        self.shell.path = path

    def set_introspection_socket(self, introspection_socket):
        self.introspection_socket = introspection_socket
        if self.namespacebrowser is not None:
            settings = self.namespacebrowser.get_view_settings()
            communicate(introspection_socket,
                        'set_remote_view_settings()',
                        settings=[settings])

    def set_autorefresh_timeout(self, interval):
        if self.introspection_socket is not None:
            try:
                communicate(self.introspection_socket,
                            "set_monitor_timeout(%d)" % interval)
            except socket.error:
                pass

    def closeEvent(self, event):
        self.quit_monitor()
        ExternalShellBase.closeEvent(self, event)

    def get_toolbar_buttons(self):
        ExternalShellBase.get_toolbar_buttons(self)
        if self.namespacebrowser_button is None \
           and self.stand_alone is not None:
            self.namespacebrowser_button = create_toolbutton(
                self,
                text=_("Variables"),
                icon=get_icon('dictedit.png'),
                tip=_("Show/hide global variables explorer"),
                toggled=self.toggle_globals_explorer,
                text_beside_icon=True)
        if self.terminate_button is None:
            self.terminate_button = create_toolbutton(
                self,
                text=_("Terminate"),
                icon=get_icon('terminate.png'),
                tip=_("""Attempts to terminate the process.
The process may not exit as a result of clicking this button
(it is given the chance to prompt the user for any unsaved files, etc)."""))
        buttons = []
        if self.namespacebrowser_button is not None:
            buttons.append(self.namespacebrowser_button)
        buttons += [
            self.run_button, self.options_button, self.terminate_button,
            self.kill_button
        ]
        return buttons

    def get_options_menu(self):
        ExternalShellBase.get_options_menu(self)
        self.interact_action = create_action(self, _("Interact"))
        self.interact_action.setCheckable(True)
        self.debug_action = create_action(self, _("Debug"))
        self.debug_action.setCheckable(True)
        self.args_action = create_action(self,
                                         _("Arguments..."),
                                         triggered=self.get_arguments)
        run_settings_menu = QMenu(_("Run settings"), self)
        add_actions(
            run_settings_menu,
            (self.interact_action, self.debug_action, self.args_action))
        self.cwd_button = create_action(
            self,
            _("Working directory"),
            icon=get_std_icon('DirOpenIcon'),
            tip=_("Set current working directory"),
            triggered=self.set_current_working_directory)
        self.env_button = create_action(self,
                                        _("Environment variables"),
                                        icon=get_icon('environ.png'),
                                        triggered=self.show_env)
        self.syspath_button = create_action(self,
                                            _("Show sys.path contents"),
                                            icon=get_icon('syspath.png'),
                                            triggered=self.show_syspath)
        actions = [
            run_settings_menu, self.show_time_action, None, self.cwd_button,
            self.env_button, self.syspath_button
        ]
        if self.menu_actions is not None:
            actions += [None] + self.menu_actions
        return actions

    def is_interpreter(self):
        """Return True if shellwidget is a Python interpreter"""
        return self.is_interpreter

    def get_shell_widget(self):
        if self.stand_alone is None:
            return self.shell
        else:
            self.namespacebrowser = NamespaceBrowser(self)
            settings = self.stand_alone
            self.namespacebrowser.set_shellwidget(self)
            self.namespacebrowser.setup(**settings)
            self.connect(self.namespacebrowser, SIGNAL('collapse()'),
                         lambda: self.toggle_globals_explorer(False))
            # Shell splitter
            self.splitter = splitter = QSplitter(Qt.Vertical, self)
            self.connect(self.splitter, SIGNAL('splitterMoved(int, int)'),
                         self.splitter_moved)
            splitter.addWidget(self.shell)
            splitter.setCollapsible(0, False)
            splitter.addWidget(self.namespacebrowser)
            splitter.setStretchFactor(0, 1)
            splitter.setStretchFactor(1, 0)
            splitter.setHandleWidth(5)
            splitter.setSizes([2, 1])
            return splitter

    def get_icon(self):
        return get_icon('python.png')

    def set_buttons_runnning_state(self, state):
        ExternalShellBase.set_buttons_runnning_state(self, state)
        self.interact_action.setEnabled(not state and not self.is_interpreter)
        self.debug_action.setEnabled(not state and not self.is_interpreter)
        self.args_action.setEnabled(not state and not self.is_interpreter)
        if state:
            if self.arguments:
                argstr = _("Arguments: %s") % self.arguments
            else:
                argstr = _("No argument")
        else:
            argstr = _("Arguments...")
        self.args_action.setText(argstr)
        self.terminate_button.setVisible(not self.is_interpreter and state)
        if not state:
            self.toggle_globals_explorer(False)
        for btn in (self.cwd_button, self.env_button, self.syspath_button):
            btn.setEnabled(state and self.monitor_enabled)
        if self.namespacebrowser_button is not None:
            self.namespacebrowser_button.setEnabled(state)

    def set_namespacebrowser(self, namespacebrowser):
        """
        Set namespace browser *widget*
        Note: this method is not used in stand alone mode
        """
        self.namespacebrowser = namespacebrowser
        self.configure_namespacebrowser()

    def configure_namespacebrowser(self):
        """Connect the namespace browser to the notification thread"""
        if self.notification_thread is not None:
            self.connect(self.notification_thread,
                         SIGNAL('refresh_namespace_browser()'),
                         self.namespacebrowser.refresh_table)
            signal = self.notification_thread.sig_process_remote_view
            signal.connect(self.namespacebrowser.process_remote_view)

    def create_process(self):
        self.shell.clear()

        self.process = QProcess(self)
        if self.merge_output_channels:
            self.process.setProcessChannelMode(QProcess.MergedChannels)
        else:
            self.process.setProcessChannelMode(QProcess.SeparateChannels)
        self.connect(self.shell, SIGNAL("wait_for_ready_read()"),
                     lambda: self.process.waitForReadyRead(250))

        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)

        #-------------------------Python specific-------------------------------
        # Python arguments
        p_args = ['-u']
        if DEBUG >= 3:
            p_args += ['-v']
        p_args += get_python_args(self.fname, self.python_args,
                                  self.interact_action.isChecked(),
                                  self.debug_action.isChecked(),
                                  self.arguments)

        env = [unicode(_path) for _path in self.process.systemEnvironment()]

        if self.pythonstartup:
            env.append('PYTHONSTARTUP=%s' % self.pythonstartup)

        # Monitor
        if self.monitor_enabled:
            env.append('SPYDER_SHELL_ID=%s' % id(self))
            env.append('SPYDER_AR_TIMEOUT=%d' % self.autorefresh_timeout)
            env.append('SPYDER_AR_STATE=%r' % self.autorefresh_state)
            from SMlib.widgets.externalshell import introspection
            introspection_server = introspection.start_introspection_server()
            introspection_server.register(self)
            notification_server = introspection.start_notification_server()
            self.notification_thread = notification_server.register(self)
            self.connect(
                self.notification_thread,
                SIGNAL('pdb(QString,int)'), lambda fname, lineno: self.emit(
                    SIGNAL('pdb(QString,int)'), fname, lineno))
            self.connect(
                self.notification_thread,
                SIGNAL('new_ipython_kernel(QString)'), lambda args: self.emit(
                    SIGNAL('create_ipython_client(QString)'), args))
            self.connect(
                self.notification_thread, SIGNAL('open_file(QString,int)'),
                lambda fname, lineno: self.emit(
                    SIGNAL('open_file(QString,int)'), fname, lineno))
            if self.namespacebrowser is not None:
                self.configure_namespacebrowser()
            env.append('SPYDER_I_PORT=%d' % introspection_server.port)
            env.append('SPYDER_N_PORT=%d' % notification_server.port)

        # External modules options
        env.append('ETS_TOOLKIT=%s' % self.ets_backend)
        env.append('MATPLOTLIB_PATCH=%r' % self.mpl_patch_enabled)
        if self.mpl_backend:
            env.append('MATPLOTLIB_BACKEND=%s' % self.mpl_backend)
        if self.qt_api:
            env.append('QT_API=%s' % self.qt_api)
        env.append('INSTALL_QT_INPUTHOOK=%s' % self.install_qt_inputhook)
        env.append('COLORIZE_SYS_STDERR=%s' % self.colorize_sys_stderr)
        #        # Socket-based alternative (see input hook in sitecustomize.py):
        #        if self.install_qt_inputhook:
        #            from PyQt4.QtNetwork import QLocalServer
        #            self.local_server = QLocalServer()
        #            self.local_server.listen(str(id(self)))
        if self.pyqt_api:
            env.append('PYQT_API=%d' % self.pyqt_api)
        env.append('IGNORE_SIP_SETAPI_ERRORS=%s' %
                   self.ignore_sip_setapi_errors)

        # User Module Deleter
        if self.is_interpreter:
            env.append('UMD_ENABLED=%r' % self.umd_enabled)
            env.append('UMD_NAMELIST=%s' % ','.join(self.umd_namelist))
            env.append('UMD_VERBOSE=%r' % self.umd_verbose)

        # IPython kernel
        env.append('IPYTHON_KERNEL=%r' % self.is_ipykernel)

        pathlist = []

        # Fix encoding with custom "sitecustomize.py"
        scpath = osp.dirname(osp.abspath(__file__))
        pathlist.append(scpath)

        # Adding Spyder path
        pathlist += self.path

        # Adding path list to PYTHONPATH environment variable
        add_pathlist_to_PYTHONPATH(env, pathlist)

        #-------------------------Python specific-------------------------------

        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process, SIGNAL("readyReadStandardError()"),
                     self.write_error)
        self.connect(self.process,
                     SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)

        self.connect(self, SIGNAL('finished()'), self.dialog_manager.close_all)

        self.connect(self.terminate_button, SIGNAL("clicked()"),
                     self.process.terminate)
        self.connect(self.kill_button, SIGNAL("clicked()"), self.process.kill)

        #-------------------------Python specific-------------------------------
        # Fixes for our Mac app:
        # 1. PYTHONPATH and PYTHONHOME are set while bootstrapping the app,
        #    but their values are messing sys.path for external interpreters
        #    (e.g. EPD) so we need to remove them from the environment.
        # 2. Add this file's dir to PYTHONPATH. This will make every external
        #    interpreter to use our sitecustomize script.
        # 3. Remove PYTHONOPTIMIZE from env so that we can have assert
        #    statements working with our interpreters (See Issue 1281)
        if sys.platform == 'darwin' and 'Spyder.app' in __file__:
            env.append('SPYDER_INTERPRETER=%s' % self.pythonexecutable)
            if 'Spyder.app' not in self.pythonexecutable:
                env = [p for p in env if not (p.startswith('PYTHONPATH') or \
                                              p.startswith('PYTHONHOME'))] # 1.

                env.append('PYTHONPATH=%s' % osp.dirname(__file__))  # 2.

            env = [p for p in env if not p.startswith('PYTHONOPTIMIZE')]  # 3.

        self.process.setEnvironment(env)
        self.process.start(self.pythonexecutable, p_args)
        #-------------------------Python specific-------------------------------

        running = self.process.waitForStarted(3000)
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(
                self, _("Error"),
                _("A Python or IPython Console failed to start!"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))

        return self.process

    def finished(self, exit_code, exit_status):
        """Reimplement ExternalShellBase method"""
        ExternalShellBase.finished(self, exit_code, exit_status)
        self.introspection_socket = None

#===============================================================================
#    Input/Output
#===============================================================================

    def write_error(self):
        if os.name == 'nt':
            #---This is apparently necessary only on Windows (not sure though):
            #   emptying standard output buffer before writing error output
            self.process.setReadChannel(QProcess.StandardOutput)
            if self.process.waitForReadyRead(1):
                self.write_output()
        self.shell.write_error(self.get_stderr())
        QApplication.processEvents()

    def send_to_process(self, text):
        if not self.is_running():
            return

        if not isinstance(text, basestring):
            text = unicode(text)
        if self.install_qt_inputhook and self.introspection_socket is not None:
            communicate(self.introspection_socket,
                        "toggle_inputhook_flag(True)")
#            # Socket-based alternative (see input hook in sitecustomize.py):
#            while self.local_server.hasPendingConnections():
#                self.local_server.nextPendingConnection().write('go!')
        if text.startswith(('%', '!')):
            text = 'evalsc(r"%s")\n' % text
        if not text.endswith('\n'):
            text += '\n'
        self.process.write(locale_codec.fromUnicode(text))
        self.process.waitForBytesWritten(-1)

        # Eventually write prompt faster (when hitting Enter continuously)
        # -- necessary/working on Windows only:
        if os.name == 'nt':
            self.write_error()

    def keyboard_interrupt(self):
        if self.introspection_socket is not None:
            communicate(self.introspection_socket, "thread.interrupt_main()")

    def quit_monitor(self):
        if self.introspection_socket is not None:
            try:
                write_packet(self.introspection_socket, "thread.exit()")
            except socket.error:
                pass

#===============================================================================
#    Globals explorer
#===============================================================================

    def toggle_globals_explorer(self, state):
        if self.stand_alone is not None:
            self.splitter.setSizes([1, 1 if state else 0])
            self.namespacebrowser_button.setChecked(state)
            if state and self.namespacebrowser is not None:
                self.namespacebrowser.refresh_table()

    def splitter_moved(self, pos, index):
        self.namespacebrowser_button.setChecked(self.splitter.sizes()[1])

#===============================================================================
#    Misc.
#===============================================================================

    def set_current_working_directory(self):
        """Set current working directory"""
        cwd = self.shell.get_cwd()
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        directory = getexistingdirectory(self, _("Select directory"), cwd)
        if directory:
            self.shell.set_cwd(directory)
        self.emit(SIGNAL('redirect_stdio(bool)'), True)

    def show_env(self):
        """Show environment variables"""
        get_func = self.shell.get_env
        set_func = self.shell.set_env
        self.dialog_manager.show(RemoteEnvDialog(get_func, set_func))

    def show_syspath(self):
        """Show sys.path contents"""
        editor = DictEditor()
        editor.setup(self.shell.get_syspath(),
                     title="sys.path",
                     readonly=True,
                     width=600,
                     icon='syspath.png')
        self.dialog_manager.show(editor)
コード例 #18
0
ファイル: mplayer.py プロジェクト: Ptaah/Ekd
class Mplayer(QDialog):

	REVENIR, PAS_PRECEDENT_SUIVANT, PRECEDENT_SUIVANT, CURSEUR_SUR_UNE_LIGNE,\
		CURSEUR_A_PART, PARCOURIR, PAS_PARCOURIR, LIST, RATIO = range(9)

	HAUTEUR, LARGEUR = range(2)

	def __init__(self, cheminVideo=[], taille=(250,225),
			choixWidget=(RATIO, REVENIR, PAS_PRECEDENT_SUIVANT,CURSEUR_SUR_UNE_LIGNE,PAS_PARCOURIR,LIST),
			debutFin=(0,0), cheminMPlayer=None, barreTaches=None, facteurLimitant=HAUTEUR,
			cheminParcourir=None, parent=None):

		"""widget mplayer"""
		QDialog.__init__(self, parent)

		#=== Paramètres généraux ===#
		self.setAttribute(Qt.WA_DeleteOnClose)
		self.setWindowTitle(_(u"Player vidéo"))
                #On réduit la marge pour gagner de l'espace
                self.setContentsMargins(0,0,0,0)

		self.systeme = os.name
                ### Quand EKD windows est installé, le chemin des dépendances sont ###########
                ### positionnées dans les variables d'environnement donc pas besoin de #######
                ### collecter le chemin des ces dépendances ##################################
                self.cheminMPlayer = "mplayer"

                ##############################################################################

		# liste de chemins vidéos
		if type(cheminVideo) != list :
			self.listeVideos=[cheminVideo]
		else :
			self.listeVideos = cheminVideo

		# est-ce que la vidéo est lue?
		self.estLue=False

		# est-ce que la vidéo est en pause?
		self.estEnPause=False

		self.debutFin = debutFin

		# Nom du fichier courant (le self n'est pas encore utile)
		txtParDefaut = u"Pas de fichier lu"
		if self.listeVideos.__len__()!=0:
			self.fichierCourant =  [txtParDefaut, self.listeVideos[0]]
		else: self.fichierCourant = [txtParDefaut, ""]

		# Barre des tâches de la fenêtre
		self.barreTaches = barreTaches

		# Taille de la vidéo
		self.tailleLargeur=taille[0]
		self.tailleHauteur=taille[1]

		# paramètres des boutons-icones
		iconTaille=22
		flat=1

		# Pour récupérer le temps courant depuis certains cadre
		self.temps = 0

		self.dureeTimer = 10 # temps en ms
		###############################################################################################################################

		#Pour être plus précis lors de la lecture, on prend comme unité la miliseconde. ######################
		## Il faut donc utiliser une echelle 1000 fois plus grande pour les unités du slider
		self.echelle=1000
		###############################################################################################################################

		# Permet de récupérer la durée de la vidéo depuis une instance de la classe
		# Sert dans certains cadres
		self.dureeVideo = 0

		# Chemin sur lequel peut s'ouvrir la boite de dialogue de fichier
		# associée au bouton parcourir
		self.cheminPourBoutonParcourir = cheminParcourir

		self.taille = taille

		debug("self.taille avant lecture : %s %s" % (self.taille, type(self.taille)))

		#=== Widgets ===#

		self.icone_lire=QIcon("Icones" + os.sep + "player_play.png")
		self.icone_pause=QIcon("Icones" + os.sep + "player_pause.png")
		self.icone_arret=QIcon("Icones" + os.sep + "player_stop.png")

		if Mplayer.REVENIR in choixWidget:
			self.bout_revenir = QPushButton(u"Revenir")
			self.bout_revenir.setIcon(QIcon("Icones" + os.sep + "revenir.png"))

		if Mplayer.PARCOURIR in choixWidget:
			self.bout_ouvVideo = QPushButton(u"Parcourir...")

		if Mplayer.PRECEDENT_SUIVANT in choixWidget:
			self.bout_prec = QPushButton(QIcon("Icones" + os.sep + "player_rew.png"),"")
			self.bout_prec.setIconSize(QSize(iconTaille, iconTaille))
			self.bout_prec.setFlat(flat)
			self.bout_suivant = QPushButton(QIcon("Icones" + os.sep + "player_fwd.png"),"")
			self.bout_suivant.setIconSize(QSize(iconTaille, iconTaille))
			self.bout_suivant.setFlat(flat)

		self.LISTW=False
		if Mplayer.LIST in choixWidget :
			self.LISTW = True
			self.listFichiers = QComboBox()
			self.listFichiers.hide()
			self.setListeVideo()


		self.bout_LectPause = QPushButton(self.icone_lire,"")
		self.bout_LectPause.setIconSize(QSize(iconTaille, iconTaille))
		self.bout_LectPause.setFlat(flat)

		self.bout_Arret = QPushButton(self.icone_arret,"")
		self.bout_Arret.setIconSize(QSize(iconTaille, iconTaille))
		self.bout_Arret.setFlat(flat)

		# widget qui contiendra la vidéo
		self.cibleVideo = DisplayVid(self)
		# par défaut le widget-cible est noir
		color = QColor(0, 0, 0)
		self.cibleVideo.setAutoFillBackground(True)
		self.cibleVideo.setPalette(QPalette(color))
		self.cibleVideo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
		self.cibleVideo.setFixedHeight(self.taille[1])
		self.cibleVideo.setToolTip(self.fichierCourant[0])

		#Choix de l'aspect ratio de la vidéo
                if Mplayer.RATIO in choixWidget :
                    self.conf = QGroupBox()
                    self.conf.setContentsMargins(0,0,0,0)
                    self.conf.setMinimumSize(QSize(self.tailleLargeur, 0))
                    self.conf.setObjectName("conf")
                    self.verticalLayout = QHBoxLayout(self.conf)
                    self.verticalLayout.setObjectName("verticalLayout")
                    self.choicenorm = QRadioButton(self.conf)
                    self.choicenorm.setObjectName("choicenorm")
                    self.verticalLayout.addWidget(self.choicenorm)
                    self.choicewide = QRadioButton(self.conf)
                    self.choicewide.setObjectName("choicewide")
                    self.verticalLayout.addWidget(self.choicewide)
                    self.choiceone = QRadioButton(self.conf)
                    self.choiceone.setObjectName("choiceone")
                    self.verticalLayout.addWidget(self.choiceone)
                    self.choicenorm.setText("4:3")
                    self.choicewide.setText("16:9")
                    self.choiceone.setText("w:h")
                # Checked le ratio de la vidéo
                if self.listeVideos.__len__()!=0:
                        self.changeRatio(self.listeVideos[0])
                else :
                        self.setRatio(4.0/3.0)
                        if Mplayer.RATIO in choixWidget :
                            self.choicenorm.setChecked(True)

		self.slider = QSlider(Qt.Horizontal)
		self.slider.setEnabled(True)

		self.mplayerProcess = QProcess(self)

		self.timer = QTimer(self)

		self.tempsChrono = TracerChrono()

		#=== mise-en-page/plan ===#
		mhbox = QHBoxLayout()
		vbox = QVBoxLayout()
		vbox.addWidget(self.cibleVideo)
                if Mplayer.RATIO in choixWidget :
                    vbox.addWidget(self.conf)
		hbox = QHBoxLayout()
		if Mplayer.REVENIR in choixWidget:
			hbox.addWidget(self.bout_revenir)
		if Mplayer.PARCOURIR in choixWidget:
			hbox.addWidget(self.bout_ouvVideo)
		hbox.addWidget(self.bout_LectPause)
		hbox.addWidget(self.bout_Arret)
		if Mplayer.PRECEDENT_SUIVANT in choixWidget:
			hbox.addWidget(self.bout_prec)
			hbox.addWidget(self.bout_suivant)
		hbox.addWidget(self.tempsChrono)
		if Mplayer.CURSEUR_A_PART not in choixWidget:
			hbox.addWidget(self.slider)
		vbox.addLayout(hbox)
		if Mplayer.CURSEUR_A_PART in choixWidget:
			hbox.setAlignment(Qt.AlignLeft)
			hbox = QHBoxLayout()
			hbox.addWidget(self.slider)
			vbox.addLayout(hbox)
		# Liste fichier dans combobox
		if self.LISTW :
			hbox = QHBoxLayout()
			hbox.addWidget(self.listFichiers)
			vbox.addLayout(hbox)

		mhbox.addLayout(vbox)
		self.setLayout(mhbox)

		#=== connexion des widgets à des fonctions ===#

		if Mplayer.REVENIR in choixWidget:
			self.connect(self.bout_revenir, SIGNAL('clicked()'), SLOT('close()'))
		if Mplayer.PARCOURIR in choixWidget:
			self.connect(self.bout_ouvVideo, SIGNAL('clicked()'), self.ouvrirVideo)
		if Mplayer.PRECEDENT_SUIVANT in choixWidget:
			self.connect(self.bout_prec, SIGNAL('clicked()'), self.precedent)
			self.connect(self.bout_suivant, SIGNAL('clicked()'), self.suivant)
		#Ajouté le 08/11/2009 - Liste des fichiers dans une combobox
		if self.LISTW :
			self.connect(self.listFichiers, SIGNAL('currentIndexChanged(int)'), self.changeVideo)
		self.connect(self.bout_LectPause, SIGNAL('clicked()'), self.lectPause)
		self.connect(self.bout_Arret, SIGNAL('clicked()'), self.arretMPlayer)
		self.connect(self.mplayerProcess, SIGNAL('readyReadStandardOutput()'), self.recupSortie)
		self.connect(self.mplayerProcess, SIGNAL('finished(int,QProcess::ExitStatus)'), self.finVideo)
		self.connect(self.timer, SIGNAL('timeout()'), self.sonderTempsActuel)
		self.connect(self.slider, SIGNAL('sliderMoved(int)'), self.changerTempsCurseur)
		self.connect(self.cibleVideo, SIGNAL('changeSize'), self.sizeMplayer)
                if Mplayer.RATIO in choixWidget :
                    self.connect(self.choicenorm, SIGNAL("clicked(bool)"), self.defRatio)
                    self.connect(self.choicewide, SIGNAL("clicked(bool)"), self.defRatio)
                    self.connect(self.choiceone, SIGNAL("clicked(bool)"), self.defRatio)

	def setListeVideo(self) :
		self.referenceVideo = []
		self.listFichiers.clear()
		for vid in self.listeVideos :
			self.referenceVideo.append(vid)
			self.listFichiers.addItem(os.path.basename(vid))
		if self.listeVideos.__len__() > 1 :
			self.listFichiers.show()

	def setAudio(self,au) :
		if au :
			self.cibleVideo.hide()
                        if "conf" in self.__dict__ :
			    self.conf.hide()
		else :
			self.cibleVideo.show()
                        if "conf" in self.__dict__ :
                            self.conf.show()
	def changeVideo(self, index) :
		self.arretMPlayer()
		if index >= 0 : # Condition ajoutée pour éviter une erreure de dépassement de range dans la liste.
			self.listeVideos = self.referenceVideo[index]
			self.listFichiers.setCurrentIndex(index)

	def defRatio(self, state=0) :
		if state :
			if self.choicenorm.isChecked() :
				self.setRatio(4.0/3.0)
			if self.choicewide.isChecked() :
				self.setRatio(16.0/9.0)
			if self.choiceone.isChecked() :
				try :
					dim=getVideoSize(unicode(self.listeVideos[0]))
					self.setRatio(dim[0]/dim[1])
				except :
					None
			self.defRatio()
		else :
			self.adjustSize()

	def setRatio(self,ratio) :
		self.ratio = ratio
		self.sizeMplayer()

	def changeRatio(self,video) :
		rv = getVideoRatio(video)
		if rv[0]==0.0 and type(rv[1])==float :
			rat = rv[1]
		else :
			rat = rv[0]

		if rat > 1.7 :
                        if "choicewide" in self.__dict__ :
                            self.choicewide.setChecked(True)
			self.setRatio(16.0/9.0)
		elif rat > 1.3 and rat <= 1.7 :
                        if "choicenorm" in self.__dict__ :
                            self.choicenorm.setChecked(True)
			self.setRatio(4.0/3.0)
		elif rat < 1.3 and rat != 0.0 :
                        if "choiceone" in self.__dict__ :
                            self.choiceone.setChecked(True)
			dim=getVideoSize(video)
			self.setRatio(dim[0]/dim[1])
		else :
                        if "choicenorm" in self.__dict__ :
                            self.choicenorm.setChecked(True)
			self.setRatio(4.0/3.0)

	def sizeMplayer(self) :
		self.cibleVideo.setFixedHeight(int(self.cibleVideo.width()/self.ratio))

	def ouvrirVideo(self):
		"""Ouverture de la boîte de dialogue de fichiers"""
		txt = u"Fichiers vidéo"
		if self.cheminPourBoutonParcourir:
			chemin = self.cheminPourBoutonParcourir

		else:
			try:
				chemin = EkdConfig.get('general','video_input_path').decode("UTF8")
			except:
				chemin = os.path.expanduser('~')

		liste=QFileDialog.getOpenFileNames(None, u"Ouvrir", chemin, "%s (*.avi *.mpg *.mpeg *.mjpeg *.flv *.mp4 *.ogg *.vob *.mov *.wmv *.3gp *.h264)\n*" %txt)
		if not liste: return
		self.listeVideos = liste
		self.changeRatio(unicode(self.listeVideos[0]))

		chemin = unicode(self.listeVideos[0])
		EkdConfig.set('general','video_input_path',os.path.dirname(chemin).encode("UTF8"))

	def setVideos(self, videos) :
		'''Définie proprement la liste des vidéos à jouer'''
		if type(videos) != list :
			self.listeVideos = [videos]
		else :
			self.listeVideos = videos
		if self.LISTW and videos.__len__() > 1 :
			self.setListeVideo()
		elif self.LISTW :
			self.listFichiers.hide()

	def demarrerMPlayer(self):
		"""démarrage de mplayer avec les arguments choisis"""
		if self.estLue:
			return True

		args = QStringList()	# Liste Qt qui contiendra les options de mplayer
					# Ajout d'options à liste: args << "-option"

		# mplayer fonctionnera comme un terminal dans ce script
		args << "-slave"
		# on ne veut pas avoir des commentaires sans grand intérêt
		args << "-quiet"

		# Sous linux, aucun driver n'a été nécessaire et pas de manip pour Wid :)
		if self.systeme=='posix':
			# try - except?
			# la fenêtre de mplayer restera attaché à la fenêtre
			# wid prend en valeur le nombre identifiant le widget (celui qui contiendra la vidéo)
			args << "-wid" << QString.number(self.cibleVideo.winId()) # Objet QString car args est une liste de ch de caractères
			settings = QSettings()
			videoOutput = settings.value("vo", QVariant('')).toString()
			if videoOutput:
				args << '-vo' << videoOutput

		# Sous windows
		else:
			# reinterpret_cast<qlonglong> obligatoire, winId() ne se laissant pas convertir gentiment ;)
			args << "-wid" << self.cibleVideo.winId().__hex__()
			args << "-vo" << "directx:noaccel"
			#args << "-vo" << "gl" # alternative

		# chemin de la vidéo
		args << self.listeVideos

		if PYQT_VERSION_STR >= "4.1.0":
			# mode de canal: on fusionne le canal de sortie normal (stdout) et celui des erreurs (stderr)
			self.mplayerProcess.setProcessChannelMode(QProcess.MergedChannels)
		# démarrage de mplayer (en tenant compte des arguments définis ci-dessus)
		# comme un nouveau processus
		self.mplayerProcess.start(self.cheminMPlayer, args)
		# au cas où mplayer ne démarrerait pas au bout de 3 sec (ex. problème de codec)
		if not self.mplayerProcess.waitForStarted(3000):
			QMessageBox.critical(self, u"Avertissement", u"Bogue au lancement de la vidéo avec mplayer")
			return False

		# donne le temps toutes les x secondes
		self.timer.start(self.dureeTimer)

		self.estLue = True

		return True

	def recupSortie(self):
		"""récupère les lignes d'information émises par QProcess (mplayerProcess) et en tire les conséquences"""
		while self.mplayerProcess.canReadLine(): # renvoie True si une ligne complète peut être lue à partir du système
			# stocker l'ensemble des bits d'une ligne
			tampon=QByteArray(self.mplayerProcess.readLine()) # readline: lit une ligne ascii à partir du système

			# On vérifie si on a eu des réponses
			if tampon.startsWith("Playing"):
				# On récupère les infos de base ('$ mplayer -input cmdlist' pour avoir la liste complète - file:///usr/share/doc/mplayer-doc/tech/slave.txt.gz pour plus de détails)
				self.mplayerProcess.write("get_video_resolution\n") # récupère la résolution de la vidéo
				self.mplayerProcess.write("get_time_length\n")
				# Nouveau fichier chargé -> on récupère son nom
				ind = tampon.length() - 2 # suppression du '.' à la fin
				tampon.remove(ind,ind)
				tampon.remove(0, 8) # vire Playing
				tampon.replace(QByteArray("\n"), QByteArray(""))
				tampon.replace(QByteArray("\r"), QByteArray(""))
				try:
					# Tour de passe-passe pour ne pas avoir de problème d'accents

					# Condition pour détection windows
					if os.name == 'nt':
						self.fichierCourant[1]=unicode(QString(tampon))
					# Condition pour détection Linux ou MacOSX
					elif os.name in ['posix', 'mac']:
						self.fichierCourant[1]=unicode(QString(tampon)).encode("Latin1").decode("UTF8")
				except UnicodeEncodeError, e:
					debug(e)
					self.fichierCourant[1]="?"
				self.cibleVideo.setToolTip(self.fichierCourant[1])
				if self.barreTaches is not None:
					self.barreTaches.showMessage(self.fichierCourant[1])

			# réponse à get_video_resolution : ANS_VIDEO_RESOLUTION='<width> x <height>'
			if tampon.startsWith("ANS_VIDEO_RESOLUTION"): # retourne True si l'ensemble de bits démarre avec "..."
				debug("tampon : %s" % tampon) # ex. -> ANS_VIDEO_RESOLUTION='352 x 288'
				tampon.remove(0, 21) # suppression des 21 1er caract -> '352 x 288'
				tampon.replace(QByteArray("'"), QByteArray("")) # -> 352 x 288
				tampon.replace(QByteArray(" "), QByteArray("")) # -> 352x288
				tampon.replace(QByteArray("\n"), QByteArray("")) # -> 352x288 # retour chariot unix
				tampon.replace(QByteArray("\r"), QByteArray("")) # -> 352x288 # retour chariot windows
				#print "-----tampon.indexOf('x') :", tampon.indexOf('x'), type(tampon.indexOf('x'))
				sepIndex = tampon.indexOf('x') # récupère la position de 'x' # 3 <type 'int'>
				#print "-----tampon.left(sepIndex).toInt():", tampon.left(sepIndex).toInt(), type(tampon.left(sepIndex).toInt())
				resX = tampon.left(sepIndex).toInt()[0] # -> 352 # (352, True) <type 'tuple'>
				#print "-----tampon.mid(sepIndex+1).toInt() :", tampon.mid(sepIndex+1).toInt(), type(tampon.mid(sepIndex+1).toInt())
				resY = tampon.mid(sepIndex+1).toInt()[0] # -> 288 # (288, True) <type 'tuple'>

				# on définit les nouvelles dimensions de l'image du widget-mplayer.
				# try pour éviter les bogues sur les fichiers audio (sans dimension d'image)!!!
				#try:
				if resX!=0 or resY!=0:
					debug( "ratio : %s - %s" % (self.ratio, type(self.ratio)))
				else:
					debug("fichier audio")

			# réponse à get_time_length : ANS_LENGTH=xx.yy
			elif tampon.startsWith("ANS_LENGTH"):
				debug("tampon : %s" % tampon) # -> ANS_LENGTH=279.38
				tampon.remove(0, 11) # vire ANS_LENGTH=
				tampon.replace(QByteArray("'"), QByteArray(""))
				tampon.replace(QByteArray(" "), QByteArray(""))
				tampon.replace(QByteArray("\n"), QByteArray(""))
				tampon.replace(QByteArray("\r"), QByteArray("")) # -> 279.38
				#print "-----tampon.toFloat() :", tampon.toFloat(), type(tampon.toFloat())
				tempsMax = tampon.toFloat()[0] # (279.3800048828125, True) <type 'tuple'>
				self.dureeVideo = tempsMax
				## Modifié le 28/05/2009 : On augmente la précision du slider
				#self.slider.setMaximum(tempsMax) # déf du domaine de valeur du curseur
				self.slider.setMaximum(tempsMax*self.echelle)

				# ATTENTION J'AI COMMENTE CETTE LIGNE !!!
				#self.slider.setMaximum(tempsMax)

			# réponse à get_time_pos : ANS_TIME_POSITION=xx.y
			elif tampon.startsWith("ANS_TIME_POSITION"):
				#print "tampon :",tampon # -> ANS_TIME_POSITION=1.4 (temps courant)
				tampon.remove(0, 18) # vire ANS_TIME_POSITION=
				tampon.replace(QByteArray("'"), QByteArray(""))
				tampon.replace(QByteArray(" "), QByteArray(""))
				tampon.replace(QByteArray("\n"), QByteArray(""))
				tampon.replace(QByteArray("\r"), QByteArray(""))
				#print "-----tampon.toFloat() :", tampon.toFloat(), type(tampon.toFloat())
				tempsCourant = tampon.toFloat()[0] # (1.3999999761581421, True) <type 'tuple'>
				# récupération du temps courant: utile dans certains cadres
				self.temps = tempsCourant
				# Programmer un arrêt. Utile pour les aperçus
				temps = float("%.1f" %self.temps)
				if self.debutFin!=(0,0) and self.debutFin[1]==temps:
					self.arretMPlayer()
					return
				self.slider.setValue(tempsCourant*self.echelle)
				#############################################################################
				self.changerTempsChrono(tempsCourant) # modifier le chrono du bouton
コード例 #19
0
ファイル: main.py プロジェクト: juancarlospaco/vagrant
class Main(plugin.Plugin):
    " Main Class "
    def initialize(self, *args, **kwargs):
        " Init Main Class "
        super(Main, self).initialize(*args, **kwargs)
        self.completer, self.dirs = QCompleter(self), QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        self.desktop, self.project, menu = '', '', QMenu('Vagrant')
        menu.addAction('UP', lambda: self.vagrant_c('up'))
        menu.addAction('HALT', lambda: self.vagrant_c('halt'))
        menu.addAction('RELOAD', lambda: self.vagrant_c('reload'))
        menu.addAction('STATUS', lambda: self.vagrant_c('status'))
        menu.addAction('SUSPEND', lambda: self.vagrant_c('suspend'))
        menu.addAction('RESUME', lambda: self.vagrant_c('resume'))
        menu.addAction('PROVISION', lambda: self.vagrant_c('provision'))
        menu.addAction('PACKAGE', lambda: self.vagrant_c('package'))
        menu.addAction('INIT', lambda: self.vagrant_c('init'))
        menu.addSeparator()
        menu.addAction('DESTROY (!!!)', lambda: self.vagrant_c('destroy'))
        self.locator.get_service('explorer').add_project_menu(menu, lang='all')

        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self.process.readyReadStandardError.connect(self.readErrors)
        self.process.finished.connect(self._process_finished)
        self.process.error.connect(self._process_finished)

        # Proxy support, by reading http_proxy os env variable
        proxy_url = QUrl(environ.get('http_proxy', ''))
        QNetworkProxy.setApplicationProxy(QNetworkProxy(QNetworkProxy.HttpProxy
            if str(proxy_url.scheme()).startswith('http')
            else QNetworkProxy.Socks5Proxy, proxy_url.host(), proxy_url.port(),
                 proxy_url.userName(), proxy_url.password())) \
            if 'http_proxy' in environ else None

        self.mainwidget = QTabWidget()
        self.mainwidget.tabCloseRequested.connect(lambda:
            self.mainwidget.setTabPosition(1)
            if self.mainwidget.tabPosition() == 0
            else self.mainwidget.setTabPosition(0))
        self.mainwidget.setStyleSheet('QTabBar{font-weight:bold;}')
        self.mainwidget.setMovable(True)
        self.mainwidget.setTabsClosable(True)

        self.dock, self.scrollable = QDockWidget(), QScrollArea()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(self.mainwidget)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)

        self.locator.get_service('misc').add_widget(self.dock,
                                 QIcon.fromTheme("virtualbox"), __doc__)

        self.tab1, self.tab2, self.tab3 = QGroupBox(), QGroupBox(), QGroupBox()
        self.tab4, self.tab5, self.tab6 = QGroupBox(), QGroupBox(), QGroupBox()
        for a, b in ((self.tab1, 'Basics'), (self.tab2, 'General Options'),
            (self.tab3, 'VM Package Manager'), (self.tab4, 'VM Provisioning'),
            (self.tab5, 'VM Desktop GUI'), (self.tab6, 'Run')):
            a.setTitle(b)
            a.setToolTip(b)
            self.mainwidget.addTab(a, QIcon.fromTheme("virtualbox"), b)

        QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock
        ).clicked.connect(lambda: QMessageBox.information(self.dock, __doc__,
        HELPMSG))

        self.vmname = QLineEdit(self.get_name())
        self.vmname.setPlaceholderText('type_your_VM_name_here_without_spaces')
        self.vmname.setToolTip('Type VM name, no spaces or special characters')
        self.target = QLabel('<b>Vagrant Target Folder: ' +
                             path.join(BASE, self.vmname.text()))
        self.vmname.textChanged.connect(lambda: self.target.setText(
            '<b>Vagrant Target Folder: ' + path.join(BASE, self.vmname.text())))
        self.btn1 = QPushButton(QIcon.fromTheme("face-smile-big"), 'Suggestion')
        self.btn1.setToolTip('Suggest me a Random VM name !')
        self.btn1.clicked.connect(lambda: self.vmname.setText(self.get_name()))
        self.vmcode, self.vmarch = QComboBox(), QComboBox()
        self.vmcode.addItems(['saucy', 'raring', 'quantal', 'precise'])
        self.vmarch.addItems(['x86_64 (amd64) 64-Bits', 'x86 (i386) 32-Bits'])
        vboxg1 = QVBoxLayout(self.tab1)
        for each_widget in (QLabel('<b>Name for VM'), self.vmname, self.btn1,
            QLabel('<b>Choose Ubuntu Codename for the VM:</b>'), self.vmcode,
            QLabel('<b>Choose Architecture for VM:'), self.vmarch, self.target):
            vboxg1.addWidget(each_widget)

        self.chrt = QCheckBox('LOW CPU priority for Backend Process')
        self.chttps = QComboBox()
        self.chttps.addItems(['https', 'http'])
        try:
            self.vinfo1 = QLabel('''<b> Vagrant Backend Version: </b> {},
                <b> VirtualBox Backend Version: </b> {}. '''.format(
                getoutput('vagrant --version', shell=1).strip(),
                getoutput('vboxmanage --version', shell=1).strip()))
        except:
            self.vinfo1 = QLabel('<b>Warning: Failed to query Vagrant Backend!')
        self.qckb1 = QCheckBox(' Open target directory later')
        self.qckb1.setToolTip('Open the target directory when finished')
        self.qckb2 = QCheckBox(' Save a LOG file to target later')
        self.qckb2.setToolTip('Save a read-only .LOG file to target')
        self.qckb3 = QCheckBox(' NO run Headless Mode, use a Window')
        self.qckb3.setToolTip('Show the VM on a Window GUI instead of Headless')
        self.cpu, self.ram = QSpinBox(), QSpinBox()
        self.cpu.setRange(25, 99)
        self.cpu.setValue(99)
        self.ram.setRange(512, 4096)
        self.ram.setValue(1024)
        vboxg2 = QVBoxLayout(self.tab2)
        for each_widget in (self.qckb1, self.qckb2, self.qckb3, self.chrt,
            QLabel('<b>Max CPU Limit for VM:</b>'), self.cpu,
            QLabel('<b>Max RAM Limit for VM:</b>'), self.ram,
            QLabel('<b>Download Protocol Type:</b>'), self.chttps, self.vinfo1):
            vboxg2.addWidget(each_widget)

        self.qckb10 = QCheckBox('Run apt-get update on the created VM')
        self.qckb11 = QCheckBox('Run apt-get dist-upgrade on the created VM')
        self.qckb12 = QCheckBox('Run apt-get check on the created VM')
        self.qckb12 = QCheckBox('Run apt-get clean on the created VM')
        self.qckb13 = QCheckBox('Run apt-get autoremove on the created VM')
        self.qckb14 = QCheckBox('Try to Fix Broken packages if any on the VM')
        self.aptproxy, self.portredirect = QLineEdit(), QLineEdit('8000, 9000')
        self.aptproxy.setPlaceholderText(' user:password@proxyaddress:port ')
        vboxg3 = QVBoxLayout(self.tab3)
        for each_widget in (self.qckb10, self.qckb11, self.qckb12, self.qckb13,
            self.qckb14,
            QLabel('<b>Network Proxy for apt-get on the VM'), self.aptproxy,
            QLabel('<b>Network Port Redirects for the VM'), self.portredirect):
            vboxg3.addWidget(each_widget)

        self.aptpkg = QTextEdit('build-essential git python-pip vim mc wget')
        self.aptppa, self.pippkg = QLineEdit(), QTextEdit('virtualenv yolk')
        self.aptppa.setPlaceholderText(' ppa:ninja-ide-developers/daily ')
        self.requirements = QLineEdit()
        self.requirements.setPlaceholderText(' /full/path/to/requirements.txt ')
        self.requirements.setCompleter(self.completer)
        vboxg4 = QVBoxLayout(self.tab4)
        for each_widget in (QLabel('<b>Custom APT Ubuntu package'), self.aptpkg,
            QLabel('<b>Custom APT Ubuntu PPA:</b>      '), self.aptppa,
            QLabel('<b>Custom PIP Python packages:</b> '), self.pippkg,
            QLabel('<b>Custom PIP Python requirements: '), self.requirements):
            vboxg4.addWidget(each_widget)

        self.buttonGroup = QButtonGroup()
        self.buttonGroup.buttonClicked[QAbstractButton].connect(self.get_de_pkg)
        vboxg5 = QVBoxLayout(self.tab5)
        for i, d in enumerate(('Ubuntu Unity', 'KDE Plasma', 'LXDE', 'XFCE')):
            button = QPushButton(d)
            button.setCheckable(True)
            button.setMinimumSize(75, 50)
            button.setToolTip(d)
            vboxg5.addWidget(button)
            self.buttonGroup.addButton(button)

        self.output = QTextEdit('''
        We have persistent objects, they are called files.  -Ken Thompson. ''')
        self.runbtn = QPushButton(QIcon.fromTheme("media-playback-start"),
            'Start Vagrant Instrumentation Now !')
        self.runbtn.setMinimumSize(75, 50)
        self.runbtn.clicked.connect(self.build)
        glow = QGraphicsDropShadowEffect(self)
        glow.setOffset(0)
        glow.setBlurRadius(99)
        glow.setColor(QColor(99, 255, 255))
        self.runbtn.setGraphicsEffect(glow)
        self.stopbt = QPushButton(QIcon.fromTheme("media-playback-stop"),
            'Stop Vagrant')
        self.stopbt.clicked.connect(lambda: self.process.stop())
        self.killbt = QPushButton(QIcon.fromTheme("application-exit"),
            'Force Kill Vagrant')
        self.killbt.clicked.connect(lambda: self.process.kill())
        vboxg6 = QVBoxLayout(self.tab6)
        for each_widget in (QLabel('<b>Multiprocess Output Logs'), self.output,
            self.runbtn, self.stopbt, self.killbt):
            vboxg6.addWidget(each_widget)

        [a.setChecked(True) for a in (self.qckb1, self.qckb2, self.qckb3,
            self.qckb10, self.qckb11, self.qckb12, self.qckb13, self.qckb14,
            self.chrt)]
        self.mainwidget.setCurrentIndex(5)

    def get_de_pkg(self, button):
        ' get package from desktop name '
        if button.text() in 'Ubuntu Unity':
            self.desktop = 'ubuntu-desktop'
        elif button.text() in 'KDE Plasma':
            self.desktop = 'kubuntu-desktop'
        elif button.text() in 'LXDE':
            self.desktop = 'lubuntu-desktop'
        else:
            self.desktop = 'xubuntu-desktop'
        return self.desktop

    def get_name(self):
        ' return a random name of stars, planets and moons of solar system '
        return choice((getuser(), 'sun', 'mercury', 'venus', 'earth', 'mars',
            'neptun', 'ceres', 'pluto', 'haumea', 'makemake', 'eris', 'moon',
            'saturn', 'europa', 'ganymede', 'callisto', 'mimas', 'enceladus',
            'tethys', 'dione', 'rhea', 'titan', 'iapetus', 'miranda', 'ariel',
            'umbriel', 'titania', 'oberon', 'triton', 'charon', 'orcus', 'io',
            'ixion', 'varuna', 'quaoar', 'sedna', 'methone', 'jupiter', ))

    def readOutput(self):
        """Read and append output to the logBrowser"""
        self.output.append(str(self.process.readAllStandardOutput()))

    def readErrors(self):
        """Read and append errors to the logBrowser"""
        self.output.append(self.formatErrorMsg(str(
                                        self.process.readAllStandardError())))

    def formatErrorMsg(self, msg):
        """Format error messages in red color"""
        return self.formatMsg(msg, 'red')

    def formatInfoMsg(self, msg):
        """Format informative messages in blue color"""
        return self.formatMsg(msg, 'green')

    def formatMsg(self, msg, color):
        """Format message with the given color"""
        return '<font color="{}">{}</font>'.format(color, msg)

    def build(self):
        """Main function calling vagrant to generate the vm"""
        self.output.setText('')
        self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now())))
        self.runbtn.setDisabled(True)
        base = path.join(BASE, self.vmname.text())
        try:
            self.output.append(self.formatInfoMsg('INFO: Dir: {}'.format(base)))
            makedirs(base)
        except:
            self.output.append(self.formatErrorMsg('ERROR:Target Folder Exist'))
        self.output.append(self.formatInfoMsg('INFO: Changed {}'.format(base)))
        chdir(base)
        try:
            self.output.append(self.formatInfoMsg('INFO:Removing Vagrant file'))
            remove(path.join(base, 'Vagrantfile'))
        except:
            self.output.append(self.formatErrorMsg('ERROR:Remove Vagrant file'))
        self.output.append(self.formatInfoMsg(' INFO: OK: Runing Vagrant Init'))
        cmd1 = getoutput('chrt --verbose -i 0 vagrant init', shell=True)
        self.output.append(self.formatInfoMsg('INFO:OK:Completed Vagrant Init'))
        self.output.append(self.formatInfoMsg('INFO: Command: {}'.format(cmd1)))
        cfg = CONFIG.format(self.vmname.text(), self.vmname.text(),
            self.chttps.currentText(), self.vmcode.currentText(),
            self.vmcode.currentText(),
            'amd64' if self.vmarch.currentIndex() is 0 else 'i386',
            '\n'.join(([
            '    config.vm.network :forwarded_port, host: {}, guest: {}'.format(
                a, a) for a in str(self.portredirect.text()).split(',')])),
            VBOXGUI.format(self.ram.value(), self.cpu.value())
                if self.qckb3.isChecked() is True else '')
        self.output.append(self.formatInfoMsg('INFO:OK:Config: {}'.format(cfg)))
        with open(path.join(base, 'Vagrantfile'), 'w') as f:
            f.write(cfg)
            self.output.append(self.formatInfoMsg('INFO: Writing Vagrantfile'))
            f.close()
        proxy = APTGET_PROXY.format(self.aptproxy.text(), self.aptproxy.text(),
            self.aptproxy.text(), self.aptproxy.text(), self.aptproxy.text(),
            self.aptproxy.text())
        prv = '\n'.join(('#!/usr/bin/env bash', '# -*- coding: utf-8 -*-',
        linesep * 2, "PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] ' ; HISTSIZE=5000",
        '# Vagrant Bootstrap Provisioning generated by Vagrant Ninja!', linesep,
        proxy if len(self.aptproxy.text()) >= 5 else '',
        'add-apt-repository -s -y {}'.format(str(self.aptppa.text()).strip()),
        'apt-get -V -u -m -y update' if self.qckb10.isChecked() is True else '',
        'apt-get -y -m dist-upgrade' if self.qckb11.isChecked() is True else '',
        'apt-get -y -m autoremove' if self.qckb11.isChecked() is True else '',
        'apt-get -y clean' if self.qckb11.isChecked() is True else '',
        'dpkg --configure -a' if self.qckb11.isChecked() is True else '',
        'apt-get -y -f install' if self.qckb11.isChecked() is True else '',
        'apt-get -y check' if self.qckb11.isChecked() is True else '',
        'apt-get -y --force-yes install {}'.format(self.aptpkg.toPlainText()),
        'pip install --verbose {}'.format(self.pippkg.toPlainText()),
        'pip install --verbose -r {}'.format(self.requirements.text()),
        'apt-get -y --force-yes -m install {}'.format(self.desktop), linesep,
        'git config --global user.name "{}"'.format(getuser()),
        'git config --global color.branch auto',
        'git config --global color.diff auto',
        'git config --global color.interactive auto',
        'git config --global color.status auto',
        'git config --global credential.helper cache',
        'git config --global user.email "{}@gmail.com"'.format(getuser()),
        'git config --global push.default simple',
        'ufw status ; service ufw stop ; ufw disable ; swapoff --verbose --all',
        'export LANGUAGE=en_US.UTF-8', 'export LANG=en_US.UTF-8',
        'export LC_ALL=en_US.UTF-8', 'locale-gen en_US.UTF-8',
        'dpkg-reconfigure locales', ))
        self.output.append(self.formatInfoMsg('INFO:OK:Script: {}'.format(prv)))
        with open(path.join(base, 'bootstrap.sh'), 'w') as f:
            f.write(prv)
            self.output.append(self.formatInfoMsg('INFO: Writing bootstrap.sh'))
            f.close()
        try:
            chmod('bootstrap.sh', 0775)  # Py2
            self.output.append(self.formatInfoMsg('INFO: bootstrap.sh is 775'))
        except:
            chmod('bootstrap.sh', 0o775)  # Py3
            self.output.append(self.formatInfoMsg('INFO: bootstrap.sh is o775'))
        self.output.append(self.formatInfoMsg(''' INFO: OK:
        Vagrant Up needs time, depends on your Internet Connection Speed !'''))
        self.output.append(self.formatInfoMsg('INFO: OK: Running Vagrant Up !'))
        self.process.start('{}vagrant up'.format('chrt --verbose -i 0 '
            if self.chrt.isChecked() is True else ''))
        if not self.process.waitForStarted():
            self.output.append(self.formatErrorMsg('ERROR: FAIL: Vagrant Fail'))
            self.runbtn.setEnabled(True)
            return
        self.runbtn.setEnabled(True)
        chdir(path.expanduser("~"))

    def _process_finished(self):
        """finished sucessfully"""
        self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now())))
        if self.qckb2.isChecked() is True:
            LOG_FILE = path.join(BASE, self.vmname.text(), 'vagrant_ninja.log')
            with open(LOG_FILE, 'w') as f:
                self.output.append(self.formatInfoMsg('INFO: OK: Writing .LOG'))
                f.write(self.output.toPlainText())
                f.close()
        if self.qckb1.isChecked() is True:
            self.output.append(self.formatInfoMsg('INFO:Opening Target Folder'))
            try:
                startfile(BASE)
            except:
                Popen(["xdg-open", BASE])
        chdir(path.expanduser("~"))

    def vagrant_c(self, option):
        ' run the choosed menu option, kind of quick-mode '
        self.output.setText('')
        self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now())))
        self.runbtn.setDisabled(True)
        chdir(path.abspath(
          self.locator.get_service('explorer').get_current_project_item().path))
        self.process.start('chrt --verbose -i 0 vagrant {}'.format(option))
        if not self.process.waitForStarted():
            self.output.append(self.formatErrorMsg('ERROR: FAIL: Vagrant Fail'))
            self.runbtn.setEnabled(True)
            return
        self.runbtn.setEnabled(True)
        self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now())))
        chdir(path.expanduser("~"))

    def finish(self):
        ' clear when finish '
        self.process.kill()
コード例 #20
0
ファイル: gui.py プロジェクト: juancarlospaco/fileXplorer
class filexplorerPluginMain(plugin.Plugin):
    ' main class for plugin '
    def initialize(self, *args, **kwargs):
        ' class init '
        global CONFIG_DIR
        ec = ExplorerContainer()
        super(filexplorerPluginMain, self).initialize(*args, **kwargs)

        self.dock = QDockWidget()
        self.dock.setAllowedAreas(Qt.LeftDockWidgetArea |
                                  Qt.RightDockWidgetArea)
        self.dock.setFeatures(QDockWidget.DockWidgetFloatable |
                              QDockWidget.DockWidgetMovable)
        self.dock.setWindowTitle("fileXplorer")
        self.dock.setStyleSheet('QDockWidget::title { text-align: center; }')

        # search for the truth
        self.srch = QLineEdit()
        #self.srch.resize(self.srch.size().height(), self.dock.size().width())
        self.srch.setPlaceholderText(' Search for Python files Local or PyPI ')
        self.srch.returnPressed.connect(self.search)

        # Disk Usage Bar
        self.hdbar = QProgressBar()
        if sys.platform != 'win32':
            self.hdbar.setMaximum(statvfs(HOME).f_blocks *
                statvfs(HOME).f_frsize / 1024 / 1024 / 1024)
            self.hdbar.setValue(statvfs(HOME).f_bfree *
                statvfs(HOME).f_frsize / 1024 / 1024 / 1024)
        self.hdbar.setToolTip(str(self.hdbar.value()) + '% Total Disk Use ')
        #self.hdbar.setStyleSheet('''QProgressBar{background-color:
        #QLinearGradient(spread:pad,x1:0,y1:0,x2:1,y2:1,stop:0 rgba(255,0,0,99),
        #stop:1 rgba(9,255,9,200));color:#fff;border:none;border-radius:9px;}
        #QProgressBar::chunk{background-color:QLinearGradient(spread:pad,y1:0,
        #x1:0,y2:1,x2:0.27,stop:0 rgb(0,0,0),stop:1 rgb(9,99,255));padding:0;
        #border:none;border-radius:9px;height:9px;margin:1px;}''')

        self.model = QDirModel()
        self.fileView = QColumnView(self.dock)
        self.fileView.setAlternatingRowColors(True)
        # self.fileView.setFont(QFont(self.fileView.font().setBold(True)))
        self.fileView.setIconSize(QSize(32, 32))
        self.fileView.setModel(self.model)
        self.fileView.updatePreviewWidget.connect(self.runfile)

        self.sli = QSlider()
        self.sli.setRange(16, 128)
        self.sli.setValue(32)
        self.sli.setToolTip('Icon Size: 32 px. Move Slider to change.')
        self.sli.setOrientation(Qt.Horizontal)
        self.sli.valueChanged.connect(lambda: self.fileView.setIconSize(
            QSize(self.sli.value(), self.sli.value())))
        self.sli.sliderReleased.connect(lambda:
            self.sli.setToolTip('Icon Size: ' + str(self.sli.value())))

        class TransientWidget(QWidget):
            ' persistant widget thingy '
            def __init__(self, widget_list):
                ' init sub class '
                super(TransientWidget, self).__init__()
                vbox = QVBoxLayout(self)
                for each_widget in widget_list:
                    vbox.addWidget(each_widget)

        tw = TransientWidget((self.srch, self.dock, self.sli, self.hdbar))
        ec.addTab(tw, "fileXplorer")

        ####

        self.process = QProcess()
        self.process.finished.connect(self.processFinished)

        self.preview = QLabel(self.fileView)
        self.preview.setTextFormat(0)
        self.preview.setStyleSheet('QLabel{font-size:9px;}')
        self.preview.setAutoFillBackground(True)
        self.fileView.setPreviewWidget(self.preview)
        self.dock.setWidget(self.fileView)

        # take a shot
        self.pic = QAction(QIcon.fromTheme("camera-photo"), 'Screenshot', self)
        self.pic.triggered.connect(lambda: QPixmap.grabWindow(
            QApplication.desktop().winId()).save(QFileDialog.getSaveFileName(
            self.dock, " Save Screenshot As ... ", HOME, ';;(*.png)')))

        # copy time
        self.tim = QAction(QIcon.fromTheme("user-away"),
                           'Date and Time to Clipboard', self)
        self.tim.triggered.connect(lambda: QApplication.clipboard().setText(
            datetime.now().strftime(" %A %B %d-%m-%Y %H:%M:%S %p ")))

        # color chooser
        self.cl = QAction(QIcon.fromTheme("applications-graphics"),
                          'Color Chooser to Clipboard', self)
        self.cl.triggered.connect(lambda: QApplication.clipboard().setText(
            '{}'.format(QColorDialog.getColor().name())))

        # icon chooser
        self.icn = QAction(QIcon.fromTheme("insert-image"),
                          'Icon Chooser to Clipboard', self)
        self.icn.triggered.connect(self.iconChooser)

        # tool bar with actions
        QToolBar(self.dock).addActions((self.cl, self.icn, self.tim, self.pic))

        self.textBrowser = QTextBrowser(self.dock)
        self.textBrowser.setAutoFillBackground(True)
        self.textBrowser.setGeometry(self.dock.geometry())
        self.textBrowser.hide()

    def processFinished(self):
        ' print info of finished processes '
        print(" INFO: OK: QProcess finished . . . ")

    def search(self):
        ' function to search python files '
        # get search results of python filenames local or remote
        pypi_url = 'http://pypi.python.org/pypi'
        # pypi query
        pypi = xmlrpclib.ServerProxy(pypi_url, transport=ProxyTransport())
        try:
            pypi_query = pypi.search({'name': str(self.srch.text()).lower()})
            pypi_fls = list(set(['pypi.python.org/pypi/' + a['name'] +
                   ' | pip install ' + a['name'] for a in pypi_query]))
        except:
            pypi_fls = '<b> ERROR: Internet not available! ಠ_ಠ </b>'
        s_out = ('<br> <br> <br> <h3> Search Local Python files: </h3> <hr> ' +
        # Jedi list comprehension for LOCAL search
        str(["{}/{}".format(root, f) for root, f in list(itertools.chain(*
            [list(itertools.product([root], files))
            for root, dirs, files in walk(str(
            QFileDialog.getExistingDirectory(self.dock,
            'Open Directory to Search', path.expanduser("~"))))]))
            if f.endswith(('.py', '.pyw', '.pth')) and not f.startswith('.')
            and str(self.srch.text()).lower().strip() in f]
        ).replace(',', '<br>') + '<hr><h3> Search PyPI Python files: </h3>' +
        # wraped pypi query REMOTE search
        str(pypi_fls).replace(',', '<br>') + '<hr>Auto-Proxy:ON,DoNotTrack:ON')
        # print(s_out)
        try:
            call('notify-send fileXplorer Searching...', shell=True)
        except:
            pass
        self.srch.clear()
        self.textBrowser.setGeometry(self.dock.geometry())
        self.textBrowser.setHtml(s_out)
        self.textBrowser.show()
        tmr = QTimer(self.fileView)
        tmr.timeout.connect(self.textBrowser.hide)
        tmr.start(20000)

    def iconChooser(self):
        ' Choose a Icon and copy it to clipboard '
        #
        from .std_icon_naming import std_icon_naming as a
        #
        prv = QDialog(self.dock)
        prv.setWindowFlags(Qt.FramelessWindowHint)
        prv.setAutoFillBackground(True)
        prv.setGeometry(self.fileView.geometry())
        table = QTableWidget(prv)
        table.setColumnCount(1)
        table.setRowCount(len(a))
        table.verticalHeader().setVisible(True)
        table.horizontalHeader().setVisible(False)
        table.setShowGrid(True)
        table.setIconSize(QSize(128, 128))
        for index, icon in enumerate(a):
            item = QTableWidgetItem(QIcon.fromTheme(icon), '')
            # item.setData(Qt.UserRole, '')
            item.setToolTip(icon)
            table.setItem(index, 0, item)
        table.clicked.connect(lambda: QApplication.clipboard().setText(
          'QtGui.QIcon.fromTheme("{}")'.format(table.currentItem().toolTip())))
        table.doubleClicked.connect(prv.close)
        table.resizeColumnsToContents()
        table.resizeRowsToContents()
        QLabel('<h3> <br> 1 Click Copy, 2 Clicks Close </h3>', table)
        table.resize(prv.size())
        prv.exec_()

    def runfile(self, index):
        ' run the choosed file '
        s = str(file(self.model.filePath(index), 'r').read().strip())
        f = str(self.model.filePath(index))
        # ctime is NOT crossplatform,metadata change on *nix,creation on Window
        # http://docs.python.org/library/os.path.html#os.path.getctime
        m = ''.join((f, N, str(path.getsize(f) / 1024), ' Kilobytes', N,
            str(len(file(f, 'r').readlines())), ' Lines', N,
            str(len(s.replace(N, ''))), ' Characters', N,
            str(len([a for a in sub('[^a-zA-Z0-9 ]', '', s).split(' ')
                if a != ''])), ' Words', N,
            str(len([a for a in s if a in punctuation])), ' Punctuation', N,
            oct(stat(f).st_mode)[-3:], ' Permissions', N,
            time.ctime(path.getatime(f)), ' Accessed', N,
            time.ctime(path.getmtime(f)), ' Modified', N,
            'Owner: ', str(self.model.fileInfo(index).owner()), N,
            'Is Writable: ', str(self.model.fileInfo(index).isWritable()), N,
            'Is Executable: ', str(self.model.fileInfo(index).isExecutable()),
            N, 'Is Hidden: ', str(self.model.fileInfo(index).isHidden()), N,
            'Is SymLink: ', str(self.model.fileInfo(index).isSymLink()), N,
            'File Extension: ', str(self.model.fileInfo(index).suffix())
        ))
        #print(m)
        self.preview.setToolTip(m)
        self.preview.setText(s)
        self.preview.resize(self.preview.size().width(),
                            self.dock.size().height())
        self.process.start('xdg-open {}'.format(f))
        if not self.process.waitForStarted():
            print((" ERROR: Process {} Failed ! ".format(str(f))))
            return
コード例 #21
0
ファイル: pylint.py プロジェクト: khertan/KhtEditor
class PyLint(Plugin, QObject):
    """ PyLint Plugin """
    capabilities = ['toolbarHook']
    __version__ = '0.5'
    thread = None
    
    def do_toolbarHook(self, widget):
        """ Hook to install the pylint toolbar button"""
        widget.addAction('PyLint', self.do_pylint)
        
        
    @pyqtSlot()
    def do_pylint(self):
        """ Launch the lint process and create the result window """
        print 'do_pylint'

        self.pylint_pross = QProcess()
        self.pylint_pross.setProcessChannelMode(QProcess.MergedChannels)
        self.pylint_pross.setWorkingDirectory( \
            os.path.dirname(str(self.parent.editor.filename)))
        self.pylint_pross.setReadChannel(QProcess.StandardOutput)

        self.connect(self.pylint_pross, \
            SIGNAL('finished(int)'), \
            self.finished)
        self.connect(self.pylint_pross, \
            SIGNAL('readyReadStandardOutput()'), \
            self.handle_stdout)
        self.connect(self.pylint_pross, \
            SIGNAL('readyReadStandardError()'), \
            self.handle_stderr)
        if (self.pylint_pross.start("pylint", \
                [self.parent.editor.filename,])):
            print 'Cannot start process'

        self.win = ResultWin()
        self.win.setWindowTitle("PyLint Results :" \
            + os.path.basename(str(self.parent.editor.filename)))
        self.win.show()
        if isMAEMO:
            self.win.setAttribute(Qt.WA_Maemo5ShowProgressIndicator, True)
            
        self.win.connect(self.win.list_view, \
            SIGNAL('doubleClicked(const QModelIndex&)'), \
            self.goto_line)

        self.pylint_pross.waitForStarted()
        
    def finished(self, _):
        """ Call back called when lint end """
        if isMAEMO:
            self.win.setAttribute(Qt.WA_Maemo5ShowProgressIndicator, False)
            
    def handle_stdout(self):
        """
        Private slot to handle the readyReadStdout
        signal of the pylint process.
        """
        result_list = []
        #regex = QRegExp('(\w)\S*:\S*(\d*):.*: (.*)')
        regex = QRegExp('(\w)\s*:\s*(\d*):(.*)')
        regex_score = \
            QRegExp('.*at.(\d.\d*)/10.*')
        while self.pylint_pross and self.pylint_pross.canReadLine():
            result = unicode(self.pylint_pross.readLine())
            if result != None:
                pos = 0
                while True:
                    pos = regex.indexIn(result, pos)
                    if pos < 0:
                        if regex_score.indexIn(result, 0) >= 0:
                            self.win.setWindowTitle( \
                                "PyLint Results :" \
                                + str(regex_score.cap(1)) \
                                + ':'                                
                                + os.path.basename(str(self.parent.editor.filename)))
                        break
                    result_list.append((regex.cap(1), regex.cap(2), regex.cap(3)))
                    #print 'Append : ',(regex.cap(1), regex.cap(2), regex.cap(3))
                    pos = pos + regex.matchedLength()
                    
        if len(result_list)>0:
            self.win.append_results(result_list)
        
    def goto_line(self, index):
        """ Callback called when a lint result is double clicked """
        line = int(self.win.list_model.items[index.row()][1])
        self.parent.do_gotoLine(line)
        
    def handle_stderr(self):
        """
        Private slot to handle the readyReadStderr
        signal of the pylint process. Currently not
        managed
        """
        print 'error stderr'
コード例 #22
0
class ExternalSystemShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = TerminalWidget
    def __init__(self, parent=None, wdir=None):
        ExternalShellBase.__init__(self, parent, wdir,
                                   history_filename='.history_ec')

    def get_icon(self):
        return get_icon('cmdprompt.png')
    
    def create_process(self):
        self.shell.clear()
            
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        
        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)
            
        # Shell arguments
        if os.name == 'nt':
            p_args = ['/Q']
        else:
            p_args = ['-i']
            
        if self.arguments:
            p_args.extend( self.arguments.split(' ') )
                        
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)
        
        self.connect(self.kill_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        if os.name == 'nt':
            self.process.start('cmd.exe', p_args)
        else:
            # Using bash:
            self.process.start('bash', p_args)
            self.send_to_process("""PS1="\u@\h:\w> "\n""")
            
        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, self.tr("Error"),
                                 self.tr("Process failed to start"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))
            
        return self.process
    
#===============================================================================
#    Input/Output
#===============================================================================
    def transcode(self, bytes):
        if os.name == 'nt':
            return encoding.transcode(str(bytes.data()), 'cp850')
        else:
            return ExternalShellBase.transcode(self, bytes)
    
    def send_to_process(self, qstr):
        if not isinstance(qstr, QString):
            qstr = QString(qstr)
        if qstr[:-1] in ["clear", "cls", "CLS"]:
            self.shell.clear()
            self.send_to_process(QString(os.linesep))
            return
        if not qstr.endsWith('\n'):
            qstr.append('\n')
        if os.name == 'nt':
            self.process.write(unicode(qstr).encode('cp850'))
        else:
            self.process.write(qstr.toLocal8Bit())
        self.process.waitForBytesWritten(-1)
        
    def keyboard_interrupt(self):
        # This does not work on Windows:
        # (unfortunately there is no easy way to send a Ctrl+C to cmd.exe)
        self.send_ctrl_to_process('c')

#        # The following code will soon be removed:
#        # (last attempt to send a Ctrl+C on Windows)
#        if os.name == 'nt':
#            pid = int(self.process.pid())
#            import ctypes, win32api, win32con
#            class _PROCESS_INFORMATION(ctypes.Structure):
#                _fields_ = [("hProcess", ctypes.c_int),
#                            ("hThread", ctypes.c_int),
#                            ("dwProcessID", ctypes.c_int),
#                            ("dwThreadID", ctypes.c_int)]
#            x = ctypes.cast( ctypes.c_void_p(pid),
#                             ctypes.POINTER(_PROCESS_INFORMATION) )
#            win32api.GenerateConsoleCtrlEvent(win32con.CTRL_C_EVENT,
#                                              x.dwProcessID)
#        else:
#            self.send_ctrl_to_process('c')
                
コード例 #23
0
class SvnChangeListsDialog(QDialog, Ui_SvnChangeListsDialog):
    """
    Class implementing a dialog to browse the change lists.
    """
    def __init__(self, vcs, parent=None):
        """
        Constructor
        
        @param vcs reference to the vcs object
        @param parent parent widget (QWidget)
        """
        QDialog.__init__(self, parent)
        self.setupUi(self)
        
        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
        self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
        
        self.process = None
        self.vcs = vcs
        
        self.rx_status = \
            QRegExp('(.{8,9})\\s+([0-9-]+)\\s+([0-9?]+)\\s+(\\S+)\\s+(.+)\\s*')
            # flags (8 or 9 anything), revision, changed rev, author, path
        self.rx_status2 = \
            QRegExp('(.{8,9})\\s+(.+)\\s*')
            # flags (8 or 9 anything), path
        self.rx_changelist = \
            QRegExp('--- \\S+ .([\\w\\s]+).:\\s+')
            # three dashes, Changelist (translated), quote,
            # changelist name, quote, :
    
    @pyqtSignature("QListWidgetItem*, QListWidgetItem*")
    def on_changeLists_currentItemChanged(self, current, previous):
        """
        Private slot to handle the selection of a new item.
        
        @param current current item (QListWidgetItem)
        @param previous previous current item (QListWidgetItem)
        """
        self.filesList.clear()
        if current is not None:
            changelist = unicode(current.text())
            if changelist in self.changeListsDict:
                self.filesList.addItems(sorted(self.changeListsDict[changelist]))
    
    def start(self, path):
        """
        Public slot to populate the data.
        
        @param path directory name to show change lists for (string)
        """
        self.changeListsDict = {}
        
        self.filesLabel.setText(self.trUtf8("Files (relative to %1):").arg(path))
        
        self.errorGroup.hide()
        self.intercept = False
        
        self.path = path
        self.currentChangelist = ""
        
        self.process = QProcess()
        self.process.finished.connect(self.__procFinished)
        self.process.readyReadStandardOutput.connect(self.__readStdout)
        self.process.readyReadStandardError.connect(self.__readStderr)
        
        args = []
        args.append('status')
        self.vcs.addArguments(args, self.vcs.options['global'])
        self.vcs.addArguments(args, self.vcs.options['status'])
        if '--verbose' not in self.vcs.options['global'] and \
           '--verbose' not in self.vcs.options['status']:
            args.append('--verbose')
        if isinstance(path, list):
            self.dname, fnames = self.vcs.splitPathList(path)
            self.vcs.addArguments(args, fnames)
        else:
            self.dname, fname = self.vcs.splitPath(path)
            args.append(fname)
        
        self.process.setWorkingDirectory(self.dname)
        
        self.process.start('svn', args)
        procStarted = self.process.waitForStarted()
        if not procStarted:
            self.inputGroup.setEnabled(False)
            self.inputGroup.hide()
            KQMessageBox.critical(self,
                self.trUtf8('Process Generation Error'),
                self.trUtf8(
                    'The process %1 could not be started. '
                    'Ensure, that it is in the search path.'
                ).arg('svn'))
        else:
            self.inputGroup.setEnabled(True)
            self.inputGroup.show()
    
    def __finish(self):
        """
        Private slot called when the process finished or the user pressed
        the button.
        """
        if self.process is not None and \
           self.process.state() != QProcess.NotRunning:
            self.process.terminate()
            QTimer.singleShot(2000, self.process.kill)
            self.process.waitForFinished(3000)
        
        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
        self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
        self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
        
        self.inputGroup.setEnabled(False)
        self.inputGroup.hide()
        
        if len(self.changeListsDict) == 0:
            self.changeLists.addItem(self.trUtf8("No changelists found"))
            self.buttonBox.button(QDialogButtonBox.Close).setFocus(Qt.OtherFocusReason)
        else:
            self.changeLists.addItems(sorted(self.changeListsDict.keys()))
            self.changeLists.setCurrentRow(0)
            self.changeLists.setFocus(Qt.OtherFocusReason)
    
    def on_buttonBox_clicked(self, button):
        """
        Private slot called by a button of the button box clicked.
        
        @param button button that was clicked (QAbstractButton)
        """
        if button == self.buttonBox.button(QDialogButtonBox.Close):
            self.close()
        elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
            self.__finish()
        
    def __procFinished(self, exitCode, exitStatus):
        """
        Private slot connected to the finished signal.
        
        @param exitCode exit code of the process (integer)
        @param exitStatus exit status of the process (QProcess.ExitStatus)
        """
        self.__finish()
        
    def __readStdout(self):
        """
        Private slot to handle the readyReadStandardOutput signal.
        
        It reads the output of the process, formats it and inserts it into
        the contents pane.
        """
        if self.process is not None:
            self.process.setReadChannel(QProcess.StandardOutput)
            
            while self.process.canReadLine():
                s = unicode(self.process.readLine(),
                            Preferences.getSystem("IOEncoding"),
                            'replace')
                if self.currentChangelist != "" and self.rx_status.exactMatch(s):
                    file = unicode(self.rx_status.cap(5)).strip()
                    filename = file.replace(self.path + os.sep, "")
                    if filename not in self.changeListsDict[self.currentChangelist]:
                        self.changeListsDict[self.currentChangelist].append(filename)
                elif self.currentChangelist != "" and self.rx_status2.exactMatch(s):
                    file = unicode(self.rx_status2.cap(2)).strip()
                    filename = file.replace(self.path + os.sep, "")
                    if filename not in self.changeListsDict[self.currentChangelist]:
                        self.changeListsDict[self.currentChangelist].append(filename)
                elif self.rx_changelist.exactMatch(s):
                    self.currentChangelist = unicode(self.rx_changelist.cap(1))
                    if self.currentChangelist not in self.changeListsDict:
                        self.changeListsDict[self.currentChangelist] = []
        
    def __readStderr(self):
        """
        Private slot to handle the readyReadStandardError signal.
        
        It reads the error output of the process and inserts it into the
        error pane.
        """
        if self.process is not None:
            self.errorGroup.show()
            s = QString(self.process.readAllStandardError())
            self.errors.insertPlainText(s)
            self.errors.ensureCursorVisible()
        
    def on_passwordCheckBox_toggled(self, isOn):
        """
        Private slot to handle the password checkbox toggled.
        
        @param isOn flag indicating the status of the check box (boolean)
        """
        if isOn:
            self.input.setEchoMode(QLineEdit.Password)
        else:
            self.input.setEchoMode(QLineEdit.Normal)
        
    @pyqtSignature("")
    def on_sendButton_clicked(self):
        """
        Private slot to send the input to the subversion process.
        """
        input = self.input.text()
        input += os.linesep
        
        if self.passwordCheckBox.isChecked():
            self.errors.insertPlainText(os.linesep)
            self.errors.ensureCursorVisible()
        else:
            self.errors.insertPlainText(input)
            self.errors.ensureCursorVisible()
        
        self.process.write(input)
        
        self.passwordCheckBox.setChecked(False)
        self.input.clear()
        
    def on_input_returnPressed(self):
        """
        Private slot to handle the press of the return key in the input field.
        """
        self.intercept = True
        self.on_sendButton_clicked()
        
    def keyPressEvent(self, evt):
        """
        Protected slot to handle a key press event.
        
        @param evt the key press event (QKeyEvent)
        """
        if self.intercept:
            self.intercept = False
            evt.accept()
            return
        QDialog.keyPressEvent(self, evt)
コード例 #24
0
class ExternalSystemShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = TerminalWidget

    def __init__(self,
                 parent=None,
                 wdir=None,
                 path=[],
                 light_background=True,
                 menu_actions=None,
                 show_buttons_inside=True,
                 show_elapsed_time=True):
        ExternalShellBase.__init__(self,
                                   parent=parent,
                                   fname=None,
                                   wdir=wdir,
                                   history_filename='.history',
                                   light_background=light_background,
                                   menu_actions=menu_actions,
                                   show_buttons_inside=show_buttons_inside,
                                   show_elapsed_time=show_elapsed_time)

        # Additional python path list
        self.path = path

        # For compatibility with the other shells that can live in the external
        # console
        self.is_ipykernel = False
        self.connection_file = None

    def get_icon(self):
        return get_icon('cmdprompt.png')

    def create_process(self):
        self.shell.clear()

        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)

        # PYTHONPATH (in case we use Python in this terminal, e.g. py2exe)
        env = [unicode(_path) for _path in self.process.systemEnvironment()]
        add_pathlist_to_PYTHONPATH(env, self.path)
        self.process.setEnvironment(env)

        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)

        # Shell arguments
        if os.name == 'nt':
            p_args = ['/Q']
        else:
            p_args = ['-i']

        if self.arguments:
            p_args.extend(shell_split(self.arguments))

        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process,
                     SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)

        self.connect(self.kill_button, SIGNAL("clicked()"), self.process.kill)

        if os.name == 'nt':
            self.process.start('cmd.exe', p_args)
        else:
            # Using bash:
            self.process.start('bash', p_args)
            self.send_to_process("""PS1="\u@\h:\w> "\n""")

        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, _("Error"),
                                 _("Process failed to start"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))

        return self.process

#===============================================================================
#    Input/Output
#===============================================================================

    def transcode(self, bytes):
        if os.name == 'nt':
            return encoding.transcode(str(bytes.data()), 'cp850')
        else:
            return ExternalShellBase.transcode(self, bytes)

    def send_to_process(self, text):
        if not isinstance(text, basestring):
            text = unicode(text)
        if text[:-1] in ["clear", "cls", "CLS"]:
            self.shell.clear()
            self.send_to_process(os.linesep)
            return
        if not text.endswith('\n'):
            text += '\n'
        if os.name == 'nt':
            self.process.write(text.encode('cp850'))
        else:
            self.process.write(locale_codec.fromUnicode(text))
        self.process.waitForBytesWritten(-1)

    def keyboard_interrupt(self):
        # This does not work on Windows:
        # (unfortunately there is no easy way to send a Ctrl+C to cmd.exe)
        self.send_ctrl_to_process('c')
コード例 #25
0
class ExternalPythonShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = ExtPyQsciShell

    def __init__(self,
                 parent=None,
                 fname=None,
                 wdir=None,
                 commands=[],
                 interact=False,
                 debug=False,
                 path=[]):
        ExternalShellBase.__init__(self,
                                   parent,
                                   wdir,
                                   history_filename='.history_ec.py')

        self.shell.set_externalshell(self)

        self.toggle_globals_explorer(False)
        self.interact_check.setChecked(interact)
        self.debug_check.setChecked(debug)

        self.monitor_socket = None
        self.interpreter = fname is None
        self.fname = startup.__file__ if fname is None else fname

        if self.interpreter:
            self.interact_check.hide()
            self.debug_check.hide()
            self.terminate_button.hide()

        self.commands = ["import sys", "sys.path.insert(0, '')"] + commands

        # Additional python path list
        self.path = path

    def get_toolbar_buttons(self):
        ExternalShellBase.get_toolbar_buttons(self)
        self.globalsexplorer_button = create_toolbutton(
            self,
            get_icon('dictedit.png'),
            self.tr("Variables"),
            tip=self.tr("Show/hide global variables explorer"),
            toggled=self.toggle_globals_explorer)
        self.terminate_button = create_toolbutton(
            self,
            get_icon('terminate.png'),
            self.tr("Terminate"),
            tip=self.tr("Attempts to terminate the process.\n"
                        "The process may not exit as a result of clicking "
                        "this button\n(it is given the chance to prompt "
                        "the user for any unsaved files, etc)."))
        self.interact_check = QCheckBox(self.tr("Interact"), self)
        self.debug_check = QCheckBox(self.tr("Debug"), self)
        return [
            self.interact_check, self.debug_check, self.globalsexplorer_button,
            self.run_button, self.terminate_button, self.kill_button
        ]

    def get_shell_widget(self):
        # Globals explorer
        self.globalsexplorer = GlobalsExplorer(self)
        self.connect(self.globalsexplorer, SIGNAL('collapse()'),
                     lambda: self.toggle_globals_explorer(False))

        # Shell splitter
        self.splitter = splitter = QSplitter(Qt.Vertical, self)
        self.connect(self.splitter, SIGNAL('splitterMoved(int, int)'),
                     self.splitter_moved)
        splitter.addWidget(self.shell)
        splitter.setCollapsible(0, False)
        splitter.addWidget(self.globalsexplorer)
        splitter.setStretchFactor(0, 2)
        splitter.setStretchFactor(1, 1)
        return splitter

    def get_icon(self):
        return get_icon('python.png')

    def set_buttons_runnning_state(self, state):
        ExternalShellBase.set_buttons_runnning_state(self, state)
        self.interact_check.setEnabled(not state)
        self.debug_check.setEnabled(not state)
        self.terminate_button.setEnabled(state)
        if not state:
            self.toggle_globals_explorer(False)
        self.globalsexplorer_button.setEnabled(state)

    def create_process(self):
        self.shell.clear()

        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        self.connect(self.shell, SIGNAL("wait_for_ready_read()"),
                     lambda: self.process.waitForReadyRead(250))

        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)

        #-------------------------Python specific-------------------------------
        # Python arguments
        p_args = ['-u']
        if self.interact_check.isChecked():
            p_args.append('-i')
        if self.debug_check.isChecked():
            p_args.extend(['-m', 'pdb'])
        p_args.append(self.fname)

        env = self.process.systemEnvironment()

        # Monitor
        env.append('SHELL_ID=%s' % id(self))
        from spyderlib.widgets.externalshell.monitor import start_server
        server, port = start_server()
        self.notification_thread = server.register(str(id(self)), self)
        self.connect(self.notification_thread, SIGNAL('refresh()'),
                     self.globalsexplorer.refresh_table)
        env.append('SPYDER_PORT=%d' % port)

        # Python init commands (interpreter only)
        if self.commands and self.interpreter:
            env.append('PYTHONINITCOMMANDS=%s' % ';'.join(self.commands))
            self.process.setEnvironment(env)

        pathlist = []

        # Fix encoding with custom "sitecustomize.py"
        scpath = osp.dirname(osp.abspath(__file__))
        pathlist.append(scpath)

        # Adding Spyder path
        pathlist += self.path

        # Adding path list to PYTHONPATH environment variable
        pypath = "PYTHONPATH"
        pathstr = os.pathsep.join(pathlist)
        if os.environ.get(pypath) is not None:
            env.replaceInStrings(pypath + '=',
                                 pypath + '=' + pathstr + os.pathsep,
                                 Qt.CaseSensitive)
        else:
            env.append(pypath + '=' + pathstr)
        self.process.setEnvironment(env)
        #-------------------------Python specific-------------------------------

        if self.arguments:
            p_args.extend(self.arguments.split(' '))

        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process,
                     SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)

        self.connect(self.terminate_button, SIGNAL("clicked()"),
                     self.process.terminate)
        self.connect(self.kill_button, SIGNAL("clicked()"), self.process.kill)

        #-------------------------Python specific-------------------------------
        self.process.start(sys.executable, p_args)
        #-------------------------Python specific-------------------------------

        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, self.tr("Error"),
                                 self.tr("Process failed to start"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))

        return self.process

#===============================================================================
#    Input/Output
#===============================================================================

    def _write_error(self, text, findstr):
        pos = text.find(findstr)
        if pos != -1:
            self.shell.write(text[:pos])
            if text.endswith(">>> "):
                self.shell.write_error(text[pos:-5])
                self.shell.write(text[-5:], flush=True)
            else:
                self.shell.write_error(text[pos:])
            return True
        return False

    def write_output(self):
        text = self.get_stdout()
        if not self._write_error(text, 'Traceback (most recent call last):') \
           and not self._write_error(text, 'File "<stdin>", line 1'):
            self.shell.write(text)
        QApplication.processEvents()

    def send_to_process(self, qstr):
        if not isinstance(qstr, QString):
            qstr = QString(qstr)
        if not qstr.endsWith('\n'):
            qstr.append('\n')
        self.process.write(qstr.toLocal8Bit())
        self.process.waitForBytesWritten(-1)

    def keyboard_interrupt(self):
        communicate(self.monitor_socket, "thread.interrupt_main()")

#===============================================================================
#    Globals explorer
#===============================================================================

    def toggle_globals_explorer(self, state):
        self.splitter.setSizes([1, 1 if state else 0])
        self.globalsexplorer_button.setChecked(state)
        if state:
            self.globalsexplorer.refresh_table()

    def splitter_moved(self, pos, index):
        self.globalsexplorer_button.setChecked(self.splitter.sizes()[1])
コード例 #26
0
ファイル: pythonshell.py プロジェクト: koll00/Gui_SM
class ExternalPythonShell(ExternalShellBase):
    """External Shell widget: execute Python script in a separate process"""
    SHELL_CLASS = ExtPythonShellWidget
    def __init__(self, parent=None, fname=None, wdir=None,
                 interact=False, debug=False, path=[], python_args='',
                 ipykernel=False, arguments='', stand_alone=None,
                 umd_enabled=True, umd_namelist=[], umd_verbose=True,
                 pythonstartup=None, pythonexecutable=None,
                 monitor_enabled=True, mpl_patch_enabled=True,
                 mpl_backend=None, ets_backend='qt4', qt_api=None, pyqt_api=0,
                 install_qt_inputhook=True, ignore_sip_setapi_errors=False,
                 merge_output_channels=False, colorize_sys_stderr=False,
                 autorefresh_timeout=3000, autorefresh_state=True,
                 light_background=True, menu_actions=None,
                 show_buttons_inside=True, show_elapsed_time=True):

        assert qt_api in (None, 'pyqt', 'pyside')

        self.namespacebrowser = None # namespace browser widget!
        
        self.dialog_manager = DialogManager()
        
        self.stand_alone = stand_alone # stand alone settings (None: plugin)
        self.pythonstartup = pythonstartup
        self.pythonexecutable = pythonexecutable
        self.monitor_enabled = monitor_enabled
        self.mpl_patch_enabled = mpl_patch_enabled
        self.mpl_backend = mpl_backend
        self.ets_backend = ets_backend
        self.qt_api = qt_api
        self.pyqt_api = pyqt_api
        self.install_qt_inputhook = install_qt_inputhook
        self.ignore_sip_setapi_errors = ignore_sip_setapi_errors
        self.merge_output_channels = merge_output_channels
        self.colorize_sys_stderr = colorize_sys_stderr
        self.umd_enabled = umd_enabled
        self.umd_namelist = umd_namelist
        self.umd_verbose = umd_verbose
        self.autorefresh_timeout = autorefresh_timeout
        self.autorefresh_state = autorefresh_state
                
        self.namespacebrowser_button = None
        self.cwd_button = None
        self.env_button = None
        self.syspath_button = None
        self.terminate_button = None

        self.notification_thread = None
        
        ExternalShellBase.__init__(self, parent=parent, fname=fname, wdir=wdir,
                                   history_filename='.history.py',
                                   light_background=light_background,
                                   menu_actions=menu_actions,
                                   show_buttons_inside=show_buttons_inside,
                                   show_elapsed_time=show_elapsed_time)

        if self.pythonexecutable is None:
            self.pythonexecutable = get_python_executable()

        self.python_args = None
        if python_args:
            assert isinstance(python_args, basestring)
            self.python_args = python_args
        
        assert isinstance(arguments, basestring)
        self.arguments = arguments
        
        self.connection_file = None
        self.is_ipykernel = ipykernel
        if self.is_ipykernel:
            interact = False
            # Running our custom startup script for IPython kernels:
            # (see spyderlib/widgets/externalshell/start_ipython_kernel.py)
            self.fname = get_module_source_path(
                'SMlib.widgets.externalshell', 'start_ipython_kernel.py')
        
        self.shell.set_externalshell(self)

        self.toggle_globals_explorer(False)
        self.interact_action.setChecked(interact)
        self.debug_action.setChecked(debug)
        
        self.introspection_socket = None
        self.is_interpreter = fname is None
        
        if self.is_interpreter:
            self.terminate_button.hide()
        
        # Additional python path list
        self.path = path
        self.shell.path = path
        
    def set_introspection_socket(self, introspection_socket):
        self.introspection_socket = introspection_socket
        if self.namespacebrowser is not None:
            settings = self.namespacebrowser.get_view_settings()
            communicate(introspection_socket,
                        'set_remote_view_settings()', settings=[settings])
        
    def set_autorefresh_timeout(self, interval):
        if self.introspection_socket is not None:
            try:
                communicate(self.introspection_socket,
                            "set_monitor_timeout(%d)" % interval)
            except socket.error:
                pass
        
    def closeEvent(self, event):
        self.quit_monitor()
        ExternalShellBase.closeEvent(self, event)
        
    def get_toolbar_buttons(self):
        ExternalShellBase.get_toolbar_buttons(self)
        if self.namespacebrowser_button is None \
           and self.stand_alone is not None:
            self.namespacebrowser_button = create_toolbutton(self,
                  text=_("Variables"), icon=get_icon('dictedit.png'),
                  tip=_("Show/hide global variables explorer"),
                  toggled=self.toggle_globals_explorer, text_beside_icon=True)
        if self.terminate_button is None:
            self.terminate_button = create_toolbutton(self,
                  text=_("Terminate"), icon=get_icon('terminate.png'),
                  tip=_("""Attempts to terminate the process.
The process may not exit as a result of clicking this button
(it is given the chance to prompt the user for any unsaved files, etc)."""))
        buttons = []
        if self.namespacebrowser_button is not None:
            buttons.append(self.namespacebrowser_button)
        buttons += [self.run_button, self.options_button,
                    self.terminate_button, self.kill_button]
        return buttons

    def get_options_menu(self):
        ExternalShellBase.get_options_menu(self)
        self.interact_action = create_action(self, _("Interact"))
        self.interact_action.setCheckable(True)
        self.debug_action = create_action(self, _("Debug"))
        self.debug_action.setCheckable(True)
        self.args_action = create_action(self, _("Arguments..."),
                                         triggered=self.get_arguments)
        run_settings_menu = QMenu(_("Run settings"), self)
        add_actions(run_settings_menu,
                    (self.interact_action, self.debug_action, self.args_action))
        self.cwd_button = create_action(self, _("Working directory"),
                                icon=get_std_icon('DirOpenIcon'),
                                tip=_("Set current working directory"),
                                triggered=self.set_current_working_directory)
        self.env_button = create_action(self, _("Environment variables"),
                                        icon=get_icon('environ.png'),
                                        triggered=self.show_env)
        self.syspath_button = create_action(self,
                                            _("Show sys.path contents"),
                                            icon=get_icon('syspath.png'),
                                            triggered=self.show_syspath)
        actions = [run_settings_menu, self.show_time_action, None,
                   self.cwd_button, self.env_button, self.syspath_button]
        if self.menu_actions is not None:
            actions += [None]+self.menu_actions
        return actions

    def is_interpreter(self):
        """Return True if shellwidget is a Python interpreter"""
        return self.is_interpreter
        
    def get_shell_widget(self):
        if self.stand_alone is None:
            return self.shell
        else:
            self.namespacebrowser = NamespaceBrowser(self)
            settings = self.stand_alone
            self.namespacebrowser.set_shellwidget(self)
            self.namespacebrowser.setup(**settings)
            self.connect(self.namespacebrowser, SIGNAL('collapse()'),
                         lambda: self.toggle_globals_explorer(False))
            # Shell splitter
            self.splitter = splitter = QSplitter(Qt.Vertical, self)
            self.connect(self.splitter, SIGNAL('splitterMoved(int, int)'),
                         self.splitter_moved)
            splitter.addWidget(self.shell)
            splitter.setCollapsible(0, False)
            splitter.addWidget(self.namespacebrowser)
            splitter.setStretchFactor(0, 1)
            splitter.setStretchFactor(1, 0)
            splitter.setHandleWidth(5)
            splitter.setSizes([2, 1])
            return splitter
    
    def get_icon(self):
        return get_icon('python.png')

    def set_buttons_runnning_state(self, state):
        ExternalShellBase.set_buttons_runnning_state(self, state)
        self.interact_action.setEnabled(not state and not self.is_interpreter)
        self.debug_action.setEnabled(not state and not self.is_interpreter)
        self.args_action.setEnabled(not state and not self.is_interpreter)
        if state:
            if self.arguments:
                argstr = _("Arguments: %s") % self.arguments
            else:
                argstr = _("No argument")
        else:
            argstr = _("Arguments...")
        self.args_action.setText(argstr)
        self.terminate_button.setVisible(not self.is_interpreter and state)
        if not state:
            self.toggle_globals_explorer(False)
        for btn in (self.cwd_button, self.env_button, self.syspath_button):
            btn.setEnabled(state and self.monitor_enabled)
        if self.namespacebrowser_button is not None:
            self.namespacebrowser_button.setEnabled(state)
    
    def set_namespacebrowser(self, namespacebrowser):
        """
        Set namespace browser *widget*
        Note: this method is not used in stand alone mode
        """
        self.namespacebrowser = namespacebrowser
        self.configure_namespacebrowser()
        
    def configure_namespacebrowser(self):
        """Connect the namespace browser to the notification thread"""
        if self.notification_thread is not None:
            self.connect(self.notification_thread,
                         SIGNAL('refresh_namespace_browser()'),
                         self.namespacebrowser.refresh_table)
            signal = self.notification_thread.sig_process_remote_view
            signal.connect(self.namespacebrowser.process_remote_view)
    
    def create_process(self):
        self.shell.clear()
            
        self.process = QProcess(self)
        if self.merge_output_channels:
            self.process.setProcessChannelMode(QProcess.MergedChannels)
        else:
            self.process.setProcessChannelMode(QProcess.SeparateChannels)
        self.connect(self.shell, SIGNAL("wait_for_ready_read()"),
                     lambda: self.process.waitForReadyRead(250))
        
        # Working directory
        if self.wdir is not None:
            self.process.setWorkingDirectory(self.wdir)

        #-------------------------Python specific-------------------------------
        # Python arguments
        p_args = ['-u']
        if DEBUG >= 3:
            p_args += ['-v']
        p_args += get_python_args(self.fname, self.python_args,
                                  self.interact_action.isChecked(),
                                  self.debug_action.isChecked(),
                                  self.arguments)
        
        env = [unicode(_path) for _path in self.process.systemEnvironment()]

        if self.pythonstartup:
            env.append('PYTHONSTARTUP=%s' % self.pythonstartup)
        
        # Monitor
        if self.monitor_enabled:
            env.append('SPYDER_SHELL_ID=%s' % id(self))
            env.append('SPYDER_AR_TIMEOUT=%d' % self.autorefresh_timeout)
            env.append('SPYDER_AR_STATE=%r' % self.autorefresh_state)
            from SMlib.widgets.externalshell import introspection
            introspection_server = introspection.start_introspection_server()
            introspection_server.register(self)
            notification_server = introspection.start_notification_server()
            self.notification_thread = notification_server.register(self)
            self.connect(self.notification_thread, SIGNAL('pdb(QString,int)'),
                         lambda fname, lineno:
                         self.emit(SIGNAL('pdb(QString,int)'), fname, lineno))
            self.connect(self.notification_thread,
                         SIGNAL('new_ipython_kernel(QString)'),
                         lambda args:
                         self.emit(SIGNAL('create_ipython_client(QString)'),
                         args))
            self.connect(self.notification_thread,
                         SIGNAL('open_file(QString,int)'),
                         lambda fname, lineno:
                         self.emit(SIGNAL('open_file(QString,int)'),
                                   fname, lineno))
            if self.namespacebrowser is not None:
                self.configure_namespacebrowser()
            env.append('SPYDER_I_PORT=%d' % introspection_server.port)
            env.append('SPYDER_N_PORT=%d' % notification_server.port)
        
        # External modules options
        env.append('ETS_TOOLKIT=%s' % self.ets_backend)
        env.append('MATPLOTLIB_PATCH=%r' % self.mpl_patch_enabled)
        if self.mpl_backend:
            env.append('MATPLOTLIB_BACKEND=%s' % self.mpl_backend)
        if self.qt_api:
            env.append('QT_API=%s' % self.qt_api)
        env.append('INSTALL_QT_INPUTHOOK=%s' % self.install_qt_inputhook)
        env.append('COLORIZE_SYS_STDERR=%s' % self.colorize_sys_stderr)
#        # Socket-based alternative (see input hook in sitecustomize.py):
#        if self.install_qt_inputhook:
#            from PyQt4.QtNetwork import QLocalServer
#            self.local_server = QLocalServer()
#            self.local_server.listen(str(id(self)))
        if self.pyqt_api:
            env.append('PYQT_API=%d' % self.pyqt_api)
        env.append('IGNORE_SIP_SETAPI_ERRORS=%s'
                   % self.ignore_sip_setapi_errors)
        
        # User Module Deleter
        if self.is_interpreter:
            env.append('UMD_ENABLED=%r' % self.umd_enabled)
            env.append('UMD_NAMELIST=%s' % ','.join(self.umd_namelist))
            env.append('UMD_VERBOSE=%r' % self.umd_verbose)

        # IPython kernel
        env.append('IPYTHON_KERNEL=%r' % self.is_ipykernel)
            
        pathlist = []

        # Fix encoding with custom "sitecustomize.py"
        scpath = osp.dirname(osp.abspath(__file__))
        pathlist.append(scpath)
        
        # Adding Spyder path
        pathlist += self.path
        
        # Adding path list to PYTHONPATH environment variable
        add_pathlist_to_PYTHONPATH(env, pathlist)

        #-------------------------Python specific-------------------------------
                        
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.write_output)
        self.connect(self.process, SIGNAL("readyReadStandardError()"),
                     self.write_error)
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)
                     
        self.connect(self, SIGNAL('finished()'), self.dialog_manager.close_all)

        self.connect(self.terminate_button, SIGNAL("clicked()"),
                     self.process.terminate)
        self.connect(self.kill_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        #-------------------------Python specific-------------------------------
        # Fixes for our Mac app:
        # 1. PYTHONPATH and PYTHONHOME are set while bootstrapping the app,
        #    but their values are messing sys.path for external interpreters
        #    (e.g. EPD) so we need to remove them from the environment.
        # 2. Add this file's dir to PYTHONPATH. This will make every external
        #    interpreter to use our sitecustomize script.
        # 3. Remove PYTHONOPTIMIZE from env so that we can have assert
        #    statements working with our interpreters (See Issue 1281)
        if sys.platform == 'darwin' and 'Spyder.app' in __file__:
            env.append('SPYDER_INTERPRETER=%s' % self.pythonexecutable)
            if 'Spyder.app' not in self.pythonexecutable:
                env = [p for p in env if not (p.startswith('PYTHONPATH') or \
                                              p.startswith('PYTHONHOME'))] # 1.

                env.append('PYTHONPATH=%s' % osp.dirname(__file__))        # 2.

            env = [p for p in env if not p.startswith('PYTHONOPTIMIZE')]   # 3.

        self.process.setEnvironment(env)
        self.process.start(self.pythonexecutable, p_args)
        #-------------------------Python specific-------------------------------
            
        running = self.process.waitForStarted(3000)
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, _("Error"),
                             _("A Python or IPython Console failed to start!"))
        else:
            self.shell.setFocus()
            self.emit(SIGNAL('started()'))
            
        return self.process

    def finished(self, exit_code, exit_status):
        """Reimplement ExternalShellBase method"""
        ExternalShellBase.finished(self, exit_code, exit_status)
        self.introspection_socket = None

    
#===============================================================================
#    Input/Output
#===============================================================================
    def write_error(self):
        if os.name == 'nt':
            #---This is apparently necessary only on Windows (not sure though):
            #   emptying standard output buffer before writing error output
            self.process.setReadChannel(QProcess.StandardOutput)
            if self.process.waitForReadyRead(1):
                self.write_output()
        self.shell.write_error(self.get_stderr())
        QApplication.processEvents()
        
    def send_to_process(self, text):
        if not self.is_running():
            return
            
        if not isinstance(text, basestring):
            text = unicode(text)
        if self.install_qt_inputhook and self.introspection_socket is not None:
            communicate(self.introspection_socket,
                        "toggle_inputhook_flag(True)")
#            # Socket-based alternative (see input hook in sitecustomize.py):
#            while self.local_server.hasPendingConnections():
#                self.local_server.nextPendingConnection().write('go!')
        if text.startswith(('%', '!')):
            text = 'evalsc(r"%s")\n' % text
        if not text.endswith('\n'):
            text += '\n'
        self.process.write(locale_codec.fromUnicode(text))
        self.process.waitForBytesWritten(-1)
        
        # Eventually write prompt faster (when hitting Enter continuously)
        # -- necessary/working on Windows only:
        if os.name == 'nt':
            self.write_error()
        
    def keyboard_interrupt(self):
        if self.introspection_socket is not None:
            communicate(self.introspection_socket, "thread.interrupt_main()")
        
    def quit_monitor(self):
        if self.introspection_socket is not None:
            try:
                write_packet(self.introspection_socket, "thread.exit()")
            except socket.error:
                pass
            
#===============================================================================
#    Globals explorer
#===============================================================================
    def toggle_globals_explorer(self, state):
        if self.stand_alone is not None:
            self.splitter.setSizes([1, 1 if state else 0])
            self.namespacebrowser_button.setChecked(state)
            if state and self.namespacebrowser is not None:
                self.namespacebrowser.refresh_table()
        
    def splitter_moved(self, pos, index):
        self.namespacebrowser_button.setChecked( self.splitter.sizes()[1] )

#===============================================================================
#    Misc.
#===============================================================================
    def set_current_working_directory(self):
        """Set current working directory"""
        cwd = self.shell.get_cwd()
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        directory = getexistingdirectory(self, _("Select directory"), cwd)
        if directory:
            self.shell.set_cwd(directory)
        self.emit(SIGNAL('redirect_stdio(bool)'), True)

    def show_env(self):
        """Show environment variables"""
        get_func = self.shell.get_env
        set_func = self.shell.set_env
        self.dialog_manager.show(RemoteEnvDialog(get_func, set_func))
        
    def show_syspath(self):
        """Show sys.path contents"""
        editor = DictEditor()
        editor.setup(self.shell.get_syspath(), title="sys.path", readonly=True,
                     width=600, icon='syspath.png')
        self.dialog_manager.show(editor)
コード例 #27
0
class TerreImageProcess():
    def __init__(self):
        self.process = QProcess()
        self.process.error[QProcess.ProcessError].connect(
            self.error_management)
        self.env = QProcessEnvironment().systemEnvironment()
        self.set_otb_process_env_default()
        self.command = ""

    def run_process(self, command):
        logger.info(u"Running {}".format(command))
        self.process.setProcessEnvironment(self.env)

        # logger.debug("..............{}".format(self.process.processEnvironment().value("OTB_APPLICATION_PATH")))
        # logger.debug("..............{}".format(self.process.processEnvironment().value("PATH")))
        # logger.debug("Environ : PATH {}".format(os.environ["PATH"]))
        # logger.debug("Environ : OTB_APPLICATION_PATH {}".format(os.environ.get("OTB_APPLICATION_PATH", "Empty")))
        self.command = command
        self.process.start(command)
        if self.process.waitForStarted():
            self.process.waitForFinished(-1)
            exit_code = self.process.exitCode()
            if exit_code != 0:
                self.error_management(exit_code)
            result = self.process.readAllStandardOutput()
            # logger.debug(" {} {}".format(type(result), result))
            error = self.process.readAllStandardError().data()
            # logger.debug(repr(error))
            if not error in ["\n", ""]:
                logger.error("error : %s" % (error))
            output = result.data()
            logger.info(output)
            return result
        else:
            code_d_erreur = self.process.error()
            self.error_management(code_d_erreur)
        return None

    def error_management(self, errorCode):
        dic_err = {
            0: "QProcess::FailedToStart",
            1: "QProcess::Crashed",
            2: "QProcess::TimedOut",
            3: "QProcess::WriteError",
            4: "QProcess::ReadError",
            5: "QProcess::UnknownError",
            127: "Other, The application may not have been found"
        }
        try:
            type_qt_error = dic_err[errorCode]
            logger.error(u"Error {} {}".format(errorCode, type_qt_error))
        except KeyError:
            type_qt_error = ""
        error = self.process.readAllStandardError().data()
        logger.error(error)
        logger.error(self.process.readAllStandardOutput())
        try:
            raise terre_image_exceptions.TerreImageRunProcessError(
                u"Error running : {}\n {}{}".format(self.command,
                                                    type_qt_error, error))
        except UnicodeError:
            raise terre_image_exceptions.TerreImageRunProcessError(
                u"Error running : {}\n {}".format(self.command, type_qt_error))

    def set_env_var(self, varname, varval, append=False, pre=False):

        if append == True:
            if pre == False:
                # insert value at the end of the variable
                self.env.insert(varname,
                                self.env.value(varname) + os.pathsep + varval)
            else:
                # insert value in head
                self.env.insert(varname,
                                varval + os.pathsep + self.env.value(varname))
        else:
            # replace value if existing
            self.env.insert(varname, varval)
        # logger.debug("env {} {}".format(varname, self.env.value(varname)))

    def set_otb_process_env(self):
        dirname = os.path.dirname(os.path.abspath(__file__))
        self.set_env_var("OTB_APPLICATION_PATH",
                         os.path.join(dirname, "win32", "plugin"),
                         pre=True)
        self.set_env_var("PATH",
                         os.path.join(dirname, "win32", "bin"),
                         append=False,
                         pre=True)

    def set_otb_process_env_custom(self, otb_app_path="", path=""):
        """
        Add the given values to OTB_APPLICATION_PATH and PATH environement variables
        Args:
            otb_app_path:
            path:

        Returns:

        """
        self.set_env_var("OTB_APPLICATION_PATH", otb_app_path, pre=True)
        self.set_env_var("PATH", path, append=False, pre=True)

    def set_otb_process_env_default(self):
        """
        Add the values from the config file to OTB_APPLICATION_PATH and PATH environement variables
        Args:
            otb_app_path:
            path:

        Returns:

        """
        self.set_env_var("OTB_APPLICATION_PATH",
                         terre_image_configuration.OTB_APPLICATION_PATH,
                         pre=True)
        self.set_env_var("PATH",
                         terre_image_configuration.PATH,
                         append=True,
                         pre=True)
        if terre_image_configuration.LD_LIBRARY_PATH:
            self.set_env_var("LD_LIBRARY_PATH",
                             terre_image_configuration.LD_LIBRARY_PATH,
                             append=True,
                             pre=True)
コード例 #28
0
ファイル: main.py プロジェクト: juancarlospaco/sphinx
class Main(plugin.Plugin):
    " Main Class "
    def initialize(self, *args, **kwargs):
        " Init Main Class "
        super(Main, self).initialize(*args, **kwargs)
        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self.process.readyReadStandardError.connect(self.readErrors)
        self.process.finished.connect(self._process_finished)
        # self.process.error.connect(self._process_error)

        self.sourceDirectory, self.outputDirectory = None, None

        self.group2 = QGroupBox()
        self.group2.setTitle(' Paths ')
        self.inf = QLineEdit(path.expanduser("~"))
        self.inf.setPlaceholderText(' /full/path/to/directory ')
        self.out, self.fle = QLineEdit(path.expanduser("~")), QLineEdit()
        self.out.setPlaceholderText(' /full/path/to/directory ')
        self.fle.setPlaceholderText(' /full/path/to/single/file ')
        self.completer, self.dirs = QCompleter(self), QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        self.inf.setCompleter(self.completer)
        self.out.setCompleter(self.completer)
        self.fle.setCompleter(self.completer)
        self.open1 = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.open1.setCursor(QCursor(Qt.PointingHandCursor))
        self.open1.clicked.connect(lambda: self.inf.setText(str(
            QFileDialog.getExistingDirectory(self.dock, "Open Source Directory",
            path.expanduser("~")))))
        self.open2 = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.open2.setCursor(QCursor(Qt.PointingHandCursor))
        self.open2.clicked.connect(lambda: self.out.setText(str(
            QFileDialog.getExistingDirectory(self.dock, "Open Target Directory",
            path.expanduser("~")))))
        self.open3 = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.open3.setCursor(QCursor(Qt.PointingHandCursor))
        self.open3.clicked.connect(lambda: self.fle.setText(str(
            QFileDialog.getOpenFileName(self.dock, "Open a Target File...",
            path.expanduser("~"), ';;'.join(['{}(*.{})'.format(e.upper(), e)
                for e in ['py', 'pyw', '*']])))))
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (
            QLabel('Source Directory Project:'), self.inf, self.open1,
            QLabel(' Target Directory Outputs: '), self.out, self.open2,
            QLabel(' Source Single File (Optional):'), self.fle, self.open3, ):
            vboxg2.addWidget(each_widget)

        self.group1 = QGroupBox()
        self.group1.setTitle(' Options ')
        self.chckbx1 = QCheckBox(' Inject Twitter Bootstrap CSS3 ')
        self.chckbx1.toggled.connect(self.toggle_styles_group)
        self.chckbx2 = QCheckBox(' Warn all missing references ')
        self.chckbx3 = QCheckBox(' Open Docs when done building ')
        self.chckbx4 = QCheckBox('Save Bash script to reproduce Sphinx Builds')
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (self.chckbx1, self.chckbx2,
                            self.chckbx3, self.chckbx4):
            vboxg1.addWidget(each_widget)
            each_widget.setChecked(True)

        self.group3 = QGroupBox()
        self.group3.setTitle(' Styles ')
        self.group3.setGraphicsEffect(QGraphicsBlurEffect(self))
        self.group3.graphicsEffect().setEnabled(False)
        self.basecss, self.fontcss = QComboBox(), QComboBox()
        self.basecss.addItems(['slate', 'united', 'spacelab', 'superhero',
            'simplex', 'journal', 'flatly', 'cyborg', 'cosmo', 'cerulean'])
        self.fontcss.addItems(['Ubuntu Light', 'Oxygen', 'Roboto', 'Droid Sans',
            'Open Sans', 'Pacifico', 'Rancho', 'Arvo', 'Fresca', 'Graduate'])
        self.backcss = QComboBox()
        self.backcss.addItems(['shattered', 'retina_wood', 'ricepaper',
            'brickwall', 'sneaker_mesh_fabric', 'diagonales_decalees',
            'noisy_grid', 'pw_pattern', 'escheresque', 'diamond_upholstery'])
        vboxg3 = QVBoxLayout(self.group3)
        for each_widget in (QLabel('<b>Twitter Bootstrap Theme'), self.basecss,
            QLabel('<b>Fonts Family'), self.fontcss,
            QLabel('<b>Background Seamless Tiled Pattern'), self.backcss):
            vboxg3.addWidget(each_widget)

        self.output = QTextEdit('''
        My brain is something more than merely mortal; As time will show.
        - Ada Lovelace ''')
        self.output.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.button = QPushButton('Document My Code')
        self.button.setCursor(QCursor(Qt.PointingHandCursor))
        self.button.setMinimumSize(75, 50)
        self.button.clicked.connect(self.build)
        glow = QGraphicsDropShadowEffect(self)
        glow.setOffset(0)
        glow.setBlurRadius(99)
        glow.setColor(QColor(99, 255, 255))
        self.button.setGraphicsEffect(glow)

        class TransientWidget(QWidget):
            ' persistant widget thingy '
            def __init__(self, widget_list):
                ' init sub class '
                super(TransientWidget, self).__init__()
                vbox = QVBoxLayout(self)
                for each_widget in widget_list:
                    vbox.addWidget(each_widget)

        tw = TransientWidget((self.group2, self.group1, self.group3,
            QLabel(linesep + ' Logs: '), self.output, self.button))
        self.scrollable, self.dock = QScrollArea(), QDockWidget()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(tw)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)
        ExplorerContainer().addTab(self.dock, "Sphinx")
        QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock
            ).clicked.connect(lambda:
            QMessageBox.information(self.dock, __doc__, HELPMSG))

    def readOutput(self):
        """Read and append sphinx-build output to the logBrowser"""
        self.output.append(str(self.process.readAllStandardOutput()))

    def readErrors(self):
        """Read and append sphinx-build errors to the logBrowser"""
        self.output.append(self.formatErrorMsg(str(
                                        self.process.readAllStandardError())))

    def formatErrorMsg(self, msg):
        """Format error messages in red color"""
        return self.formatMsg(msg, 'red')

    def formatInfoMsg(self, msg):
        """Format informative messages in blue color"""
        return self.formatMsg(msg, 'green')

    def formatMsg(self, msg, color):
        """Format message with the given color"""
        return '<font color="{}">{}</font>'.format(color, msg)

    def build(self):
        """Main function calling sphinx-build to generate the project"""
        self.output.setText('')
        self.output.append(self.formatInfoMsg(
                            'INFO: OK: Starting at {}'.format(datetime.now())))
        self.button.setDisabled(True)
        self.sourceDirectory = str(self.inf.text()).strip()
        self.outputDirectory = str(self.out.text()).strip()
        if not len(self.sourceDirectory):
            self.output.append(' ERROR: FAIL: Source directory cannot be empty')
        else:
            self.output.append(self.formatInfoMsg(
            'INFO: OK: Source Directory is {}'.format(self.sourceDirectory)))
        if not len(self.outputDirectory):
            self.output.append(' ERROR: FAIL: Output directory cannot be empty')
        else:
            self.output.append(self.formatInfoMsg(
            'INFO: OK: Output Directory is {}'.format(self.outputDirectory)))
        if not(len(self.sourceDirectory) or len(self.outputDirectory)):
            self.button.setDisabled(False)
            return
        self.output.append(self.formatInfoMsg('INFO:OK: Building. Please wait'))

        args = ['-n' if self.chckbx2.isChecked() is True else '',
                '-b', 'html', self.sourceDirectory, self.outputDirectory]
        if len(self.fle.text()):
            args.append(str(self.fle.text()).strip().replace('file:///', '/'))
            self.output.append(self.formatInfoMsg(
                'INFO: OK: Source Single File is {}'.format(self.fle.text())))
        self.output.append(self.formatInfoMsg('INFO:OK: Running sphinx-build!'))

        self.process.start('sphinx-build', args)
        if not self.process.waitForStarted():
            self.output.append(self.formatErrorMsg('ERROR: FAIL: Build Failed'))
            self.output.append(self.formatErrorMsg(
                'ERROR: FAIL: Failed with Arguments: {} '.format(args)))
            self.button.setEnabled(True)
            return
        # write a .sh bash script file on target
        if self.chckbx4.isChecked() is True:
            sh_file = 'build_sphinx_documentation.sh'
            with open(path.join(self.sourceDirectory, sh_file), 'w') as _sh:
                self.output.append(self.formatInfoMsg('''INFO: OK: Writing Bash:
                    {}'''.format(path.join(self.sourceDirectory, sh_file))))
                _sh.write('#!/usr/bin/env bash {}'.format(linesep) +
                          'sphinx-build {}'.format(' '.join(args)))
                _sh.close()
            self.output.append(self.formatInfoMsg('INFO: OK: Bash chmod: 775'))
            try:
                chmod(path.join(self.sourceDirectory, sh_file), 0775)  # Py2
            except:
                chmod(path.join(self.sourceDirectory, sh_file), 0o775)  # Py3
        self.button.setEnabled(True)

    def _process_finished(self):
        """sphinx-build finished sucessfully"""
        self.output.append(self.formatInfoMsg(
                            'INFO: OK: Finished at {}'.format(datetime.now())))
        if self.chckbx1.isChecked() is True:
            with open(path.join(self.outputDirectory, '_static', 'default.css'),
                'a') as f:
                css = CSS3.replace('CSSWEBFONT', str(self.fontcss.currentText())
                      ).replace('CSSBACKGR', str(self.backcss.currentText())
                      ).replace('CSSCUSTOM', str(self.basecss.currentText()))
                f.write(css)
                f.close()
        if self.chckbx3.isChecked() is True:
            call('xdg-open ' + path.join(self.outputDirectory, 'index.html'),
                 shell=True)

    def toggle_styles_group(self):
        ' toggle on or off the styles checkboxes '
        try:
            if self.chckbx1.isChecked() is True:
                self.group3.graphicsEffect().setEnabled(False)
                self.group3.setEnabled(True)
            else:
                self.group3.graphicsEffect().setEnabled(True)
                self.group3.setEnabled(False)
        except:
            pass
コード例 #29
0
class Main(plugin.Plugin):
    " Main Class "

    def initialize(self, *args, **kwargs):
        " Init Main Class "
        super(Main, self).initialize(*args, **kwargs)
        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self.process.readyReadStandardError.connect(self.readErrors)
        self.process.finished.connect(self._process_finished)
        self.process.error.connect(self._process_finished)
        # directory auto completer
        self.completer, self.dirs = QCompleter(self), QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        self.group0 = QGroupBox()
        self.group0.setTitle(' Source ')
        self.source, self.infile = QComboBox(), QLineEdit(path.expanduser("~"))
        self.source.addItems(['Local File', 'Remote URL'])
        self.source.currentIndexChanged.connect(self.on_source_changed)
        self.infile.setPlaceholderText(' /full/path/to/file.html ')
        self.infile.setCompleter(self.completer)
        self.open = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.open.setCursor(QCursor(Qt.PointingHandCursor))
        self.open.clicked.connect(lambda: self.infile.setText(
            str(
                QFileDialog.getOpenFileName(
                    self.dock, "Open a File to read from", path.expanduser(
                        "~"), ';;'.join([
                            '{}(*.{})'.format(e.upper(), e) for e in
                            ['html', 'webp', 'webm', 'svg', 'css', 'js', '*']
                        ])))))
        self.inurl, self.output = QLineEdit('http://www.'), QTextEdit()
        self.inurl.setPlaceholderText(
            'http://www.full/url/to/remote/file.html')
        self.inurl.hide()
        vboxg0 = QVBoxLayout(self.group0)
        for each_widget in (self.source, self.infile, self.open, self.inurl):
            vboxg0.addWidget(each_widget)

        self.group1 = QGroupBox()
        self.group1.setTitle(' Mobile ')
        self.ckcss1 = QCheckBox('Run in full screen using current resolution')
        self.ckcss2 = QCheckBox('Disable touch mode and use keypad mode')
        self.ckcss3 = QCheckBox(
            'Disable touch mode but allow to use the mouse')
        self.ckcss4 = QCheckBox(
            'Enable mouse,disable pointer & zoom emulation')
        self.ckcss5 = QCheckBox('Start the Mobile version of the browser')
        self.ckcss6 = QCheckBox('Start the Tablet version of the browser')
        self.ckcss7 = QCheckBox('Emulate hardware with Menu and Back keys')
        self.ckcss8 = QCheckBox('Start the browser in Kiosk mode')
        self.width, self.height = QSpinBox(), QSpinBox()
        self.zoom, self.ram, self.dpi = QSpinBox(), QSpinBox(), QSpinBox()
        self.cpulag, self.gpulag = QSpinBox(), QSpinBox()
        self.lang, self.agent = QComboBox(), QComboBox()
        self.lang.addItems(['EN', 'ES', 'PT', 'JA', 'ZH', 'DE', 'RU', 'FR'])
        self.agent.addItems(['Default', 'Android', 'MeeGo', 'Desktop'])
        self.fonts = QLineEdit()
        self.width.setMaximum(9999)
        self.width.setMinimum(100)
        self.width.setValue(480)
        self.height.setMaximum(9999)
        self.height.setMinimum(100)
        self.height.setValue(800)
        self.zoom.setMaximum(999)
        self.zoom.setMinimum(1)
        self.zoom.setValue(100)
        self.ram.setMaximum(999)
        self.ram.setMinimum(1)
        self.ram.setValue(100)
        self.dpi.setMaximum(200)
        self.dpi.setMinimum(50)
        self.dpi.setValue(96)
        self.cpulag.setMaximum(9999)
        self.cpulag.setMinimum(0)
        self.cpulag.setValue(1)
        self.gpulag.setMaximum(9999)
        self.gpulag.setMinimum(0)
        self.gpulag.setValue(1)
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (
                self.ckcss1, self.ckcss2, self.ckcss3, self.ckcss4,
                self.ckcss5, self.ckcss6, self.ckcss7, self.ckcss8,
                QLabel('Width Pixels of the emulated device screen'),
                self.width,
                QLabel('Height Pixels of the emulated device screen'),
                self.height,
                QLabel('Zoom Percentage of emulated screen'), self.zoom,
                QLabel('RAM MegaBytes of the emulated device'), self.ram,
                QLabel('Language of the emulated device'), self.lang,
                QLabel('D.P.I. of the emulated device'), self.dpi,
                QLabel('User-Agent of the emulated device'), self.agent,
                QLabel('CPU Core Lag Miliseconds of emulated device'),
                self.cpulag,
                QLabel('GPU Video Lag Miliseconds of emulated device'),
                self.gpulag, QLabel('Extra Fonts Directory Full Path'),
                self.fonts):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle(' General ')
        self.nice, self.opera = QSpinBox(), QLineEdit(path.expanduser("~"))
        self.nice.setValue(20)
        self.nice.setMaximum(20)
        self.nice.setMinimum(0)
        self.opera.setCompleter(self.completer)
        if path.exists(CONFIG_FILE):
            with codecs.open(CONFIG_FILE, encoding='utf-8') as fp:
                self.opera.setText(fp.read())
        self.open2 = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.open2.setCursor(QCursor(Qt.PointingHandCursor))
        self.open2.clicked.connect(lambda: self.opera.setText(
            str(
                QFileDialog.getOpenFileName(
                    self.dock, "Open Opera Mobile Emulator",
                    path.expanduser("~"),
                    'Opera Mobile Emulator Executable(opera-mobile-emulator)'))
        ))
        self.help1 = QLabel('''<a href=
            "http://www.opera.com/developer/mobile-emulator">
            <small><center>Download Opera Mobile Emulator !</a>''')
        self.help1.setTextInteractionFlags(Qt.LinksAccessibleByMouse)
        self.help1.setOpenExternalLinks(True)
        vboxg4 = QVBoxLayout(self.group2)
        for each_widget in (QLabel(' Backend CPU priority: '), self.nice,
                            QLabel(' Opera Mobile Emulator Full Path: '),
                            self.opera, self.open2, self.help1):
            vboxg4.addWidget(each_widget)

        self.button = QPushButton('Preview on Mobile')
        self.button.setCursor(QCursor(Qt.PointingHandCursor))
        self.button.setMinimumSize(100, 50)
        self.button.clicked.connect(self.run)
        glow = QGraphicsDropShadowEffect(self)
        glow.setOffset(0)
        glow.setBlurRadius(99)
        glow.setColor(QColor(99, 255, 255))
        self.button.setGraphicsEffect(glow)
        glow.setEnabled(True)

        class TransientWidget(QWidget):
            ' persistant widget thingy '

            def __init__(self, widget_list):
                ' init sub class '
                super(TransientWidget, self).__init__()
                vbox = QVBoxLayout(self)
                for each_widget in widget_list:
                    vbox.addWidget(each_widget)

        tw = TransientWidget((
            QLabel('<b>Mobile Browser Emulator'),
            self.group0,
            self.group1,
            self.group2,
            self.output,
            self.button,
        ))
        self.scrollable, self.dock = QScrollArea(), QDockWidget()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(tw)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)
        ExplorerContainer().addTab(self.dock, "Mobile")
        QPushButton(
            QIcon.fromTheme("help-about"), 'About', self.dock).clicked.connect(
                lambda: QMessageBox.information(self.dock, __doc__, HELPMSG))

    def run(self):
        ' run the string replacing '
        self.output.clear()
        self.button.setEnabled(False)
        self.output.append(self.formatInfoMsg('INFO:{}'.format(
            datetime.now())))
        if self.source.currentText() == 'Local File':
            target = 'file://' + str(self.infile.text()).strip()
        else:
            target = self.inurl.text()
        self.output.append(self.formatInfoMsg(' INFO: OK: Parsing Arguments'))
        cmd = ' '.join(
            ('nice --adjustment={}'.format(self.nice.value()), '"{}"'.format(
                self.opera.text()),
             '-fullscreen' if self.ckcss1.isChecked() is True else '',
             '-notouch' if self.ckcss2.isChecked() is True else '',
             '-notouchwithtouchevents' if self.ckcss3.isChecked() is True else
             '', '-usemouse' if self.ckcss4.isChecked() is True else '',
             '-mobileui' if self.ckcss5.isChecked() is True else '',
             '-tabletui' if self.ckcss6.isChecked() is True else '',
             '-hasmenuandback' if self.ckcss7.isChecked() is True else '',
             '-k' if self.ckcss8.isChecked() is True else '',
             '-displaysize {}x{}'.format(
                 self.width.value(),
                 self.height.value()), '-displayzoom {}'.format(
                     self.zoom.value()), '-mem {}M'.format(self.ram.value()),
             '-lang {}'.format(self.lang.currentText()), '-ppi {}'.format(
                 self.dpi.value()), '-extra-fonts {}'.format(self.fonts.text())
             if str(self.fonts.text()).strip() is not '' else '',
             '-user-agent-string {}'.format(
                 self.agent.currentText()), '-delaycorethread {}'.format(
                     self.cpulag.value()), '-delayuithread {}'.format(
                         self.gpulag.value()), '-url "{}"'.format(target)))
        self.output.append(self.formatInfoMsg(
            'INFO:OK:Command:{}'.format(cmd)))
        self.process.start(cmd)
        if not self.process.waitForStarted():
            self.output.append(self.formatErrorMsg(' ERROR: FAIL: Meh. '))
            self.output.append(
                self.formatErrorMsg(
                    'ERROR: FAIL: Failed with Arguments: {} '.format(cmd)))
            self.button.setEnabled(True)
            return
        self.output.setFocus()
        self.output.selectAll()
        self.button.setEnabled(True)

    def on_source_changed(self):
        ' do something when the desired source has changed '
        if self.source.currentText() == 'Local File':
            self.open.show()
            self.infile.show()
            self.inurl.hide()
        else:
            self.inurl.show()
            self.open.hide()
            self.infile.hide()

    def _process_finished(self):
        """ finished sucessfully """
        self.output.append(self.formatInfoMsg('INFO:{}'.format(
            datetime.now())))
        self.output.selectAll()
        self.output.setFocus()

    def readOutput(self):
        """Read and append output to the logBrowser"""
        self.output.append(str(self.process.readAllStandardOutput()).strip())

    def readErrors(self):
        """Read and append errors to the logBrowser"""
        self.output.append(
            self.formatErrorMsg(str(self.process.readAllStandardError())))

    def formatErrorMsg(self, msg):
        """Format error messages in red color"""
        return self.formatMsg(msg, 'red')

    def formatInfoMsg(self, msg):
        """Format informative messages in blue color"""
        return self.formatMsg(msg, 'green')

    def formatMsg(self, msg, color):
        """Format message with the given color"""
        return '<font color="{}">{}</font>'.format(color, msg)

    def finish(self):
        ' save when finish '
        with codecs.open(CONFIG_FILE, "w", encoding='utf-8') as fp:
            fp.write(self.opera.text())
コード例 #30
0
ファイル: pylintgui.py プロジェクト: Brainsciences/luminoso
class PylintWidget(QWidget):
    """
    Pylint widget
    """
    DATAPATH = get_conf_path('.pylint.results')
    VERSION = '1.0.2'
    
    def __init__(self, parent, max_entries=100):
        QWidget.__init__(self, parent)
        
        self.output = None
        self.error_output = None
        
        self.max_entries = max_entries
        self.data = [self.VERSION]
        if osp.isfile(self.DATAPATH):
            try:
                data = cPickle.load(file(self.DATAPATH))
                if data[0] == self.VERSION:
                    self.data = data
            except EOFError:
                pass

        self.filecombo = PythonModulesComboBox(self)
        if self.data:
            self.remove_obsolete_items()
            self.filecombo.addItems(self.get_filenames())
        
        self.start_button = create_toolbutton(self, get_icon('run.png'),
                                    translate('Pylint', "Analyze"),
                                    tip=translate('Pylint', "Run analysis"),
                                    triggered=self.start)
        self.stop_button = create_toolbutton(self, get_icon('terminate.png'),
                                    translate('Pylint', "Stop"),
                                    tip=translate('Pylint',
                                                  "Stop current analysis"))
        self.connect(self.filecombo, SIGNAL('valid(bool)'),
                     self.start_button.setEnabled)
        self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)

        browse_button = create_toolbutton(self, get_icon('fileopen.png'),
                               tip=translate('Pylint', 'Select Python script'),
                               triggered=self.select_file)

        self.ratelabel = QLabel()
        self.datelabel = QLabel()
        self.log_button = create_toolbutton(self, get_icon('log.png'),
                                    translate('Pylint', "Output"),
                                    tip=translate('Pylint',
                                                  "Complete Pylint output"),
                                    triggered=self.show_log)
        self.treewidget = ResultsTree(self)
        
        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.filecombo)
        hlayout1.addWidget(browse_button)
        hlayout1.addWidget(self.start_button)
        hlayout1.addWidget(self.stop_button)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self.ratelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.datelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.log_button)
        
        layout = QVBoxLayout()
        layout.addLayout(hlayout1)
        layout.addLayout(hlayout2)
        layout.addWidget(self.treewidget)
        self.setLayout(layout)
        
        self.process = None
        self.set_running_state(False)
        
        if not is_pylint_installed():
            for widget in (self.treewidget, self.filecombo,
                           self.start_button, self.stop_button):
                widget.setDisabled(True)
            text = translate('Pylint', 'Please install <b>pylint</b>:')
            url = 'http://www.logilab.fr'
            text += ' <a href=%s>%s</a>' % (url, url)
            self.ratelabel.setText(text)
        else:
            self.show_data()
        
    def analyze(self, filename):
        if not is_pylint_installed():
            return
        filename = unicode(filename) # filename is a QString instance
        self.kill_if_running()
        index, _data = self.get_data(filename)
        if index is None:
            self.filecombo.addItem(filename)
            self.filecombo.setCurrentIndex(self.filecombo.count()-1)
        else:
            self.filecombo.setCurrentIndex(index)
        self.filecombo.selected()
        if self.filecombo.is_valid():
            self.start()
            
    def select_file(self):
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        filename = QFileDialog.getOpenFileName(self,
                      translate('Pylint', "Select Python script"), os.getcwdu(),
                      translate('Pylint', "Python scripts")+" (*.py ; *.pyw)")
        self.emit(SIGNAL('redirect_stdio(bool)'), False)
        if filename:
            self.analyze(filename)
            
    def remove_obsolete_items(self):
        """Removing obsolete items"""
        self.data = [self.VERSION] + \
                    [(filename, data) for filename, data in self.data[1:]
                     if is_module_or_package(filename)]
        
    def get_filenames(self):
        return [filename for filename, _data in self.data[1:]]
    
    def get_data(self, filename):
        filename = osp.abspath(filename)
        for index, (fname, data) in enumerate(self.data[1:]):
            if fname == filename:
                return index, data
        else:
            return None, None
            
    def set_data(self, filename, data):
        filename = osp.abspath(filename)
        index, _data = self.get_data(filename)
        if index is not None:
            self.data.pop(index)
        self.data.append( (filename, data) )
        self.save()
        
    def set_max_entries(self, max_entries):
        self.max_entries = max_entries
        self.save()
        
    def save(self):
        while len(self.data) > self.max_entries+1:
            self.data.pop(1)
        cPickle.dump(self.data, file(self.DATAPATH, 'w'))
        
    def show_log(self):
        if self.output:
            TextEditor(self.output, title=translate('Pylint', "Pylint output"),
                       readonly=True, size=(700, 500)).exec_()
        
    def start(self):
        filename = unicode(self.filecombo.currentText())
        
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.SeparateChannels)
        self.process.setWorkingDirectory(osp.dirname(filename))
        self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
                     self.read_output)
        self.connect(self.process, SIGNAL("readyReadStandardError()"),
                     lambda: self.read_output(error=True))
        self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"),
                     self.finished)
        self.connect(self.stop_button, SIGNAL("clicked()"),
                     self.process.kill)
        
        self.output = ''
        self.error_output = ''
        p_args = [osp.basename(filename)]
        self.process.start(PYLINT_PATH, p_args)
        
        running = self.process.waitForStarted()
        self.set_running_state(running)
        if not running:
            QMessageBox.critical(self, translate('Pylint', "Error"),
                                 translate('Pylint', "Process failed to start"))
    
    def set_running_state(self, state=True):
        self.start_button.setEnabled(not state)
        self.stop_button.setEnabled(state)
        
    def read_output(self, error=False):
        if error:
            self.process.setReadChannel(QProcess.StandardError)
        else:
            self.process.setReadChannel(QProcess.StandardOutput)
        bytes = QByteArray()
        while self.process.bytesAvailable():
            if error:
                bytes += self.process.readAllStandardError()
            else:
                bytes += self.process.readAllStandardOutput()
        text = unicode( QString.fromLocal8Bit(bytes.data()) )
        if error:
            self.error_output += text
        else:
            self.output += text
        
    def finished(self):
        self.set_running_state(False)
        if not self.output:
            return
        
        # Convention, Refactor, Warning, Error
        results = {'C:': [], 'R:': [], 'W:': [], 'E:': []}
        txt_module = '************* Module '
        
        module = '' # Should not be needed - just in case something goes wrong
        for line in self.output.splitlines():
            if line.startswith(txt_module):
                # New module
                module = line[len(txt_module):]
                continue
            for prefix in results:
                if line.startswith(prefix):
                    break
            else:
                continue
            i1 = line.find(':')
            if i1 == -1:
                continue
            i2 = line.find(':', i1+1)
            if i2 == -1:
                continue
            line_nb = line[i1+1:i2].strip()
            if not line_nb:
                continue
            line_nb = int(line_nb)
            message = line[i2+1:]
            item = (module, line_nb, message)
            results[line[:i1+1]].append(item)                
            
        # Rate
        rate = None
        txt_rate = 'Your code has been rated at '
        i_rate = self.output.find(txt_rate)
        if i_rate > 0:
            i_rate_end = self.output.find('/10', i_rate)
            if i_rate_end > 0:
                rate = self.output[i_rate+len(txt_rate):i_rate_end]
        
        # Previous run
        previous = ''
        if rate is not None:
            txt_prun = 'previous run: '
            i_prun = self.output.find(txt_prun, i_rate_end)
            if i_prun > 0:
                i_prun_end = self.output.find('/10', i_prun)
                previous = self.output[i_prun+len(txt_prun):i_prun_end]
            
        
        filename = unicode(self.filecombo.currentText())
        self.set_data(filename, (time.localtime(), rate, previous, results))
        self.output = self.error_output + self.output
        self.show_data(justanalyzed=True)
        
    def kill_if_running(self):
        if self.process is not None:
            if self.process.state() == QProcess.Running:
                self.process.kill()
                self.process.waitForFinished()
        
    def show_data(self, justanalyzed=False):
        if not justanalyzed:
            self.output = None
        self.log_button.setEnabled(self.output is not None \
                                   and len(self.output) > 0)
        self.kill_if_running()
        filename = unicode(self.filecombo.currentText())
        if not filename:
            return
        
        _index, data = self.get_data(filename)
        if data is None:
            text = translate('Pylint', 'Source code has not been rated yet.')
            self.treewidget.clear()
            date_text = ''
        else:
            datetime, rate, previous_rate, results = data
            if rate is None:
                text = translate('Pylint', 'Analysis did not succeed '
                                           '(see output for more details).')
                self.treewidget.clear()
                date_text = ''
            else:
                text_style = "<span style=\'color: #444444\'><b>%s </b></span>"
                rate_style = "<span style=\'color: %s\'><b>%s</b></span>"
                prevrate_style = "<span style=\'color: #666666\'>%s</span>"
                color = "#FF0000"
                if float(rate) > 5.:
                    color = "#22AA22"
                elif float(rate) > 3.:
                    color = "#EE5500"
                text = translate('Pylint', 'Global evaluation:')
                text = (text_style % text)+(rate_style % (color,
                                                          ('%s/10' % rate)))
                if previous_rate:
                    text_prun = translate('Pylint', 'previous run:')
                    text_prun = ' (%s %s/10)' % (text_prun, previous_rate)
                    text += prevrate_style % text_prun
                self.treewidget.set_results(filename, results)
                date_text = text_style % time.strftime("%d %b %Y %H:%M",
                                                       datetime)
            
        self.ratelabel.setText(text)
        self.datelabel.setText(date_text)
コード例 #31
0
class TerreImageProcess():

    def __init__(self):
        self.process = QProcess()
        self.process.error[QProcess.ProcessError].connect(self.error_management)
        self.env = QProcessEnvironment().systemEnvironment()
        self.set_otb_process_env_default()
        self.command = ""

    def run_process(self, command):
        logger.info(u"Running {}".format(command))
        self.process.setProcessEnvironment(self.env)

        # logger.debug("..............{}".format(self.process.processEnvironment().value("OTB_APPLICATION_PATH")))
        # logger.debug("..............{}".format(self.process.processEnvironment().value("PATH")))
        # logger.debug("Environ : PATH {}".format(os.environ["PATH"]))
        # logger.debug("Environ : OTB_APPLICATION_PATH {}".format(os.environ.get("OTB_APPLICATION_PATH", "Empty")))
        self.command = command
        self.process.start(command)
        if self.process.waitForStarted():
            self.process.waitForFinished(-1)
            exit_code = self.process.exitCode()
            if exit_code != 0:
                self.error_management(exit_code)
            result = self.process.readAllStandardOutput()
            # logger.debug(" {} {}".format(type(result), result))
            error = self.process.readAllStandardError().data()
            # logger.debug(repr(error))
            if not error in ["\n", ""]:
                logger.error("error : %s"%(error))
            output = result.data()
            logger.info(output)
            return result
        else:
            code_d_erreur = self.process.error()
            self.error_management(code_d_erreur)
        return None

    def error_management(self, errorCode):
        dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed",
            2:"QProcess::TimedOut", 3:"QProcess::WriteError",
            4:"QProcess::ReadError", 5:"QProcess::UnknownError",
            127:"Other, The application may not have been found"}
        try:
            type_qt_error = dic_err[errorCode]
            logger.error(u"Error {} {}".format(errorCode, type_qt_error))
        except KeyError:
            type_qt_error = ""
        error = self.process.readAllStandardError().data()
        logger.error(error)
        logger.error( self.process.readAllStandardOutput())
        try:
            raise terre_image_exceptions.TerreImageRunProcessError(u"Error running : {}\n {}{}".format(self.command,
                                                                                  type_qt_error, error
                                                                                  ))
        except UnicodeError:
            raise terre_image_exceptions.TerreImageRunProcessError(u"Error running : {}\n {}".format(self.command,
                                                                                  type_qt_error))

    def set_env_var(self, varname, varval, append = False, pre = False):

        if append == True:
            if pre == False:
                # insert value at the end of the variable
                self.env.insert(varname, self.env.value(varname) + os.pathsep + varval)
            else:
                # insert value in head
                self.env.insert(varname, varval + os.pathsep + self.env.value(varname))
        else:
            # replace value if existing
            self.env.insert(varname, varval)
        # logger.debug("env {} {}".format(varname, self.env.value(varname)))

    def set_otb_process_env(self):
        dirname = os.path.dirname(os.path.abspath(__file__))
        self.set_env_var("OTB_APPLICATION_PATH", os.path.join(dirname, "win32", "plugin"), pre=True)
        self.set_env_var("PATH", os.path.join(dirname, "win32", "bin"), append = False, pre=True)


    def set_otb_process_env_custom(self, otb_app_path="", path=""):
        """
        Add the given values to OTB_APPLICATION_PATH and PATH environement variables
        Args:
            otb_app_path:
            path:

        Returns:

        """
        self.set_env_var("OTB_APPLICATION_PATH", otb_app_path, pre=True)
        self.set_env_var("PATH", path, append = False, pre=True)


    def set_otb_process_env_default(self):
        """
        Add the values from the config file to OTB_APPLICATION_PATH and PATH environement variables
        Args:
            otb_app_path:
            path:

        Returns:

        """
        self.set_env_var("OTB_APPLICATION_PATH",
                         terre_image_configuration.OTB_APPLICATION_PATH, pre=True)
        self.set_env_var("PATH", terre_image_configuration.PATH, append = True, pre=True)
        if terre_image_configuration.LD_LIBRARY_PATH:
            self.set_env_var("LD_LIBRARY_PATH", terre_image_configuration.LD_LIBRARY_PATH, append = True, pre=True)
コード例 #32
0
class Main(plugin.Plugin):
    ' main class for plugin '
    def initialize(self, *args, **kwargs):
        ' class init '
        super(Main, self).initialize(*args, **kwargs)
        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self.process.readyReadStandardError.connect(self.readErrors)
        self.process.finished.connect(self._process_finished)
        self.process.error.connect(self._process_finished)
        # directory auto completer
        self.completer, self.dirs = QCompleter(self), QDirModel(self)
        self.dirs.setFilter(QDir.Dirs | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        # menu
        menu = QMenu('VirtualEnv')
        menu.addAction('Make VirtualEnv here', lambda: self.make_virtualenv())
        self.locator.get_service('explorer').add_project_menu(menu, lang='all')

        self.group1 = QGroupBox()
        self.group1.setTitle(' Paths ')
        self.outdir = QLineEdit(path.expanduser("~"))
        self.outdir.setPlaceholderText('Target Directory for Virtualenv files')
        self.outdir.setCompleter(self.completer)
        self.btn1 = QPushButton(QIcon.fromTheme("document-open"), ' Open ')
        self.btn1.clicked.connect(lambda: self.outdir.setText(str(
            QFileDialog.getExistingDirectory(self.dock,
            'Please, Open a Target Directory for the Python VirtualEnv...',
            path.expanduser("~")))))
        self.srcdir, self.prefx = QLineEdit(), QLineEdit()
        self.srcdir.setPlaceholderText(
                    'Extra search path to look for setuptools/distribute/pip')
        self.srcdir.setToolTip('''
        Specify Extra search path to look for setuptools/distribute/pip.
        Defaults to Empty, then the setting is ignored.Defaults are OK.''')
        self.srcdir.setCompleter(self.completer)
        self.btn2 = QPushButton(QIcon.fromTheme("document-open"), ' Open ')
        self.btn2.setToolTip(
            'Specify Extra search path to look for setuptools/distribute/pip')
        self.btn2.clicked.connect(lambda: self.srcdir.setText(str(
            QFileDialog.getExistingDirectory(self.dock,
            'Please, Open a Extra search path to look for setuptools/pip...',
            path.expanduser("~")))))
        self.prefx.setPlaceholderText('Prompt prefix for this environment')
        self.prefx.setToolTip('''
        Specify a custom alternative prompt prefix for this environment.
        Defaults to Empty,this is optional,short prefix are recommended.''')
        self.btn3 = QPushButton(QIcon.fromTheme("face-smile-big"), 'Suggestion')
        self.btn3.setToolTip('Suggest me a Random CLI prompt prefix !')
        self.btn3.clicked.connect(lambda: self.prefx.setText(choice((getuser(),
        'tesla', 'einstein', 'turing', 'ritchie', 'darwin', 'curie', 'planck',
        'lovelace', 'dijsktra', 'galileo', 'schroedinger', 'perlman', 'hopper',
        'newton', 'pasteur', 'maxwell', 'aristotle‎', 'volta', 'mendelev',
        'bohr', 'crick', 'watson', 'archimedes', 'nash', 'fermi', 'dirac',
        'feynman', 'kepler', 'copernicus', 'lorentz', 'faraday', 'heisenberg',
        ))))
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (
            QLabel(' Target directory dath: '), self.outdir, self.btn1,
            QLabel(' Extra search path: '), self.srcdir, self.btn2,
            QLabel(' CLI Prompt prefix (Optional): '), self.prefx, self.btn3):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle(' Options ')
        self.group2.setCheckable(True)
        self.group2.setGraphicsEffect(QGraphicsBlurEffect(self))
        self.group2.graphicsEffect().setEnabled(False)
        self.group2.toggled.connect(self.toggle_options_group)
        self.qckb1, self.combo1 = QCheckBox(' Use Debug'), QDoubleSpinBox()
        self.qckb2 = QCheckBox(' Clear out the target directory')
        self.qckb3 = QCheckBox(' System-wide Python Packages')
        self.qckb4 = QCheckBox(' Unzip Setuptool or Distribute to virtualenv')
        self.qckb5 = QCheckBox(' Force the use of SetupTools')
        self.qckb6 = QCheckBox(' Never download packages')
        self.qckb7 = QCheckBox(' Delete .PYC files from virtualenv')
        self.qckb8 = QCheckBox(' Open target directory later')
        self.qckb9 = QCheckBox(' Save a LOG file to target later')
        self.qckb10 = QCheckBox(' No install PIP in the new virtualenv')
        self.qckb11 = QCheckBox('Save Bash script to reproduce virtenv later')
        self.chrt = QCheckBox('LOW CPU priority for Backend Process')
        self.combo1.setValue(2.7)
        self.combo1.setMaximum(3.4)
        self.combo1.setMinimum(2.4)
        self.combo1.setDecimals(1)
        self.combo1.setSingleStep(0.1)
        try:
            self.vinfo = QLabel('<small><b> Virtualenv Version: </b>' +
                            getoutput('virtualenv --version', shell=1).strip())
        except:
            self.vinfo = QLabel('Warning: Failed to query Virtualenv Backend!')
        [a.setChecked(True) for a in (self.qckb1, self.qckb4, self.qckb7,
                                self.chrt, self.qckb8, self.qckb9, self.qckb11)]
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (self.qckb1, self.qckb2, self.qckb3, self.qckb4,
            self.qckb5, self.qckb6, self.qckb7, self.qckb8, self.qckb9,
            self.qckb10, self.qckb11, QLabel(' Python interpreter version: '),
            self.combo1, QLabel(' Backend CPU priority: '), self.chrt):
            vboxg2.addWidget(each_widget)

        self.button = QPushButton(' Make Virtualenv ')
        self.button.setCursor(QCursor(Qt.PointingHandCursor))
        self.button.setMinimumSize(75, 50)
        self.button.clicked.connect(self.run)
        glow = QGraphicsDropShadowEffect(self)
        glow.setOffset(0)
        glow.setBlurRadius(99)
        glow.setColor(QColor(99, 255, 255))
        self.button.setGraphicsEffect(glow)
        self.output = QTextEdit(''' " Let the future tell the truth,
        and evaluate each one according to his work and accomplishments.
        The present is theirs; the future, for which I really worked, is mine. "
        -Nikola Tesla. ''')

        class TransientWidget(QWidget):
            ' persistant widget thingy '
            def __init__(self, widget_list):
                ' init sub class '
                super(TransientWidget, self).__init__()
                vbox = QVBoxLayout(self)
                for each_widget in widget_list:
                    vbox.addWidget(each_widget)

        tw = TransientWidget((self.group1, self.group2, QLabel('Backend Logs'),
                              self.output, self.vinfo, self.button))
        self.scrollable, self.dock = QScrollArea(), QDockWidget()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(tw)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)
        ExplorerContainer().addTab(self.dock, "Virtualenv")
        QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock
            ).clicked.connect(lambda:
            QMessageBox.information(self.dock, __doc__, HELPMSG))

    def readOutput(self):
        """Read and append sphinx-build output to the logBrowser"""
        self.output.append(str(self.process.readAllStandardOutput()).strip())

    def readErrors(self):
        """Read and append sphinx-build errors to the logBrowser"""
        self.output.append(self.formatErrorMsg(str(
                                        self.process.readAllStandardError())))

    def formatErrorMsg(self, msg):
        """Format error messages in red color"""
        return self.formatMsg(msg, 'red')

    def formatInfoMsg(self, msg):
        """Format informative messages in blue color"""
        return self.formatMsg(msg, 'green')

    def formatMsg(self, msg, color):
        """Format message with the given color"""
        return '<font color="{}">{}</font>'.format(color, msg)

    def make_virtualenv(self):
        ' make virtualenv from contextual sub menu '
        self.outdir.setText(self.ex_locator.get_current_project_item().path)
        self.run()

    def run(self):
        ' run the actions '
        self.output.clear()
        self.output.append(self.formatInfoMsg(
                            'INFO: OK: Starting at {}'.format(datetime.now())))
        self.button.setDisabled(True)
        # Parse Values
        arg0 = '' if self.qckb10.isChecked() is False else '--no-pip '
        arg1 = '--quiet ' if self.qckb1.isChecked() is False else '--verbose '
        arg2 = '' if self.qckb2.isChecked() is False else '--clear '
        arg3 = '' if self.qckb3.isChecked() is False else '--system-site-packages '
        arg4 = '' if self.qckb4.isChecked() is False else '--unzip-setuptools '
        arg5 = '' if self.qckb5.isChecked() is False else '--setuptools '
        arg6 = '' if self.qckb6.isChecked() is False else '--never-download '
        # if the target is empty return
        if not len(str(self.outdir.text()).strip()):
            self.output.append(self.formatErrorMsg('ERROR: FAIL: Target empty'))
            self.button.setEnabled(True)
            return
        else:
            self.output.append(self.formatInfoMsg(
            'INFO: OK: Output Directory is {}'.format(self.outdir.text())))
        # prefix
        prf = str(self.prefx.text()).upper().strip().replace(' ', '')
        arg10 = '' if prf is '' else '--prompt="{}_" '.format(prf)
        self.output.append(self.formatInfoMsg('INFO: Prefix: {}'.format(arg10)))
        # extra search dir
        src = str(self.srcdir.text()).strip()
        arg11 = '' if src is '' else '--extra-search-dir="{}" '.format(src)
        self.output.append(self.formatInfoMsg(' INFO: Extra: {}'.format(arg11)))
        self.output.append(self.formatInfoMsg(
            ' INFO: OK: Write Logs ?: {} '.format(self.qckb9.isChecked())))
        self.output.append(self.formatInfoMsg(
            ' INFO: OK: Open Directory ?: {} '.format(self.qckb8.isChecked())))
        # run the subprocesses
        cmd = '{}virtualenv {}{}{}{}{}{}{}-p python{} {}{} {}'.format(
            'chrt --verbose -i 0 ' if self.chrt.isChecked() is True else '',
            arg0, arg1, arg2, arg3, arg4, arg5, arg6,
            self.combo1.value(), arg11, arg10, str(self.outdir.text()).strip())
        self.output.append(self.formatInfoMsg('INFO:OK:Command:{}'.format(cmd)))
        self.process.start(cmd)
        if not self.process.waitForStarted():
            self.output.append(self.formatErrorMsg(' ERROR: FAIL: Meh. '))
            self.output.append(self.formatErrorMsg(
                'ERROR: FAIL: Failed with Arguments: {} '.format(cmd)))
            self.button.setEnabled(True)
            return
         # write a .sh bash script file on target
        if self.qckb11.isChecked() is True:
            sh_file = 'create_virtualenv.sh'
            with open(path.join(str(self.outdir.text()), sh_file), 'w') as _sh:
                self.output.append(self.formatInfoMsg('''INFO: OK: Writing Bash:
                    {}'''.format(path.join(str(self.outdir.text()), sh_file))))
                _sh.write('#!/usr/bin/env bash' + linesep + cmd)
                _sh.close()
            self.output.append(self.formatInfoMsg('INFO: OK: Bash chmod: 775'))
            try:
                chmod(path.join(str(self.outdir.text()), sh_file), 0775)  # Py2
            except:
                chmod(path.join(str(self.outdir.text()), sh_file), 0o775)  # Py3
        self.readOutput()
        self.readErrors()
        self.button.setEnabled(True)

    def _process_finished(self):
        """ finished sucessfully """
        self.output.append(self.formatInfoMsg(
                            'INFO: OK: Finished at {}'.format(datetime.now())))
        # remove all *.PYC bytecode
        if self.qckb7.isChecked() is True:
            self.output.append(self.formatInfoMsg(' INFO: OK: Removing *.PYC '))
            self.output.append(self.formatInfoMsg(' INFO: This takes a moment'))
            [remove(path.join(root, f)) for root, f in list(itertools.chain(*
            [list(itertools.product([root], files))
            for root, dirs, files in walk(str(self.outdir.text()).strip())]))
            if f.endswith(('.pyc', '.PYC')) and not f.startswith('.')]
        # write a .log file on target
        if self.qckb9.isChecked() is True:
            log_file = 'virtualenv_gui.log'
            with open(path.join(str(self.outdir.text()), log_file), 'w') as log:
                self.output.append(self.formatInfoMsg('''INFO: OK: Writing Logs:
                    {}'''.format(path.join(str(self.outdir.text()), log_file))))
                log.write(self.output.toPlainText())
                log.close()
        # open target dir
        if self.qckb8.isChecked() is True:
            try:
                startfile(str(self.outdir.text()))
            except:
                Popen(["xdg-open", str(self.outdir.text())])
        self.output.selectAll()
        self.output.setFocus()

    def toggle_options_group(self):
        ' toggle on off the options group '
        if self.group2.isChecked() is True:
            [a.setChecked(True) for a in (self.qckb1, self.qckb4, self.qckb7,
                                self.chrt, self.qckb8, self.qckb9, self.qckb11)]
            self.combo1.setValue(2.7)
            self.group2.graphicsEffect().setEnabled(False)
        else:
            [a.setChecked(False) for a in (self.qckb1, self.qckb4, self.qckb7,
                                self.chrt, self.qckb8, self.qckb9, self.qckb11)]
            self.group2.graphicsEffect().setEnabled(True)

    def finish(self):
        ' clear when finish '
        self.process.kill()
コード例 #33
0
class MyMainWindow(QMainWindow):
    ' Main Window '
    def __init__(self, AUTO):
        ' Initialize QWidget inside MyMainWindow '
        super(MyMainWindow, self).__init__()
        QWidget.__init__(self)
        self.auto = AUTO
        self.statusBar().showMessage('               {}'.format(__doc__))
        self.setStyleSheet('QStatusBar{color:grey;}')
        self.setWindowTitle(__doc__)
        self.setWindowIcon(QIcon.fromTheme("face-monkey"))
        self.setFont(QFont('Ubuntu Light', 10))
        self.setMaximumSize(QDesktopWidget().screenGeometry().width(),
                            QDesktopWidget().screenGeometry().height())

        self.base = path.abspath(path.join(getcwd(), str(datetime.now().year)))

        # directory auto completer
        self.completer = QCompleter(self)
        self.dirs = QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        # process
        self.process1 = None
        self.process2 = None
        self.cmd1 = 'nice -n {n} arecord{v} -f {f} -c {c} -r {b} -t raw'
        self.cmd2 = 'oggenc - -r -C {c} -R {b} -q {q} {d}{t}{a} -o {o}'
        self.process3 = QProcess(self)
        #self.process3.finished.connect(self.on_process3_finished)
        #self.process3.error.connect(self.on_process3_error)

        self.cmd3 = ('nice -n 20 ' +
          'sox "{o}" -n spectrogram -x {x} -y {y} -z 99 -t "{o}" -o "{o}.png"')
        self.actual_file = ''

        # re starting timers, one stops, one starts
        self.timerFirst = QTimer(self)
        self.timerFirst.timeout.connect(self.end)
        self.timerSecond = QTimer(self)
        self.timerSecond.timeout.connect(self.run)

        # Proxy support, by reading http_proxy os env variable
        proxy_url = QUrl(environ.get('http_proxy', ''))
        QNetworkProxy.setApplicationProxy(QNetworkProxy(QNetworkProxy.HttpProxy
            if str(proxy_url.scheme()).startswith('http')
            else QNetworkProxy.Socks5Proxy, proxy_url.host(), proxy_url.port(),
                 proxy_url.userName(), proxy_url.password())) \
            if 'http_proxy' in environ else None
        print((' INFO: Proxy Auto-Config as ' + str(proxy_url)))

        # basic widgets layouts and set up
        self.mainwidget = QTabWidget()
        self.mainwidget.setToolTip(__doc__)
        self.mainwidget.setMovable(True)
        self.mainwidget.setTabShape(QTabWidget.Triangular)
        self.mainwidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.mainwidget.setStyleSheet('QTabBar{color:white;font-weight:bold;}')
        self.mainwidget.setTabBar(TabBar(self))
        self.mainwidget.setTabsClosable(False)
        self.setCentralWidget(self.mainwidget)
        self.dock1 = QDockWidget()
        self.dock2 = QDockWidget()
        self.dock3 = QDockWidget()
        self.dock4 = QDockWidget()
        self.dock5 = QDockWidget()
        for a in (self.dock1, self.dock2, self.dock3, self.dock4, self.dock5):
            a.setWindowModality(Qt.NonModal)
            # a.setWindowOpacity(0.9)
            a.setWindowTitle(__doc__
                             if a.windowTitle() == '' else a.windowTitle())
            a.setStyleSheet('QDockWidget::title{text-align:center;}')
            self.mainwidget.addTab(a, QIcon.fromTheme("face-smile"),
                                   'Double Click Me')

        # Paleta de colores para pintar transparente
        self.palette().setBrush(QPalette.Base, Qt.transparent)
        self.setPalette(self.palette())
        self.setAttribute(Qt.WA_OpaquePaintEvent, False)

        # toolbar and basic actions
        self.toolbar = QToolBar(self)
        self.toolbar.setIconSize(QSize(24, 24))
        # spacer widget for left
        self.left_spacer = QWidget(self)
        self.left_spacer.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)
        # spacer widget for right
        self.right_spacer = QWidget(self)
        self.right_spacer.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Expanding)
        qaqq = QAction(QIcon.fromTheme("application-exit"), 'Quit', self)
        qaqq.setShortcut('Ctrl+Q')
        qaqq.triggered.connect(exit)
        qamin = QAction(QIcon.fromTheme("go-down"), 'Minimize', self)
        qamin.triggered.connect(lambda: self.showMinimized())
        qamax = QAction(QIcon.fromTheme("go-up"), 'Maximize', self)
        qanor = QAction(QIcon.fromTheme("view-fullscreen"),
                        'AutoCenter AutoResize', self)
        qanor.triggered.connect(self.center)
        qatim = QAction(QIcon.fromTheme("mail-signed-verified"),
                        'View Date and Time', self)
        qatim.triggered.connect(self.timedate)
        qabug = QAction(QIcon.fromTheme("help-about"), 'Report a Problem', self)
        qabug.triggered.connect(lambda: qabug.setDisabled(True) if not call(
            'xdg-open mailto:' + '*****@*****.**'.decode('rot13'),
            shell=True) else ' ERROR ')
        qamax.triggered.connect(lambda: self.showMaximized())
        qaqt = QAction(QIcon.fromTheme("help-about"), 'About Qt', self)
        qaqt.triggered.connect(lambda: QMessageBox.aboutQt(self))
        qakde = QAction(QIcon.fromTheme("help-about"), 'About KDE', self)
        if KDE:
            qakde.triggered.connect(KHelpMenu(self, "", False).aboutKDE)
        qaslf = QAction(QIcon.fromTheme("help-about"), 'About Self', self)
        if KDE:
            qaslf.triggered.connect(
                                KAboutApplicationDialog(aboutData, self).exec_)
        else:
            qaslf.triggered.connect(lambda: QMessageBox.about(self.mainwidget,
            __doc__, ''.join((__doc__, linesep, 'version ', __version__, ', (',
            __license__, '), by ', __author__, ', ( ', __email__, ' )', linesep
            ))))
        qafnt = QAction(QIcon.fromTheme("tools-check-spelling"),
                        'Set GUI Font', self)
        if KDE:
            font = QFont()
            qafnt.triggered.connect(lambda:
            self.setStyleSheet(''.join((
                '*{font-family:', str(font.toString()), '}'))
                if KFontDialog.getFont(font)[0] == QDialog.Accepted else ''))
        else:
            qafnt.triggered.connect(lambda:
                self.setStyleSheet(''.join(('*{font-family:',
                            str(QFontDialog.getFont()[0].toString()), '}'))))
        qasrc = QAction(QIcon.fromTheme("applications-development"),
                        'View Source Code', self)
        qasrc.triggered.connect(lambda:
                            call('xdg-open {}'.format(__file__), shell=True))
        qakb = QAction(QIcon.fromTheme("input-keyboard"),
                       'Keyboard Shortcuts', self)
        qakb.triggered.connect(lambda: QMessageBox.information(self.mainwidget,
                               'Keyboard Shortcuts', ' Ctrl+Q = Quit '))
        qapic = QAction(QIcon.fromTheme("camera-photo"),
                        'Take a Screenshot', self)
        qapic.triggered.connect(lambda: QPixmap.grabWindow(
            QApplication.desktop().winId()).save(QFileDialog.getSaveFileName(
            self.mainwidget, " Save Screenshot As ...", path.expanduser("~"),
            ';;(*.png) PNG', 'png')))
        qatb = QAction(QIcon.fromTheme("go-top"), 'Toggle ToolBar', self)
        qatb.triggered.connect(lambda: self.toolbar.hide()
                if self.toolbar.isVisible() is True else self.toolbar.show())
        qati = QAction(QIcon.fromTheme("zoom-in"),
                       'Switch ToolBar Icon Size', self)
        qati.triggered.connect(lambda:
            self.toolbar.setIconSize(self.toolbar.iconSize() * 4)
            if self.toolbar.iconSize().width() * 4 == 24
            else self.toolbar.setIconSize(self.toolbar.iconSize() / 4))
        qasb = QAction(QIcon.fromTheme("preferences-other"),
                       'Toggle Tabs Bar', self)
        qasb.triggered.connect(lambda: self.mainwidget.tabBar().hide()
                               if self.mainwidget.tabBar().isVisible() is True
                               else self.mainwidget.tabBar().show())
        qadoc = QAction(QIcon.fromTheme("help-browser"), 'On-line Docs', self)
        qadoc.triggered.connect(lambda: open_new_tab(str(__url__).strip()))
        qapy = QAction(QIcon.fromTheme("help-about"), 'About Python', self)
        qapy.triggered.connect(lambda: open_new_tab('http://python.org/about'))
        qali = QAction(QIcon.fromTheme("help-browser"), 'Read Licence', self)
        qali.triggered.connect(lambda: open_new_tab(__full_licence__))
        qacol = QAction(QIcon.fromTheme("preferences-system"), 'Set GUI Colors',
                        self)
        if KDE:
            color = QColor()
            qacol.triggered.connect(lambda:
                self.setStyleSheet(''.join(('* { background-color: ',
                                            str(color.name()), '}')))
                if KColorDialog.getColor(color, self) else '')
        else:
            qacol.triggered.connect(lambda: self.setStyleSheet(''.join((
                ' * { background-color: ', str(QColorDialog.getColor().name()),
                ' } '))))
        qatit = QAction(QIcon.fromTheme("preferences-system"),
                        'Set the App Window Title', self)
        qatit.triggered.connect(self.seTitle)
        self.toolbar.addWidget(self.left_spacer)
        self.toolbar.addSeparator()
        self.toolbar.addActions((qaqq, qamin, qanor, qamax, qasrc, qakb, qacol,
            qatim, qatb, qafnt, qati, qasb, qatit, qapic, qadoc, qali, qaslf,
            qaqt, qakde, qapy, qabug))
        self.addToolBar(Qt.TopToolBarArea, self.toolbar)
        self.toolbar.addSeparator()
        self.toolbar.addWidget(self.right_spacer)
        # define the menu
        menu = self.menuBar()
        # File menu items
        menu.addMenu('&File').addActions((qaqq, ))
        menu.addMenu('&Window').addActions((qamax, qanor, qamin))
        # Settings menu
        menu.addMenu('&Settings').addActions((qasrc, qacol, qafnt, qatim,
                                              qatb, qati, qasb, qapic))
        # Help menu items
        menu.addMenu('&Help').addActions((qadoc, qakb, qabug, qali,
                                          qaqt, qakde, qapy, qaslf))
        # Tray Icon
        tray = QSystemTrayIcon(QIcon.fromTheme("face-devilish"), self)
        tray.setToolTip(__doc__)
        traymenu = QMenu()
        traymenu.addActions((qamax, qanor, qamin, qaqq))
        tray.setContextMenu(traymenu)
        tray.show()

        def contextMenuRequested(point):
            ' quick and dirty custom context menu '
            menu = QMenu()
            menu.addActions((qaqq, qamin, qanor, qamax, qasrc, qakb, qacol,
                qafnt, qati, qasb, qatb, qatim, qatit, qapic, qadoc, qali,
                qaslf, qaqt, qakde, qapy, qabug))
            menu.exec_(self.mapToGlobal(point))
        self.mainwidget.customContextMenuRequested.connect(contextMenuRequested)

        def must_be_checked(widget_list):
            ' widget tuple passed as argument should be checked as ON '
            for each_widget in widget_list:
                try:
                    each_widget.setChecked(True)
                except:
                    pass

        def must_have_tooltip(widget_list):
            ' widget tuple passed as argument should have tooltips '
            for each_widget in widget_list:
                try:
                    each_widget.setToolTip(each_widget.text())
                except:
                    each_widget.setToolTip(each_widget.currentText())
                finally:
                    each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        def must_autofillbackground(widget_list):
            ' widget tuple passed as argument should have filled background '
            for each_widget in widget_list:
                try:
                    each_widget.setAutoFillBackground(True)
                except:
                    pass

        def must_glow(widget_list):
            ' apply an glow effect to the widget '
            for glow, each_widget in enumerate(widget_list):
                try:
                    if each_widget.graphicsEffect() is None:
                        glow = QGraphicsDropShadowEffect(self)
                        glow.setOffset(0)
                        glow.setBlurRadius(99)
                        glow.setColor(QColor(99, 255, 255))
                        each_widget.setGraphicsEffect(glow)
                        # glow.setEnabled(False)
                        try:
                            each_widget.clicked.connect(lambda:
                            each_widget.graphicsEffect().setEnabled(True)
                            if each_widget.graphicsEffect().isEnabled() is False
                            else each_widget.graphicsEffect().setEnabled(False))
                        except:
                            each_widget.sliderPressed.connect(lambda:
                            each_widget.graphicsEffect().setEnabled(True)
                            if each_widget.graphicsEffect().isEnabled() is False
                            else each_widget.graphicsEffect().setEnabled(False))
                except:
                    pass

        #######################################################################

        # dock 1
        QLabel('<h1 style="color:white;"> Record !</h1>', self.dock1).resize(
               self.dock3.size().width() / 4, 25)
        self.group1 = QGroupBox()
        self.group1.setTitle(__doc__)

        self.spec = QPushButton(self)
        self.spec.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.spec.setMinimumSize(self.spec.size().width(), 250)
        self.spec.setFlat(True)
        self.spec.clicked.connect(self.spectro)

        self.clock = QLCDNumber()
        self.clock.setSegmentStyle(QLCDNumber.Flat)
        self.clock.setMinimumSize(self.clock.size().width(), 50)
        self.clock.setNumDigits(25)
        self.timer1 = QTimer(self)
        self.timer1.timeout.connect(lambda: self.clock.display(
            datetime.now().strftime("%d-%m-%Y %H:%M:%S %p")))
        self.timer1.start(1000)
        self.clock.setToolTip(datetime.now().strftime("%c %x"))
        self.clock.setCursor(QCursor(Qt.CrossCursor))

        self.diskBar = QProgressBar()
        self.diskBar.setMinimum(0)
        self.diskBar.setMaximum(statvfs(HOME).f_blocks *
            statvfs(HOME).f_frsize / 1024 / 1024 / 1024)
        self.diskBar.setValue(statvfs(HOME).f_bfree *
            statvfs(HOME).f_frsize / 1024 / 1024 / 1024)
        self.diskBar.setToolTip(str(statvfs(HOME).f_bfree *
            statvfs(HOME).f_frsize / 1024 / 1024 / 1024) + ' Gigabytes free')

        self.feedback = QPlainTextEdit(''.join(('<center><h3>', __doc__,
            ', version', __version__, __license__, ' <br> by ', __author__,
            ' <i>(Dev)</i>, Radio Comunitaria FM Reconquista <i>(Q.A.)</i><br>',
            'FMReconquista.org.ar & GitHub.com/JuanCarlosPaco/Cinta-Testigo')))

        self.rec = QPushButton(QIcon.fromTheme("media-record"), 'Record')
        self.rec.setMinimumSize(self.rec.size().width(), 50)
        self.rec.clicked.connect(self.go)  # self.run

        self.stop = QPushButton(QIcon.fromTheme("media-playback-stop"), 'Stop')
        self.stop.clicked.connect(self.end)

        self.kill = QPushButton(QIcon.fromTheme("process-stop"), 'Kill')
        self.kill.clicked.connect(self.killer)

        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (
            QLabel('<b style="color:white;"> Spectro'), self.spec,
            QLabel('<b style="color:white;"> Time '), self.clock,
            QLabel('<b style="color:white;"> Disk '), self.diskBar,
            QLabel('<b style="color:white;"> STDOUT + STDIN '), self.feedback,
            QLabel('<b style="color:white;"> Record '), self.rec, self.stop,
            self.kill):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle(__doc__)

        self.slider = QSlider(self)
        self.slid_l = QLabel(self.slider)
        self.slider.setCursor(QCursor(Qt.OpenHandCursor))
        self.slider.sliderPressed.connect(lambda:
                            self.slider.setCursor(QCursor(Qt.ClosedHandCursor)))
        self.slider.sliderReleased.connect(lambda:
                            self.slider.setCursor(QCursor(Qt.OpenHandCursor)))
        self.slider.valueChanged.connect(lambda:
                            self.slider.setToolTip(str(self.slider.value())))
        self.slider.valueChanged.connect(lambda: self.slid_l.setText(
                    '<h2 style="color:white;">{}'.format(self.slider.value())))
        self.slider.setMinimum(10)
        self.slider.setMaximum(99)
        self.slider.setValue(30)
        self.slider.setOrientation(Qt.Vertical)
        self.slider.setTickPosition(QSlider.TicksBothSides)
        self.slider.setTickInterval(2)
        self.slider.setSingleStep(10)
        self.slider.setPageStep(10)

        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (
            QLabel('<b style="color:white;">MINUTES of recording'), self.slider,
            QLabel('<b style="color:white;"> Default: 30 Min')):
            vboxg2.addWidget(each_widget)

        group3 = QGroupBox()
        group3.setTitle(__doc__)
        try:
            self.label2 = QLabel(getoutput('sox --version', shell=True))
            self.label4 = QLabel(getoutput('arecord --version', shell=1)[:25])
            self.label6 = QLabel(str(getoutput('oggenc --version', shell=True)))
        except:
            print(''' ERROR: No SOX, OGGenc avaliable !
                  ( sudo apt-get install vorbis-tools sox alsa-utils ) ''')
            exit()

        self.button5 = QPushButton(QIcon.fromTheme("audio-x-generic"),
                                   'OGG --> ZIP')
        self.button5.clicked.connect(lambda: make_archive(
            str(QFileDialog.getSaveFileName(self, "Save OGG to ZIP file As...",
            getcwd(), ';;(*.zip)', 'zip')).replace('.zip', ''), "zip",
            path.abspath(path.join(getcwd(), str(datetime.now().year)))))

        self.button1 = QPushButton(QIcon.fromTheme("folder-open"), 'Files')
        self.button1.clicked.connect(lambda:
                                     call('xdg-open ' + getcwd(), shell=True))

        self.button0 = QPushButton(
            QIcon.fromTheme("preferences-desktop-screensaver"), 'LCD OFF')
        self.button0.clicked.connect(lambda:
            call('sleep 3 ; xset dpms force off', shell=True))

        vboxg3 = QVBoxLayout(group3)
        for each_widget in (
            QLabel('<b style="color:white;"> OGG Output Codec '), self.label6,
            QLabel('<b style="color:white;"> Raw Record Backend '), self.label4,
            QLabel('<b style="color:white;"> Helper Libs '), self.label2,
            QLabel('<b style="color:white;"> OGG ZIP '), self.button5,
            QLabel('<b style="color:white;"> Files '), self.button1,
            QLabel('<b style="color:white;"> LCD '), self.button0):
            vboxg3.addWidget(each_widget)
        container = QWidget()
        hbox = QHBoxLayout(container)
        for each_widget in (self.group2, self.group1, group3):
            hbox.addWidget(each_widget)
        self.dock1.setWidget(container)

        # dock 2
        QLabel('<h1 style="color:white;"> Hardware !</h1>', self.dock2).resize(
               self.dock2.size().width() / 4, 25)
        try:
            audioDriverStr = {Solid.AudioInterface.Alsa: "ALSA",
                Solid.AudioInterface.OpenSoundSystem: "Open Sound",
                Solid.AudioInterface.UnknownAudioDriver: "Unknown?"}
            audioInterfaceTypeStr = {
                Solid.AudioInterface.AudioControl: "Control",
                Solid.AudioInterface.UnknownAudioInterfaceType: "Unknown?",
                Solid.AudioInterface.AudioInput: "In",
                Solid.AudioInterface.AudioOutput: "Out"}
            soundcardTypeStr = {
                Solid.AudioInterface.InternalSoundcard: "Internal",
                Solid.AudioInterface.UsbSoundcard: "USB3",
                Solid.AudioInterface.FirewireSoundcard: "FireWire",
                Solid.AudioInterface.Headset: "Headsets",
                Solid.AudioInterface.Modem: "Modem"}
            display = QTreeWidget()
            display.setAlternatingRowColors(True)
            display.setHeaderLabels(["Items", "ID", "Drivers", "I / O", "Type"])
            display.setColumnWidth(0, 350)
            display.setColumnWidth(1, 350)
            display.setColumnWidth(3, 75)
            # retrieve a list of Solid.Device for this machine
            deviceList = Solid.Device.allDevices()
            # filter the list of all devices and display matching results
            # note that we never create a Solid.AudioInterface object, but
            # receive one from the 'asDeviceInterface' call
            for device in deviceList:
                if device.isDeviceInterface(
                                         Solid.DeviceInterface.AudioInterface):
                    audio = device.asDeviceInterface(
                            Solid.DeviceInterface.AudioInterface)
                    devtype = audio.deviceType()
                    devstr = []
                    for key in audioInterfaceTypeStr:
                        flag = key & devtype
                        if flag:
                            devstr.append(audioInterfaceTypeStr[key])
                    QTreeWidgetItem(display, [device.product(), audio.name(),
                        audioDriverStr[audio.driver()], "/".join(devstr),
                        soundcardTypeStr[audio.soundcardType()]])
            self.dock2.setWidget(display)
        except:
            self.dock2.setWidget(QLabel(""" <center style='color:white;'>
            <h1>:(<br>ERROR: Please, install PyKDE !</h1><br>
            <br><i> (Sorry, can not use non-Qt Libs). Thanks </i><center>"""))

        ## dock 3
        QLabel('<h1 style="color:white;"> Previews !</h1>', self.dock3).resize(
               self.dock3.size().width() / 4, 25)
        self.fileView = QColumnView()
        self.fileView.updatePreviewWidget.connect(self.play)
        self.fileView.setToolTip(' Browse and Preview Files ')
        self.media = None
        self.model = QDirModel()
        self.fileView.setModel(self.model)
        self.dock3.setWidget(self.fileView)

        # dock4
        QLabel('<h1 style="color:white;"> Setup !</h1>', self.dock4).resize(
               self.dock4.size().width() / 4, 25)
        self.group4 = QGroupBox()
        self.group4.setTitle(__doc__)

        self.combo0 = QComboBox()
        self.combo0.addItems(['S16_LE', 'S32_LE', 'S16_BE', 'U16_LE', 'U16_BE',
          'S24_LE', 'S24_BE', 'U24_LE', 'U24_BE', 'S32_BE', 'U32_LE', 'U32_BE'])

        self.combo1 = QComboBox()
        self.combo1.addItems(['1', '-1', '0', '2', '3', '4',
                              '5', '6', '7', '8', '9', '10'])

        self.combo2 = QComboBox()
        self.combo2.addItems(['128', '256', '512', '1024', '64', '32', '16'])

        self.combo3 = QComboBox(self)
        self.combo3.addItems(['MONO', 'STEREO', 'Surround'])

        self.combo4 = QComboBox()
        self.combo4.addItems(['44100', '96000', '48000', '32000',
                              '22050', '16000', '11025', '8000'])

        self.combo5 = QComboBox(self)
        self.combo5.addItems(['20', '19', '18', '17', '16', '15', '14', '13',
            '12', '10', '9', '8', '7', '6', '5', '4', '3', '2', '1', '0'])

        self.nepochoose = QCheckBox('Auto-Tag Files using Nepomuk Semantic')

        self.chckbx0 = QCheckBox('Disable Software based Volume Control')

        self.chckbx1 = QCheckBox('Output Sound Stereo-to-Mono Downmix')

        self.chckbx2 = QCheckBox('Add Date and Time MetaData to Sound files')

        self.chckbx3 = QCheckBox('Add Yourself as the Author Artist of Sound')

        vboxg4 = QVBoxLayout(self.group4)
        for each_widget in (
            QLabel('<b style="color:white;"> Sound OGG Quality'), self.combo1,
            QLabel('<b style="color:white;"> Sound Record Format'), self.combo0,
            QLabel('<b style="color:white;"> Sound KBps '), self.combo2,
            QLabel('<b style="color:white;"> Sound Channels '), self.combo3,
            QLabel('<b style="color:white;"> Sound Sample Rate '), self.combo4,
            QLabel('<b style="color:white;"> Sound Volume'), self.chckbx0,
            QLabel('<b style="color:white;"> Sound Mix'), self.chckbx1,
            QLabel('<b style="color:white;"> Sound Meta'), self.chckbx2,
            QLabel('<b style="color:white;"> Sound Authorship'), self.chckbx3,
            QLabel('<b style="color:white;"> CPUs Priority'), self.combo5,
            QLabel('<b style="color:white;">Nepomuk Semantic User Experience'),
            self.nepochoose):
            vboxg4.addWidget(each_widget)
        self.dock4.setWidget(self.group4)

        # dock 5
        QLabel('<h1 style="color:white;"> Voice Changer ! </h1>', self.dock5
               ).resize(self.dock5.size().width() / 3, 25)
        self.group5 = QGroupBox()
        self.group5.setTitle(__doc__)

        self.dial = QDial()
        self.dial.setCursor(QCursor(Qt.OpenHandCursor))
        self.di_l = QLabel(self.dial)
        self.di_l.resize(self.dial.size() / 8)
        self.dial.sliderPressed.connect(lambda:
                            self.dial.setCursor(QCursor(Qt.ClosedHandCursor)))
        self.dial.sliderReleased.connect(lambda:
                            self.dial.setCursor(QCursor(Qt.OpenHandCursor)))
        self.dial.valueChanged.connect(lambda:
                            self.dial.setToolTip(str(self.dial.value())))
        self.dial.valueChanged.connect(lambda: self.di_l.setText(
                    '<h1 style="color:white;">{}'.format(self.dial.value())))
        self.dial.setValue(0)
        self.dial.setMinimum(-999)
        self.dial.setMaximum(999)
        self.dial.setSingleStep(100)
        self.dial.setPageStep(100)
        self.dial.setWrapping(False)
        self.dial.setNotchesVisible(True)

        self.defo = QPushButton(QIcon.fromTheme("media-playback-start"), 'Run')
        self.defo.setMinimumSize(self.defo.size().width(), 50)
        self.defo.clicked.connect(lambda: self.process3.start(
            'play -q -V0 "|rec -q -V0 -n -d -R riaa pitch {} "'
            .format(self.dial.value()) if int(self.dial.value()) != 0 else
            'play -q -V0 "|rec -q -V0 --multi-threaded -n -d -R bend {} "'
            .format(' 3,2500,3 3,-2500,3 ' * 999)))

        self.qq = QPushButton(QIcon.fromTheme("media-playback-stop"), 'Stop')
        self.qq.clicked.connect(self.process3.kill)

        self.die = QPushButton(QIcon.fromTheme("process-stop"), 'Kill')
        self.die.clicked.connect(lambda: call('killall rec', shell=True))

        vboxg5 = QVBoxLayout(self.group5)
        for each_widget in (self.dial, self.defo, self.qq, self.die):
            vboxg5.addWidget(each_widget)
        self.dock5.setWidget(self.group5)

        # configure some widget settings
        must_be_checked((self.nepochoose, self.chckbx1,
                         self.chckbx2, self.chckbx3))
        must_have_tooltip((self.label2, self.label4, self.label6, self.combo0,
            self.nepochoose, self.combo1, self.combo2, self.combo3, self.combo4,
            self.combo5, self.chckbx0, self.chckbx1, self.chckbx2, self.chckbx3,
            self.rec, self.stop, self.defo, self.qq, self.die, self.kill,
            self.button0, self.button1, self.button5))
        must_autofillbackground((self.clock, self.label2, self.label4,
            self.label6, self.nepochoose, self.chckbx0, self.chckbx1,
            self.chckbx2, self.chckbx3))
        must_glow((self.rec, self.dial, self.combo1))
        self.nepomuk_get('testigo')
        if self.auto is True:
            self.go()

    def play(self, index):
        ' play with delay '
        if not self.media:
            self.media = Phonon.MediaObject(self)
            audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self)
            Phonon.createPath(self.media, audioOutput)
        self.media.setCurrentSource(Phonon.MediaSource(
            self.model.filePath(index)))
        self.media.play()

    def end(self):
        ' kill it with fire '
        print((' INFO: Stoping Processes at {}'.format(str(datetime.now()))))
        self.process1.terminate()
        self.process2.terminate()
        self.feedback.setText('''
            <h5>Errors for RECORDER QProcess 1:</h5>{}<hr>
            <h5>Errors for ENCODER QProcess 2:</h5>{}<hr>
            <h5>Output for RECORDER QProcess 1:</h5>{}<hr>
            <h5>Output for ENCODER QProcess 2:</h5>{}<hr>
            '''.format(self.process1.readAllStandardError(),
                       self.process2.readAllStandardError(),
                       self.process1.readAllStandardOutput(),
                       self.process2.readAllStandardOutput(),
        ))

    def killer(self):
        ' kill -9 '
        QMessageBox.information(self.mainwidget, __doc__,
            ' KILL -9 was sent to the multi-process backend ! ')
        self.process1.kill()
        self.process2.kill()

    def go(self):
        ' run timeout re-starting timers '
        self.timerFirst.start(int(self.slider.value()) * 60 * 1000 + 2000)
        self.timerSecond.start(int(self.slider.value()) * 60 * 1000 + 2010)
        self.run()

    def run(self):
        ' run forest run '
        print((' INFO: Working at {}'.format(str(datetime.now()))))

        chnl = 1 if self.combo3.currentText() == 'MONO' else 2
        print((' INFO: Using {} Channels . . . '.format(chnl)))

        btrt = int(self.combo4.currentText())
        print((' INFO: Using {} Hz per Second . . . '.format(btrt)))

        threshold = int(self.dial.value())
        print((' INFO: Using Thresold of {} . . . '.format(threshold)))

        print((' INFO: Using Recording time of {}'.format(self.slider.value())))

        frmt = str(self.combo0.currentText()).strip()
        print((' INFO: Using Recording quality of {} ...'.format(frmt)))

        qlt = str(self.combo1.currentText()).strip()
        print((' INFO: Using Recording quality of {} ...'.format(qlt)))

        prio = str(self.combo5.currentText()).strip()
        print((' INFO: Using CPU Priority of {} ...'.format(prio)))

        downmix = '--downmix ' if self.chckbx1.isChecked() is True else ''
        print((' INFO: Using Downmix is {} ...'.format(downmix)))

        aut = '-a ' + getuser() if self.chckbx3.isChecked() is True else ''
        print((' INFO: The Author Artist of this sound is: {}'.format(aut)))

        T = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
        tim = '--date {} '.format(T) if self.chckbx2.isChecked() is True else ''
        print((' INFO: The Date and Time of this sound is: {}'.format(tim)))

        vol = ' --disable-softvol' if self.chckbx0.isChecked() is True else ''
        print((' INFO: Software based Volume Control is: {}'.format(vol)))

        # make base directory
        try:
            mkdir(self.base)
            print((' INFO: Base Directory path created {}'.format(self.base)))
        except OSError:
            print((' INFO: Base Directory already exist {}'.format(self.base)))
        except:
            print((' ERROR: Can not create Directory ?, {}'.format(self.base)))

        # make directory tree
        try:
            for dr in range(1, 13):
                mkdir(path.abspath(path.join(self.base, str(dr))))
                print((' INFO:Directory created {}/{}'.format(self.base, dr)))
        except OSError:
            print((' INFO: Directory already exist {}/1,12'.format(self.base)))
        except:
            print((' ERROR: Cant create Directory?, {}/1,12'.format(self.base)))

        # make new filename
        flnm = path.abspath(path.join(self.base, str(datetime.now().month),
                   datetime.now().strftime("%Y-%m-%d_%H:%M:%S.ogg")))
        self.actual_file = flnm
        print((' INFO: Recording on the file {}'.format(flnm)))

        # make custom commands
        cmd1 = self.cmd1.format(n=prio, f=frmt, c=chnl, b=btrt, v=vol)
        cmd2 = self.cmd2.format(c=chnl, b=btrt, q=qlt,
                                d=downmix, o=flnm, a=aut, t=tim)
        print((cmd1, cmd2))
        #  multiprocess recording loop pipe
        self.process1 = QProcess(self)
        self.process2 = QProcess(self)
        self.process1.setStandardOutputProcess(self.process2)
        self.process1.start(cmd1)
        if not self.process1.waitForStarted():
            print((" ERROR: RECORDER QProcess 1 Failed: \n {}   ".format(cmd1)))
        self.process2.start(cmd2)
        if not self.process2.waitForStarted():
            print((" ERROR: ENCODER QProcess 2 Failed: \n   {} ".format(cmd2)))
        self.nepomuk_set(flnm, 'testigo', 'testigo', 'AutoTag by Cinta-Testigo')

    def spectro(self):
        ' spectrometer '
        wid = self.spec.size().width()
        hei = self.spec.size().height()
        command = self.cmd3.format(o=self.actual_file, x=wid, y=hei)
        print(' INFO: Spectrometer is deleting OLD .ogg.png Files on target ')
        call('rm --verbose --force {}/*/*.ogg.png'.format(self.base), shell=1)
        print(' INFO: Spectrometer finished Deleting Files, Starting Render ')
        call(command, shell=True)
        print((''' INFO: Spectrometer finished Rendering Sound using:
               {}{}   OutPut: {}'''.format(command, linesep, self.actual_file)))
        self.spec.setIcon(QIcon('{o}.png'.format(o=self.actual_file)))
        self.spec.setIconSize(QSize(wid, hei))
        self.spec.resize(wid, hei)

    ###########################################################################

    def paintEvent(self, event):
        'Paint semi-transparent background, animated pattern, background text'
        QWidget.paintEvent(self, event)
        # make a painter
        p = QPainter(self)
        p.setRenderHint(QPainter.TextAntialiasing)
        p.setRenderHint(QPainter.HighQualityAntialiasing)
        # fill a rectangle with transparent painting
        p.fillRect(event.rect(), Qt.transparent)
        # animated random dots background pattern
        for i in range(4096):
            x = randint(9, self.size().width() - 9)
            y = randint(9, self.size().height() - 9)
            p.setPen(QPen(QColor(randint(200, 255), randint(200, 255), 255), 1))
            p.drawPoint(x, y)
        # set pen to use white color
        p.setPen(QPen(QColor(randint(9, 255), randint(9, 255), 255), 1))
        # Rotate painter 45 Degree
        p.rotate(35)
        # Set painter Font for text
        p.setFont(QFont('Ubuntu', 300))
        # draw the background text, with antialiasing
        p.drawText(99, 199, "Radio")
        # Rotate -45 the QPen back !
        p.rotate(-35)
        # set the pen to no pen
        p.setPen(Qt.NoPen)
        # Background Color
        p.setBrush(QColor(0, 0, 0))
        # Background Opacity
        p.setOpacity(0.75)
        # Background Rounded Borders
        p.drawRoundedRect(self.rect(), 50, 50)
        # finalize the painter
        p.end()

    def seTitle(self):
        ' set the title of the main window '
        dialog = QDialog(self)
        textEditInput = QLineEdit(' Type Title Here ')
        ok = QPushButton(' O K ')
        ok.clicked.connect(lambda: self.setWindowTitle(textEditInput.text()))
        ly = QVBoxLayout()
        [ly.addWidget(wdgt) for wdgt in (QLabel('Title:'), textEditInput, ok)]
        dialog.setLayout(ly)
        dialog.exec_()

    def timedate(self):
        ' get the time and date '
        dialog = QDialog(self)
        clock = QLCDNumber()
        clock.setNumDigits(24)
        timer = QTimer()
        timer.timeout.connect(lambda: clock.display(
            datetime.now().strftime("%d-%m-%Y %H:%M:%S %p")))
        timer.start(1000)
        clock.setToolTip(datetime.now().strftime("%c %x"))
        ok = QPushButton(' O K ')
        ok.clicked.connect(dialog.close)
        ly = QVBoxLayout()
        [ly.addWidget(wdgt) for wdgt in (QCalendarWidget(), clock, ok)]
        dialog.setLayout(ly)
        dialog.exec_()

    def closeEvent(self, event):
        ' Ask to Quit '
        if QMessageBox.question(self, ' Close ', ' Quit ? ',
           QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

    def center(self):
        ' Center and resize the window '
        self.showNormal()
        self.resize(QDesktopWidget().screenGeometry().width() // 1.25,
                    QDesktopWidget().screenGeometry().height() // 1.25)
        qr = self.frameGeometry()
        qr.moveCenter(QDesktopWidget().availableGeometry().center())
        self.move(qr.topLeft())

    def nepomuk_set(self, file_tag=None, __tag='', _label='', _description=''):
        ' Quick and Easy Nepomuk Taggify for Files '
        print((''' INFO: Semantic Desktop Experience is Tagging Files :
              {}, {}, {}, {})'''.format(file_tag, __tag, _label, _description)))
        if Nepomuk.ResourceManager.instance().init() is 0:
            fle = Nepomuk.Resource(KUrl(QFileInfo(file_tag).absoluteFilePath()))
            _tag = Nepomuk.Tag(__tag)
            _tag.setLabel(_label)
            fle.addTag(_tag)
            fle.setDescription(_description)
            print(([str(a.label()) for a in fle.tags()], fle.description()))
            return ([str(a.label()) for a in fle.tags()], fle.description())
        else:
            print(" ERROR: FAIL: Nepomuk is not running ! ")

    def nepomuk_get(self, query_to_search):
        ' Quick and Easy Nepomuk Query for Files '
        print((''' INFO: Semantic Desktop Experience is Quering Files :
              {} '''.format(query_to_search)))
        results = []
        nepo = Nepomuk.Query.QueryServiceClient()
        nepo.desktopQuery("hasTag:{}".format(query_to_search))

        def _query(data):
            ''' ('filename.ext', 'file description', ['list', 'of', 'tags']) '''
            results.append(([str(a.resource().genericLabel()) for a in data][0],
                            [str(a.resource().description()) for a in data][0],
            [str(a.label()) for a in iter([a.resource().tags() for a in data][0]
            )]))
        nepo.newEntries.connect(_query)

        def _end():
            '''
            [  ('filename.ext', 'file description', ['list', 'of', 'tags']),
               ('filename.ext', 'file description', ['list', 'of', 'tags']),
               ('filename.ext', 'file description', ['list', 'of', 'tags'])  ]
            '''
            nepo.newEntries.disconnect
            print(results)
            return results
        nepo.finishedListing.connect(_end)
コード例 #34
0
class Main(plugin.Plugin):
    " Main Class "

    def initialize(self, *args, **kwargs):
        " Init Main Class "
        super(Main, self).initialize(*args, **kwargs)
        self.scriptPath, self.scriptArgs = "", []
        self.profilerPath, self.tempPath = profilerPath, tempPath
        self.output = " ERROR: FAIL: No output ! "

        self.process = QProcess()
        self.process.finished.connect(self.on_process_finished)
        self.process.error.connect(self.on_process_error)

        self.tabWidget, self.stat = QTabWidget(), QWidget()
        self.tabWidget.tabCloseRequested.connect(
            lambda: self.tabWidget.setTabPosition(1) if self.tabWidget.
            tabPosition() == 0 else self.tabWidget.setTabPosition(0))
        self.tabWidget.setStyleSheet('QTabBar{font-weight:bold;}')
        self.tabWidget.setMovable(True)
        self.tabWidget.setTabsClosable(True)
        self.vboxlayout1 = QVBoxLayout(self.stat)
        self.hboxlayout1 = QHBoxLayout()
        self.filterTableLabel = QLabel("<b>Type to Search : </b>", self.stat)
        self.hboxlayout1.addWidget(self.filterTableLabel)
        self.filterTableLineEdit = QLineEdit(self.stat)
        self.filterTableLineEdit.setPlaceholderText(' Type to Search . . . ')
        self.hboxlayout1.addWidget(self.filterTableLineEdit)
        self.filterHintTableLabel = QLabel(" ? ", self.stat)
        self.hboxlayout1.addWidget(self.filterHintTableLabel)
        self.vboxlayout1.addLayout(self.hboxlayout1)
        self.tableWidget = QTableWidget(self.stat)
        self.tableWidget.setAlternatingRowColors(True)
        self.tableWidget.setColumnCount(8)
        self.tableWidget.setRowCount(2)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(2, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(3, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(4, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(5, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(6, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(7, item)
        self.tableWidget.itemDoubleClicked.connect(
            self.on_tableWidget_itemDoubleClicked)
        self.vboxlayout1.addWidget(self.tableWidget)
        self.tabWidget.addTab(self.stat, " ? ")

        self.source = QWidget()
        self.gridlayout = QGridLayout(self.source)
        self.scintillaWarningLabel = QLabel(
            "QScintilla is not installed!. Falling back to basic text edit!.",
            self.source)
        self.gridlayout.addWidget(self.scintillaWarningLabel, 1, 0, 1, 2)
        self.sourceTreeWidget = QTreeWidget(self.source)
        self.sourceTreeWidget.setAlternatingRowColors(True)
        self.sourceTreeWidget.itemActivated.connect(
            self.on_sourceTreeWidget_itemActivated)
        self.sourceTreeWidget.itemClicked.connect(
            self.on_sourceTreeWidget_itemClicked)
        self.sourceTreeWidget.itemDoubleClicked.connect(
            self.on_sourceTreeWidget_itemClicked)

        self.gridlayout.addWidget(self.sourceTreeWidget, 0, 0, 1, 1)
        self.sourceTextEdit = QTextEdit(self.source)
        self.sourceTextEdit.setReadOnly(True)
        self.gridlayout.addWidget(self.sourceTextEdit, 0, 1, 1, 1)
        self.tabWidget.addTab(self.source, " ? ")

        self.result = QWidget()
        self.vlayout = QVBoxLayout(self.result)
        self.globalStatGroupBox = QGroupBox(self.result)
        self.hboxlayout = QHBoxLayout(self.globalStatGroupBox)
        self.totalTimeLcdNumber = QLCDNumber(self.globalStatGroupBox)
        self.totalTimeLcdNumber.setSegmentStyle(QLCDNumber.Filled)
        self.totalTimeLcdNumber.setNumDigits(7)
        self.totalTimeLcdNumber.display(1000000)
        self.totalTimeLcdNumber.setFrameShape(QFrame.StyledPanel)
        self.totalTimeLcdNumber.setSizePolicy(QSizePolicy.Expanding,
                                              QSizePolicy.Expanding)
        self.hboxlayout.addWidget(self.totalTimeLcdNumber)
        self.tTimeLabel = QLabel("<b>Total Time (Sec)</b>",
                                 self.globalStatGroupBox)
        self.tTimeLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.hboxlayout.addWidget(self.tTimeLabel)
        self.numCallLcdNumber = QLCDNumber(self.globalStatGroupBox)
        self.numCallLcdNumber.setNumDigits(7)
        self.numCallLcdNumber.display(1000000)
        self.numCallLcdNumber.setSegmentStyle(QLCDNumber.Filled)
        self.numCallLcdNumber.setFrameShape(QFrame.StyledPanel)
        self.numCallLcdNumber.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Expanding)
        self.hboxlayout.addWidget(self.numCallLcdNumber)
        self.numCallLabel = QLabel("<b>Number of calls</b>",
                                   self.globalStatGroupBox)
        self.numCallLabel.setSizePolicy(QSizePolicy.Minimum,
                                        QSizePolicy.Minimum)
        self.hboxlayout.addWidget(self.numCallLabel)
        self.primCallLcdNumber = QLCDNumber(self.globalStatGroupBox)
        self.primCallLcdNumber.setSegmentStyle(QLCDNumber.Filled)
        self.primCallLcdNumber.setFrameShape(QFrame.StyledPanel)
        self.primCallLcdNumber.setNumDigits(7)
        self.primCallLcdNumber.display(1000000)
        self.primCallLcdNumber.setSizePolicy(QSizePolicy.Expanding,
                                             QSizePolicy.Expanding)
        self.hboxlayout.addWidget(self.primCallLcdNumber)
        self.primCallLabel = QLabel("<b>Primitive calls (%)</b>",
                                    self.globalStatGroupBox)
        self.primCallLabel.setSizePolicy(QSizePolicy.Minimum,
                                         QSizePolicy.Minimum)
        self.hboxlayout.addWidget(self.primCallLabel)
        self.vlayout.addWidget(self.globalStatGroupBox)
        try:
            from PyKDE4.kdeui import KRatingWidget
            self.rating = KRatingWidget(self.globalStatGroupBox)
            self.rating.setToolTip('Profiling Performance Rating')
        except ImportError:
            pass
        self.tabWidget.addTab(self.result, " Get Results ! ")

        self.resgraph = QWidget()
        self.vlayout2 = QVBoxLayout(self.result)
        self.graphz = QGroupBox(self.resgraph)
        self.hboxlayout2 = QHBoxLayout(self.graphz)
        try:
            from PyKDE4.kdeui import KLed
            KLed(self.graphz)
        except ImportError:
            pass
        self.hboxlayout2.addWidget(
            QLabel('''
            Work in Progress  :)  Not Ready Yet'''))
        self.vlayout2.addWidget(self.graphz)
        self.tabWidget.addTab(self.resgraph, " Graphs and Charts ")

        self.pathz = QWidget()
        self.vlayout3 = QVBoxLayout(self.pathz)
        self.patz = QGroupBox(self.pathz)
        self.hboxlayout3 = QVBoxLayout(self.patz)
        self.profilepath = QLineEdit(profilerPath)
        self.getprofile = QPushButton(QIcon.fromTheme("document-open"), 'Open')
        self.getprofile.setToolTip(
            'Dont touch if you dont know what are doing')
        self.getprofile.clicked.connect(lambda: self.profilepath.setText(
            str(
                QFileDialog.getOpenFileName(
                    self.patz, ' Open the profile.py file ',
                    path.expanduser("~"), ';;(profile.py)'))))
        self.hboxlayout3.addWidget(
            QLabel(
                '<center><b>Profile.py Python Library Full Path:</b></center>')
        )
        self.hboxlayout3.addWidget(self.profilepath)
        self.hboxlayout3.addWidget(self.getprofile)

        self.argGroupBox = QGroupBox(self.pathz)
        self.hbxlayout = QHBoxLayout(self.argGroupBox)
        self.argLineEdit = QLineEdit(self.argGroupBox)
        self.argLineEdit.setToolTip(
            'Not touch if you dont know what are doing')
        self.argLineEdit.setPlaceholderText(
            'Dont touch if you dont know what are doing')
        self.hbxlayout.addWidget(
            QLabel('<b>Additional Profile Arguments:</b>'))
        self.hbxlayout.addWidget(self.argLineEdit)
        self.hboxlayout3.addWidget(self.argGroupBox)

        self.vlayout3.addWidget(self.patz)
        self.tabWidget.addTab(self.pathz, " Paths and Configs ")

        self.outp = QWidget()
        self.vlayout4 = QVBoxLayout(self.outp)
        self.outgro = QGroupBox(self.outp)
        self.outgro.setTitle(" MultiProcessing Output Logs ")
        self.hboxlayout4 = QVBoxLayout(self.outgro)
        self.outputlog = QTextEdit()
        self.outputlog.setText('''
        I do not fear computers, I fear the lack of them.   -Isaac Asimov ''')
        self.hboxlayout4.addWidget(self.outputlog)
        self.vlayout4.addWidget(self.outgro)
        self.tabWidget.addTab(self.outp, " Logs ")

        self.actionNew_profiling = QAction(QIcon.fromTheme("document-new"),
                                           'New Profiling', self)
        self.actionLoad_profile = QAction(QIcon.fromTheme("document-open"),
                                          'Open Profiling', self)
        self.actionClean = QAction(QIcon.fromTheme("edit-clear"), 'Clean',
                                   self)
        self.actionClean.triggered.connect(lambda: self.clearContent)
        self.actionAbout = QAction(QIcon.fromTheme("help-about"), 'About',
                                   self)
        self.actionAbout.triggered.connect(lambda: QMessageBox.about(
            self.dock, __doc__, ', '.join(
                (__doc__, __license__, __author__, __email__))))
        self.actionSave_profile = QAction(QIcon.fromTheme("document-save"),
                                          'Save Profiling', self)
        self.actionManual = QAction(QIcon.fromTheme("help-contents"), 'Help',
                                    self)
        self.actionManual.triggered.connect(lambda: open_new_tab(
            'http://docs.python.org/library/profile.html'))

        self.tabWidget.setCurrentIndex(2)

        self.globalStatGroupBox.setTitle("Global Statistics")
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText("Number of Calls")
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText("Total Time")
        item = self.tableWidget.horizontalHeaderItem(2)
        item.setText("Per Call")
        item = self.tableWidget.horizontalHeaderItem(3)
        item.setText("Cumulative Time")
        item = self.tableWidget.horizontalHeaderItem(4)
        item.setText("Per Call")
        item = self.tableWidget.horizontalHeaderItem(5)
        item.setText("Filename")
        item = self.tableWidget.horizontalHeaderItem(6)
        item.setText("Line")
        item = self.tableWidget.horizontalHeaderItem(7)
        item.setText("Function")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.stat),
                                  "Statistics per Function")

        self.sourceTreeWidget.headerItem().setText(0, "Source files")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.source),
                                  "Sources Navigator")
        #######################################################################

        self.scrollable, self.dock = QScrollArea(), QDockWidget()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(self.tabWidget)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)
        QToolBar(self.dock).addActions(
            (self.actionNew_profiling, self.actionClean,
             self.actionSave_profile, self.actionLoad_profile,
             self.actionManual, self.actionAbout))

        self.actionNew_profiling.triggered.connect(
            self.on_actionNew_profiling_triggered)
        self.actionLoad_profile.triggered.connect(
            self.on_actionLoad_profile_triggered)
        self.actionSave_profile.triggered.connect(
            self.on_actionSave_profile_triggered)

        self.locator.get_service('misc').add_widget(
            self.dock, QIcon.fromTheme("document-open-recent"), __doc__)

        if QSCI:
            # Scintilla source editor management
            self.scintillaWarningLabel.setText(' QScintilla is Ready ! ')
            layout = self.source.layout()
            layout.removeWidget(self.sourceTextEdit)
            self.sourceTextEdit = Qsci.QsciScintilla(self.source)
            layout.addWidget(self.sourceTextEdit, 0, 1)
            doc = self.sourceTextEdit
            doc.setLexer(Qsci.QsciLexerPython(self.sourceTextEdit))
            doc.setReadOnly(True)
            doc.setEdgeMode(Qsci.QsciScintilla.EdgeLine)
            doc.setEdgeColumn(80)
            doc.setEdgeColor(QColor("#FF0000"))
            doc.setFolding(Qsci.QsciScintilla.BoxedTreeFoldStyle)
            doc.setBraceMatching(Qsci.QsciScintilla.SloppyBraceMatch)
            doc.setCaretLineVisible(True)
            doc.setMarginLineNumbers(1, True)
            doc.setMarginWidth(1, 25)
            doc.setTabWidth(4)
            doc.setEolMode(Qsci.QsciScintilla.EolUnix)
            self.marker = {}
            for color in COLORS:
                mnr = doc.markerDefine(Qsci.QsciScintilla.Background)
                doc.setMarkerBackgroundColor(color, mnr)
                self.marker[color] = mnr
        self.currentSourcePath = None

        # Connect table and tree filter edit signal to unique slot
        self.filterTableLineEdit.textEdited.connect(
            self.on_filterLineEdit_textEdited)

        # Timer to display filter hint message
        self.filterHintTimer = QTimer(self)
        self.filterHintTimer.setSingleShot(True)
        self.filterHintTimer.timeout.connect(self.on_filterHintTimer_timeout)

        # Timer to start search
        self.filterSearchTimer = QTimer(self)
        self.filterSearchTimer.setSingleShot(True)
        self.filterSearchTimer.timeout.connect(
            self.on_filterSearchTimer_timeout)

        self.tabLoaded = {}
        for i in range(10):
            self.tabLoaded[i] = False
        self.backgroundTreeMatchedItems = {}
        self.resizeWidgetToContent(self.tableWidget)

    def on_actionNew_profiling_triggered(self):
        self.clearContent()
        self.scriptPath = str(
            QFileDialog.getOpenFileName(self.dock,
                                        "Choose your script to profile",
                                        path.expanduser("~"),
                                        "Python (*.py *.pyw)"))
        commandLine = [
            self.profilerPath, "-o", self.tempPath, self.scriptPath
        ] + self.scriptArgs
        commandLine = " ".join(commandLine)
        ##if self.termCheckBox.checkState() == Qt.Checked:
        #termList = ["xterm", "aterm"]
        #for term in termList:
        #termPath = which(term)
        #if termPath:
        #break
        #commandLine = """%s -e "%s ; echo 'Press ENTER Exit' ; read" """ \
        #% (termPath, commandLine)
        self.process.start(commandLine)
        if not self.process.waitForStarted():
            print((" ERROR: {} failed!".format(commandLine)))
            return

    def on_process_finished(self, exitStatus):
        ' whan the process end '
        print((" INFO: OK: QProcess is %s" % self.process.exitCode()))
        self.output = self.process.readAll().data()
        if not self.output:
            self.output = " ERROR: FAIL: No output ! "
        self.outputlog.setText(self.output + str(self.process.exitCode()))
        if path.exists(self.tempPath):
            self.setStat(self.tempPath)
            remove(self.tempPath)
        else:
            self.outputlog.setText(" ERROR: QProcess FAIL: Profiling failed.")
        self.tabWidget.setCurrentIndex(2)

    def on_process_error(self, error):
        ' when the process fail, I hope you never see this '
        print(" ERROR: QProcess FAIL: Profiler Dead, wheres your God now ? ")
        if error == QProcess.FailedToStart:
            self.outputlog.setText(" ERROR: FAIL: Profiler execution failed ")
        elif error == QProcess.Crashed:
            self.outputlog.setText(" ERROR: FAIL: Profiler execution crashed ")
        else:
            self.outputlog.setText(" ERROR: FAIL: Profiler unknown error ")

    def on_actionLoad_profile_triggered(self):
        """Load a previous profile sessions"""
        statPath = str(
            QFileDialog.getOpenFileName(self.dock, "Open profile dump",
                                        path.expanduser("~"),
                                        "Profile file (*)"))
        if statPath:
            self.clearContent()
            print(' INFO: OK: Loading profiling from ' + statPath)
            self.setStat(statPath)

    def on_actionSave_profile_triggered(self):
        """Save a profile sessions"""
        statPath = str(
            QFileDialog.getSaveFileName(self.dock, "Save profile dump",
                                        path.expanduser("~"),
                                        "Profile file (*)"))
        if statPath:
            #TODO: handle error case and give feelback to user
            print(' INFO: OK: Saving profiling to ' + statPath)
            self.stat.save(statPath)

    #=======================================================================#
    # Common parts                                                          #
    #=======================================================================#

    def on_tabWidget_currentChanged(self, index):
        """slot for tab change"""
        # Kill search and hint timer if running to avoid cross effect
        for timer in (self.filterHintTimer, self.filterSearchTimer):
            if timer.isActive():
                timer.stop()
        if not self.stat:
            #No stat loaded, nothing to do
            return
        self.populateTable()
        self.populateSource()

    def on_filterLineEdit_textEdited(self, text):
        """slot for filter change (table or tree"""
        if self.filterSearchTimer.isActive():
            # Already runnning, stop it
            self.filterSearchTimer.stop()
        # Start timer
        self.filterSearchTimer.start(300)

    def on_filterHintTimer_timeout(self):
        """Timeout to warn user about text length"""
        print("timeout")
        tab = self.tabWidget.currentIndex()
        if tab == TAB_FUNCTIONSTAT:
            label = self.filterHintTableLabel
        label.setText("Type > 2 characters to search")

    def on_filterSearchTimer_timeout(self):
        """timeout to start search"""
        tab = self.tabWidget.currentIndex()
        if tab == TAB_FUNCTIONSTAT:
            text = self.filterTableLineEdit.text()
            label = self.filterHintTableLabel
            edit = self.filterTableLineEdit
            widget = self.tableWidget
        else:
            print("Unknow tab for filterSearch timeout !")

        print(("do search for %s" % text))
        if not len(text):
            # Empty keyword, just clean all
            if self.filterHintTimer.isActive():
                self.filterHintTimer.stop()
            label.setText(" ? ")
            self.warnUSer(True, edit)
            self.clearSearch()
            return
        if len(text) < 2:
            # Don't filter if text is too short and tell it to user
            self.filterHintTimer.start(600)
            return
        else:
            if self.filterHintTimer.isActive():
                self.filterHintTimer.stop()
            label.setText(" ? ")

        # Search
        self.clearSearch()
        matchedItems = []
        if tab == TAB_FUNCTIONSTAT:
            # Find items
            matchedItems = widget.findItems(text, Qt.MatchContains)
            widget.setSortingEnabled(False)
            matchedRows = [item.row() for item in matchedItems]
            # Hide matched items
            header = widget.verticalHeader()
            for row in range(widget.rowCount()):
                if row not in matchedRows:
                    header.hideSection(row)
            widget.setSortingEnabled(True)
        else:
            print(" Unknow tab for filterSearch timeout ! ")

        print(("got %s members" % len(matchedItems)))
        self.warnUSer(matchedItems, edit)
        self.resizeWidgetToContent(widget)

    def resizeWidgetToContent(self, widget):
        """Resize all columns according to content"""
        for i in range(widget.columnCount()):
            widget.resizeColumnToContents(i)

    def clearSearch(self):
        """Clean search result
        For table, show all items
        For tree, remove colored items"""
        tab = self.tabWidget.currentIndex()
        if tab == TAB_FUNCTIONSTAT:
            header = self.tableWidget.verticalHeader()
            if header.hiddenSectionCount():
                for i in range(header.count()):
                    if header.isSectionHidden(i):
                        header.showSection(i)

    def clearContent(self):
        # Clear tabs
        self.tableWidget.clearContents()
        self.sourceTreeWidget.clear()
        # Reset LCD numbers
        for lcdNumber in (self.totalTimeLcdNumber, self.numCallLcdNumber,
                          self.primCallLcdNumber):
            lcdNumber.display(1000000)
        # Reset stat
        self.pstat = None
        # Disable save as menu
        self.actionSave_profile.setEnabled(False)
        # Mark all tabs as unloaded
        for i in range(10):
            self.tabLoaded[i] = False

    def warnUSer(self, result, inputWidget):
        palette = inputWidget.palette()
        if result:
            palette.setColor(QPalette.Normal, QPalette.Base,
                             QColor(255, 255, 255))
        else:
            palette.setColor(QPalette.Normal, QPalette.Base,
                             QColor(255, 136, 138))
        inputWidget.setPalette(palette)
        inputWidget.update()

    def setStat(self, statPath):
        self.stat = Stat(path=statPath)
        # Global stat update
        self.totalTimeLcdNumber.display(self.stat.getTotalTime())
        self.numCallLcdNumber.display(self.stat.getCallNumber())
        self.primCallLcdNumber.display(self.stat.getPrimitiveCallRatio())
        # Refresh current tab
        self.on_tabWidget_currentChanged(self.tabWidget.currentIndex())
        # Activate save as menu
        self.actionSave_profile.setEnabled(True)
        try:
            self.rating.setMaxRating(10)
            self.rating.setRating(
                int(self.stat.getPrimitiveCallRatio()) / 10 - 1)
        except:
            pass

    #========================================================================#
    # Statistics table                                                      #
    #=======================================================================#

    def populateTable(self):
        row = 0
        rowCount = self.stat.getStatNumber()
        progress = QProgressDialog("Populating statistics table...", "Abort",
                                   0, 2 * rowCount)
        self.tableWidget.setSortingEnabled(False)
        self.tableWidget.setRowCount(rowCount)

        progress.setWindowModality(Qt.WindowModal)
        for (key, value) in self.stat.getStatItems():
            #ncalls
            item = StatTableWidgetItem(str(value[0]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_NCALLS, item)
            colorTableItem(item, self.stat.getCallNumber(), value[0])
            #total time
            item = StatTableWidgetItem(str(value[2]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_TTIME, item)
            colorTableItem(item, self.stat.getTotalTime(), value[2])
            #per call (total time)
            if value[0] != 0:
                tPerCall = str(value[2] / value[0])
                cPerCall = str(value[3] / value[0])
            else:
                tPerCall = ""
                cPerCall = ""
            item = StatTableWidgetItem(tPerCall)
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_TPERCALL, item)
            colorTableItem(
                item,
                100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(),
                tPerCall)
            #per call (cumulative time)
            item = StatTableWidgetItem(cPerCall)
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_CPERCALL, item)
            colorTableItem(
                item,
                100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(),
                cPerCall)
            #cumulative time
            item = StatTableWidgetItem(str(value[3]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_CTIME, item)
            colorTableItem(item, self.stat.getTotalTime(), value[3])
            #Filename
            self.tableWidget.setItem(row, STAT_FILENAME,
                                     StatTableWidgetItem(str(key[0])))
            #Line
            item = StatTableWidgetItem(str(key[1]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_LINE, item)
            #Function name
            self.tableWidget.setItem(row, STAT_FUNCTION,
                                     StatTableWidgetItem(str(key[2])))
            row += 1
            # Store it in stat hash array
            self.stat.setStatLink(item, key, TAB_FUNCTIONSTAT)
            progress.setValue(row)
            if progress.wasCanceled():
                return

        for i in range(self.tableWidget.rowCount()):
            progress.setValue(row + i)
            for j in range(self.tableWidget.columnCount()):
                item = self.tableWidget.item(i, j)
                if item:
                    item.setFlags(Qt.ItemIsEnabled)

        self.tableWidget.setSortingEnabled(True)
        self.resizeWidgetToContent(self.tableWidget)
        progress.setValue(2 * rowCount)

    def on_tableWidget_itemDoubleClicked(self, item):
        matchedItems = []
        filename = str(self.tableWidget.item(item.row(), STAT_FILENAME).text())
        if not filename or filename.startswith("<"):
            # No source code associated, return immediatly
            return
        function = self.tableWidget.item(item.row(), STAT_FUNCTION).text()
        line = self.tableWidget.item(item.row(), STAT_LINE).text()

        self.on_tabWidget_currentChanged(TAB_SOURCE)  # load source tab
        function = "%s (%s)" % (function, line)
        fathers = self.sourceTreeWidget.findItems(filename, Qt.MatchContains,
                                                  SOURCE_FILENAME)
        print(("find %s father" % len(fathers)))
        for father in fathers:
            findItems(father, function, SOURCE_FILENAME, matchedItems)
        print(("find %s items" % len(matchedItems)))

        if matchedItems:
            self.tabWidget.setCurrentIndex(TAB_SOURCE)
            self.sourceTreeWidget.scrollToItem(matchedItems[0])
            self.on_sourceTreeWidget_itemClicked(matchedItems[0],
                                                 SOURCE_FILENAME)
            matchedItems[0].setSelected(True)
        else:
            print("oups, item found but cannot scroll to it !")

    #=======================================================================#
    # Source explorer                                                      #
    #=====================================================================#

    def populateSource(self):
        items = {}
        for stat in self.stat.getStatKeys():
            source = stat[0]
            function = "%s (%s)" % (stat[2], stat[1])
            if source in ("", "profile") or source.startswith("<"):
                continue
            # Create the function child
            child = QTreeWidgetItem([function])
            # Store it in stat hash array
            self.stat.setStatLink(child, stat, TAB_SOURCE)
            if source in items:
                father = items[source]
            else:
                # Create the father
                father = QTreeWidgetItem([source])
                items[source] = father
            father.addChild(child)
        self.sourceTreeWidget.setSortingEnabled(False)
        for value in list(items.values()):
            self.sourceTreeWidget.addTopLevelItem(value)
        self.sourceTreeWidget.setSortingEnabled(True)

    def on_sourceTreeWidget_itemActivated(self, item, column):
        self.on_sourceTreeWidget_itemClicked(item, column)

    def on_sourceTreeWidget_itemClicked(self, item, column):
        line = 0
        parent = item.parent()
        if QSCI:
            doc = self.sourceTextEdit
        if parent:
            pathz = parent.text(column)
            result = match("(.*) \(([0-9]+)\)", item.text(column))
            if result:
                try:
                    function = str(result.group(1))
                    line = int(result.group(2))
                except ValueError:
                    # We got garbage... falling back to line 0
                    pass
        else:
            pathz = item.text(column)
        pathz = path.abspath(str(pathz))
        if self.currentSourcePath != pathz:
            # Need to load source
            self.currentSourcePath == pathz
            try:
                if QSCI:
                    doc.clear()
                    doc.insert(file(pathz).read())
                else:
                    self.sourceTextEdit.setPlainText(file(pathz).read())
            except IOError:
                QMessageBox.warning(self, "Error",
                                    "Source file could not be found",
                                    QMessageBox.Ok)
                return

            if QSCI:
                for function, line in [(i[2], i[1])
                                       for i in self.stat.getStatKeys()
                                       if i[0] == pathz]:
                    # expr, regexp, case sensitive, whole word, wrap, forward
                    doc.findFirst("def", False, True, True, False, True, line,
                                  0, True)
                    end, foo = doc.getCursorPosition()
                    time = self.stat.getStatTotalTime((pathz, line, function))
                    colorSource(doc, self.stat.getTotalTime(), time, line, end,
                                self.marker)
        if QSCI:
            doc.ensureLineVisible(line)
コード例 #35
0
ファイル: render.py プロジェクト: ViktorNova/Cadence
class RenderW(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.ui = ui_render.Ui_RenderW()
        self.ui.setupUi(self)

        self.fFreewheel = False
        self.fLastTime  = -1
        self.fMaxTime   = 180

        self.fTimer   = QTimer(self)
        self.fProcess = QProcess(self)

        # -------------------------------------------------------------
        # Get JACK client and base information

        global gJackClient

        if gJackClient:
            self.fJackClient = gJackClient
        else:
            self.fJackClient = jacklib.client_open("Render-Dialog", jacklib.JackNoStartServer, None)

        self.fBufferSize = int(jacklib.get_buffer_size(self.fJackClient))
        self.fSampleRate = int(jacklib.get_sample_rate(self.fJackClient))

        for i in range(self.ui.cb_buffer_size.count()):
            if int(self.ui.cb_buffer_size.itemText(i)) == self.fBufferSize:
                self.ui.cb_buffer_size.setCurrentIndex(i)
                break
        else:
            self.ui.cb_buffer_size.addItem(str(self.fBufferSize))
            self.ui.cb_buffer_size.setCurrentIndex(self.ui.cb_buffer_size.count() - 1)

        # -------------------------------------------------------------
        # Set-up GUI stuff

        # Get List of formats
        self.fProcess.start(gJackCapturePath, ["-pf"])
        self.fProcess.waitForFinished()

        formats     = str(self.fProcess.readAllStandardOutput(), encoding="utf-8").split(" ")
        formatsList = []

        for i in range(len(formats) - 1):
            iFormat = formats[i].strip()
            if iFormat:
                formatsList.append(iFormat)

        formatsList.sort()

        # Put all formats in combo-box, select 'wav' option
        for i in range(len(formatsList)):
            self.ui.cb_format.addItem(formatsList[i])
            if formatsList[i] == "wav":
                self.ui.cb_format.setCurrentIndex(i)

        self.ui.cb_depth.setCurrentIndex(4) #Float
        self.ui.rb_stereo.setChecked(True)

        self.ui.te_end.setTime(QTime(0, 3, 0))
        self.ui.progressBar.setFormat("")
        self.ui.progressBar.setMinimum(0)
        self.ui.progressBar.setMaximum(1)
        self.ui.progressBar.setValue(0)

        self.ui.b_render.setIcon(getIcon("media-record"))
        self.ui.b_stop.setIcon(getIcon("media-playback-stop"))
        self.ui.b_close.setIcon(getIcon("window-close"))
        self.ui.b_open.setIcon(getIcon("document-open"))
        self.ui.b_stop.setVisible(False)
        self.ui.le_folder.setText(HOME)

        # -------------------------------------------------------------
        # Set-up connections

        self.connect(self.ui.b_render, SIGNAL("clicked()"), SLOT("slot_renderStart()"))
        self.connect(self.ui.b_stop, SIGNAL("clicked()"), SLOT("slot_renderStop()"))
        self.connect(self.ui.b_open, SIGNAL("clicked()"), SLOT("slot_getAndSetPath()"))
        self.connect(self.ui.b_now_start, SIGNAL("clicked()"), SLOT("slot_setStartNow()"))
        self.connect(self.ui.b_now_end, SIGNAL("clicked()"), SLOT("slot_setEndNow()"))
        self.connect(self.ui.te_start, SIGNAL("timeChanged(const QTime)"), SLOT("slot_updateStartTime(const QTime)"))
        self.connect(self.ui.te_end, SIGNAL("timeChanged(const QTime)"), SLOT("slot_updateEndTime(const QTime)"))
        self.connect(self.ui.group_time, SIGNAL("clicked(bool)"), SLOT("slot_transportChecked(bool)"))
        self.connect(self.fTimer, SIGNAL("timeout()"), SLOT("slot_updateProgressbar()"))

        # -------------------------------------------------------------

        self.loadSettings()

    @pyqtSlot()
    def slot_renderStart(self):
        if not os.path.exists(self.ui.le_folder.text()):
            QMessageBox.warning(self, self.tr("Warning"), self.tr("The selected directory does not exist. Please choose a valid one."))
            return

        timeStart = self.ui.te_start.time()
        timeEnd   = self.ui.te_end.time()
        minTime   = (timeStart.hour() * 3600) + (timeStart.minute() * 60) + (timeStart.second())
        maxTime   = (timeEnd.hour() * 3600) + (timeEnd.minute() * 60) + (timeEnd.second())

        newBufferSize = int(self.ui.cb_buffer_size.currentText())
        useTransport  = self.ui.group_time.isChecked()

        self.fFreewheel = bool(self.ui.cb_render_mode.currentIndex() == 1)
        self.fLastTime  = -1
        self.fMaxTime   = maxTime

        if self.fFreewheel:
            self.fTimer.setInterval(100)
        else:
            self.fTimer.setInterval(500)

        self.ui.group_render.setEnabled(False)
        self.ui.group_time.setEnabled(False)
        self.ui.group_encoding.setEnabled(False)
        self.ui.b_render.setVisible(False)
        self.ui.b_stop.setVisible(True)
        self.ui.b_close.setEnabled(False)

        if useTransport:
            self.ui.progressBar.setFormat("%p%")
            self.ui.progressBar.setMinimum(minTime)
            self.ui.progressBar.setMaximum(maxTime)
            self.ui.progressBar.setValue(minTime)
        else:
            self.ui.progressBar.setFormat("")
            self.ui.progressBar.setMinimum(0)
            self.ui.progressBar.setMaximum(0)
            self.ui.progressBar.setValue(0)

        self.ui.progressBar.update()

        arguments = []

        # Filename prefix
        arguments.append("-fp")
        arguments.append(self.ui.le_prefix.text())

        # Format
        arguments.append("-f")
        arguments.append(self.ui.cb_format.currentText())

        # Bit depth
        arguments.append("-b")
        arguments.append(self.ui.cb_depth.currentText())

        # Channels
        arguments.append("-c")
        if self.ui.rb_mono.isChecked():
            arguments.append("1")
        elif self.ui.rb_stereo.isChecked():
            arguments.append("2")
        else:
            arguments.append(str(self.ui.sb_channels.value()))

        # Controlled only by freewheel
        if self.fFreewheel:
            arguments.append("-jf")

        # Controlled by transport
        elif useTransport:
            arguments.append("-jt")

        # Silent mode
        arguments.append("-dc")
        arguments.append("-s")

        # Change current directory
        os.chdir(self.ui.le_folder.text())

        if newBufferSize != int(jacklib.get_buffer_size(self.fJackClient)):
            print("NOTICE: buffer size changed before render")
            jacklib.set_buffer_size(self.fJackClient, newBufferSize)

        if useTransport:
            if jacklib.transport_query(self.fJackClient, None) > jacklib.JackTransportStopped: # rolling or starting
                jacklib.transport_stop(self.fJackClient)

            jacklib.transport_locate(self.fJackClient, minTime * self.fSampleRate)

        self.fProcess.start(gJackCapturePath, arguments)
        self.fProcess.waitForStarted()

        if self.fFreewheel:
            print("NOTICE: rendering in freewheel mode")
            sleep(1)
            jacklib.set_freewheel(self.fJackClient, 1)

        if useTransport:
            self.fTimer.start()
            jacklib.transport_start(self.fJackClient)

    @pyqtSlot()
    def slot_renderStop(self):
        useTransport = self.ui.group_time.isChecked()

        if useTransport:
            jacklib.transport_stop(self.fJackClient)

        if self.fFreewheel:
            jacklib.set_freewheel(self.fJackClient, 0)
            sleep(1)

        self.fProcess.close()

        if useTransport:
            self.fTimer.stop()

        self.ui.group_render.setEnabled(True)
        self.ui.group_time.setEnabled(True)
        self.ui.group_encoding.setEnabled(True)
        self.ui.b_render.setVisible(True)
        self.ui.b_stop.setVisible(False)
        self.ui.b_close.setEnabled(True)

        self.ui.progressBar.setFormat("")
        self.ui.progressBar.setMinimum(0)
        self.ui.progressBar.setMaximum(1)
        self.ui.progressBar.setValue(0)
        self.ui.progressBar.update()

        # Restore buffer size
        newBufferSize = int(jacklib.get_buffer_size(self.fJackClient))

        if newBufferSize != self.fBufferSize:
            jacklib.set_buffer_size(self.fJackClient, newBufferSize)

    @pyqtSlot()
    def slot_getAndSetPath(self):
        getAndSetPath(self, self.ui.le_folder.text(), self.ui.le_folder)

    @pyqtSlot()
    def slot_setStartNow(self):
        time = int(jacklib.get_current_transport_frame(self.fJackClient) / self.fSampleRate)
        secs = time % 60
        mins = int(time / 60) % 60
        hrs  = int(time / 3600) % 60
        self.ui.te_start.setTime(QTime(hrs, mins, secs))

    @pyqtSlot()
    def slot_setEndNow(self):
        time = int(jacklib.get_current_transport_frame(self.fJackClient) / self.fSampleRate)
        secs = time % 60
        mins = int(time / 60) % 60
        hrs  = int(time / 3600) % 60
        self.ui.te_end.setTime(QTime(hrs, mins, secs))

    @pyqtSlot(QTime)
    def slot_updateStartTime(self, time):
        if time >= self.ui.te_end.time():
            self.ui.te_end.setTime(time)
            renderEnabled = False
        else:
            renderEnabled = True

        if self.ui.group_time.isChecked():
            self.ui.b_render.setEnabled(renderEnabled)

    @pyqtSlot(QTime)
    def slot_updateEndTime(self, time):
        if time <= self.ui.te_start.time():
            self.ui.te_start.setTime(time)
            renderEnabled = False
        else:
            renderEnabled = True

        if self.ui.group_time.isChecked():
            self.ui.b_render.setEnabled(renderEnabled)

    @pyqtSlot(bool)
    def slot_transportChecked(self, yesNo):
        if yesNo:
            renderEnabled = bool(self.ui.te_end.time() > self.ui.te_start.time())
        else:
            renderEnabled = True

        self.ui.b_render.setEnabled(renderEnabled)

    @pyqtSlot()
    def slot_updateProgressbar(self):
        time = int(jacklib.get_current_transport_frame(self.fJackClient)) / self.fSampleRate
        self.ui.progressBar.setValue(time)

        if time > self.fMaxTime or (self.fLastTime > time and not self.fFreewheel):
            self.slot_renderStop()

        self.fLastTime = time

    def saveSettings(self):
        settings = QSettings("Cadence", "Cadence-Render")

        if self.ui.rb_mono.isChecked():
            channels = 1
        elif self.ui.rb_stereo.isChecked():
            channels = 2
        else:
            channels = self.ui.sb_channels.value()

        settings.setValue("Geometry", self.saveGeometry())
        settings.setValue("OutputFolder", self.ui.le_folder.text())
        settings.setValue("FilenamePrefix", self.ui.le_prefix.text())
        settings.setValue("EncodingFormat", self.ui.cb_format.currentText())
        settings.setValue("EncodingDepth", self.ui.cb_depth.currentText())
        settings.setValue("EncodingChannels", channels)
        settings.setValue("UseTransport", self.ui.group_time.isChecked())
        settings.setValue("StartTime", self.ui.te_start.time())
        settings.setValue("EndTime", self.ui.te_end.time())

    def loadSettings(self):
        settings = QSettings("Cadence", "Cadence-Render")

        self.restoreGeometry(settings.value("Geometry", ""))

        outputFolder = settings.value("OutputFolder", HOME)

        if os.path.exists(outputFolder):
            self.ui.le_folder.setText(outputFolder)

        self.ui.le_prefix.setText(settings.value("FilenamePrefix", "jack_capture_"))

        encFormat = settings.value("EncodingFormat", "Wav", type=str)

        for i in range(self.ui.cb_format.count()):
            if self.ui.cb_format.itemText(i) == encFormat:
                self.ui.cb_format.setCurrentIndex(i)
                break

        encDepth = settings.value("EncodingDepth", "Float", type=str)

        for i in range(self.ui.cb_depth.count()):
            if self.ui.cb_depth.itemText(i) == encDepth:
                self.ui.cb_depth.setCurrentIndex(i)
                break

        encChannels = settings.value("EncodingChannels", 2, type=int)

        if encChannels == 1:
            self.ui.rb_mono.setChecked(True)
        elif encChannels == 2:
            self.ui.rb_stereo.setChecked(True)
        else:
            self.ui.rb_outro.setChecked(True)
            self.ui.sb_channels.setValue(encChannels)

        self.ui.group_time.setChecked(settings.value("UseTransport", False, type=bool))
        self.ui.te_start.setTime(settings.value("StartTime", self.ui.te_start.time(), type=QTime))
        self.ui.te_end.setTime(settings.value("EndTime", self.ui.te_end.time(), type=QTime))

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

        if self.fJackClient:
            jacklib.client_close(self.fJackClient)

        QDialog.closeEvent(self, event)

    def done(self, r):
        QDialog.done(self, r)
        self.close()
コード例 #36
0
class RenderW(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.ui = ui_render.Ui_RenderW()
        self.ui.setupUi(self)

        self.fFreewheel = False
        self.fLastTime = -1
        self.fMaxTime = 180

        self.fTimer = QTimer(self)
        self.fProcess = QProcess(self)

        # -------------------------------------------------------------
        # Get JACK client and base information

        global gJackClient

        if gJackClient:
            self.fJackClient = gJackClient
        else:
            self.fJackClient = jacklib.client_open("Render-Dialog",
                                                   jacklib.JackNoStartServer,
                                                   None)

        self.fBufferSize = int(jacklib.get_buffer_size(self.fJackClient))
        self.fSampleRate = int(jacklib.get_sample_rate(self.fJackClient))

        for i in range(self.ui.cb_buffer_size.count()):
            if int(self.ui.cb_buffer_size.itemText(i)) == self.fBufferSize:
                self.ui.cb_buffer_size.setCurrentIndex(i)
                break
        else:
            self.ui.cb_buffer_size.addItem(str(self.fBufferSize))
            self.ui.cb_buffer_size.setCurrentIndex(
                self.ui.cb_buffer_size.count() - 1)

        # -------------------------------------------------------------
        # Set-up GUI stuff

        # Get List of formats
        self.fProcess.start(gJackCapturePath, ["-pf"])
        self.fProcess.waitForFinished()

        formats = str(self.fProcess.readAllStandardOutput(),
                      encoding="utf-8").split(" ")
        formatsList = []

        for i in range(len(formats) - 1):
            iFormat = formats[i].strip()
            if iFormat:
                formatsList.append(iFormat)

        formatsList.sort()

        # Put all formats in combo-box, select 'wav' option
        for i in range(len(formatsList)):
            self.ui.cb_format.addItem(formatsList[i])
            if formatsList[i] == "wav":
                self.ui.cb_format.setCurrentIndex(i)

        self.ui.cb_depth.setCurrentIndex(4)  #Float
        self.ui.rb_stereo.setChecked(True)

        self.ui.te_end.setTime(QTime(0, 3, 0))
        self.ui.progressBar.setFormat("")
        self.ui.progressBar.setMinimum(0)
        self.ui.progressBar.setMaximum(1)
        self.ui.progressBar.setValue(0)

        self.ui.b_render.setIcon(getIcon("media-record"))
        self.ui.b_stop.setIcon(getIcon("media-playback-stop"))
        self.ui.b_close.setIcon(getIcon("window-close"))
        self.ui.b_open.setIcon(getIcon("document-open"))
        self.ui.b_stop.setVisible(False)
        self.ui.le_folder.setText(HOME)

        # -------------------------------------------------------------
        # Set-up connections

        self.connect(self.ui.b_render, SIGNAL("clicked()"),
                     SLOT("slot_renderStart()"))
        self.connect(self.ui.b_stop, SIGNAL("clicked()"),
                     SLOT("slot_renderStop()"))
        self.connect(self.ui.b_open, SIGNAL("clicked()"),
                     SLOT("slot_getAndSetPath()"))
        self.connect(self.ui.b_now_start, SIGNAL("clicked()"),
                     SLOT("slot_setStartNow()"))
        self.connect(self.ui.b_now_end, SIGNAL("clicked()"),
                     SLOT("slot_setEndNow()"))
        self.connect(self.ui.te_start, SIGNAL("timeChanged(const QTime)"),
                     SLOT("slot_updateStartTime(const QTime)"))
        self.connect(self.ui.te_end, SIGNAL("timeChanged(const QTime)"),
                     SLOT("slot_updateEndTime(const QTime)"))
        self.connect(self.ui.group_time, SIGNAL("clicked(bool)"),
                     SLOT("slot_transportChecked(bool)"))
        self.connect(self.fTimer, SIGNAL("timeout()"),
                     SLOT("slot_updateProgressbar()"))

        # -------------------------------------------------------------

        self.loadSettings()

    @pyqtSlot()
    def slot_renderStart(self):
        if not os.path.exists(self.ui.le_folder.text()):
            QMessageBox.warning(
                self, self.tr("Warning"),
                self.
                tr("The selected directory does not exist. Please choose a valid one."
                   ))
            return

        timeStart = self.ui.te_start.time()
        timeEnd = self.ui.te_end.time()
        minTime = (timeStart.hour() * 3600) + (timeStart.minute() *
                                               60) + (timeStart.second())
        maxTime = (timeEnd.hour() * 3600) + (timeEnd.minute() *
                                             60) + (timeEnd.second())

        newBufferSize = int(self.ui.cb_buffer_size.currentText())
        useTransport = self.ui.group_time.isChecked()

        self.fFreewheel = bool(self.ui.cb_render_mode.currentIndex() == 1)
        self.fLastTime = -1
        self.fMaxTime = maxTime

        if self.fFreewheel:
            self.fTimer.setInterval(100)
        else:
            self.fTimer.setInterval(500)

        self.ui.group_render.setEnabled(False)
        self.ui.group_time.setEnabled(False)
        self.ui.group_encoding.setEnabled(False)
        self.ui.b_render.setVisible(False)
        self.ui.b_stop.setVisible(True)
        self.ui.b_close.setEnabled(False)

        if useTransport:
            self.ui.progressBar.setFormat("%p%")
            self.ui.progressBar.setMinimum(minTime)
            self.ui.progressBar.setMaximum(maxTime)
            self.ui.progressBar.setValue(minTime)
        else:
            self.ui.progressBar.setFormat("")
            self.ui.progressBar.setMinimum(0)
            self.ui.progressBar.setMaximum(0)
            self.ui.progressBar.setValue(0)

        self.ui.progressBar.update()

        arguments = []

        # Filename prefix
        arguments.append("-fp")
        arguments.append(self.ui.le_prefix.text())

        # Format
        arguments.append("-f")
        arguments.append(self.ui.cb_format.currentText())

        # Bit depth
        arguments.append("-b")
        arguments.append(self.ui.cb_depth.currentText())

        # Channels
        arguments.append("-c")
        if self.ui.rb_mono.isChecked():
            arguments.append("1")
        elif self.ui.rb_stereo.isChecked():
            arguments.append("2")
        else:
            arguments.append(str(self.ui.sb_channels.value()))

        # Controlled only by freewheel
        if self.fFreewheel:
            arguments.append("-jf")

        # Controlled by transport
        elif useTransport:
            arguments.append("-jt")

        # Silent mode
        arguments.append("-dc")
        arguments.append("-s")

        # Change current directory
        os.chdir(self.ui.le_folder.text())

        if newBufferSize != int(jacklib.get_buffer_size(self.fJackClient)):
            print("NOTICE: buffer size changed before render")
            jacklib.set_buffer_size(self.fJackClient, newBufferSize)

        if useTransport:
            if jacklib.transport_query(
                    self.fJackClient, None
            ) > jacklib.JackTransportStopped:  # rolling or starting
                jacklib.transport_stop(self.fJackClient)

            jacklib.transport_locate(self.fJackClient,
                                     minTime * self.fSampleRate)

        self.fProcess.start(gJackCapturePath, arguments)
        self.fProcess.waitForStarted()

        if self.fFreewheel:
            print("NOTICE: rendering in freewheel mode")
            sleep(1)
            jacklib.set_freewheel(self.fJackClient, 1)

        if useTransport:
            self.fTimer.start()
            jacklib.transport_start(self.fJackClient)

    @pyqtSlot()
    def slot_renderStop(self):
        useTransport = self.ui.group_time.isChecked()

        if useTransport:
            jacklib.transport_stop(self.fJackClient)

        if self.fFreewheel:
            jacklib.set_freewheel(self.fJackClient, 0)
            sleep(1)

        self.fProcess.close()

        if useTransport:
            self.fTimer.stop()

        self.ui.group_render.setEnabled(True)
        self.ui.group_time.setEnabled(True)
        self.ui.group_encoding.setEnabled(True)
        self.ui.b_render.setVisible(True)
        self.ui.b_stop.setVisible(False)
        self.ui.b_close.setEnabled(True)

        self.ui.progressBar.setFormat("")
        self.ui.progressBar.setMinimum(0)
        self.ui.progressBar.setMaximum(1)
        self.ui.progressBar.setValue(0)
        self.ui.progressBar.update()

        # Restore buffer size
        newBufferSize = int(jacklib.get_buffer_size(self.fJackClient))

        if newBufferSize != self.fBufferSize:
            jacklib.set_buffer_size(self.fJackClient, newBufferSize)

    @pyqtSlot()
    def slot_getAndSetPath(self):
        getAndSetPath(self, self.ui.le_folder.text(), self.ui.le_folder)

    @pyqtSlot()
    def slot_setStartNow(self):
        time = int(
            jacklib.get_current_transport_frame(self.fJackClient) /
            self.fSampleRate)
        secs = time % 60
        mins = int(time / 60) % 60
        hrs = int(time / 3600) % 60
        self.ui.te_start.setTime(QTime(hrs, mins, secs))

    @pyqtSlot()
    def slot_setEndNow(self):
        time = int(
            jacklib.get_current_transport_frame(self.fJackClient) /
            self.fSampleRate)
        secs = time % 60
        mins = int(time / 60) % 60
        hrs = int(time / 3600) % 60
        self.ui.te_end.setTime(QTime(hrs, mins, secs))

    @pyqtSlot(QTime)
    def slot_updateStartTime(self, time):
        if time >= self.ui.te_end.time():
            self.ui.te_end.setTime(time)
            renderEnabled = False
        else:
            renderEnabled = True

        if self.ui.group_time.isChecked():
            self.ui.b_render.setEnabled(renderEnabled)

    @pyqtSlot(QTime)
    def slot_updateEndTime(self, time):
        if time <= self.ui.te_start.time():
            self.ui.te_start.setTime(time)
            renderEnabled = False
        else:
            renderEnabled = True

        if self.ui.group_time.isChecked():
            self.ui.b_render.setEnabled(renderEnabled)

    @pyqtSlot(bool)
    def slot_transportChecked(self, yesNo):
        if yesNo:
            renderEnabled = bool(
                self.ui.te_end.time() > self.ui.te_start.time())
        else:
            renderEnabled = True

        self.ui.b_render.setEnabled(renderEnabled)

    @pyqtSlot()
    def slot_updateProgressbar(self):
        time = int(jacklib.get_current_transport_frame(
            self.fJackClient)) / self.fSampleRate
        self.ui.progressBar.setValue(time)

        if time > self.fMaxTime or (self.fLastTime > time
                                    and not self.fFreewheel):
            self.slot_renderStop()

        self.fLastTime = time

    def saveSettings(self):
        settings = QSettings("Cadence", "Cadence-Render")

        if self.ui.rb_mono.isChecked():
            channels = 1
        elif self.ui.rb_stereo.isChecked():
            channels = 2
        else:
            channels = self.ui.sb_channels.value()

        settings.setValue("Geometry", self.saveGeometry())
        settings.setValue("OutputFolder", self.ui.le_folder.text())
        settings.setValue("FilenamePrefix", self.ui.le_prefix.text())
        settings.setValue("EncodingFormat", self.ui.cb_format.currentText())
        settings.setValue("EncodingDepth", self.ui.cb_depth.currentText())
        settings.setValue("EncodingChannels", channels)
        settings.setValue("UseTransport", self.ui.group_time.isChecked())
        settings.setValue("StartTime", self.ui.te_start.time())
        settings.setValue("EndTime", self.ui.te_end.time())

    def loadSettings(self):
        settings = QSettings("Cadence", "Cadence-Render")

        self.restoreGeometry(settings.value("Geometry", ""))

        outputFolder = settings.value("OutputFolder", HOME)

        if os.path.exists(outputFolder):
            self.ui.le_folder.setText(outputFolder)

        self.ui.le_prefix.setText(
            settings.value("FilenamePrefix", "jack_capture_"))

        encFormat = settings.value("EncodingFormat", "Wav", type=str)

        for i in range(self.ui.cb_format.count()):
            if self.ui.cb_format.itemText(i) == encFormat:
                self.ui.cb_format.setCurrentIndex(i)
                break

        encDepth = settings.value("EncodingDepth", "Float", type=str)

        for i in range(self.ui.cb_depth.count()):
            if self.ui.cb_depth.itemText(i) == encDepth:
                self.ui.cb_depth.setCurrentIndex(i)
                break

        encChannels = settings.value("EncodingChannels", 2, type=int)

        if encChannels == 1:
            self.ui.rb_mono.setChecked(True)
        elif encChannels == 2:
            self.ui.rb_stereo.setChecked(True)
        else:
            self.ui.rb_outro.setChecked(True)
            self.ui.sb_channels.setValue(encChannels)

        self.ui.group_time.setChecked(
            settings.value("UseTransport", False, type=bool))
        self.ui.te_start.setTime(
            settings.value("StartTime", self.ui.te_start.time(), type=QTime))
        self.ui.te_end.setTime(
            settings.value("EndTime", self.ui.te_end.time(), type=QTime))

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

        if self.fJackClient:
            jacklib.client_close(self.fJackClient)

        QDialog.closeEvent(self, event)

    def done(self, r):
        QDialog.done(self, r)
        self.close()
コード例 #37
0
def run_process(fused_command, read_output = False):
    #     print "run process", fused_command
    #     qprocess = QProcess()
    #     set_process_env(qprocess)
    #     code_de_retour = qprocess.execute(fused_command)
    #     print "code de retour", code_de_retour
    #     logger.info("command: ")
    #     logger.info(fused_command)
    #     logger.info("code de retour" + str(code_de_retour))
    #
    # #     if not qprocess.waitForStarted():
    # #         # handle a failed command here
    # #         print "qprocess.waitForStarted()"
    # #         return
    # #
    # #     if not qprocess.waitForReadyRead():
    # #         # handle a timeout or error here
    # #         print "qprocess.waitForReadyRead()"
    # #         return
    # #     #if not qprocess.waitForFinished(1):
    # #     #    qprocess.kill()
    # #     #    qprocess.waitForFinished(1)
    #
    # #     if read_output:
    #
    #     # logger.info("Erreur")
    #     code_d_erreur = qprocess.error()
    #     dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError" }
    #     logger.info("Code de retour: " + str(code_d_erreur))
    #     logger.info(dic_err[code_d_erreur])
    #
    #     print "get output"
    #     output = str(qprocess.readAllStandardOutput())
    #     # print "output", output
    #     print 'end output'
    process = QProcess()
    process.start(fused_command)
    if process.waitForStarted():
        process.waitForFinished(-1)
        exit_code = process.exitCode()
        logger.info("Code de sortie : " + str(exit_code))
        if exit_code < 0:
            code_d_erreur = process.error().data
            dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError" }
            logger.info("Code erreur : " + str(code_d_erreur))
            logger.info(dic_err[code_d_erreur])

        result = process.readAllStandardOutput()
        # print type(result), result
        error = process.readAllStandardError().data()
        # print repr(error)
        if not error == "\n":
            logger.info("error : " + "\'" + str(error) + "\'")
        logger.info("output : " + result.data() + "fin output")
        return result
    else:
        code_d_erreur = process.error()
        dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError" }
        logger.info("Code erreur : " + str(code_d_erreur))
        logger.info(dic_err[code_d_erreur])
    return None
コード例 #38
0
ファイル: mplayer.py プロジェクト: Ptaah/Ekd
def getParamVideo(cheminVideoEntre, parameter, hashInfo = None):
	"""Renvoie un ou plusieurs paramètres de la vidéo sous forme de flottant.
	La variable «cheminVideoEntre» est le chemin de la vidéo de type unicode.
	La variable «parameter» est un tuple de paramètres à renvoyer.
	La dernière variable renvoyée est un tuple des lignes de log
	23/07/2009 : hashInfo contiendra la hashmap des infos demandées
	"""


	#cheminVideoEntre = cheminVideoEntre.encode("UTF8")
	if hashInfo == None:
		hashInfo = {}
	# Condition pour détection windows
	if os.name == 'nt':
		commande = u'mplayer.exe -vo null -ao null -identify -frames 0 '+ u"\"" + unicode(cheminVideoEntre) + u"\""
	# Condition pour détection Linux ou MacOSX
	elif os.name in ['posix', 'mac']:
		commande = u'mplayer ' + u"\""+ unicode(cheminVideoEntre) + u"\" -vo null -ao null -frames 0 -identify '$@' 2>/dev/null"

        #recupDonneesVideo = os.popen(commande.encode(coding)).readlines()
        processus = QProcess()
        processus.start(commande)
        if (not processus.waitForStarted()):
            raise (u"Erreur de récupération des informations")
        if ( not processus.waitForFinished()):
            raise (u"Erreur de récupération des informations")
        recupDonneesVideo = QString(processus.readAllStandardOutput())

	lstValeurs = []
	log = []

	#for ligne in recupDonneesVideo:
	for ligne in recupDonneesVideo.split("\n"):
		try:
			# On veut que les caractères non ASCII s'affichent
                        # correctement pour les noms de fichiers
			log.append(ligne)
		except UnicodeDecodeError:
			debug("Traitement d'exception unicode au niveau de " \
                                "getParamVideo() probablement dûe aux " \
                                "méta-données de la vidéo")
			log.append(ligne)
		for param in parameter:
			if param in ligne:
				ligne = ligne.replace(param, "")
				ligne = ligne.replace("=", "")
				ligne = ligne.replace("\n", "")
				############################################
				# Commenté le 01/09/10 --> voir si tout 
				# fonctionne malgré tout (commenté pour
				# pouvoir lire les tags vidéos correctement)
				#ligne = ligne.replace(" ", "")
				############################################

				############################################
				# Le 01/09/10 Essai de réglage de la sortie  
				# pour les accents dans les tags vidéo
				# VOIR SI SYNTAXE PLUS GENERIQUE
				ligne = ligne.replace("é", "e")
				ligne = ligne.replace("è", "e")
				ligne = ligne.replace("ç", "c")
				ligne = ligne.replace("à", "a")
				ligne = ligne.replace("ù", "u")
				ligne = ligne.replace("ä", "a")
				ligne = ligne.replace("ü", "u")
				ligne = ligne.replace("ö", "o")
				############################################

				try :
					lstValeurs.append(float(ligne))
					hashInfo[param] = float(ligne)
				except :
					lstValeurs.append(str(ligne))
					hashInfo[param] = str(ligne)

	lstValeurs.append(log)
	#lstValeurs.append(hashInfo)
	return lstValeurs
コード例 #39
0
class Kitty(QObject):
    """manage kitty process (terminals)"""
    exe_name = 'kitty'
    DELAY = 150

    def __init__(self,
                 ip,
                 port,
                 protocol,
                 name,
                 log_path,
                 window_title,
                 log_name,
                 parent=None):
        QObject.__init__(self, parent)
        self.ip = ip
        self.port = port
        self.protocol = protocol
        self.log_path = log_path
        self.log_name = log_name
        self.id = str(os.getpid()) + name
        self.window_title = window_title
        self.terminal = QProcess()
        self.terminal.finished.connect(self.close)
        self.terminal.stateChanged.connect(self.state)
        self.send_process = QProcess()
        self.send_process.finished.connect(self.end_send)

    def open(self):
        """ kitty -telnet -P 9696 hostname """
        if self.terminal.state() == QProcess.Running:
            return
        file_name = utils.set_log_name(self.log_name,
                                       self.log_path,
                                       ext='.txt')
        args = [
            '-{}'.format(self.protocol), self.ip, '-P', self.port, '-log',
            os.path.join(self.log_path, file_name), '-title',
            self.window_title, '-classname', self.id
        ]
        while self.terminal.state() == QProcess.NotRunning:
            self.terminal.start(os.path.join(dep_dir, Kitty.exe_name), args)
            self.terminal.waitForStarted()
            QThread.msleep(Kitty.DELAY)

    def send(self, text):
        if self.send_process.state() == QProcess.Running:
            self.send_process.close()
        self.show_terminal()
        args = ['-classname', self.id, '-sendcmd', text]
        self.send_process.start(os.path.join(dep_dir, Kitty.exe_name), args)
        self.send_process.waitForStarted()
        self.send_process.waitForFinished()
        QThread.msleep(Kitty.DELAY)

    def show_terminal(self):
        if self.terminal.state() == QProcess.NotRunning:
            return
        autowin.show_window(autowin.get_qprocess_pid(self.terminal.pid()))
        QThread.msleep(Kitty.DELAY)

    @staticmethod
    def show_main():
        autowin.show_window(os.getpid())

    def end_send(self):
        pass

    def close(self):
        self.terminal.close()

    def state(self, st):
        print(st)
コード例 #40
0
ファイル: PluginBase.py プロジェクト: albfan/seascope
class PluginProcessBase(QObject):
    proc_list = []

    def __init__(self, wdir):
        QObject.__init__(self)

        PluginProcess.proc_list.append(self)
        self.is_rebuild = False
        self.is_query_fl = False

        self.sig = QuerySignal()

        self.proc = QProcess()
        self.proc.finished.connect(self._finished_cb)
        self.proc.error.connect(self._error_cb)

        self.proc.setWorkingDirectory(wdir)
        self.wdir = wdir

    def _cleanup(self):
        PluginProcess.proc_list.remove(self)
        if self.err_str != '':
            s = '<b>' + self.p_cmd + '</b><p>' + '<p>'.join(
                self.err_str.splitlines())
            QMessageBox.warning(None, "Seascope", s, QMessageBox.Ok)
        if self.res != '':
            s = '<b>' + self.p_cmd + '</b><p>Summary<p>' + self.res
            QMessageBox.information(None, "Seascope", s, QMessageBox.Ok)

    def _error_cb(self, err):
        err_dict = {
            QProcess.FailedToStart: 'FailedToStart',
            QProcess.Crashed: 'Crashed',
            QProcess.Timedout: 'The last waitFor...() function timed out',
            QProcess.WriteError:
            'An error occurred when attempting to write to the process',
            QProcess.ReadError:
            'An error occurred when attempting to read from the process',
            QProcess.UnknownError: 'An unknown error occurred',
        }
        self.err_str = '<b>' + self.p_cmd + '</b><p>' + err_dict[err]
        self._cleanup()

    def _finished_cb(self, ret):
        res = str(self.proc.readAllStandardOutput())
        self.err_str = str(self.proc.readAllStandardError())

        #print 'output', res
        #print 'cmd:', self.p_cmd
        if self.is_rebuild:
            self.res = res
            self.sig.sig_rebuild.emit()
        elif self.is_query_fl:
            self.res = ''
            res = self.parse_query_fl(res)
            self.sig.sig_query_fl.emit(res)
        else:
            self.res = ''
            self.sig.sig_result_dbg.emit(self.p_cmd, res, self.err_str)
            try:
                res = self.parse_result(res, self.sig)
            except Exception as e:
                print e
                res = [[
                    '', '', '', 'error while parsing output of: ' + self.p_cmd
                ]]
            if res != None:
                self.sig.emit_result(res)

        self._cleanup()

    def run_query_process(self, pargs, sym, rquery=None):
        self.sig.sym = sym
        self.sig.rquery = rquery
        self.p_cmd = ' '.join(pargs)
        if os.getenv('SEASCOPE_DEBUG'):
            print self.p_cmd
        self.proc.start(pargs[0], pargs[1:])
        if self.proc.waitForStarted() == False:
            return None
        self.proc.closeWriteChannel()
        return [self.sig.sig_result, self.sig.sig_result_dbg]

    def run_rebuild_process(self, pargs):
        self.is_rebuild = True
        self.p_cmd = ' '.join(pargs)
        self.proc.start(pargs[0], pargs[1:])
        if self.proc.waitForStarted() == False:
            return None
        #print 'cmd:', pargs
        self.sig.sig_rebuild.connect(CtagsCache.flush)
        return self.sig.sig_rebuild

    def run_query_fl(self, pargs):
        self.is_query_fl = True
        self.p_cmd = ' '.join(pargs)
        self.proc.start(pargs[0], pargs[1:])
        if self.proc.waitForStarted() == False:
            return None
        return self.sig.sig_query_fl

    def parse_query_fl(self, text):
        fl = []
        for f in re.split('\r?\n', text.strip()):
            if f == '':
                continue
            fl.append(os.path.join(self.wdir, f))
        return fl
コード例 #41
0
ファイル: main.py プロジェクト: juancarlospaco/profiler
class Main(plugin.Plugin):
    " Main Class "
    def initialize(self, *args, **kwargs):
        " Init Main Class "
        super(Main, self).initialize(*args, **kwargs)
        self.scriptPath, self.scriptArgs = "", []
        self.profilerPath, self.tempPath = profilerPath, tempPath
        self.output = " ERROR: FAIL: No output ! "

        self.process = QProcess()
        self.process.finished.connect(self.on_process_finished)
        self.process.error.connect(self.on_process_error)

        self.tabWidget, self.stat = QTabWidget(), QWidget()
        self.tabWidget.tabCloseRequested.connect(lambda:
            self.tabWidget.setTabPosition(1)
            if self.tabWidget.tabPosition() == 0
            else self.tabWidget.setTabPosition(0))
        self.tabWidget.setStyleSheet('QTabBar{font-weight:bold;}')
        self.tabWidget.setMovable(True)
        self.tabWidget.setTabsClosable(True)
        self.vboxlayout1 = QVBoxLayout(self.stat)
        self.hboxlayout1 = QHBoxLayout()
        self.filterTableLabel = QLabel("<b>Type to Search : </b>", self.stat)
        self.hboxlayout1.addWidget(self.filterTableLabel)
        self.filterTableLineEdit = QLineEdit(self.stat)
        self.filterTableLineEdit.setPlaceholderText(' Type to Search . . . ')
        self.hboxlayout1.addWidget(self.filterTableLineEdit)
        self.filterHintTableLabel = QLabel(" ? ", self.stat)
        self.hboxlayout1.addWidget(self.filterHintTableLabel)
        self.vboxlayout1.addLayout(self.hboxlayout1)
        self.tableWidget = QTableWidget(self.stat)
        self.tableWidget.setAlternatingRowColors(True)
        self.tableWidget.setColumnCount(8)
        self.tableWidget.setRowCount(2)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(2, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(3, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(4, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(5, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(6, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(7, item)
        self.tableWidget.itemDoubleClicked.connect(
                                        self.on_tableWidget_itemDoubleClicked)
        self.vboxlayout1.addWidget(self.tableWidget)
        self.tabWidget.addTab(self.stat, " ? ")

        self.source = QWidget()
        self.gridlayout = QGridLayout(self.source)
        self.scintillaWarningLabel = QLabel(
            "QScintilla is not installed!. Falling back to basic text edit!.",
            self.source)
        self.gridlayout.addWidget(self.scintillaWarningLabel, 1, 0, 1, 2)
        self.sourceTreeWidget = QTreeWidget(self.source)
        self.sourceTreeWidget.setAlternatingRowColors(True)
        self.sourceTreeWidget.itemActivated.connect(
                                        self.on_sourceTreeWidget_itemActivated)
        self.sourceTreeWidget.itemClicked.connect(
                                          self.on_sourceTreeWidget_itemClicked)
        self.sourceTreeWidget.itemDoubleClicked.connect(
                                          self.on_sourceTreeWidget_itemClicked)

        self.gridlayout.addWidget(self.sourceTreeWidget, 0, 0, 1, 1)
        self.sourceTextEdit = QTextEdit(self.source)
        self.sourceTextEdit.setReadOnly(True)
        self.gridlayout.addWidget(self.sourceTextEdit, 0, 1, 1, 1)
        self.tabWidget.addTab(self.source, " ? ")

        self.result = QWidget()
        self.vlayout = QVBoxLayout(self.result)
        self.globalStatGroupBox = QGroupBox(self.result)
        self.hboxlayout = QHBoxLayout(self.globalStatGroupBox)
        self.totalTimeLcdNumber = QLCDNumber(self.globalStatGroupBox)
        self.totalTimeLcdNumber.setSegmentStyle(QLCDNumber.Filled)
        self.totalTimeLcdNumber.setNumDigits(7)
        self.totalTimeLcdNumber.display(1000000)
        self.totalTimeLcdNumber.setFrameShape(QFrame.StyledPanel)
        self.totalTimeLcdNumber.setSizePolicy(QSizePolicy.Expanding,
                                              QSizePolicy.Expanding)
        self.hboxlayout.addWidget(self.totalTimeLcdNumber)
        self.tTimeLabel = QLabel("<b>Total Time (Sec)</b>",
                                 self.globalStatGroupBox)
        self.tTimeLabel.setSizePolicy(QSizePolicy.Minimum,
                                      QSizePolicy.Minimum)
        self.hboxlayout.addWidget(self.tTimeLabel)
        self.numCallLcdNumber = QLCDNumber(self.globalStatGroupBox)
        self.numCallLcdNumber.setNumDigits(7)
        self.numCallLcdNumber.display(1000000)
        self.numCallLcdNumber.setSegmentStyle(QLCDNumber.Filled)
        self.numCallLcdNumber.setFrameShape(QFrame.StyledPanel)
        self.numCallLcdNumber.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Expanding)
        self.hboxlayout.addWidget(self.numCallLcdNumber)
        self.numCallLabel = QLabel("<b>Number of calls</b>",
                                   self.globalStatGroupBox)
        self.numCallLabel.setSizePolicy(QSizePolicy.Minimum,
                                        QSizePolicy.Minimum)
        self.hboxlayout.addWidget(self.numCallLabel)
        self.primCallLcdNumber = QLCDNumber(self.globalStatGroupBox)
        self.primCallLcdNumber.setSegmentStyle(QLCDNumber.Filled)
        self.primCallLcdNumber.setFrameShape(QFrame.StyledPanel)
        self.primCallLcdNumber.setNumDigits(7)
        self.primCallLcdNumber.display(1000000)
        self.primCallLcdNumber.setSizePolicy(QSizePolicy.Expanding,
                                             QSizePolicy.Expanding)
        self.hboxlayout.addWidget(self.primCallLcdNumber)
        self.primCallLabel = QLabel("<b>Primitive calls (%)</b>",
                                    self.globalStatGroupBox)
        self.primCallLabel.setSizePolicy(QSizePolicy.Minimum,
                                         QSizePolicy.Minimum)
        self.hboxlayout.addWidget(self.primCallLabel)
        self.vlayout.addWidget(self.globalStatGroupBox)
        try:
            from PyKDE4.kdeui import KRatingWidget
            self.rating = KRatingWidget(self.globalStatGroupBox)
            self.rating.setToolTip('Profiling Performance Rating')
        except ImportError:
            pass
        self.tabWidget.addTab(self.result, " Get Results ! ")

        self.resgraph = QWidget()
        self.vlayout2 = QVBoxLayout(self.result)
        self.graphz = QGroupBox(self.resgraph)
        self.hboxlayout2 = QHBoxLayout(self.graphz)
        try:
            from PyKDE4.kdeui import KLed
            KLed(self.graphz)
        except ImportError:
            pass
        self.hboxlayout2.addWidget(QLabel('''
            Work in Progress  :)  Not Ready Yet'''))
        self.vlayout2.addWidget(self.graphz)
        self.tabWidget.addTab(self.resgraph, " Graphs and Charts ")

        self.pathz = QWidget()
        self.vlayout3 = QVBoxLayout(self.pathz)
        self.patz = QGroupBox(self.pathz)
        self.hboxlayout3 = QVBoxLayout(self.patz)
        self.profilepath = QLineEdit(profilerPath)
        self.getprofile = QPushButton(QIcon.fromTheme("document-open"), 'Open')
        self.getprofile.setToolTip('Dont touch if you dont know what are doing')
        self.getprofile.clicked.connect(lambda: self.profilepath.setText(str(
            QFileDialog.getOpenFileName(self.patz, ' Open the profile.py file ',
            path.expanduser("~"), ';;(profile.py)'))))
        self.hboxlayout3.addWidget(QLabel(
            '<center><b>Profile.py Python Library Full Path:</b></center>'))
        self.hboxlayout3.addWidget(self.profilepath)
        self.hboxlayout3.addWidget(self.getprofile)

        self.argGroupBox = QGroupBox(self.pathz)
        self.hbxlayout = QHBoxLayout(self.argGroupBox)
        self.argLineEdit = QLineEdit(self.argGroupBox)
        self.argLineEdit.setToolTip('Not touch if you dont know what are doing')
        self.argLineEdit.setPlaceholderText(
            'Dont touch if you dont know what are doing')
        self.hbxlayout.addWidget(QLabel('<b>Additional Profile Arguments:</b>'))
        self.hbxlayout.addWidget(self.argLineEdit)
        self.hboxlayout3.addWidget(self.argGroupBox)

        self.vlayout3.addWidget(self.patz)
        self.tabWidget.addTab(self.pathz, " Paths and Configs ")

        self.outp = QWidget()
        self.vlayout4 = QVBoxLayout(self.outp)
        self.outgro = QGroupBox(self.outp)
        self.outgro.setTitle(" MultiProcessing Output Logs ")
        self.hboxlayout4 = QVBoxLayout(self.outgro)
        self.outputlog = QTextEdit()
        self.outputlog.setText('''
        I do not fear computers, I fear the lack of them.   -Isaac Asimov ''')
        self.hboxlayout4.addWidget(self.outputlog)
        self.vlayout4.addWidget(self.outgro)
        self.tabWidget.addTab(self.outp, " Logs ")

        self.actionNew_profiling = QAction(QIcon.fromTheme("document-new"),
                                           'New Profiling', self)
        self.actionLoad_profile = QAction(QIcon.fromTheme("document-open"),
                                          'Open Profiling', self)
        self.actionClean = QAction(QIcon.fromTheme("edit-clear"), 'Clean', self)
        self.actionClean.triggered.connect(lambda: self.clearContent)
        self.actionAbout = QAction(QIcon.fromTheme("help-about"), 'About', self)
        self.actionAbout.triggered.connect(lambda: QMessageBox.about(self.dock,
            __doc__, ', '.join((__doc__, __license__, __author__, __email__))))
        self.actionSave_profile = QAction(QIcon.fromTheme("document-save"),
                                          'Save Profiling', self)
        self.actionManual = QAction(QIcon.fromTheme("help-contents"),
                                    'Help', self)
        self.actionManual.triggered.connect(lambda:
                    open_new_tab('http://docs.python.org/library/profile.html'))

        self.tabWidget.setCurrentIndex(2)

        self.globalStatGroupBox.setTitle("Global Statistics")
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText("Number of Calls")
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText("Total Time")
        item = self.tableWidget.horizontalHeaderItem(2)
        item.setText("Per Call")
        item = self.tableWidget.horizontalHeaderItem(3)
        item.setText("Cumulative Time")
        item = self.tableWidget.horizontalHeaderItem(4)
        item.setText("Per Call")
        item = self.tableWidget.horizontalHeaderItem(5)
        item.setText("Filename")
        item = self.tableWidget.horizontalHeaderItem(6)
        item.setText("Line")
        item = self.tableWidget.horizontalHeaderItem(7)
        item.setText("Function")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.stat),
                                  "Statistics per Function")

        self.sourceTreeWidget.headerItem().setText(0, "Source files")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.source),
                                  "Sources Navigator")
        #######################################################################

        self.scrollable, self.dock = QScrollArea(), QDockWidget()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(self.tabWidget)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)
        QToolBar(self.dock).addActions((self.actionNew_profiling,
            self.actionClean, self.actionSave_profile, self.actionLoad_profile,
            self.actionManual, self.actionAbout))

        self.actionNew_profiling.triggered.connect(
                                        self.on_actionNew_profiling_triggered)
        self.actionLoad_profile.triggered.connect(
                                        self.on_actionLoad_profile_triggered)
        self.actionSave_profile.triggered.connect(
                                        self.on_actionSave_profile_triggered)

        self.locator.get_service('misc').add_widget(self.dock,
                            QIcon.fromTheme("document-open-recent"), __doc__)

        if QSCI:
            # Scintilla source editor management
            self.scintillaWarningLabel.setText(' QScintilla is Ready ! ')
            layout = self.source.layout()
            layout.removeWidget(self.sourceTextEdit)
            self.sourceTextEdit = Qsci.QsciScintilla(self.source)
            layout.addWidget(self.sourceTextEdit, 0, 1)
            doc = self.sourceTextEdit
            doc.setLexer(Qsci.QsciLexerPython(self.sourceTextEdit))
            doc.setReadOnly(True)
            doc.setEdgeMode(Qsci.QsciScintilla.EdgeLine)
            doc.setEdgeColumn(80)
            doc.setEdgeColor(QColor("#FF0000"))
            doc.setFolding(Qsci.QsciScintilla.BoxedTreeFoldStyle)
            doc.setBraceMatching(Qsci.QsciScintilla.SloppyBraceMatch)
            doc.setCaretLineVisible(True)
            doc.setMarginLineNumbers(1, True)
            doc.setMarginWidth(1, 25)
            doc.setTabWidth(4)
            doc.setEolMode(Qsci.QsciScintilla.EolUnix)
            self.marker = {}
            for color in COLORS:
                mnr = doc.markerDefine(Qsci.QsciScintilla.Background)
                doc.setMarkerBackgroundColor(color, mnr)
                self.marker[color] = mnr
        self.currentSourcePath = None

        # Connect table and tree filter edit signal to unique slot
        self.filterTableLineEdit.textEdited.connect(
                                            self.on_filterLineEdit_textEdited)

        # Timer to display filter hint message
        self.filterHintTimer = QTimer(self)
        self.filterHintTimer.setSingleShot(True)
        self.filterHintTimer.timeout.connect(self.on_filterHintTimer_timeout)

        # Timer to start search
        self.filterSearchTimer = QTimer(self)
        self.filterSearchTimer.setSingleShot(True)
        self.filterSearchTimer.timeout.connect(
                                            self.on_filterSearchTimer_timeout)

        self.tabLoaded = {}
        for i in range(10):
            self.tabLoaded[i] = False
        self.backgroundTreeMatchedItems = {}
        self.resizeWidgetToContent(self.tableWidget)

    def on_actionNew_profiling_triggered(self):
        self.clearContent()
        self.scriptPath = str(QFileDialog.getOpenFileName(self.dock,
            "Choose your script to profile", path.expanduser("~"),
            "Python (*.py *.pyw)"))
        commandLine = [self.profilerPath, "-o", self.tempPath,
                       self.scriptPath] + self.scriptArgs
        commandLine = " ".join(commandLine)
        ##if self.termCheckBox.checkState() == Qt.Checked:
        #termList = ["xterm", "aterm"]
        #for term in termList:
            #termPath = which(term)
            #if termPath:
                #break
        #commandLine = """%s -e "%s ; echo 'Press ENTER Exit' ; read" """ \
                      #% (termPath, commandLine)
        self.process.start(commandLine)
        if not self.process.waitForStarted():
            print((" ERROR: {} failed!".format(commandLine)))
            return

    def on_process_finished(self, exitStatus):
        ' whan the process end '
        print((" INFO: OK: QProcess is %s" % self.process.exitCode()))
        self.output = self.process.readAll().data()
        if not self.output:
            self.output = " ERROR: FAIL: No output ! "
        self.outputlog.setText(self.output + str(self.process.exitCode()))
        if path.exists(self.tempPath):
            self.setStat(self.tempPath)
            remove(self.tempPath)
        else:
            self.outputlog.setText(" ERROR: QProcess FAIL: Profiling failed.")
        self.tabWidget.setCurrentIndex(2)

    def on_process_error(self, error):
        ' when the process fail, I hope you never see this '
        print(" ERROR: QProcess FAIL: Profiler Dead, wheres your God now ? ")
        if error == QProcess.FailedToStart:
            self.outputlog.setText(" ERROR: FAIL: Profiler execution failed ")
        elif error == QProcess.Crashed:
            self.outputlog.setText(" ERROR: FAIL: Profiler execution crashed ")
        else:
            self.outputlog.setText(" ERROR: FAIL: Profiler unknown error ")

    def on_actionLoad_profile_triggered(self):
        """Load a previous profile sessions"""
        statPath = str(QFileDialog.getOpenFileName(self.dock,
            "Open profile dump", path.expanduser("~"), "Profile file (*)"))
        if statPath:
            self.clearContent()
            print(' INFO: OK: Loading profiling from ' + statPath)
            self.setStat(statPath)

    def on_actionSave_profile_triggered(self):
        """Save a profile sessions"""
        statPath = str(QFileDialog.getSaveFileName(self.dock,
                "Save profile dump", path.expanduser("~"), "Profile file (*)"))
        if statPath:
            #TODO: handle error case and give feelback to user
            print(' INFO: OK: Saving profiling to ' + statPath)
            self.stat.save(statPath)

    #=======================================================================#
    # Common parts                                                          #
    #=======================================================================#

    def on_tabWidget_currentChanged(self, index):
        """slot for tab change"""
        # Kill search and hint timer if running to avoid cross effect
        for timer in (self.filterHintTimer, self.filterSearchTimer):
            if timer.isActive():
                timer.stop()
        if not self.stat:
            #No stat loaded, nothing to do
            return
        self.populateTable()
        self.populateSource()

    def on_filterLineEdit_textEdited(self, text):
        """slot for filter change (table or tree"""
        if self.filterSearchTimer.isActive():
            # Already runnning, stop it
            self.filterSearchTimer.stop()
        # Start timer
        self.filterSearchTimer.start(300)

    def on_filterHintTimer_timeout(self):
        """Timeout to warn user about text length"""
        print("timeout")
        tab = self.tabWidget.currentIndex()
        if tab == TAB_FUNCTIONSTAT:
            label = self.filterHintTableLabel
        label.setText("Type > 2 characters to search")

    def on_filterSearchTimer_timeout(self):
        """timeout to start search"""
        tab = self.tabWidget.currentIndex()
        if tab == TAB_FUNCTIONSTAT:
            text = self.filterTableLineEdit.text()
            label = self.filterHintTableLabel
            edit = self.filterTableLineEdit
            widget = self.tableWidget
        else:
            print("Unknow tab for filterSearch timeout !")

        print(("do search for %s" % text))
        if not len(text):
            # Empty keyword, just clean all
            if self.filterHintTimer.isActive():
                self.filterHintTimer.stop()
            label.setText(" ? ")
            self.warnUSer(True, edit)
            self.clearSearch()
            return
        if len(text) < 2:
            # Don't filter if text is too short and tell it to user
            self.filterHintTimer.start(600)
            return
        else:
            if self.filterHintTimer.isActive():
                self.filterHintTimer.stop()
            label.setText(" ? ")

        # Search
        self.clearSearch()
        matchedItems = []
        if tab == TAB_FUNCTIONSTAT:
            # Find items
            matchedItems = widget.findItems(text, Qt.MatchContains)
            widget.setSortingEnabled(False)
            matchedRows = [item.row() for item in matchedItems]
            # Hide matched items
            header = widget.verticalHeader()
            for row in range(widget.rowCount()):
                if row not in matchedRows:
                    header.hideSection(row)
            widget.setSortingEnabled(True)
        else:
            print(" Unknow tab for filterSearch timeout ! ")

        print(("got %s members" % len(matchedItems)))
        self.warnUSer(matchedItems, edit)
        self.resizeWidgetToContent(widget)

    def resizeWidgetToContent(self, widget):
        """Resize all columns according to content"""
        for i in range(widget.columnCount()):
            widget.resizeColumnToContents(i)

    def clearSearch(self):
        """Clean search result
        For table, show all items
        For tree, remove colored items"""
        tab = self.tabWidget.currentIndex()
        if tab == TAB_FUNCTIONSTAT:
            header = self.tableWidget.verticalHeader()
            if header.hiddenSectionCount():
                for i in range(header.count()):
                    if header.isSectionHidden(i):
                        header.showSection(i)

    def clearContent(self):
        # Clear tabs
        self.tableWidget.clearContents()
        self.sourceTreeWidget.clear()
        # Reset LCD numbers
        for lcdNumber in (self.totalTimeLcdNumber, self.numCallLcdNumber,
                          self.primCallLcdNumber):
            lcdNumber.display(1000000)
        # Reset stat
        self.pstat = None
        # Disable save as menu
        self.actionSave_profile.setEnabled(False)
        # Mark all tabs as unloaded
        for i in range(10):
            self.tabLoaded[i] = False

    def warnUSer(self, result, inputWidget):
        palette = inputWidget.palette()
        if result:
            palette.setColor(QPalette.Normal, QPalette.Base,
                             QColor(255, 255, 255))
        else:
            palette.setColor(QPalette.Normal, QPalette.Base,
                             QColor(255, 136, 138))
        inputWidget.setPalette(palette)
        inputWidget.update()

    def setStat(self, statPath):
        self.stat = Stat(path=statPath)
        # Global stat update
        self.totalTimeLcdNumber.display(self.stat.getTotalTime())
        self.numCallLcdNumber.display(self.stat.getCallNumber())
        self.primCallLcdNumber.display(self.stat.getPrimitiveCallRatio())
        # Refresh current tab
        self.on_tabWidget_currentChanged(self.tabWidget.currentIndex())
        # Activate save as menu
        self.actionSave_profile.setEnabled(True)
        try:
            self.rating.setMaxRating(10)
            self.rating.setRating(
                                int(self.stat.getPrimitiveCallRatio()) / 10 - 1)
        except:
            pass

    #========================================================================#
    # Statistics table                                                      #
    #=======================================================================#

    def populateTable(self):
        row = 0
        rowCount = self.stat.getStatNumber()
        progress = QProgressDialog("Populating statistics table...",
                                         "Abort", 0, 2 * rowCount)
        self.tableWidget.setSortingEnabled(False)
        self.tableWidget.setRowCount(rowCount)

        progress.setWindowModality(Qt.WindowModal)
        for (key, value) in self.stat.getStatItems():
            #ncalls
            item = StatTableWidgetItem(str(value[0]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_NCALLS, item)
            colorTableItem(item, self.stat.getCallNumber(), value[0])
            #total time
            item = StatTableWidgetItem(str(value[2]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_TTIME, item)
            colorTableItem(item, self.stat.getTotalTime(), value[2])
            #per call (total time)
            if value[0] != 0:
                tPerCall = str(value[2] / value[0])
                cPerCall = str(value[3] / value[0])
            else:
                tPerCall = ""
                cPerCall = ""
            item = StatTableWidgetItem(tPerCall)
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_TPERCALL, item)
            colorTableItem(item, 100.0 * self.stat.getTotalTime() /
                           self.stat.getCallNumber(), tPerCall)
            #per call (cumulative time)
            item = StatTableWidgetItem(cPerCall)
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_CPERCALL, item)
            colorTableItem(item, 100.0 * self.stat.getTotalTime() /
                           self.stat.getCallNumber(), cPerCall)
            #cumulative time
            item = StatTableWidgetItem(str(value[3]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_CTIME, item)
            colorTableItem(item, self.stat.getTotalTime(), value[3])
            #Filename
            self.tableWidget.setItem(row, STAT_FILENAME,
                                        StatTableWidgetItem(str(key[0])))
            #Line
            item = StatTableWidgetItem(str(key[1]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_LINE, item)
            #Function name
            self.tableWidget.setItem(row, STAT_FUNCTION,
                                        StatTableWidgetItem(str(key[2])))
            row += 1
            # Store it in stat hash array
            self.stat.setStatLink(item, key, TAB_FUNCTIONSTAT)
            progress.setValue(row)
            if progress.wasCanceled():
                return

        for i in range(self.tableWidget.rowCount()):
            progress.setValue(row + i)
            for j in range(self.tableWidget.columnCount()):
                item = self.tableWidget.item(i, j)
                if item:
                    item.setFlags(Qt.ItemIsEnabled)

        self.tableWidget.setSortingEnabled(True)
        self.resizeWidgetToContent(self.tableWidget)
        progress.setValue(2 * rowCount)

    def on_tableWidget_itemDoubleClicked(self, item):
        matchedItems = []
        filename = str(self.tableWidget.item(item.row(), STAT_FILENAME).text())
        if not filename or filename.startswith("<"):
            # No source code associated, return immediatly
            return
        function = self.tableWidget.item(item.row(), STAT_FUNCTION).text()
        line = self.tableWidget.item(item.row(), STAT_LINE).text()

        self.on_tabWidget_currentChanged(TAB_SOURCE)  # load source tab
        function = "%s (%s)" % (function, line)
        fathers = self.sourceTreeWidget.findItems(filename, Qt.MatchContains,
                                                  SOURCE_FILENAME)
        print(("find %s father" % len(fathers)))
        for father in fathers:
            findItems(father, function, SOURCE_FILENAME, matchedItems)
        print(("find %s items" % len(matchedItems)))

        if matchedItems:
            self.tabWidget.setCurrentIndex(TAB_SOURCE)
            self.sourceTreeWidget.scrollToItem(matchedItems[0])
            self.on_sourceTreeWidget_itemClicked(matchedItems[0],
                                                 SOURCE_FILENAME)
            matchedItems[0].setSelected(True)
        else:
            print("oups, item found but cannot scroll to it !")

    #=======================================================================#
    # Source explorer                                                      #
    #=====================================================================#

    def populateSource(self):
        items = {}
        for stat in self.stat.getStatKeys():
            source = stat[0]
            function = "%s (%s)" % (stat[2], stat[1])
            if source in ("", "profile") or source.startswith("<"):
                continue
            # Create the function child
            child = QTreeWidgetItem([function])
            # Store it in stat hash array
            self.stat.setStatLink(child, stat, TAB_SOURCE)
            if source in items:
                father = items[source]
            else:
                # Create the father
                father = QTreeWidgetItem([source])
                items[source] = father
            father.addChild(child)
        self.sourceTreeWidget.setSortingEnabled(False)
        for value in list(items.values()):
            self.sourceTreeWidget.addTopLevelItem(value)
        self.sourceTreeWidget.setSortingEnabled(True)

    def on_sourceTreeWidget_itemActivated(self, item, column):
        self.on_sourceTreeWidget_itemClicked(item, column)

    def on_sourceTreeWidget_itemClicked(self, item, column):
        line = 0
        parent = item.parent()
        if QSCI:
            doc = self.sourceTextEdit
        if parent:
            pathz = parent.text(column)
            result = match("(.*) \(([0-9]+)\)", item.text(column))
            if result:
                try:
                    function = str(result.group(1))
                    line = int(result.group(2))
                except ValueError:
                    # We got garbage... falling back to line 0
                    pass
        else:
            pathz = item.text(column)
        pathz = path.abspath(str(pathz))
        if self.currentSourcePath != pathz:
            # Need to load source
            self.currentSourcePath == pathz
            try:
                if QSCI:
                    doc.clear()
                    doc.insert(file(pathz).read())
                else:
                    self.sourceTextEdit.setPlainText(file(pathz).read())
            except IOError:
                QMessageBox.warning(self,
                                     "Error", "Source file could not be found",
                                     QMessageBox.Ok)
                return

            if QSCI:
                for function, line in [(i[2], i[1]
                           ) for i in self.stat.getStatKeys() if i[0] == pathz]:
                    # expr, regexp, case sensitive, whole word, wrap, forward
                    doc.findFirst("def", False, True, True, False, True, line,
                                  0, True)
                    end, foo = doc.getCursorPosition()
                    time = self.stat.getStatTotalTime((pathz, line, function))
                    colorSource(doc, self.stat.getTotalTime(), time, line, end,
                                self.marker)
        if QSCI:
            doc.ensureLineVisible(line)