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()