taste-progress-dialog.py 4.23 KB
Newer Older
1 2
#!/usr/bin/env python

3
from __future__ import print_function
4 5 6
import sys
import time
import signal
7
import os
8
from collections import deque
9

10
import PySide
11 12
from PySide import QtGui
from PySide.QtCore import QThread, Signal, QObject, Qt, Slot
13 14 15

from PySide.QtGui import (QApplication,
                          QMessageBox,
16 17
                          QDialog,
                          QPushButton,
18 19
                          QProgressDialog)

20 21 22 23 24
log = deque()




25
class MyThread(QThread, QObject):
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
    ''' Thread waiting for data on stdin and sending signals to the prgress
    bar in case something came in.
    Text can be formatted:
      * if the line starts with a number, it will use the value (range 0..100)
        to update the progress bar, and it will display the text above the bar.
      * if the line starts with @ERROR@ the process will stop and all the
        history will be dispayed in a log dialog.
      * in all other cases, the line is appended to the log
    '''
    text       = Signal(str)
    progress   = Signal(int)
    end        = Signal()
    error      = Signal()
    force_quit = False

41 42 43 44
    def run(self):
        value = 10
        while True:
            # read from stdin without any buffering
45 46
            if self.force_quit:
                return
47 48
            line = sys.stdin.readline()
            if len(line) == 0:
49 50
                print("Bye")
                self.end.emit()
51 52
                return
            else:
53
                split = line.split()
Maxime Perrotin's avatar
Maxime Perrotin committed
54
                try:
55
                    # check for format "NUMBER text"
Maxime Perrotin's avatar
Maxime Perrotin committed
56 57
                    possible_val = split[0]
                    value = int(possible_val)
58 59
                    if 100 < value < 0:
                        raise ValueError
Maxime Perrotin's avatar
Maxime Perrotin committed
60 61
                    text = ' '.join(split[1:])
                    self.progress.emit(value)
62 63 64 65
                    self.text.emit(text)
                    if value == 100:
                        self.end.emit()
                        return
Maxime Perrotin's avatar
Maxime Perrotin committed
66 67
                except (ValueError, IndexError):
                    text = line
68
                log.append(text)
69 70 71
                try:
                    if split[0] == '@ERROR@':
                        self.error.emit()
72
                        return
73 74
                except IndexError:
                    pass
75

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
class MyDialog(QDialog):
    def __init__(self):
        super(MyDialog, self).__init__()
        self.bar         = QtGui.QProgressBar()
        self.more_button = QtGui.QPushButton("Details")
        self.extension   = QtGui.QWidget()
        self.log_window  = QtGui.QListWidget()
        self.label       = QtGui.QLabel()

        # Layouts
        self.top_layout  = QtGui.QVBoxLayout()
        self.ext_layout  = QtGui.QVBoxLayout()
        self.main_layout = QtGui.QVBoxLayout()

        self.more_button.setCheckable(True)
        self.more_button.hide()
        self.more_button.toggled.connect(self.log_window.setVisible)

        self.top_layout.addWidget(self.label)
        self.top_layout.addWidget(self.bar)
        #self.top_layout.addWidget(self.more_button)
        self.top_layout.setStretch(0, 0)
        self.top_layout.setStretch(1, 0)
        self.top_layout.setStretch(2, 1)
        self.main_layout.addLayout(self.top_layout)
        self.main_layout.addWidget(self.log_window)
        self.setLayout(self.main_layout)
        self.main_layout.setStretch(2, 1)
        self.setWindowTitle("TASTE")
        self.extension.hide()
        self.log_window.hide()

        self.done = False

    @Slot()
    def complete_or_cancel(self):
        self.done = True

    def closeEvent(self, e):
        if not self.done:
            e.ignore()


def handle_error():
    print("== An error occured, here is the log ==")
    print("\n".join(log))
122 123 124


def run_gui():
125 126 127 128 129
    app       = QApplication(sys.argv)
    thread    = MyThread()
    dialog    = MyDialog()
    progress  = dialog.bar

130 131
    progress.setValue(0)

132 133 134
    thread.text.connect     (dialog.label.setText)
    thread.end.connect      (dialog.complete_or_cancel)
    thread.end.connect      (dialog.close)
135
    thread.progress.connect (progress.setValue)
136
    thread.error.connect    (handle_error)
137 138

    thread.start()
139 140
    dialog.exec_()

141
    thread.wait()
142 143 144 145 146 147 148 149

def main():
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    run_gui()

if __name__ == '__main__':
    main()