コード例 #1
0
class 진행바(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.bar1 = QProgressBar(self)
        self.bar1.setOrientation(Qt.Vertical)  #Horizontal
        self.bar1.setGeometry(50, 50, 50, 300)  # (x, y, width, height)

        self.bar2 = QProgressBar(self)
        self.bar2.setGeometry(150, 200, 250, 30)  # (x, y, width, height)
        self.bar2.setRange(0, 50)

        self.label1 = QLabel(
            f'이 바의 범위는 {self.bar2.minimum()} 부터 {self.bar2.maximum()} 입니다.',
            self)
        self.label1.move(170, 240)

        self.label2 = QLabel('이 곳에 첫 번째 바의 값이 나옵니다.', self)
        self.label2.move(50, 360)

        self.btn = QPushButton('시작', self)
        self.btn.move(50, 390)
        self.btn.clicked.connect(self.runTimer)

        self.value = 0
        self.timer = QBasicTimer()
        self.bar1.valueChanged.connect(self.changeValue)

        self.setGeometry(300, 300, 500, 500)
        self.setWindowTitle('QProgressBar')
        self.show()

    def runTimer(self):
        if self.timer.isActive():
            self.timer.stop()
            self.btn.setText('시작')
        else:
            self.timer.start(self.bar1.maximum(), self)
            self.btn.setText('중지')

    def timerEvent(self, event):
        if self.value >= self.bar1.maximum():
            self.timer.stop()
            self.btn.setText('완료')
            return
        self.value += 1
        self.bar1.setValue(self.value)

    def changeValue(self):
        self.label2.setText(str(self.bar1.value()))
コード例 #2
0
class ProgressWindow(QWidget):
    def __init__(self, maximum, txt):
        QWidget.__init__(self)
        self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint)

        self.setWindowTitle("Traitement en cours...")
        self.resize(400, 40)
        # self.setWindowFlags(self.windowFlags() | Qt.Window)
        self.setWindowModality(Qt.ApplicationModal)

        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        self.label = QLabel(str(txt))
        self.layout.addWidget(self.label)

        self.bar = QProgressBar()
        self.layout.addWidget(self.bar)

        self.bar.setMinimum(0)
        self.bar.setMaximum(maximum)

        self.show()
        QCoreApplication.processEvents()

    def set(self, k, txt):
        if k == None: k = self.bar.value() + 1
        if k >= self.bar.maximum(): self.deleteLater()
        self.bar.setValue(k)
        self.label.setText(txt)
        QCoreApplication.processEvents()
コード例 #3
0
class ProgressDialog(QDialog):
    def __init__(self, parent, limit):
        super().__init__(parent)
        self.setWindowModality(Qt.ApplicationModal)
        self.setWindowTitle('Parsing Replay')
        self.setMinimumSize(QSize(400, 75))
        self.setMaximumSize(QSize(400, 75))
        vlayout = QVBoxLayout(self)
        vlayout.setSizeConstraint(QLayout.SetMinAndMaxSize)

        self.pbar = QProgressBar(self)
        self.pbar.setRange(0, limit)
        self.pbar.setAlignment(Qt.AlignCenter)
        self.pbar.setFormat("Parsing Netstream %p%")
        self.pbar.setMinimumSize(QSize(380, 20))
        self.pbar.setMaximumSize(QSize(380, 20))
        size_policy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.pbar.setSizePolicy(size_policy)
        vlayout.addWidget(self.pbar)

        self.btn_cancel = QPushButton(self)
        self.btn_cancel.setSizePolicy(size_policy)
        self.btn_cancel.setMinimumSize(QSize(120, 23))
        self.btn_cancel.setMaximumSize(QSize(120, 23))
        self.btn_cancel.setText("MISSION ABORT!")
        size_policy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.btn_cancel.setSizePolicy(size_policy)
        vlayout.addWidget(self.btn_cancel)

        self.btn_cancel.clicked.connect(self.close)

    def set_value(self, value):
        self.pbar.setProperty("value", value)
        if value == self.pbar.maximum():
            self.close()
コード例 #4
0
class MyProgressDlg(QDialog):
    
    def __init__(self,parent):
        super(MyProgressDlg,self).__init__(parent)
        self.progress = QProgressBar(self)
        self.setModal(True)
        
        self.__initUI()
        self.hide()

    def __initUI(self):
        self.progress.valueChanged.connect(self.processValuechanged)
        self.progress.setMaximum(100)
        self.label = QLabel(self)
        self.label.setText("Please wait for loading")
        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.progress)
        self.resize(200,100)
        self.setWindowTitle("Loading...")
        pass

    def processValuechanged(self,value):
        if(value == self.progress.maximum()):
            self.hide()
        else:
            pass
コード例 #5
0
class LoadStage2QT(QDialog):
    """
    Dialog with a Progress Bar marking the progress of loading the data.
    Adapted from: https://stackoverflow.com/documentation/pyqt5/9544/introduction-to-progress-bars#t=201709081442594430681
    """
    def __init__(self, chart_panel, mainwindow, func_dict):
        super().__init__(mainwindow)
        self.chart_panel = chart_panel
        self.progress_helper = ProgressHelper()
        self.func_dict = func_dict
        self.func_count = 0
        self.initUI()

    def initUI(self):
        self.setWindowTitle('Initializing...')
        self.progress = QProgressBar(self)
        self.progress_helper.set_bar(self.progress)
        self.progress.setGeometry(0, 0, 300, 25)
        self.progress.setRange(0, 0)
        self.progress.setTextVisible(False)
        self.show()

        self.calc = Stage2LoadThread(self.chart_panel, self, self.func_dict)
        self.calc.set_progress_helper(self.progress_helper)
        self.calc.countChanged.connect(self.on_count_changed)
        self.calc.start()

    def on_count_changed(self, value):
        if value < 0:
            self.accept()
            self.chart_panel.plot_data_updated()
        elif value == 0:
            self.setWindowTitle("Computing analysis...")
            self.func_count += 1
            self.progress.setFormat(
                '{:1.0f}%'.format(100.0 * value / self.progress.maximum()) +
                ' (' + str(self.func_count) + ' of 5)')
            self.progress.setValue(value)
        else:
            self.progress.setFormat(
                '{:1.0f}%'.format(100.0 * value / self.progress.maximum()) +
                ' (' + str(self.func_count) + ' of 5)')
            self.progress.setValue(value)
コード例 #6
0
ファイル: widgets.py プロジェクト: c0re100/vidcutter
class VCProgressBar(QDialog):
    def __init__(self, parent=None, flags=Qt.FramelessWindowHint):
        super(VCProgressBar, self).__init__(parent, flags)
        self.parent = parent
        if sys.platform.startswith('linux'):
            self.taskbar = TaskbarProgress(self)
        self._progress = QProgressBar(self.parent)
        self._progress.setRange(0, 0)
        self._progress.setTextVisible(False)
        self._progress.setStyle(QStyleFactory.create('fusion'))
        self._label = QLabel(parent)
        self._label.setAlignment(Qt.AlignCenter)
        layout = QGridLayout()
        layout.addWidget(self._progress, 0, 0)
        layout.addWidget(self._label, 0, 0)
        self.setWindowModality(Qt.ApplicationModal)
        self.setMinimumWidth(500)
        self.setLayout(layout)

    def value(self) -> int:
        return self._progress.value()

    def setStyle(self, style: QStyle) -> None:
        self._progress.setStyle(style)

    def setText(self, val: str) -> None:
        self._label.setText(val)

    def setMinimum(self, val: int) -> None:
        self._progress.setMinimum(val)

    def setMaximum(self, val: int) -> None:
        self._progress.setMaximum(val)

    def setRange(self, minval: int, maxval: int) -> None:
        self._progress.setRange(minval, maxval)

    def setValue(self, val: int) -> None:
        if sys.platform.startswith('linux'):
            self.taskbar.setProgress(float(val / self._progress.maximum()),
                                     True)
        self._progress.setValue(val)

    def updateProgress(self, value: int, text: str) -> None:
        self.setValue(value)
        self.setText(text)
        qApp.processEvents()

    @pyqtSlot()
    def close(self) -> None:
        if sys.platform.startswith('linux'):
            self.taskbar.clear()
        self.deleteLater()
        super(VCProgressBar, self).close()
コード例 #7
0
class ProgressDialog(QDialog):
    def __init__(self, parent=None, **kwargs):
        super().__init__(parent, **kwargs)

        self._errors = 0

        l = QFormLayout(self)

        self._file_list_progress = QProgressBar(self)
        self._file_list_progress.setFormat("%v/%m")
        l.addRow("Files copied:", self._file_list_progress)

        self._file_copy_progress = QProgressBar(self)
        l.addRow("Current File Progress:", self._file_copy_progress)

        self._current_file_label = QLabel(self)
        l.addRow("", self._current_file_label)

        self._error_count_label = QLabel("0", self)
        l.addRow("Errors:", self._error_count_label)

        self._button_box = QDialogButtonBox(QDialogButtonBox.Ok, self)
        self._button_box.button(QDialogButtonBox.Ok).setEnabled(False)
        self._button_box.accepted.connect(self.accept)
        l.addWidget(self._button_box)

        self.setModal(True)

    def set_file_dict(self, file_dict: Dict[str, str]):
        self._file_dict = file_dict
        self._file_list_progress.setRange(0, len(file_dict))
        self._file_list_progress.setValue(0)
        self._errors = 0

    def set_file_progress(self, uid: str, progress: int, total: int):
        current_file: FileModelRecord = self._file_dict[uid]
        self._current_file_label.setText(current_file.file_name)
        self._file_copy_progress.setRange(0, total)
        self._file_copy_progress.setValue(progress)

    def file_copy_error(self, uid: str):
        self._file_dict.pop(uid)
        self._file_list_progress.setRange(0, len(self._file_dict))
        self._errors += 1
        self._error_count_label.setText(f"{self._errors}")

    def file_copy_finished(self):
        self._file_list_progress.setValue(self._file_list_progress.value() + 1)
        if self._file_list_progress.value(
        ) == self._file_list_progress.maximum():
            self._current_file_label.setText("")
            self._button_box.button(QDialogButtonBox.Ok).setEnabled(True)
コード例 #8
0
ファイル: SvgPackage.py プロジェクト: coyove/RouteMaster
class Loader(QMainWindow):
    Single = None

    def __init__(self):
        super().__init__(flags=QtCore.Qt.WindowType.WindowCloseButtonHint
                         | QtCore.Qt.WindowType.WindowStaysOnTopHint)
        self.setWindowTitle(APP_NAME)
        self.setMaximumWidth(WIN_WIDTH * 2)
        self.show()

        w = QWidget(self)
        box = QVBoxLayout()
        w.setLayout(box)

        self.bar = QProgressBar(w)
        self.bar.show()
        self.bar.setRange(0, 0)

        box.addWidget(QLabel(TR("__download_icons__")), 1)
        self.progress = QLabel('0')
        box.addWidget(self.progress)
        box.addWidget(self.bar, 1)

        self.setCentralWidget(w)
        self.setVisible(False)
        self.tasks = set()
        Loader.Single = self

    def addTask(self, fn: str):
        if fn in self.tasks:
            return
        self.tasks.add(fn)
        loading = LoadTask(self, fn)
        loading.start()
        self.setVisible(True)
        self.updateProgress()
        self.bar.setMaximum(self.bar.maximum() + 1)
        loading.taskFinished.connect(lambda: self.onComplete(fn))

    def updateProgress(self):
        self.progress.setText('({}) -> {}'.format(len(self.tasks),
                                                  '/'.join(self.tasks)))

    def onComplete(self, fn: str) -> None:
        self.tasks.remove(fn)
        self.updateProgress()
        self.bar.setValue(self.bar.value() + 1)
        if len(self.tasks) == 0:
            self.setVisible(False)
            SvgSource.Search.reload()
コード例 #9
0
ファイル: multi_fit.py プロジェクト: StarostinV/GIWAXS_GUI_2
class ProgressWidget(QWidget):
    def __init__(self,
                 num: int,
                 progress_label: str,
                 finish_label: str,
                 parent=None):
        super().__init__(parent)
        self.progress_label: str = progress_label
        self.finish_label: str = finish_label

        self.setWindowFlag(Qt.Window)
        self.setWindowFlag(Qt.FramelessWindowHint)
        self.setWindowModality(Qt.ApplicationModal)
        self.setAttribute(Qt.WA_DeleteOnClose, True)

        self._init_ui(num)
        center_widget(self)
        self.show()

    def _init_ui(self, num: int):
        layout = QVBoxLayout(self)
        self.progress = QProgressBar()
        self.progress.setMaximum(num)
        self.close_button = QPushButton('Close')
        self.close_button.clicked.connect(self.close)
        self.label = QLabel(self.progress_label)
        layout.addWidget(self.label)
        layout.addWidget(self.progress)
        layout.addWidget(self.close_button)
        self.close_button.hide()

        if not num:
            self.progress.setMaximum(1)
            self.progress.setValue(1)
            self.finished()

    @pyqtSlot(int, name='setProgress')
    def set_progress(self, value: int):
        self.progress.setValue(value)

    @pyqtSlot(name='finished')
    def finished(self):
        self.label.setText(self.finish_label)
        self.progress.setValue(self.progress.maximum())
        self.close_button.show()
コード例 #10
0
ファイル: statusbar.py プロジェクト: mthnzbk/domestic
class StatusBar(QStatusBar):
    def __init__(self, parent=None):
        super(QStatusBar, self).__init__(parent)
        self.parent = parent
        self.progress = QProgressBar(self)
        self.progress.setFormat("%v/%m")
        self.progress.setTextVisible(False)
        self.progress.setMaximumWidth(200)
        self.addPermanentWidget(self.progress)
        self.count = 0
        self.progress.hide()

    def setProgress(self):
        self.count += 1
        self.progress.setValue(self.count)
        if self.progress.maximum() > self.count:
            self.progress.show()
        else:
            QApplication.restoreOverrideCursor()
            self.progress.hide()
            self.count = 0
コード例 #11
0
ファイル: share.py プロジェクト: ChiNeSeFree/gridsync
class InviteReceiver(QDialog):
    done = pyqtSignal(QWidget)
    closed = pyqtSignal(QWidget)

    def __init__(self, gateways):
        super(InviteReceiver, self).__init__()
        self.gateways = gateways
        self.wormhole = None
        self.setup_runner = None
        self.joined_folders = []
        self.use_tor = False

        self.setMinimumSize(500, 300)

        self.mail_closed_icon = QLabel()
        self.mail_closed_icon.setPixmap(
            QPixmap(resource('mail-envelope-closed.png')).scaled(128, 128))
        self.mail_closed_icon.setAlignment(Qt.AlignCenter)

        self.mail_open_icon = QLabel()
        self.mail_open_icon.setPixmap(
            QPixmap(resource('mail-envelope-open.png')).scaled(128, 128))
        self.mail_open_icon.setAlignment(Qt.AlignCenter)

        self.folder_icon = QLabel()
        icon = QFileIconProvider().icon(QFileInfo(config_dir))
        self.folder_icon.setPixmap(icon.pixmap(128, 128))
        self.folder_icon.setAlignment(Qt.AlignCenter)

        self.invite_code_widget = InviteCodeWidget(self)
        self.label = self.invite_code_widget.label
        self.tor_checkbox = self.invite_code_widget.checkbox
        self.tor_checkbox.stateChanged.connect(self.on_checkbox_state_changed)
        self.lineedit = self.invite_code_widget.lineedit
        self.lineedit.error.connect(self.show_error)
        self.lineedit.go.connect(self.go)

        self.tor_label = QLabel()
        self.tor_label.setToolTip(
            "This connection is being routed through the Tor network.")
        self.tor_label.setPixmap(
            QPixmap(resource('tor-onion.png')).scaled(32, 32))

        self.progressbar = QProgressBar(self)
        self.progressbar.setValue(0)
        self.progressbar.setMaximum(6)  # XXX
        self.progressbar.setTextVisible(False)

        self.message_label = QLabel()
        self.message_label.setStyleSheet("color: grey")
        self.message_label.setAlignment(Qt.AlignCenter)

        self.error_label = QLabel()
        self.error_label.setStyleSheet("color: red")
        self.error_label.setAlignment(Qt.AlignCenter)

        self.close_button = QPushButton("Close")
        self.close_button.clicked.connect(self.close)

        layout = QGridLayout(self)
        layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 0, 0)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 2)
        layout.addWidget(self.mail_closed_icon, 1, 2, 1, 3)
        layout.addWidget(self.mail_open_icon, 1, 2, 1, 3)
        layout.addWidget(self.folder_icon, 1, 2, 1, 3)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 4)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 5)
        layout.addWidget(self.label, 2, 3, 1, 1)
        layout.addWidget(self.tor_label, 3, 1, 1, 1,
                         Qt.AlignRight | Qt.AlignVCenter)
        layout.addWidget(self.lineedit, 3, 2, 1, 3)
        layout.addWidget(self.progressbar, 3, 2, 1, 3)
        layout.addWidget(self.tor_checkbox, 4, 2, 1, 3, Qt.AlignCenter)
        layout.addWidget(self.message_label, 5, 1, 1, 5)
        layout.addWidget(self.error_label, 5, 2, 1, 3)
        layout.addWidget(self.close_button, 6, 3)
        layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 7, 1)

        self.reset()

    def reset(self):
        self.mail_open_icon.hide()
        self.folder_icon.hide()
        self.mail_closed_icon.show()
        self.label.setText("Enter invite code:")
        self.lineedit.show()
        self.lineedit.setText('')
        self.tor_checkbox.show()
        self.progressbar.hide()
        self.message_label.setText(
            "Invite codes can be used to join a grid or a folder")
        self.error_label.setText('')
        self.error_label.hide()
        self.close_button.hide()
        self.tor_label.hide()

    def on_checkbox_state_changed(self, state):
        self.use_tor = bool(state)
        logging.debug("use_tor=%s", self.use_tor)
        if state:
            self.progressbar.setStyleSheet(
                'QProgressBar::chunk {{ background-color: {}; }}'.format(
                    TOR_PURPLE))
        else:
            self.progressbar.setStyleSheet('')

    def show_error(self, text):
        self.error_label.setText(text)
        self.message_label.hide()
        self.error_label.show()
        reactor.callLater(3, self.error_label.hide)
        reactor.callLater(3, self.message_label.show)

    def update_progress(self, message):
        step = self.progressbar.value() + 1
        self.progressbar.setValue(step)
        self.message_label.setText(message)
        if step == 3:
            self.mail_closed_icon.hide()
            self.mail_open_icon.show()
        if step == 4:
            self.mail_open_icon.hide()
            self.folder_icon.show()

    def set_joined_folders(self, folders):
        self.joined_folders = folders

    def on_done(self, _):
        self.progressbar.setValue(self.progressbar.maximum())
        self.close_button.show()
        self.done.emit(self)
        self.label.setPixmap(
            QPixmap(resource('green_checkmark.png')).scaled(32, 32))
        if self.joined_folders and len(self.joined_folders) == 1:
            target = self.joined_folders[0]
            self.message_label.setText(
                'Successfully joined folder "{0}"!\n"{0}" is now available '
                'for download'.format(target))
        elif self.joined_folders:
            target = humanized_list(self.joined_folders, 'folders')
            self.message_label.setText(
                'Successfully joined {0}!\n{0} are now available for '
                'download'.format(target))

    def on_grid_already_joined(self, grid_name):
        QMessageBox.information(
            self, "Already connected",
            'You are already connected to "{}"'.format(grid_name))
        self.close()

    def got_message(self, message):
        self.update_progress("Reading invitation...")  # 3
        message = validate_settings(message, self.gateways, self)
        self.setup_runner = SetupRunner(self.gateways, self.use_tor)
        if not message.get('magic-folders'):
            self.setup_runner.grid_already_joined.connect(
                self.on_grid_already_joined)
        self.setup_runner.update_progress.connect(self.update_progress)
        self.setup_runner.joined_folders.connect(self.set_joined_folders)
        self.setup_runner.done.connect(self.on_done)
        self.setup_runner.run(message)

    def got_welcome(self):
        self.update_progress("Connected; waiting for message...")  # 2

    def handle_failure(self, failure):
        logging.error(str(failure))
        if failure.type == CancelledError and self.progressbar.value() > 2:
            return
        show_failure(failure, self)
        self.close()

    def go(self, code):
        self.reset()
        self.label.setText(' ')
        self.lineedit.hide()
        self.tor_checkbox.hide()
        self.progressbar.show()
        if self.use_tor:
            self.tor_label.show()
        self.update_progress("Verifying invitation...")  # 1
        if code.split('-')[0] == "0":
            settings = get_settings_from_cheatcode(code[2:])
            if settings:
                self.got_message(settings)
                return
        self.wormhole = Wormhole(self.use_tor)
        self.wormhole.got_welcome.connect(self.got_welcome)
        self.wormhole.got_message.connect(self.got_message)
        d = self.wormhole.receive(code)
        d.addErrback(self.handle_failure)
        reactor.callLater(30, d.cancel)

    def enterEvent(self, event):
        event.accept()
        self.lineedit.update_action_button()

    def closeEvent(self, event):
        event.accept()
        try:
            self.wormhole.close()
        except AttributeError:
            pass
        self.closed.emit(self)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            self.close()
コード例 #12
0
ファイル: kbslider.py プロジェクト: cutie/KanvasBuddy
class KBSliderSpinBox(QWidget):  # Base Class
    def __init__(self, min=0, max=100, parent=None):
        super(KBSliderSpinBox, self).__init__(parent)
        self.setMinimumWidth(100)
        self.setFixedHeight(16)
        self.setLayout(QStackedLayout(self))
        self.layout().setStackingMode(QStackedLayout.StackAll)
        self.setCursor(Qt.SplitHCursor)
        self.scaling = 1

        self.progbar = QProgressBar(self)
        self.progbar.setRange(min, max)
        self.progbar.setValue(0)

        self.spinbox = QSpinBox(self)
        self.spinbox.setRange(min, max)
        self.spinbox.setAlignment(Qt.AlignHCenter)
        self.spinbox.setButtonSymbols(self.spinbox.NoButtons)

        self.layout().addWidget(self.spinbox)
        self.layout().addWidget(self.progbar)

        self.spinbox.hide()

        self.spinbox.editingFinished.connect(self.closeSpinBox)
        self.spinbox.lineEdit().returnPressed.connect(self.closeSpinBox)
        self.spinbox.valueChanged.connect(self.updateFormat)
        self.spinbox.valueChanged.connect(self.updateProgBar)

    def mousePressEvent(self, e):
        if e.buttons() == Qt.LeftButton:
            self.setFocus()
            delta = e.pos().x() / self.width()
            self.spinbox.setValue(delta**self.scaling * self.spinbox.maximum())
            self.progbar.setValue(delta * self.progbar.maximum())

    def updateProgBar(self):
        delta = (self.spinbox.value() / self.spinbox.maximum())**(1. /
                                                                  self.scaling)
        self.progbar.setValue(delta * self.progbar.maximum())

    def mouseMoveEvent(self, e):
        self.mousePressEvent(e)

    def mouseDoubleClickEvent(self, e):
        self.openSpinBox()

    def keyPressEvent(self, e):
        if (e.key() == Qt.Key_Return or e.key() == Qt.Key_Enter
                or e.key() == Qt.Key_Escape):
            if self.spinbox.isVisible():
                self.closeSpinBox()
        elif e.text().isdecimal():
            if self.spinbox.isHidden():
                self.openSpinBox()
                self.spinbox.lineEdit().keyPressEvent(e)

    def closeSpinBox(self):
        self.spinbox.clearFocus()
        self.spinbox.hide()

    def openSpinBox(self):
        self.spinbox.show()
        self.spinbox.lineEdit().clear()
        self.spinbox.lineEdit().setFocus()

    def setMinimum(self, min):
        self.spinbox.setMinimum(min)

    def setMaximum(self, max):
        self.spinbox.setMinimum(max)

    def setRange(self, min, max):
        self.spinbox.setRange(min, max)

    def setScaling(self, s):
        self.scaling = s

    def updateFormat(self):
        self.progbar.setFormat(
            f"{self.spinbox.prefix()}{self.spinbox.value()}{self.spinbox.suffix()}"
        )

    def value(self):
        return self.spinbox.value()

    def setValue(self, val):
        self.spinbox.setValue(val)
        self.updateProgBar()

    def setPrefix(self, pre):
        self.spinbox.setPrefix(pre)

    def setSuffix(self, suf):
        self.spinbox.setSuffix(suf)

    def setAffixes(self, pre, suf):
        self.spinbox.setPrefix(pre)
        self.spinbox.setSuffix(suf)
        self.updateFormat()

    def connectValueChanged(self, func):
        self.spinbox.valueChanged.connect(func)
コード例 #13
0
class SpellCheckApp(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.initUI()

    def initUI(self):
        self.setWindowTitle('맞춤법 검사기')
        self.resize(600, 300)
        self.setWindowIcon(QIcon('pencil.png'))

        self.setStyleSheet(
            'QPushButton{border-radius: 5px; border: 1px solid #ccc;'
            'padding: 5px; background-color:white; color: #555;}'
            'QPushButton:pressed{background-color:#ccc;}'
            'QPushButton:flat{background-color:#03cf5d; color:white; font-weight:bold;}'
            'QTextEdit{padding:5px; border-radius:5px; border: 1px solid #ccc;'
            'background-color:white; color: #555;}'
            'QProgressBar{border: 1px solid #ccc; padding: 2px;'
            'border-radius: 5px; text-align:center; font-weight:bold;'
            'background-color:white; color:#333;}'
            'QProgressBar::chunk{background-color:#03CF5D;'
            'border-radius:5px;}')

        grid = QGridLayout()

        self.check = QPushButton('검사', self)
        self.check.clicked.connect(self._check_)
        self.clear = QPushButton('초기화', self)
        self.clear.clicked.connect(self.clear_all)
        self.load = QPushButton('불러오기', self)
        self.load.clicked.connect(self.open_file)
        self.save = QPushButton('저장', self)
        self.save.clicked.connect(self.save_file)
        self.top = QPushButton('항상 위', self)
        self.top.clicked.connect(self.allways_top)
        self.origin = QTextEdit()
        self.origin.setAcceptRichText(False)
        self.origin.setPlaceholderText('검사할 내용을 작성하거나 텍스트 파일을 불러오세요.')
        self.checked = QTextBrowser()
        self.copy = QPushButton('복사', self)
        self.copy.clicked.connect(self._copy_)
        self.checked.setToolTip('<b><p style="color:red">맞춤법</p>'
                                '<p style="color:#B22AF8">표준어 의심</p>'
                                '<p style="color:#03CF5D">띄어쓰기</p>'
                                '<p style="color:blue">통계적 교정</p></b>')
        self.checked.setAcceptRichText(True)
        self.checked.setReadOnly(True)
        self.pb = QProgressBar()

        grid.addWidget(self.load, 0, 0)
        grid.addWidget(self.check, 0, 1)
        grid.addWidget(self.clear, 0, 2)
        grid.addWidget(self.save, 0, 3)
        grid.addWidget(self.copy, 0, 4)
        grid.addWidget(self.top, 0, 5)

        grid.addWidget(self.origin, 1, 0, 1, 3)
        grid.addWidget(self.checked, 1, 3, 1, 3)
        grid.addWidget(self.pb, 2, 0, 1, 6)

        self.setLayout(grid)

        self.show()

    def open_file(self):
        file_name = QFileDialog.getOpenFileName(
            self, 'Open', '', 'Text Files(*.txt);; All Files(*)', '')
        if file_name[0]:
            self.clear_all()
            with open(file_name[0], 'r', encoding='utf8') as f:
                lines = f.readlines()
                for line in lines:
                    self.origin.append(line)

    def clear_all(self):
        self.origin.clear()
        self.checked.clear()

    def _check_(self):
        txt = self.origin.toPlainText()
        self.checked.clear()

        self.pb.setMaximum(len(txt))

        self.get_thread = SpellCheckThread(txt)
        self.get_thread.progress.connect(self.get_progress_value)
        self.get_thread.add.connect(self.add)
        self.get_thread.start()
        self.checked.setEnabled(False)

    def save_file(self):
        file_name = QFileDialog.getSaveFileName(
            self, 'Save', '', 'Text File(*.txt);; All File(*)', '')
        if file_name[0]:
            with open(file_name[0], 'w', encoding='utf8') as f:
                lines = self.checked.toPlainText()
                f.writelines(lines)
                QMessageBox.about(self, 'Saved', file_name[0] + '에 저장했습니다.')

    def allways_top(self):
        if self.top.isFlat():
            self.top.setFlat(False)
            self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
        else:
            self.top.setFlat(True)
            self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
        self.show()

    def _copy_(self):
        self.checked.selectAll()
        self.checked.copy()

    @pyqtSlot(str)
    def add(self, txt):
        self.checked.insertHtml(txt)

    @pyqtSlot(int)
    def get_progress_value(self, val):
        self.pb.setValue(val)
        if val == self.pb.maximum():
            self.checked.setEnabled(True)
コード例 #14
0
ファイル: progressbar_dialog.py プロジェクト: sczyz/RASE
class ProgressBar(QDialog):
    """
    Generic progress bar dialog that run a Worker function.
    The worker function needs to define a sig_step and sig_done signals
    and must have a 'work' and 'abort' methods.
    Once finished, a sig_finished signal is emitted.
    """

    sig_abort_worker = pyqtSignal()
    sig_finished = pyqtSignal(bool)

    def __init__(self, parent):
        super(ProgressBar, self).__init__(parent)
        self.setWindowTitle('Progress')

        self.progress = QProgressBar(self)
        self.progress.setGeometry(0, 0, 300, 35)
        self.progress.setFormat("%p%")
        self.progress.setTextVisible(True)

        self.button_stop = QPushButton('Cancel', self)
        self.button_stop.clicked.connect(self.abort_worker)
        self.button_stop.move(0, 30)

        self.label = QLabel()
        self.label.setText("Estimating time remaining...")

        self.title = QLabel()
        self.title.setText("Working")

        self.layout = QGridLayout()
        self.layout.addWidget(self.title, 0, 0)
        self.layout.addWidget(self.progress, 1, 0)
        self.layout.addWidget(self.label, 2, 0)
        self.layout.addWidget(self.button_stop, 3, 0)

        self.setLayout(self.layout)
        self.setModal(True)
        self.show()

        self.t = 0
        # self.button_stop.setDisabled(True)

    def run(
        self,
        worker,
    ):
        # get the worker function to a
        self.worker = worker
        self.thread = QThread()
        self.worker.moveToThread(self.thread)

        # get progress messages from worker:
        self.worker.sig_step.connect(self.onCountChanged)
        self.worker.sig_done.connect(self.on_worker_done)

        # control worker:
        self.sig_abort_worker.connect(self.worker.abort)

        # get ready to start worker:
        self.thread.started.connect(self.worker.work)
        self.thread.start(
        )  # this will emit 'started' and start thread's event loop
        self.t = time.time()

    @pyqtSlot(int)
    def onCountChanged(self, value):
        self.progress.setValue(value)
        deltaT = (time.time() - self.t) / float(value)
        # self.t = curr_time
        time_str = str(int(deltaT * (self.progress.maximum() - value)) + 1)
        self.label.setText("Time Remaining: " + time_str + " seconds")

    @pyqtSlot(bool)
    def on_worker_done(self, value):
        self.thread.quit()
        self.thread.wait()
        self.close()
        self.sig_finished.emit(value)

    @pyqtSlot()
    def abort_worker(self):
        self.sig_abort_worker.emit()

    # override close event method to ensure thread is aborted
    def closeEvent(self, event):
        self.abort_worker()
        event.accept()  # let the window close
コード例 #15
0
ファイル: share.py プロジェクト: rustforfuture/gridsync
class InviteReceiverDialog(QDialog):
    done = pyqtSignal(object)  # Tahoe gateway
    closed = pyqtSignal(QWidget)

    def __init__(self, gateways):
        super(InviteReceiverDialog, self).__init__()
        self.gateways = gateways
        self.invite_receiver = None
        self.joined_folders = []

        self.setMinimumSize(500, 300)

        self.mail_closed_icon = QLabel()
        self.mail_closed_icon.setPixmap(
            QPixmap(resource('mail-envelope-closed.png')).scaled(128, 128))
        self.mail_closed_icon.setAlignment(Qt.AlignCenter)

        self.mail_open_icon = QLabel()
        self.mail_open_icon.setPixmap(
            QPixmap(resource('mail-envelope-open.png')).scaled(128, 128))
        self.mail_open_icon.setAlignment(Qt.AlignCenter)

        self.folder_icon = QLabel()
        icon = QFileIconProvider().icon(QFileInfo(config_dir))
        self.folder_icon.setPixmap(icon.pixmap(128, 128))
        self.folder_icon.setAlignment(Qt.AlignCenter)

        self.invite_code_widget = InviteCodeWidget(self)
        self.invite_code_widget.lineedit.go.connect(self.go)  # XXX

        self.tor_label = QLabel()
        self.tor_label.setToolTip(
            "This connection is being routed through the Tor network.")
        self.tor_label.setPixmap(
            QPixmap(resource('tor-onion.png')).scaled(24, 24,
                                                      Qt.KeepAspectRatio,
                                                      Qt.SmoothTransformation))

        self.checkmark = QLabel()
        self.checkmark.setAlignment(Qt.AlignCenter)
        self.checkmark.setPixmap(
            QPixmap(resource('green_checkmark.png')).scaled(32, 32))

        self.progressbar = QProgressBar(self)
        self.progressbar.setValue(0)
        self.progressbar.setMaximum(6)  # XXX
        self.progressbar.setTextVisible(False)

        self.message_label = QLabel(' ')
        self.message_label.setStyleSheet("color: grey")
        self.message_label.setAlignment(Qt.AlignCenter)

        self.error_label = QLabel()
        self.error_label.setStyleSheet("color: red")
        self.error_label.setAlignment(Qt.AlignCenter)

        self.close_button = QPushButton("Close")
        self.close_button.clicked.connect(self.close)

        layout = QGridLayout(self)
        layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 0, 0)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 2)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 3)
        layout.addWidget(self.mail_closed_icon, 1, 2, 1, 3)
        layout.addWidget(self.mail_open_icon, 1, 2, 1, 3)
        layout.addWidget(self.folder_icon, 1, 2, 1, 3)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 4)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 5)
        layout.addWidget(self.invite_code_widget, 2, 2, 1, 3)
        layout.addWidget(self.checkmark, 2, 3, 1, 1)
        layout.addWidget(self.tor_label, 3, 1, 1, 1,
                         Qt.AlignRight | Qt.AlignVCenter)
        layout.addWidget(self.progressbar, 3, 2, 1, 3)
        layout.addWidget(self.message_label, 5, 1, 1, 5)
        layout.addWidget(self.error_label, 5, 2, 1, 3)
        layout.addWidget(self.close_button, 6, 3)
        layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 7, 1)

        self.reset()

    def reset(self):
        self.mail_open_icon.hide()
        self.folder_icon.hide()
        self.mail_closed_icon.show()
        self.progressbar.hide()
        self.error_label.setText('')
        self.error_label.hide()
        self.close_button.hide()
        self.tor_label.hide()
        self.checkmark.hide()
        self.progressbar.setStyleSheet('')

    def show_error(self, text):
        self.error_label.setText(text)
        self.message_label.hide()
        self.error_label.show()
        reactor.callLater(3, self.error_label.hide)
        reactor.callLater(3, self.message_label.show)

    def update_progress(self, message):
        step = self.progressbar.value() + 1
        self.progressbar.setValue(step)
        self.message_label.setText(message)
        if step == 3:
            self.mail_closed_icon.hide()
            self.mail_open_icon.show()

    def set_joined_folders(self, folders):
        self.joined_folders = folders
        if folders:
            self.mail_open_icon.hide()
            self.folder_icon.show()

    def on_got_icon(self, path):
        self.mail_open_icon.setPixmap(QPixmap(path).scaled(128, 128))
        self.mail_closed_icon.hide()
        self.mail_open_icon.show()

    def on_done(self, gateway):
        self.progressbar.setValue(self.progressbar.maximum())
        self.close_button.show()
        self.checkmark.show()
        self.done.emit(gateway)
        if self.joined_folders and len(self.joined_folders) == 1:
            target = self.joined_folders[0]
            self.message_label.setText(
                'Successfully joined folder "{0}"!\n"{0}" is now available '
                'for download'.format(target))
        elif self.joined_folders:
            target = humanized_list(self.joined_folders, 'folders')
            self.message_label.setText(
                'Successfully joined {0}!\n{0} are now available for '
                'download'.format(target))
        self.close()  # TODO: Cleanup

    def on_grid_already_joined(self, grid_name):
        QMessageBox.information(
            self, "Already connected",
            'You are already connected to "{}"'.format(grid_name))
        self.close()

    def got_message(self, _):
        self.update_progress("Reading invitation...")  # 3

    def got_welcome(self):
        self.update_progress("Connected; waiting for message...")  # 2

    def handle_failure(self, failure):
        logging.error(str(failure))
        if failure.type == CancelledError and self.progressbar.value() > 2:
            return
        show_failure(failure, self)
        self.close()

    def go(self, code):
        self.reset()
        self.invite_code_widget.hide()
        self.progressbar.show()
        if self.invite_code_widget.tor_checkbox.isChecked():
            use_tor = True
            self.tor_label.show()
            self.progressbar.setStyleSheet(
                'QProgressBar::chunk {{ background-color: {}; }}'.format(
                    TOR_PURPLE))
        else:
            use_tor = False
        self.update_progress("Verifying invitation...")  # 1
        self.invite_receiver = InviteReceiver(self.gateways, use_tor)
        self.invite_receiver.got_welcome.connect(self.got_welcome)
        self.invite_receiver.got_message.connect(self.got_message)
        self.invite_receiver.grid_already_joined.connect(
            self.on_grid_already_joined)
        self.invite_receiver.update_progress.connect(self.update_progress)
        self.invite_receiver.got_icon.connect(self.on_got_icon)
        self.invite_receiver.joined_folders.connect(self.set_joined_folders)
        self.invite_receiver.done.connect(self.on_done)
        d = self.invite_receiver.receive(code)
        d.addErrback(self.handle_failure)
        reactor.callLater(30, d.cancel)

    def enterEvent(self, event):
        event.accept()
        self.invite_code_widget.lineedit.update_action_button()  # XXX

    def closeEvent(self, event):
        event.accept()
        try:
            self.invite_receiver.cancel()
        except AttributeError:
            pass
        self.closed.emit(self)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            self.close()
コード例 #16
0
ファイル: dialogs.py プロジェクト: UIUCLibrary/Speedwagon
 def set_progress_to_full(progress_bar: QtWidgets.QProgressBar) -> None:
     progress_bar.setValue(progress_bar.maximum())
コード例 #17
0
ファイル: qtgui3.py プロジェクト: jaebin-choi/pyspad
class WidgetGallery(QDialog):
    def __init__(self, parent=None):
        super(WidgetGallery, self).__init__(parent)

        # initialize GUI
        self.initializeGUI()

        # connect buttons
        self.btnRun.clicked.connect(self.ifbtnRunClicked)
        self.btnFlash.clicked.connect(self.ifbtnFlashClicked)
        self.btnReset.clicked.connect(self.ifbtnResetClicked)
        self.btnStop.clicked.connect(self.ifbtnStopClicked)

        # global parameters upon initiation
        self.sidx = 1
        self.npix = 512

        # create threads
        self.threadrun = ThRunAcq()
        # self.threadplot = ThPlotLive()
        # self.threadplotOn = True

        # threads, from Yihan's
        # self.plotRefresherThread = threading.Thread()  # 'target' statement deleted
        # self.stopPlotRefresher = threading.Event()
        # self.channelLock = threading.RLock()

        self.mainThreadTimer = QTimer(self)
        self.startMainThread()

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

    def startMainThread(self):
        if self.mainThreadTimer.isActive():
            self.mainThreadTimer.stop()
        self.mainThreadTimer.timeout.connect(self.mainThread)
        self.mainThreadTimer.setInterval(constants.MAIN_UPDATING_INTERVAL)
        self.mainThreadTimer.setSingleShot(False)
        self.mainThreadTimer.start()

    def mainThread(self):
        self.plotlive()

    def plotlive(self):  # find most recent, parse it, and update
        newest = self.get_latest_file()
        [self.img, self.scatt, self.goodframes] = \
            parse_singledat.Parse(self.npix, self.fnum, self.fignore, newest).get_data()

        # update plots with parsed data
        self.plot2.plot(self.img)  # flattened image
        self.plot3.plot(np.tile(range(0, self.npix), self.goodframes),
                        self.scatt[0:self.goodframes *
                                   self.npix])  # raw count scatterplot
        self.setPlotWidget(self.plot2, 0, 512, 0, max(self.img), 'Pixel',
                           'Accumulated Counts', '', '')
        self.setPlotWidget(self.plot3, 0, 512, 0, max(self.scatt), 'Pixel',
                           'Flattened Counts', '', '')

    def get_latest_file(self):
        pathnow = os.getcwd() + '\\' + self.sdir + '\\'
        files = os.listdir(pathnow)
        for i in range(0, len(files)):
            files[i] = pathnow + files[i]
        files2 = sorted(files, key=os.path.getmtime)
        newest = files2[-1]
        return newest

    # def stopMainThread(self):
    #     self.mainThreadTimer.stop()
    #
    # def closeEvent(self, event):
    #     print("Killing auto-updating threads ...")
    #     self.stopPlotRefresherThread()
    #     self.stopMainThread()
    #     print("Closing the connection to the Opal Kelly ...")
    #     # Wait for the opal kelly components to clean itself properly
    #     # Otherwise core dump is likely to be raised
    #     time.sleep(1.1)
    #     event.accept()
    #
    # def startPlotRefresherThread(self):
    #     if not self.plotRefresherThread.isAlive():
    #         self.plotRefresherThread = threading.Thread()
    #
    #     try:
    #         self.plotRefresherThread.start()
    #     except RuntimeError as e:
    #         a = 1
    #     else:
    #         self.stopPlotRefresher.clear()
    #
    # def stopPlotRefresherThread(self):
    #     self.stopPlotRefresher.set()
    #
    # def updatePlots(self):
    #     self.channelLock.acquire()
    #
    #     if not self.channels[self.plot1Number].isEmpty():
    #         self.plot1Handle.clear()
    #         self.plot1Handle.plot(self.channels[self.plot1Number].getData())
    #         self.plot1Handle.setXRange(0, 512)
    #
    #     if not self.channels[self.plot2Number].isEmpty():
    #         self.plot2Handle.clear()
    #         self.plot2Handle.plot(self.channels[self.plot2Number].getData())
    #         self.plot2Handle.setXRange(0, 512)
    #         self.plot2Handle.getAxis('bottom').setLabel('Time', units='s')
    #
    #     self.channelLock.release()

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

    def initializeGUI(self):
        # create widgets
        self.originalPalette = QApplication.palette()
        self.createControlGroupBox()
        self.createProgressBar()
        self.plot1 = pg.PlotWidget(name='Plot1')
        self.plot2 = pg.PlotWidget(name='Plot2')
        self.plot3 = pg.PlotWidget(name='Plot3')

        # self.setPlot1Handle(self.plot1)

        # place different widgets on mainLayout
        self.mainLayout = QGridLayout()
        self.mainLayout.addWidget(self.controlGroupBox, 0, 0)
        self.mainLayout.addWidget(self.plot1, 1, 0)
        self.mainLayout.addWidget(self.plot2, 0, 1)
        self.mainLayout.addWidget(self.plot3, 1, 1)
        self.mainLayout.addWidget(self.progressBar, 2, 0, 1, 2)

        # box sizes
        self.controlGroupBox.setMinimumWidth(600)
        self.plot2.setMinimumWidth(800)
        self.plot2.setMinimumHeight(200)
        self.plot3.setMinimumWidth(800)
        self.plot3.setMinimumHeight(200)
        self.setLayout(self.mainLayout)
        self.setWindowTitle("SPAD Probe Acquisition")

        # set plot axes
        self.setPlotWidget(self.plot1, 0, 512, 0, 512, 'Pixel', 'Counts', '',
                           '')
        self.setPlotWidget(self.plot2, 0, 512, 0, 1, 'Pixel',
                           'Accumulated Counts', '', '')
        self.setPlotWidget(self.plot3, 0, 512, 0, 63, 'Pixel',
                           'Flattened Counts', '', '')

        self.getValuesFromGUI()

        print('GUI initialized.')

    def getValuesFromGUI(self):
        # Acquisition settings
        self.Flash = int(self.tglFlash.isChecked())
        self.Reset = int(self.tglReset.isChecked())
        self.ReprogPLL = int(self.tglReprogPLL.isChecked())
        self.Parse = int(self.tglParse.isChecked())
        self.Save = int(self.tglSave.isChecked())
        # parameters
        self.bitfile = self.LEbitfile.text()
        self.rstcode = self.LErstcode.text()
        self.fpgaSwitches = self.LEswitch.text()  # ep00wire
        self.fvco = self.LEfvco.text()
        self.frep = self.LEfrep.text()
        self.duty = self.LEduty.text()
        self.phase = self.LEphase.text()
        self.flen = self.LEflen.text()  # ep02wire. framelength
        self.fignore = self.LEfignore.text()
        self.fnum = self.LEfnum.text()  # datasize
        self.inum = self.LEinum.text()
        self.tacq = self.LEtacq.text()
        self.sdir = self.LEsdir.text()
        self.sname = self.LEsname.text()
        # self.sidx = self.LEsidx.text()  # throws error when 'Run' is clicked

        self.clkdiv = round(int(self.fvco) / int(self.frep))

    @pyqtSlot()
    def ifbtnFlashClicked(self):
        self.getValuesFromGUI()
        flash = True
        reset = True
        reprogpll = True
        parseenable = False
        saveenable = False
        getdata = False

        [self.img, self.scatt,
         self.goodframes] = acquire_bytearray_extinput.AcqOK(
             flash, reset, reprogpll, parseenable, saveenable, getdata,
             self.npix, self.bitfile, self.rstcode, self.fpgaSwitches,
             self.clkdiv, self.duty, self.phase, self.flen, self.fignore,
             self.fnum, self.inum, self.sdir, self.sname).outputdata()

    @pyqtSlot()
    def ifbtnResetClicked(self):
        self.getValuesFromGUI()
        flash = False
        reset = True
        reprogpll = True
        parseenable = False
        saveenable = False
        getdata = False

        [self.img, self.scatt,
         self.goodframes] = acquire_bytearray_extinput.AcqOK(
             flash, reset, reprogpll, parseenable, saveenable, getdata,
             self.npix, self.bitfile, self.rstcode, self.fpgaSwitches,
             self.clkdiv, self.duty, self.phase, self.flen, self.fignore,
             self.fnum, self.inum, self.sdir, self.sname).outputdata()

    @pyqtSlot()
    def ifbtnRunClicked(self):
        self.threadrun.start()
        # self.threadplotOn = True
        # self.threadplot.start()

    @pyqtSlot()
    def ifbtnStopClicked(self):
        self.threadrun.terminate()
        # self.threadplotOn = False
        # self.threadplot.terminate()

        # When stop button is clicked, opal kelly stops responding to commands. Error Code -8. Need to add part to
        # re-secure opal kelly connection after terminating the data acquisition thread.

    def createControlGroupBox(self):
        self.controlGroupBox = QGroupBox("Controls")

        # create and initialize lineEdits
        self.LEbitfile = QLineEdit(
            'bitfile\\Nov2018_dualprobe_v1_03mmfpc_pll_intclk.bit')
        self.LErstcode = QLineEdit('7')
        self.LEswitch = QLineEdit('10000000100110000')
        self.LEfvco = QLineEdit('960')
        self.LEfrep = QLineEdit('10')
        self.LEduty = QLineEdit('50')
        self.LEphase = QLineEdit('180')
        self.LEflen = QLineEdit('1000')
        self.LEfignore = QLineEdit('10')
        self.LEfnum = QLineEdit('1000')
        self.LEinum = QLineEdit('100')  # or infinite
        self.LEtacq = QLineEdit('?')
        self.LEsdir = QLineEdit('rawdata')
        self.LEsname = QLineEdit('sample')
        self.LEsidx = QLineEdit('1')

        # create text labels
        Tbitfile = QLabel('Bitfile')
        Tbitfile.setBuddy(self.LEbitfile)
        Trstcode = QLabel('Rst Code')
        Trstcode.setBuddy(self.LErstcode)
        Tswitch = QLabel('FPGA Switches')
        Tswitch.setBuddy(self.LEswitch)
        Tclock = QLabel('Clock')
        Tfvco = QLabel('Fvco')
        Tfvco.setBuddy(self.LEfvco)
        Tfrep = QLabel('Rep Rate')
        Tfrep.setBuddy(self.LEfrep)
        Tduty = QLabel('Duty Cycle')
        Tduty.setBuddy(self.LEduty)
        Tphase = QLabel('Phase')
        Tphase.setBuddy(self.LEphase)
        Tacquire = QLabel('Acquire')
        Tflen = QLabel('Frame length')
        Tflen.setBuddy(self.LEflen)
        Tfignore = QLabel('Pass length')
        Tfignore.setBuddy(self.LEfignore)
        Tfnum = QLabel('#Frames')
        Tfnum.setBuddy(self.LEfnum)
        Tinum = QLabel('#Images')
        Tinum.setBuddy(self.LEinum)
        Ttacq = QLabel('Tacq/Img')
        Ttacq.setBuddy(self.LEtacq)
        Tsave = QLabel('Save')
        Tsdir = QLabel('Dir')
        Tsdir.setBuddy(self.LEsdir)
        Tsname = QLabel('Name')
        Tsname.setBuddy(self.LEsname)
        Tsidx = QLabel('Nxt Idx')
        Tsidx.setBuddy(self.LEsidx)

        # create buttons
        self.btnFlash = QPushButton("Flash")
        self.btnFlash.setDefault(True)
        self.btnReset = QPushButton("Reset")
        self.btnReset.setDefault(True)
        btngroup1 = QButtonGroup(self.controlGroupBox)
        btngroup1.setExclusive(False)
        self.tglFlash = QRadioButton("Flash")
        self.tglFlash.setChecked(False)
        self.tglReset = QRadioButton("Reset")
        self.tglReset.setChecked(True)
        self.tglReprogPLL = QRadioButton("reprogram PLL")
        self.tglReprogPLL.setChecked(False)
        self.tglParse = QRadioButton("Parse")
        self.tglParse.setChecked(False)
        self.tglSave = QRadioButton("Save")
        self.tglSave.setChecked(True)
        btngroup1.addButton(self.tglFlash)
        btngroup1.addButton(self.tglReset)
        btngroup1.addButton(self.tglReprogPLL)
        btngroup1.addButton(self.tglParse)
        btngroup1.addButton(self.tglSave)
        self.btnRun = QPushButton("Run")
        self.btnRun.setDefault(False)
        self.btnStop = QPushButton("Stop")
        self.btnStop.setDefault(False)

        # create layout
        boxlayout = QVBoxLayout()

        line = [Tbitfile, self.LEbitfile, self.btnFlash]
        size = [1, 100, 1]
        self.layoutSingleLine(boxlayout, line, size)
        line = [
            Trstcode, self.LErstcode, Tswitch, self.LEswitch, self.btnReset
        ]
        size = [1, 1, 1, 80, 1, 1]
        self.layoutSingleLine(boxlayout, line, size)
        line = [
            Tclock, Tfvco, self.LEfvco, Tfrep, self.LEfrep, Tduty, self.LEduty,
            Tphase, self.LEphase
        ]
        size = [1, 0, 1, 0, 1, 0, 1, 0, 1]
        self.layoutSingleLine(boxlayout, line, size)
        line = [
            Tacquire, Tflen, self.LEflen, Tfignore, self.LEfignore, Tfnum,
            self.LEfnum, Tinum, self.LEinum, Ttacq, self.LEtacq
        ]
        size = [2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
        self.layoutSingleLine(boxlayout, line, size)
        line = [
            Tsave, Tsdir, self.LEsdir, Tsname, self.LEsname, Tsidx, self.LEsidx
        ]
        size = [2, 1, 100, 1, 30, 1, 1]
        self.layoutSingleLine(boxlayout, line, size)
        line = [
            self.tglFlash, self.tglReset, self.tglReprogPLL, self.tglParse,
            self.tglSave, self.btnRun, self.btnStop
        ]
        size = [1, 1, 1, 1, 1, 100, 100]
        self.layoutSingleLine(boxlayout, line, size)

        self.controlGroupBox.setLayout(boxlayout)

    def setPlotWidget(self, plot, xmin, xmax, ymin, ymax, xlabel, ylabel,
                      xunit, yunit):
        plot.setLabel('bottom', xlabel, units=xunit)
        plot.setLabel('left', ylabel, units=yunit)
        plot.setXRange(xmin, xmax)
        plot.setYRange(ymin, ymax)

    def layoutSingleLine(self, boxlayout, line, size):
        hlayout = QHBoxLayout()
        for i in range(len(line)):
            hlayout.addWidget(line[i], size[i])
        boxlayout.addLayout(hlayout)

    def createProgressBar(self):
        self.progressBar = QProgressBar()
        self.progressBar.setRange(0, 10000)
        self.progressBar.setValue(0)

        timer = QTimer(self)
        timer.timeout.connect(self.advanceProgressBar)
        timer.start(1000)

    def advanceProgressBar(self):
        curVal = self.progressBar.value()
        maxVal = self.progressBar.maximum()
        self.progressBar.setValue(curVal + int((maxVal - curVal) / 100))
コード例 #18
0
ファイル: window_v2.py プロジェクト: yongmeibian/Demos
class WidgetProxyZero(QDialog):
    def __init__(self, parent=None, path=""):
        super(WidgetProxyZero, self).__init__(parent)
        if len(path.strip()) <= 0:
            path = os.path.join(os.getcwd(), 'data.cfg')
        self.filePath = path
        self.propertyData = []
        self.addDataChildWindow = None
        # 创建样式操作控件
        self._create_style_change_layout()

        # 生成主体控件
        self._create_top_left_group_box()
        self._create_top_right_group_box()
        self._create_bottom_tab()
        self._create_progress_bar()

        # 布局主体
        self._layout_main_window()

        # 设置应用头部标题
        self.setWindowTitle("WidgetProxyZero Ver 0.0.1")

    # 改变系统样式
    def _change_style(self, style_name):
        QApplication.setStyle(QStyleFactory.create(style_name))
        self._change_palette()

    # 应用系统样式
    def _change_palette(self):
        if self.useStylePaletteCheckBox.isChecked():
            QApplication.setPalette(QApplication.style().standardPalette())
        else:
            QApplication.setPalette(self.originalPalette)

    # 创建样式操作控件
    def _create_style_change_layout(self):
        self.originalPalette = QApplication.palette()

        style_combo_box = QComboBox()
        style_items = QStyleFactory.keys()
        style_items.reverse()
        style_combo_box.addItems(style_items)
        style_label = QLabel("&Style:")
        style_label.setBuddy(style_combo_box)
        self.useStylePaletteCheckBox = QCheckBox(
            "&Use style's standard palette")
        # self.useStylePaletteCheckBox.setChecked(True)

        # 样式事件绑定
        style_combo_box.activated[str].connect(self._change_style)
        self.useStylePaletteCheckBox.toggled.connect(self._change_palette)

        # 头部
        self.topLayout = QHBoxLayout()
        self.topLayout.addWidget(style_label)
        self.topLayout.addWidget(style_combo_box)
        # - addStretch设置中间的空白
        self.topLayout.addStretch(1)
        self.topLayout.addWidget(self.useStylePaletteCheckBox)
        # 初始化样式
        self._change_style(style_items[0])

    # 创建左上侧配置信息控件
    def _create_top_left_group_box(self):
        self.topLeftGroupBox = QGroupBox("Config")

        self.editHost = QLineEdit("http://localhost")
        regex = QRegExp()
        regex.setPattern(
            "((http|https)://)(([a-zA-Z0-9\._-]+\.[a-zA-Z]{2,6})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))"
        )
        q_validate = QRegExpValidator()
        q_validate.setRegExp(regex)
        self.editHost.setValidator(q_validate)

        self.editPort = QLineEdit("8080")
        regex = QRegExp()
        regex.setPattern("([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])")
        q_validate = QRegExpValidator()
        q_validate.setRegExp(regex)
        self.editPort.setValidator(q_validate)

        layout = QFormLayout()
        layout.addRow(QLabel("Host:"), self.editHost)
        layout.addRow(QLabel("Port:"), self.editPort)

        self.topLeftGroupBox.setLayout(layout)

    # 创建右上侧操作按钮控件
    def _create_top_right_group_box(self):
        self.topRightGroupBox = QGroupBox("Operate")

        self.btnStart = QPushButton()
        self.btnStart.setText("Start")

        self.btnStop = QPushButton()
        self.btnStop.setText("Stop")
        self.btnStop.setDisabled(True)

        self.btnRestart = QPushButton()
        self.btnRestart.setText("Restart")
        self.btnRestart.setDisabled(True)

        self.btnReload = QPushButton()
        self.btnReload.setText("Reload")

        self.btnAdd = QPushButton()
        self.btnAdd.setText("Add")

        self.btnRemove = QPushButton()
        self.btnRemove.setText("Remove")
        self.btnRemove.setDisabled(True)

        self.btnEnable = QPushButton()
        self.btnEnable.setText("Enable")
        self.btnEnable.setDisabled(True)

        self.btnDisable = QPushButton()
        self.btnDisable.setText("Disable")
        self.btnDisable.setDisabled(True)

        # TODO 绑定事件
        self.btnReload.clicked.connect(self._reload_data_)
        self.btnAdd.clicked.connect(self._add_data)
        self.btnRemove.clicked.connect(self._remove_data)
        self.btnEnable.clicked.connect(self._enable_data)
        self.btnDisable.clicked.connect(self._disable_data)

        layout = QGridLayout()
        layout.addWidget(self.btnStart, 0, 0)
        layout.addWidget(self.btnStop, 0, 1)
        layout.addWidget(self.btnReload, 1, 0)
        layout.addWidget(self.btnRestart, 1, 1)
        layout.addWidget(self.btnAdd, 2, 0)
        layout.addWidget(self.btnRemove, 2, 1)
        layout.addWidget(self.btnEnable, 3, 0)
        layout.addWidget(self.btnDisable, 3, 1)
        self.topRightGroupBox.setLayout(layout)

    def _opt_btn_init(self, bool_value):
        self.btnRemove.setDisabled(bool_value)
        self.btnEnable.setDisabled(bool_value)
        self.btnDisable.setDisabled(bool_value)

    def _add_data(self):
        self.addDataChildWindow = AddDataChildWindow(self)
        self.addDataChildWindow.show()

    def _remove_data(self):
        if len(self.propertyData) <= 0 or len(self.selectCodes) <= 0:
            return
        for x in self.propertyData:
            for y in self.selectCodes:
                if x.code == y:
                    self.propertyData.remove(x)
        self._rewrite_data_()
        self._reload_data_()
        self._opt_btn_init(True)

    def _enable_data(self):
        if len(self.propertyData) <= 0 or len(self.selectCodes) <= 0:
            return
        for x in self.propertyData:
            for y in self.selectCodes:
                if x.code == y:
                    x.status = True
        self._rewrite_data_()
        self._reload_data_()
        self._opt_btn_init(True)

    def _disable_data(self):
        if len(self.propertyData) <= 0 or len(self.selectCodes) <= 0:
            return
        for x in self.propertyData:
            for y in self.selectCodes:
                if x.code == y:
                    x.status = False
        self._rewrite_data_()
        self._reload_data_()
        self._opt_btn_init(True)

    # 创建底部表单控件
    def _create_bottom_tab(self):
        self.bottomTabWidget = QGroupBox("Properties")
        self.widget_data = QTableView()
        self.widget_data.setLayoutDirection(Qt.LeftToRight)
        self.widget_data.setObjectName("widget_data")
        self.model = QStandardItemModel(self.widget_data)

        # 设置表格属性:
        self.model.setColumnCount(6)

        # 设置表头
        self.model.setHeaderData(0, Qt.Horizontal, '')
        self.model.setHeaderData(1, Qt.Horizontal, 'Path')
        self.model.setHeaderData(2, Qt.Horizontal, 'Status')
        self.model.setHeaderData(3, Qt.Horizontal, 'Method')
        self.model.setHeaderData(4, Qt.Horizontal, 'Head')
        self.model.setHeaderData(5, Qt.Horizontal, 'Remark')
        # self.model.setHeaderData(6, Qt.Horizontal, 'Operate')
        self.widget_data.setModel(self.model)

        # 设置列宽
        self.widget_data.setColumnWidth(0, 50)

        # 更新数据
        self._reload_data_()

        table_box = QHBoxLayout()
        table_box.setContentsMargins(5, 5, 5, 5)
        table_box.addWidget(self.widget_data)
        self.bottomTabWidget.setLayout(table_box)

    def _do_reload_data_(self):
        str_data = FileOpt.read_data_from_file(self.filePath)
        if len(str_data) <= 0:
            return
        lit = json.loads(str_data)
        result = []
        for x in lit:
            data = PropertyData.dict2data(x)
            result.append(data)
        tmp_result = []
        for x in result:
            if x.status:
                tmp_result.append(x)
        for x in result:
            if not x.status:
                tmp_result.append(x)
        return tmp_result

    def _rewrite_data_(self):
        str_data = json.dumps(self.propertyData,
                              default=PropertyData.data2dict)
        FileOpt.write_data_from_file(self.filePath,
                                     bytes(str_data, encoding="utf8"))

    def _reload_data_(self):
        self.tableData = []
        self.propertyData = self._do_reload_data_()
        table_len = len(self.propertyData)
        if table_len <= 0:
            return

        # 设置行数
        self.model.setRowCount(table_len)

        # 迭代数据
        for i, data in enumerate(self.propertyData):
            # 配置 第一列的checkbox
            tmp_check_box = QCheckBox()
            tmp_widget = QWidget()
            tmp_layout = QHBoxLayout()
            tmp_layout.addWidget(tmp_check_box)
            tmp_layout.setAlignment(Qt.AlignCenter)
            tmp_layout.setContentsMargins(5, 5, 5, 5)
            tmp_widget.setLayout(tmp_layout)
            tmp_check_box.setObjectName(data.code)

            self.widget_data.setIndexWidget(self.model.index(i, 0), tmp_widget)

            # 配置 其他数据
            tmp_item = QStandardItem(data.path)
            tmp_item.setEditable(False)
            self.model.setItem(i, 1, tmp_item)
            tmp_item = QStandardItem(str(data.status))
            tmp_item.setTextAlignment(Qt.AlignCenter)
            tmp_item.setEditable(False)
            self.model.setItem(i, 2, tmp_item)
            tmp_item = QStandardItem(json.dumps(data.method))
            tmp_item.setTextAlignment(Qt.AlignCenter)
            tmp_item.setEditable(False)
            self.model.setItem(i, 3, tmp_item)
            tmp_item = QStandardItem(json.dumps(data.head))
            tmp_item.setEditable(False)
            self.model.setItem(i, 4, tmp_item)
            tmp_item = QStandardItem(data.remark)
            tmp_item.setEditable(False)
            self.model.setItem(i, 5, tmp_item)

            # 事件相关逻辑
            tmp_check_box.toggled.connect(self._check_box_selected)

            self.tableData.append(tmp_check_box)

        self.widget_data.setModel(self.model)

    # 数据被选中时的事件
    def _check_box_selected(self):
        if len(self.tableData) <= 0:
            return
        self.selectCodes = []
        for x in self.tableData:
            if x.isChecked():
                self.selectCodes.append(x.objectName())

        if len(self.selectCodes) <= 0:
            self._opt_btn_init(True)
            return

        self._opt_btn_init(False)

    # 创建进度条
    def _create_progress_bar(self):
        self.progressBar = QProgressBar()
        self.progressBar.setRange(0, 10000)
        self.progressBar.setValue(0)
        timer = QTimer(self)
        timer.timeout.connect(self._advance_progress_bar)
        timer.start(1000)

    def _advance_progress_bar(self):
        cur_val = self.progressBar.value()
        max_val = self.progressBar.maximum()
        self.progressBar.setValue(cur_val + (max_val - cur_val) / 100)

    def _layout_main_window(self):
        main_layout = QGridLayout()
        main_layout.addLayout(self.topLayout, 0, 0, 1, 2)
        main_layout.addWidget(self.topLeftGroupBox, 1, 0)
        main_layout.addWidget(self.topRightGroupBox, 1, 1)
        main_layout.addWidget(self.bottomTabWidget, 2, 0, 1, 2)
        main_layout.addWidget(self.progressBar, 3, 0, 1, 2)
        main_layout.setRowStretch(1, 1)
        main_layout.setRowStretch(2, 1)
        main_layout.setColumnStretch(0, 1)
        main_layout.setColumnStretch(1, 1)
        self.setLayout(main_layout)
コード例 #19
0
class Indexer(QWidget):
    def __init__(self, wheres_the_fck_receipt: api_interface.WheresTheFckReceipt, parent=None):
        QWidget.__init__(self, parent=None)
        self.wheres_the_fck_receipt = wheres_the_fck_receipt
        self.index_job = None  # type: api_interface.IndexJob
        self.index_job_timer = QTimer()
        self.index_job_timer.timeout.connect(self.index_job_timer_timeout)

        # WIDGETS
        # add dir button
        self.add_directory = QPushButton('Add Directory')
        self.add_directory.setEnabled(True)
        self.add_directory.clicked.connect(self.add_directory_clicked)

        # locations
        self.directories = QListWidget()
        self.directories.itemSelectionChanged.connect(self.directories_selection_changed)
        self.directories.setSelectionMode(QAbstractItemView.SingleSelection)
        for dir in self.wheres_the_fck_receipt.get_directories():
            self.directories.addItem(dir)

        # the locations_action_bar
        self.index = QPushButton('Update')
        self.index.clicked.connect(self.update_clicked)
        self.remove_dir = QPushButton('Remove')
        self.remove_dir.clicked.connect(self.remove_clicked)
        self.re_index = QPushButton('Re-Index')
        self.re_index.clicked.connect(self.reindex_clicked)
        file_list_action_bar_layout = QHBoxLayout()
        file_list_action_bar_layout.setContentsMargins(0, 0, 0, 0)
        file_list_action_bar_layout.addWidget(self.index)
        file_list_action_bar_layout.addWidget(self.remove_dir)
        file_list_action_bar_layout.addWidget(self.re_index)
        self.file_list_action_bar_widget = QWidget()
        self.file_list_action_bar_widget.setLayout(file_list_action_bar_layout)
        self.file_list_action_bar_widget.setEnabled(False)

        # index_status_widget
        self.index_progress = QProgressBar()
        self.index_progress.setEnabled(False)
        self.stop_index = QPushButton('Stop Indexing')
        self.stop_index.setEnabled(False)
        self.stop_index.clicked.connect(self.stop_index_clicked)
        index_status_widget_layout = QHBoxLayout()
        index_status_widget_layout.setContentsMargins(0, 0, 0, 0)
        index_status_widget_layout.addWidget(self.index_progress)
        index_status_widget_layout.addWidget(self.stop_index)
        index_status_widget = QWidget()
        index_status_widget.setLayout(index_status_widget_layout)

        # index console
        self.index_console = QTextEdit()
        self.index_console.setReadOnly(True)
        # self.index_console.setEnabled(False)

        # layout
        layout = QVBoxLayout()
        layout.addWidget(QLabel("Indexed Directories:"))
        layout.addWidget(self.add_directory)
        layout.addWidget(self.directories)
        layout.addWidget(self.file_list_action_bar_widget)
        layout.addWidget(QLabel("Indexer Status:"))
        layout.addWidget(index_status_widget)
        layout.addWidget(self.index_console)
        self.setLayout(layout)

    def directories_selection_changed(self):
        list_items = self.directories.selectedItems()
        self.file_list_action_bar_widget.setEnabled(len(list_items) == 1)

    def add_directory_clicked(self):

        settings = QSettings('WheresTheFckReceipt', 'WheresTheFckReceipt')
        last_directory_added = settings.value("last_directory_added", "")

        directory = str(QFileDialog.getExistingDirectory(self, "Select Directory",
                                                         last_directory_added,
                                                         QFileDialog.ShowDirsOnly))
        if directory:
            settings.setValue("last_directory_added", directory)
            del settings
            # get the job
            if not self.directories.findItems(directory, Qt.MatchExactly):
                self.directories.addItem(directory)
            self.index_job = self.wheres_the_fck_receipt.add_directory(directory)
            self.run_indexer()

    def run_indexer(self):
        # manage gui
        self.add_directory.setEnabled(False)
        self.directories.setEnabled(False)
        self.file_list_action_bar_widget.setEnabled(False)
        self.index_progress.setEnabled(True)
        self.index_progress.reset()
        self.stop_index.setEnabled(True)
        # self.index_console.setEnabled(True)
        self.index_console.clear()
        # start job
        self.stop_index.setEnabled(True)
        self.index_job.start()
        self.index_job_timer.start(500)

    def update_clicked(self):
        self.index_job = self.wheres_the_fck_receipt.update_directory(self.directories.currentItem().text())
        self.run_indexer()

    def remove_clicked(self):

        self.add_directory.setEnabled(False)
        self.directories.setEnabled(False)
        self.file_list_action_bar_widget.setEnabled(False)
        progress_updater = ProgressUpdater(self)
        self.wheres_the_fck_receipt.remove_directory(self.directories.currentItem().text(), progress_updater)
        if progress_updater.canceled() is False:
            self.directories.takeItem(self.directories.currentRow())

        self.add_directory.setEnabled(True)
        self.directories.setEnabled(True)
        self.file_list_action_bar_widget.setEnabled(True)

    def reindex_clicked(self):
        self.index_job = self.wheres_the_fck_receipt.reindex_directory(self.directories.currentItem().text())
        self.run_indexer()

    def stop_index_clicked(self):
        self.index_job.stop()
        self.indexing_stopped()

    def indexing_stopped(self):
        self.index_job_timer.stop()
        self.add_directory.setEnabled(True)
        self.directories.setEnabled(True)
        self.file_list_action_bar_widget.setEnabled(len(self.directories.selectedItems()) > 0)
        self.index_progress.setEnabled(False)
        self.stop_index.setEnabled(False)
        # self.index_console.setEnabled(False)
        self.index_job = None

    def index_job_timer_timeout(self):
        for msg in self.index_job.get_messages():
            self.index_console.append(msg)
        num_files = self.index_job.get_num_files()
        if num_files and self.index_progress.maximum() != num_files:
            self.index_progress.setRange(0, num_files)
        curr_file_idx = self.index_job.get_curr_file_index()
        if curr_file_idx:
            self.index_progress.setValue(curr_file_idx)
        if self.index_job.is_finished():
            self.index_progress.setValue(self.index_progress.maximum())
            self.indexing_stopped()
コード例 #20
0
ファイル: __main__.py プロジェクト: OptimusGREEN/tvlinker
class TVLinker(QWidget):
    def __init__(self, settings: QSettings, parent=None):
        super(TVLinker, self).__init__(parent)
        self.firstrun = True
        self.rows, self.cols = 0, 0
        self.parent = parent
        self.settings = settings
        self.taskbar = TaskbarProgress(self)
        self.init_styles()
        self.init_settings()
        self.init_icons()
        if sys.platform.startswith('linux'):
            notify.init(qApp.applicationName())
        layout = QVBoxLayout()
        layout.setSpacing(0)
        layout.setContentsMargins(15, 15, 15, 0)
        form_groupbox = QGroupBox(self, objectName='mainForm')
        form_groupbox.setLayout(self.init_form())
        self.table = TVLinkerTable(0, 4, self)
        self.table.doubleClicked.connect(self.show_hosters)
        layout.addWidget(form_groupbox)
        layout.addWidget(self.table)
        layout.addLayout(self.init_metabar())
        self.setLayout(layout)
        qApp.setWindowIcon(self.icon_app)
        self.resize(FixedSettings.windowSize)
        self.show()
        self.start_scraping()
        self.firstrun = False

    class ProcError(Enum):
        FAILED_TO_START = 0
        CRASHED = 1
        TIMED_OUT = 2
        READ_ERROR = 3
        WRITE_ERROR = 4
        UNKNOWN_ERROR = 5

    class NotifyIcon(Enum):
        SUCCESS = ':assets/images/tvlinker.png'
        DEFAULT = ':assets/images/tvlinker.png'

    def init_threads(self, threadtype: str = 'scrape') -> None:
        if threadtype == 'scrape':
            if hasattr(self, 'scrapeThread'):
                if not sip.isdeleted(
                        self.scrapeThread) and self.scrapeThread.isRunning():
                    self.scrapeThread.terminate()
                    del self.scrapeWorker
                    del self.scrapeThread
            self.scrapeThread = QThread(self)
            self.scrapeWorker = ScrapeWorker(self.source_url, self.user_agent,
                                             self.dl_pagecount)
            self.scrapeThread.started.connect(self.show_progress)
            self.scrapeThread.started.connect(self.scrapeWorker.begin)
            self.scrapeWorker.moveToThread(self.scrapeThread)
            self.scrapeWorker.addRow.connect(self.add_row)
            self.scrapeWorker.workFinished.connect(self.scrape_finished)
            self.scrapeWorker.workFinished.connect(
                self.scrapeWorker.deleteLater, Qt.DirectConnection)
            self.scrapeWorker.workFinished.connect(self.scrapeThread.quit,
                                                   Qt.DirectConnection)
            self.scrapeThread.finished.connect(self.scrapeThread.deleteLater,
                                               Qt.DirectConnection)
        elif threadtype == 'unrestrict':
            pass

    @staticmethod
    def load_stylesheet(qssfile: str) -> None:
        if QFileInfo(qssfile).exists():
            qss = QFile(qssfile)
            qss.open(QFile.ReadOnly | QFile.Text)
            qApp.setStyleSheet(QTextStream(qss).readAll())

    def init_styles(self) -> None:
        if sys.platform == 'darwin':
            qss_stylesheet = self.get_path('%s_osx.qss' %
                                           qApp.applicationName().lower())
        else:
            qss_stylesheet = self.get_path('%s.qss' %
                                           qApp.applicationName().lower())
        TVLinker.load_stylesheet(qss_stylesheet)
        QFontDatabase.addApplicationFont(':assets/fonts/opensans.ttf')
        QFontDatabase.addApplicationFont(':assets/fonts/opensans-bold.ttf')
        QFontDatabase.addApplicationFont(':assets/fonts/opensans-semibold.ttf')
        qApp.setFont(QFont('Open Sans',
                           12 if sys.platform == 'darwin' else 10))

    def init_icons(self) -> None:
        self.icon_app = QIcon(
            self.get_path('images/%s.png' % qApp.applicationName().lower()))
        self.icon_faves_off = QIcon(':assets/images/star_off.png')
        self.icon_faves_on = QIcon(':assets/images/star_on.png')
        self.icon_refresh = QIcon(':assets/images/refresh.png')
        self.icon_menu = QIcon(':assets/images/menu.png')
        self.icon_settings = QIcon(':assets/images/cog.png')
        self.icon_updates = QIcon(':assets/images/cloud.png')

    def init_settings(self) -> None:
        self.provider = 'Scene-RLS'
        self.select_provider(0)
        self.user_agent = self.settings.value('user_agent')
        self.dl_pagecount = self.settings.value('dl_pagecount', 20, int)
        self.dl_pagelinks = FixedSettings.linksPerPage
        self.realdebrid_api_token = self.settings.value('realdebrid_apitoken')
        self.realdebrid_api_proxy = self.settings.value('realdebrid_apiproxy')
        self.download_manager = self.settings.value('download_manager')
        self.persepolis_cmd = self.settings.value('persepolis_cmd')
        self.pyload_host = self.settings.value('pyload_host')
        self.pyload_username = self.settings.value('pyload_username')
        self.pyload_password = self.settings.value('pyload_password')
        self.idm_exe_path = self.settings.value('idm_exe_path')
        self.kget_cmd = self.settings.value('kget_cmd')
        self.favorites = self.settings.value('favorites')

    def init_form(self) -> QHBoxLayout:
        self.search_field = QLineEdit(self,
                                      clearButtonEnabled=True,
                                      placeholderText='Enter search criteria')
        self.search_field.setObjectName('searchInput')
        self.search_field.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Fixed)
        self.search_field.setFocus()
        self.search_field.textChanged.connect(self.clear_filters)
        self.search_field.returnPressed.connect(
            lambda: self.filter_table(self.search_field.text()))
        self.favorites_button = QPushButton(parent=self,
                                            flat=True,
                                            cursor=Qt.PointingHandCursor,
                                            objectName='favesButton',
                                            toolTip='Favorites',
                                            checkable=True,
                                            toggled=self.filter_faves,
                                            checked=self.settings.value(
                                                'faves_filter', False, bool))
        self.refresh_button = QPushButton(parent=self,
                                          flat=True,
                                          cursor=Qt.PointingHandCursor,
                                          objectName='refreshButton',
                                          toolTip='Refresh',
                                          clicked=self.start_scraping)
        self.dlpages_field = QComboBox(self,
                                       toolTip='Pages',
                                       editable=False,
                                       cursor=Qt.PointingHandCursor)
        self.dlpages_field.addItems(
            ('10', '20', '30', '40', '50', '60', '70', '80'))
        self.dlpages_field.setCurrentIndex(
            self.dlpages_field.findText(str(self.dl_pagecount),
                                        Qt.MatchFixedString))
        self.dlpages_field.currentIndexChanged.connect(self.update_pagecount)
        self.settings_button = QPushButton(parent=self,
                                           flat=True,
                                           toolTip='Menu',
                                           objectName='menuButton',
                                           cursor=Qt.PointingHandCursor)
        self.settings_button.setMenu(self.settings_menu())
        layout = QHBoxLayout(spacing=10)
        # providerCombo = QComboBox(self, toolTip='Provider', editable=False, cursor=Qt.PointingHandCursor)
        # providerCombo.setObjectName('providercombo')
        # providerCombo.addItem(QIcon(':assets/images/provider-scenerls.png'), '')
        # providerCombo.addItem(QIcon(':assets/images/provider-tvrelease.png'), '')
        # providerCombo.setIconSize(QSize(146, 36))
        # providerCombo.setMinimumSize(QSize(160, 40))
        # providerCombo.setStyleSheet('''
        #     QComboBox, QComboBox::drop-down { background-color: transparent; border: none; margin: 5px; }
        #     QComboBox::down-arrow { image: url(:assets/images/down_arrow.png); }
        #     QComboBox QAbstractItemView { selection-background-color: #DDDDE4; }
        # ''')
        # providerCombo.currentIndexChanged.connect(self.select_provider)
        layout.addWidget(
            QLabel(pixmap=QPixmap(':assets/images/provider-scenerls.png')))
        layout.addWidget(self.search_field)
        layout.addWidget(self.favorites_button)
        layout.addWidget(self.refresh_button)
        layout.addWidget(QLabel('Pages:'))
        layout.addWidget(self.dlpages_field)
        layout.addWidget(self.settings_button)
        return layout

    @pyqtSlot(int)
    def select_provider(self, index: int):
        if index == 0:
            self.provider = 'Scene-RLS'
            self.source_url = 'http://scene-rls.net/releases/index.php?p={0}&cat=TV%20Shows'
        elif index == 1:
            self.provider = 'TV-Release'
            self.source_url = 'http://tv-release.pw/?cat=TV'
        self.setWindowTitle('%s :: %s' %
                            (qApp.applicationName(), self.provider))

    def settings_menu(self) -> QMenu:
        settings_action = QAction(self.icon_settings,
                                  'Settings',
                                  self,
                                  triggered=self.show_settings)
        updates_action = QAction(self.icon_updates,
                                 'Check for updates',
                                 self,
                                 triggered=self.check_update)
        aboutqt_action = QAction('About Qt', self, triggered=qApp.aboutQt)
        about_action = QAction('About %s' % qApp.applicationName(),
                               self,
                               triggered=self.about_app)
        menu = QMenu()
        menu.addAction(settings_action)
        menu.addAction(updates_action)
        menu.addSeparator()
        menu.addAction(aboutqt_action)
        menu.addAction(about_action)
        return menu

    def init_metabar(self) -> QHBoxLayout:
        self.meta_template = 'Total number of links retrieved: <b>%i</b> / <b>%i</b>'
        self.progress = QProgressBar(parent=self,
                                     minimum=0,
                                     maximum=(self.dl_pagecount *
                                              self.dl_pagelinks),
                                     visible=False)
        self.taskbar.setProgress(0.0, True)
        if sys.platform == 'win32':
            self.win_taskbar_button = QWinTaskbarButton(self)

        self.meta_label = QLabel(textFormat=Qt.RichText,
                                 alignment=Qt.AlignRight,
                                 objectName='totals')
        self.update_metabar()
        layout = QHBoxLayout()
        layout.setContentsMargins(10, 5, 10, 10)
        layout.addWidget(self.progress, Qt.AlignLeft)
        layout.addWidget(self.meta_label, Qt.AlignRight)
        return layout

    @pyqtSlot()
    def check_update(self) -> None:
        QDesktopServices.openUrl(QUrl(FixedSettings.latest_release_url))

    @pyqtSlot()
    def show_settings(self) -> None:
        settings_win = Settings(self, self.settings)
        settings_win.exec_()

    def update_metabar(self) -> bool:
        rowcount = self.table.rowCount()
        self.meta_label.setText(
            self.meta_template %
            (rowcount, self.dl_pagecount * self.dl_pagelinks))
        self.progress.setValue(rowcount)
        self.taskbar.setProgress(rowcount / self.progress.maximum())
        if sys.platform == 'win32':
            self.win_taskbar_button.progress().setValue(self.progress.value())
        return True

    def start_scraping(self) -> None:
        self.init_threads('scrape')
        self.rows = 0
        self.table.clearContents()
        self.table.setRowCount(0)
        self.table.setSortingEnabled(False)
        self.update_metabar()
        self.scrapeThread.start()

    @pyqtSlot()
    def about_app(self) -> None:
        about_html = '''<style>
        a { color:#441d4e; text-decoration:none; font-weight:bold; }
        a:hover { text-decoration:underline; }
    </style>
    <p style="font-size:24pt; font-weight:bold; color:#6A687D;">%s</p>
    <p>
        <span style="font-size:13pt;"><b>Version: %s</b></span>
        <span style="font-size:10pt;position:relative;left:5px;">( %s )</span>
    </p>
    <p style="font-size:13px;">
        Copyright &copy; %s <a href="mailto:[email protected]">Pete Alexandrou</a>
        <br/>
        Web: <a href="%s">%s</a>
    </p>
    <p style="font-size:11px;">
        This program is free software; you can redistribute it and/or
        modify it under the terms of the GNU General Public License
        as published by the Free Software Foundation; either version 2
        of the License, or (at your option) any later version.
    </p>''' % (qApp.applicationName(), qApp.applicationVersion(),
               platform.architecture()[0], datetime.now().year,
               qApp.organizationDomain(), qApp.organizationDomain())
        QMessageBox.about(self, 'About %s' % qApp.applicationName(),
                          about_html)

    @pyqtSlot(int)
    def update_pagecount(self, index: int) -> None:
        self.dl_pagecount = int(self.dlpages_field.itemText(index))
        self.scrapeWorker.maxpages = self.dl_pagecount
        self.progress.setMaximum(self.dl_pagecount * self.dl_pagelinks)
        self.settings.setValue('dl_pagecount', self.dl_pagecount)
        if sys.platform == 'win32':
            self.win_taskbar_button.progress().setMaximum(self.dl_pagecount *
                                                          self.dl_pagelinks)
        if self.scrapeThread.isRunning():
            self.scrapeThread.requestInterruption()
        self.start_scraping()

    @pyqtSlot()
    def show_progress(self):
        self.progress.show()
        self.taskbar.setProgress(0.0, True)
        if sys.platform == 'win32':
            self.win_taskbar_button.setWindow(self.windowHandle())
            self.win_taskbar_button.progress().setRange(
                0, self.dl_pagecount * self.dl_pagelinks)
            self.win_taskbar_button.progress().setVisible(True)
            self.win_taskbar_button.progress().setValue(self.progress.value())

    @pyqtSlot()
    def scrape_finished(self) -> None:
        self.progress.hide()
        self.taskbar.setProgress(0.0, False)
        if sys.platform == 'win32':
            self.win_taskbar_button.progress().setVisible(False)
        self.table.setSortingEnabled(True)
        self.filter_table(text='')

    @pyqtSlot(list)
    def add_row(self, row: list) -> None:
        if self.scrapeThread.isInterruptionRequested():
            self.scrapeThread.terminate()
        else:
            self.cols = 0
            self.table.setRowCount(self.rows + 1)
            if self.table.cursor() != Qt.PointingHandCursor:
                self.table.setCursor(Qt.PointingHandCursor)
            for item in row:
                table_item = QTableWidgetItem(item)
                table_item.setToolTip(
                    '%s\n\nDouble-click to view hoster links.' % row[1])
                table_item.setFont(QFont('Open Sans', weight=QFont.Normal))
                if self.cols == 2:
                    if sys.platform == 'win32':
                        table_item.setFont(
                            QFont('Open Sans Semibold', pointSize=10))
                    elif sys.platform == 'darwin':
                        table_item.setFont(
                            QFont('Open Sans Bold', weight=QFont.Bold))
                    else:
                        table_item.setFont(
                            QFont('Open Sans',
                                  weight=QFont.DemiBold,
                                  pointSize=10))
                    table_item.setText('  ' + table_item.text())
                elif self.cols in (0, 3):
                    table_item.setTextAlignment(Qt.AlignCenter)
                self.table.setItem(self.rows, self.cols, table_item)
                self.update_metabar()
                self.cols += 1
            self.rows += 1

    @pyqtSlot(list)
    def add_hosters(self, links: list) -> None:
        self.hosters_win.show_hosters(links)

    @pyqtSlot(QModelIndex)
    def show_hosters(self, index: QModelIndex) -> None:
        qApp.setOverrideCursor(Qt.BusyCursor)
        self.hosters_win = HosterLinks(self)
        self.hosters_win.downloadLink.connect(self.download_link)
        self.hosters_win.copyLink.connect(self.copy_download_link)
        self.links = HostersThread(
            self.table.item(self.table.currentRow(), 1).text(),
            self.user_agent)
        self.links.setHosters.connect(self.add_hosters)
        self.links.noLinks.connect(self.no_links)
        self.links.start()

    @pyqtSlot()
    def no_links(self) -> None:
        self.hosters_win.loading_progress.cancel()
        self.hosters_win.close()
        QMessageBox.warning(
            self, 'No Links Available',
            'No links are available yet for the chosen TV show. ' +
            'This is most likely due to the files still being uploaded. This is normal if the '
            +
            'link was published 30-45 mins ago.\n\nPlease check back again in 10-15 minutes.'
        )

    @pyqtSlot(bool)
    def filter_faves(self, checked: bool) -> None:
        self.settings.setValue('faves_filter', checked)
        # if hasattr(self, 'scrapeWorker') and (sip.isdeleted(self.scrapeWorker) or self.scrapeWorker.complete):
        if not self.firstrun:
            self.filter_table()

    @pyqtSlot(str)
    @pyqtSlot()
    def filter_table(self, text: str = '') -> None:
        filters = []
        if self.favorites_button.isChecked():
            filters = self.favorites
            self.table.sortItems(2, Qt.AscendingOrder)
        else:
            self.table.sortItems(0, Qt.DescendingOrder)
        if len(text):
            filters.append(text)
        if not len(filters) or not hasattr(self, 'valid_rows'):
            self.valid_rows = []
        for search_term in filters:
            for item in self.table.findItems(search_term, Qt.MatchContains):
                self.valid_rows.append(item.row())
        for row in range(0, self.table.rowCount()):
            if not len(filters):
                self.table.showRow(row)
            else:
                if row not in self.valid_rows:
                    self.table.hideRow(row)
                else:
                    self.table.showRow(row)

    @pyqtSlot()
    def clear_filters(self):
        if not len(self.search_field.text()):
            self.filter_table('')

    @pyqtSlot(bool)
    def aria2_confirmation(self, success: bool) -> None:
        qApp.restoreOverrideCursor()
        if success:
            if sys.platform.startswith('linux'):
                self.notify(
                    title=qApp.applicationName(),
                    msg='Your download link has been unrestricted and now ' +
                    'queued in Aria2 RPC Daemon',
                    icon=self.NotifyIcon.SUCCESS)
            else:
                QMessageBox.information(
                    self, qApp.applicationName(),
                    'Download link has been queued in Aria2.', QMessageBox.Ok)
        else:
            QMessageBox.critical(
                self, 'Aria2 RPC Daemon',
                'Could not connect to Aria2 RPC Daemon. ' +
                'Check your %s settings and try again.' %
                qApp.applicationName(), QMessageBox.Ok)

    @pyqtSlot(str)
    def download_link(self, link: str) -> None:
        if len(self.realdebrid_api_token) > 0 and 'real-debrid.com' not in link \
            and 'rdeb.io' not in link:
            qApp.setOverrideCursor(Qt.BusyCursor)
            self.unrestrict_link(link, True)
        else:
            if self.download_manager == 'aria2':
                self.aria2 = Aria2Thread(settings=self.settings, link_url=link)
                self.aria2.aria2Confirmation.connect(self.aria2_confirmation)
                self.aria2.start()
                self.hosters_win.close()
            elif self.download_manager == 'pyload':
                self.pyload_conn = PyloadConnection(self.pyload_host,
                                                    self.pyload_username,
                                                    self.pyload_password)
                pid = self.pyload_conn.addPackage(name='TVLinker',
                                                  links=[link])
                qApp.restoreOverrideCursor()
                self.hosters_win.close()
                if sys.platform.startswith('linux'):
                    self.notify(title='Download added to %s' %
                                self.download_manager,
                                icon=self.NotifyIcon.SUCCESS)
                else:
                    QMessageBox.information(
                        self, self.download_manager,
                        'Your link has been queued in %s.' %
                        self.download_manager, QMessageBox.Ok)
                # open_pyload = msgbox.addButton('Open pyLoad', QMessageBox.AcceptRole)
                # open_pyload.clicked.connect(self.open_pyload)
            elif self.download_manager in ('kget', 'persepolis'):
                provider = self.kget_cmd if self.download_manager == 'kget' else self.persepolis_cmd
                cmd = '{0} "{1}"'.format(provider, link)
                if self.cmdexec(cmd):
                    qApp.restoreOverrideCursor()
                    self.hosters_win.close()
                    if sys.platform.startswith('linux'):
                        self.notify(title='Download added to %s' %
                                    self.download_manager,
                                    icon=self.NotifyIcon.SUCCESS)
                    else:
                        QMessageBox.information(
                            self, self.download_manager,
                            'Your link has been queued in %s.' %
                            self.download_manager, QMessageBox.Ok)
            elif self.download_manager == 'idm':
                cmd = '"%s" /n /d "%s"' % (self.idm_exe_path, link)
                if self.cmdexec(cmd):
                    qApp.restoreOverrideCursor()
                    self.hosters_win.close()
                    QMessageBox.information(
                        self, 'Internet Download Manager',
                        'Your link has been queued in IDM.')
                else:
                    print('IDM QProcess error = %s' %
                          self.ProcError(self.idm.error()).name)
                    qApp.restoreOverrideCursor()
                    self.hosters_win.close()
                    QMessageBox.critical(
                        self, 'Internet Download Manager',
                        '<p>Could not connect to your local IDM application instance. '
                        +
                        'Please check your settings and ensure the IDM executable path is correct '
                        +
                        'according to your installation.</p><p>Error Code: %s</p>'
                        % self.ProcError(self.idm.error()).name,
                        QMessageBox.Ok)
            else:
                dlpath, _ = QFileDialog.getSaveFileName(
                    self, 'Save File',
                    link.split('/')[-1])
                if dlpath != '':
                    self.directdl_win = DirectDownload(parent=self)
                    self.directdl = DownloadThread(link_url=link,
                                                   dl_path=dlpath)
                    self.directdl.dlComplete.connect(
                        self.directdl_win.download_complete)
                    if sys.platform.startswith('linux'):
                        self.directdl.dlComplete.connect(
                            lambda: self.notify(qApp.applicationName(
                            ), 'Download complete', self.NotifyIcon.SUCCESS))
                    else:
                        self.directdl.dlComplete.connect(
                            lambda: QMessageBox.information(
                                self, qApp.applicationName(),
                                'Download complete', QMessageBox.Ok))
                    self.directdl.dlProgressTxt.connect(
                        self.directdl_win.update_progress_label)
                    self.directdl.dlProgress.connect(
                        self.directdl_win.update_progress)
                    self.directdl_win.cancelDownload.connect(
                        self.cancel_download)
                    self.directdl.start()
                    self.hosters_win.close()

    def _init_notification_icons(self):
        for icon in self.NotifyIcon:
            icon_file = QPixmap(icon.value, 'PNG')
            icon_file.save(
                os.path.join(FixedSettings.config_path,
                             os.path.basename(icon.value)), 'PNG', 100)

    def notify(self,
               title: str,
               msg: str = '',
               icon: Enum = None,
               urgency: int = 1) -> bool:
        icon_path = icon.value if icon is not None else self.NotifyIcon.DEFAULT.value
        icon_path = os.path.join(FixedSettings.config_path,
                                 os.path.basename(icon_path))
        if not os.path.exists(icon_path):
            self._init_notification_icons()
        notification = notify.Notification(title, msg, icon_path)
        notification.set_urgency(urgency)
        return notification.show()

    def cmdexec(self, cmd: str) -> bool:
        self.proc = QProcess()
        self.proc.setProcessChannelMode(QProcess.MergedChannels)
        if hasattr(self.proc, 'errorOccurred'):
            self.proc.errorOccurred.connect(lambda error: print(
                'Process error = %s' % self.ProcError(error).name))
        if self.proc.state() == QProcess.NotRunning:
            self.proc.start(cmd)
            self.proc.waitForFinished(-1)
            rc = self.proc.exitStatus(
            ) == QProcess.NormalExit and self.proc.exitCode() == 0
            self.proc.deleteLater()
            return rc
        return False

    @pyqtSlot()
    def cancel_download(self) -> None:
        self.directdl.cancel_download = True
        self.directdl.quit()
        self.directdl.deleteLater()

    def open_pyload(self) -> None:
        QDesktopServices.openUrl(QUrl(self.pyload_config.host))

    @pyqtSlot(str)
    def copy_download_link(self, link: str) -> None:
        if len(self.realdebrid_api_token) > 0 and 'real-debrid.com' not in link \
            and 'rdeb.io' not in link:
            qApp.setOverrideCursor(Qt.BusyCursor)
            self.unrestrict_link(link, False)
        else:
            clip = qApp.clipboard()
            clip.setText(link)
            self.hosters_win.close()
            qApp.restoreOverrideCursor()

    def unrestrict_link(self, link: str, download: bool = True) -> None:
        caller = inspect.stack()[1].function
        self.realdebrid = RealDebridThread(
            settings=self.settings,
            api_url=FixedSettings.realdebrid_api_url,
            link_url=link,
            action=RealDebridThread.RealDebridAction.UNRESTRICT_LINK)
        self.realdebrid.errorMsg.connect(self.error_handler)
        if download:
            self.realdebrid.unrestrictedLink.connect(self.download_link)
        else:
            self.realdebrid.unrestrictedLink.connect(self.copy_download_link)
        self.realdebrid.start()

    def closeEvent(self, event: QCloseEvent) -> None:
        if hasattr(self, 'scrapeThread'):
            if not sip.isdeleted(
                    self.scrapeThread) and self.scrapeThread.isRunning():
                self.scrapeThread.requestInterruption()
                self.scrapeThread.quit()
        qApp.quit()

    def error_handler(self, props: list) -> None:
        qApp.restoreOverrideCursor()
        QMessageBox.critical(self, props[0], props[1], QMessageBox.Ok)

    @staticmethod
    def get_path(path: str = None, override: bool = False) -> str:
        if override:
            if getattr(sys, 'frozen', False):
                return os.path.join(sys._MEIPASS, path)
            return os.path.join(QFileInfo(__file__).absolutePath(), path)
        return ':assets/%s' % path

    @staticmethod
    def get_version(filename: str = '__init__.py') -> str:
        with open(TVLinker.get_path(filename, override=True), 'r') as initfile:
            for line in initfile.readlines():
                m = re.match('__version__ *= *[\'](.*)[\']', line)
                if m:
                    return m.group(1)
コード例 #21
0
ファイル: main.py プロジェクト: Anosema/AnosePlayer
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.playlist = []
        self.files = []

        self.menu = QMenu()
        self.menu.addAction(icons["ti-file"] + " Open a file",
                            lambda: print("file"))
        self.menu.addAction(icons["ti-files"] + " Open a files",
                            lambda: print("files"), "Ctrl+O")
        self.menu.addAction(icons["ti-folder"] + " Open a folder",
                            lambda: print("folder"), "Ctrl+Shift+O")
        self.menu.setStyleSheet("font-family: themify;")

        self.setMinimumSize(500, 60)
        self.move(100, 100)

        self.player = QMediaPlayer()
        self.titleBar = CustomTitleBar(self, "AnosePlayer", "ti-music-alt")
        self.prevBut = QPushButton(icons["ti-control-skip-backward"], self)
        self.pausBut = QPushButton(icons["ti-control-pause"], self)
        self.nextBut = QPushButton(icons["ti-control-skip-forward"], self)
        self.progress = QProgressBar(self)
        self.openFile = QPushButton(icons["ti-plus"], self)

        self.prevBut.setObjectName("Control")
        self.pausBut.setObjectName("Control")
        self.nextBut.setObjectName("Control")
        self.openFile.setObjectName("Control")

        self.progress.setTextVisible(False)
        self.openFile.setMenu(self.menu)
        self.player.setVolume(10)

        self.player.positionChanged.connect(self.updateTime)
        self.player.durationChanged.connect(self.showDuration)
        self.player.mediaChanged.connect(self.changedMedia)
        self.player.volumeChanged.connect(self.showVolume)
        self.player.stateChanged.connect(lambda *args: print(args))
        self.prevBut.clicked.connect(self.previousSong)
        self.pausBut.clicked.connect(self.playPause)
        self.nextBut.clicked.connect(self.nextSong)

        self.player.setMedia(
            QMediaContent(
                QUrl.fromLocalFile(
                    "/home/martin/Music/Principal/System Of A Down - ATWA.mp3")
            ))

        with open("theme.css", "r") as file:
            self.setStyleSheet(file.read())

    def oFile(self):
        file = QFileDialog.getExistingDirectory(
            self, "QFileDialog.getOpenFileName()", "",
            "All Files (*);;Python Files (*.py)")

    # def oFiles(self):
    def oFolde(self):
        file = QFileDialog.getExistingDirectory(
            self, "QFileDialog.getOpenFileName()", "",
            "All Files (*);;Python Files (*.py)")

    def updateTime(self, time):
        self.progress.setValue(time)
        self.progress.repaint()
        print(self.progress.value())

    def showDuration(self, totalTime):
        self.progress.setMaximum(totalTime)
        print(self.progress.maximum())

    def changedMedia(self, *args):
        print(args)

    def showVolume(self, volume):
        print(volume)

    def changeTime(self, time):
        self.player.setPosition(time)

    def previousSong(self):
        if self.i - 1 >= 0:
            self.i -= 1
            self.player.setMedia(
                QMediaContent(QUrl.fromLocalFile(self.playlist[self.i])))

    def playPause(self):
        if self.player.state() == 1:
            self.player.pause()
            self.pausBut.setText(icons["ti-control-play"])
        else:
            self.player.play()
            self.pausBut.setText(icons["ti-control-pause"])

    def nextSong(self):
        if self.i + 1 >= len(self.playlist):
            self.playlist.append(choice(self.files))
        self.i += 1
        self.player.setMedia(
            QMediaContent(QUrl.fromLocalFile(self.playlist[self.i])))

    def resizeEvent(self, e):
        self.titleBar.setGeometry(0, 0, self.width(), 20)
        self.prevBut.setGeometry(0, 20, 30, 30)
        self.pausBut.setGeometry(30, 20, 30, 30)
        self.nextBut.setGeometry(60, 20, 30, 30)
        self.progress.setGeometry(100, 25, 390, 20)
        self.openFile.setGeometry(0, 50, 30, 30)
コード例 #22
0
class NTimer(QFrame):
    def __init__(self,
                 name="base",
                 timestamp=None,
                 duration=6,
                 icon=1,
                 style=None,
                 sound=None,
                 direction=NDirection.DOWN,
                 persistent=False,
                 noreplace=False):
        super().__init__()
        self.name = name
        self.timestamp = timestamp if timestamp else datetime.datetime.now()
        self._duration = duration
        self._icon = icon
        self._style = style
        self._active = True
        self._sound = sound
        self._alert = False
        self._direction = direction
        self.persistent = persistent
        self.noreplace = noreplace
        self.progress = QProgressBar()

        # ui
        self.setMaximumHeight(18)
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        self.setLayout(layout)
        layout.addWidget(get_spell_icon(self._icon), 0)

        # progress bar
        self.progress = QProgressBar()
        self.progress.setTextVisible(False)
        self.progress.setAutoFillBackground(True)

        # labels
        progress_layout = QHBoxLayout(self.progress)
        progress_layout.setContentsMargins(5, 0, 5, 0)
        self._name_label = QLabel(string.capwords(self.name), self.progress)
        progress_layout.addWidget(self._name_label)
        progress_layout.insertStretch(2, 1)
        self._time_label = QLabel('', self.progress)
        progress_layout.addWidget(self._time_label)
        layout.addWidget(self.progress, 1)

        # init
        self._calculate(self.timestamp)
        self.setStyleSheet(self._style)
        self._update()

    def _calculate(self, timestamp):
        self.end_time = timestamp + datetime.timedelta(seconds=self._duration)
        self.progress.setMaximum(self._duration)

    def recalculate(self, timestamp):
        self._calculate(timestamp)
        self.setStyleSheet(self._style)

    def _update(self):
        if self._active:
            remaining = self.end_time - datetime.datetime.now()
            remaining_seconds = max(remaining.total_seconds(), 0)
            self.progress.setValue(
                remaining.seconds if self._direction ==
                NDirection.DOWN else self.progress.maximum() -
                remaining_seconds)
            if remaining_seconds <= 30:
                self.setStyleSheet(self.styleSheet() + styles.spell_warning())
                if not self._alert:
                    self._alert = True
                    if self._sound:
                        sound.play(self._sound)
            else:
                self._alert = False
            if remaining_seconds <= 0:
                if self.persistent:
                    self._time_label.setText("")
                else:
                    self._remove()
            else:
                self._time_label.setText(format_time(remaining))
            self.progress.update()
        QTimer.singleShot(1000, self._update)

    def pause(self):
        self._active = False

    def resume(self):
        self._active = True

    def elongate(self, seconds):
        self.end_time += datetime.timedelta(seconds=seconds)

    def _remove(self):
        self.setParent(None)
        self.deleteLater()

    def mouseDoubleClickEvent(self, _):
        self._remove()
コード例 #23
0
class Example(QWidget):
    def __init__(self):
        super().__init__()

        # make a text window for terminal output
        self.txt = QTextEdit()
        self.txt.setReadOnly(True)

        # do something with a push button
        self.btn = QPushButton('scan')
        self.btn.clicked.connect(self.run_scan)

        # A sort of Gadget widget - here using pyqt's model/view concept
        self.model = GadgetModel()
        self.tree = QTreeView()
        self.tree.setModel(self.model)
        self.tree.expandAll()
        self.monitor = GadgetMonitor()
        self.monitor.update.connect(self.model.motor_update)
        self.monitor.start()

        # A progress bar for scans
        self.progress = QProgressBar()
        self.progress.setMinimum(0)
        self._last_dt = 0

        self.plot = pg.PlotWidget(parent=self, background='white')

        # layout containing these things
        hbox = QHBoxLayout()
        col1 = QVBoxLayout()
        col2 = QVBoxLayout()
        col1.addWidget(self.tree)
        col1.addWidget(self.txt)
        col1.addWidget(self.btn)
        col1.addWidget(self.progress)
        col2.addWidget(self.plot)
        hbox.addLayout(col1)
        hbox.addLayout(col2)
        self.setLayout(hbox)
        self.resize(1200, 700)

        # redirect stdout
        queue = Queue()
        sys.stdout = StreamWriter(queue)
        self.reader = StreamReader(queue)
        self.reader.signal.connect(self.new_stdout)
        self.reader.start()

        # a special recorder which generates qt signals
        queue = MP_Queue()
        self.qtrec = PyQtRecorder(queue, name='qtrec')
        self.qtrec.start()
        self.emitter = RecorderEmitter(queue)
        self.emitter.new.connect(self.new_data)
        self.emitter.start()

        # a scan runner object we can refer to,
        self.runner = None

        # quote
        contrast.wisdom()

    @pyqtSlot(dict)
    def new_data(self, dct):
        self.txt.setTextColor(QColor('black'))  # for example
        if 'status' in dct.keys():
            # header/footer
            if dct['status'] == 'started':
                self.progress.setValue(0)
        else:
            # update progress bar
            m = self.progress.maximum()
            n = self.progress.value() + 1
            eta = str(
                datetime.timedelta(
                    seconds=((m - n) *
                             (dct['dt'] - self._last_dt)))).split('.')[0]
            self.progress.setValue(n)
            self.progress.setFormat('%u/%u (done in %s)' % (n, m, eta))
            self._last_dt = dct['dt']
            # plot something
            self.plot.plot([dct['sx']], [dct['det1']], symbol='o', color='k')

    @pyqtSlot(str)
    def new_stdout(self, msg):
        """
        Intercepts the stdout signal and adds it to a text box or so.
        """
        if len(msg) < 2:
            # exclude empty strings
            return
        if '\r' in msg:
            # exclude overwritten text
            return
        self.print(msg, 'gray')

    def print(self, msg, color='black'):
        self.txt.setTextColor(QColor(color))
        self.txt.append(str(msg))

    def run_scan(self):
        """
        Helper method which puts together the scan to run, and launches
        a ScanRunner object.
        """
        if self.runner and self.runner.isRunning():
            return
        N = np.random.randint(5, 40)
        self.progress.setMaximum(N + 1)
        self.runner = ScanRunner(AScan, *[bl.sx, 0, 1, N, .1])
        self.runner.start()
コード例 #24
0
ファイル: TransCodaApp.py プロジェクト: ag-sd/py
class TransCodaApp(QMainWindow):

    def __init__(self):
        super().__init__()
        self.main_panel = MainPanel()
        self.tool_bar = MainToolBar()
        self.progressbar = QProgressBar()
        self.message = QLabel("Ready")
        self.encoder = QLabel("Encoder")
        self.terminal_btn = QPushButton()
        self.terminal_view = TerminalView()
        self.executor = None
        self.timer = QTimer()
        self.init_ui()

    def init_ui(self):
        encoder_name = TransCodaSettings.get_encoder_name()
        self.main_panel.set_items(TransCodaSettings.get_encode_list())
        self.main_panel.files_changed_event.connect(self.files_changed_event)
        self.main_panel.menu_item_event.connect(self.action_event)
        self.tool_bar.set_encode_state(file_count=self.main_panel.row_count(),
                                       encoder_name=encoder_name,
                                       output_dir=TransCodaSettings.get_output_dir())
        self.tool_bar.button_pressed.connect(self.action_event)
        self.addToolBar(QtCore.Qt.LeftToolBarArea, self.tool_bar)
        self.setCentralWidget(self.main_panel)
        self.statusBar().addPermanentWidget(QVLine())
        if encoder_name:
            self.encoder.setText(TransCodaSettings.get_encoder_name())
        else:
            self.encoder.setText("No encoder selected.")
        self.terminal_btn.setIcon(TransCoda.theme.ico_terminal)
        self.terminal_btn.setFlat(True)
        self.terminal_btn.setToolTip("Show Encoder Logs")
        self.terminal_btn.clicked.connect(self.show_encode_logs)
        self.statusBar().addPermanentWidget(self.encoder, 0)
        self.statusBar().addPermanentWidget(QVLine())
        self.statusBar().addPermanentWidget(self.progressbar, 0)
        self.statusBar().addPermanentWidget(self.terminal_btn, 0)

        self.setMinimumSize(800, 600)
        self.setWindowTitle(TransCoda.__APP_NAME__)
        self.setWindowIcon(TransCoda.theme.ico_app_icon)
        self.timer.timeout.connect(self.timer_timeout_event)
        self.timer.setInterval(6000)
        self.timer.setSingleShot(True)
        TransCodaSettings.settings.settings_change_event.connect(self.settings_changed)
        TransCodaSettings.settings.load_ui(self, TransCoda.logger)
        self.show()
        # Executed after the show, where all dimensions are calculated
        self.progressbar.setFixedWidth(self.progressbar.width())
        self.progressbar.setVisible(False)

    def action_event(self, event, item_indices=None):
        if event == Action.ADD_FILE:
            file, _ = QFileDialog.getOpenFileUrl(caption="Select a File")
            if not file.isEmpty():
                self.files_changed_event(True, [file])
        elif event == Action.ADD_DIR:
            _dir = QFileDialog.getExistingDirectoryUrl(caption="Select a directory")
            if not _dir.isEmpty():
                self.files_changed_event(True, [_dir])
        elif event == Action.SETTINGS:
            TransCodaSettings.TransCodaSettings().exec()
        elif event == Action.DEL_ALL:
            self.main_panel.clear_table()
        elif event == Action.DEL_FILE:
            self.main_panel.remove_files(item_indices)
        elif event == Action.ENCODE:
            if self.executor is not None and self.executor.is_running():
                self.executor.stop_scan()
                self.statusBar().showMessage("Stop command issued. Waiting for threads to finish")
                return
            self.validate_and_start_encoding(run_indices=item_indices)
        elif event == Action.CHANGE_STATUS_SUCCESS:
            self.main_panel.update_item_status(item_indices, EncoderStatus.SUCCESS)
        elif event == Action.CHANGE_STATUS_READY:
            self.main_panel.update_item_status(item_indices, EncoderStatus.READY)
        elif event == Action.OPEN_FILE:
            self.open_paths_in_system_default(item_indices, "file")
        elif event == Action.OPEN_SOURCE:
            self.open_paths_in_system_default(item_indices, "file", func=os.path.dirname)
        elif event == Action.OPEN_DEST:
            self.open_paths_in_system_default(item_indices, "output_file", func=os.path.dirname)

        elif event == Action.ABOUT:
            with open(os.path.join(os.path.dirname(__file__), "resource/about.html"), 'r') as file:
                about_html = file.read()
            QMessageBox.about(self, TransCoda.__APP_NAME__, about_html.format(APP_NAME=TransCoda.__APP_NAME__,
                                                                              VERSION=TransCoda.__VERSION__,
                                                                              YEAR=datetime.now().year))

    def files_changed_event(self, is_added, files):
        if is_added:
            self.statusBar().showMessage("Scanning files please wait...")
            scanner = CommonUtils.FileScanner(files, recurse=True, is_qfiles=True)
            self.statusBar().showMessage(f"Loading files into {TransCoda.__APP_NAME__}")
            # Add files first
            total_added = self.main_panel.add_files(scanner.files)
            # Fetch and enrich with metadata
            batches = []
            for batch in CommonUtils.batch(list(scanner.files), batch_size=20):
                retriever = FileMetaDataExtractor(batch, batch_size=len(batch))
                retriever.signals.result.connect(self.result_received_event)
                batches.append(retriever)
            # UX
            self.begin_tasks(batches, f"Fetching meta-data for {total_added} files", total_added)
        self.tool_bar.set_encode_state(file_count=self.main_panel.row_count(),
                                       encoder_name=TransCodaSettings.get_encoder_name(),
                                       output_dir=TransCodaSettings.get_output_dir())

    def validate_and_start_encoding(self, run_indices=None):
        def create_runnable(_item):
            runnable = EncoderCommand(_item)
            runnable.signals.result.connect(self.result_received_event)
            runnable.signals.status.connect(self.status_received_event)
            runnable.signals.log_message.connect(self.terminal_view.log_message)
            return runnable

        runnables = []
        is_video = False
        if run_indices is not None:
            self.main_panel.update_item_status(run_indices, EncoderStatus.WAITING)
            for index in run_indices:
                item = self.main_panel.get_items(index)
                is_video = is_video or item.is_video()
                runnables.append(create_runnable(item))
        else:
            for index in range(0, self.main_panel.row_count()):
                item = self.main_panel.get_items(index)
                self.main_panel.update_item_status([index], EncoderStatus.WAITING)
                is_video = is_video or item.is_video()
                runnables.append(create_runnable(item))

        if len(runnables) <= 0:
            self.statusBar().showMessage("Nothing to encode!")
            return

        if TransCodaSettings.sort_by_size():
            runnables.sort(key=lambda x: x.file.file_size)
        self.tool_bar.encoding_started()
        if is_video and TransCodaSettings.is_single_thread_video():
            self.begin_tasks(runnables, f"Dispatching {len(runnables)} jobs for serial encoding", len(runnables),
                             threads=1)
        else:
            self.begin_tasks(runnables, f"Dispatching {len(runnables)} jobs for encoding", len(runnables),
                             threads=TransCodaSettings.get_max_threads())

    def begin_tasks(self, tasks, status_message, total_size, threads=TransCodaSettings.get_max_threads()):
        TransCoda.logger.info(status_message)
        self.progressbar.setVisible(True)
        self.progressbar.setValue(0)
        self.progressbar.setMaximum(total_size)
        self.executor = CommonUtils.CommandExecutionFactory(tasks,
                                                            logger=TransCoda.logger,
                                                            max_threads=threads)
        self.executor.finish_event.connect(self.jobs_complete_event)
        self.statusBar().showMessage(status_message)
        self.executor.start()

    def reset_timer(self):
        if self.timer.isActive() and not self.executor.is_running():
            self.timer.stop()
        self.timer.start()

    def result_received_event(self, result):
        for result_item in result:
            if result_item.status in [EncoderStatus.SUCCESS, EncoderStatus.ERROR]:
                TransCodaHistory.set_history(
                    input_file=result_item.display_name(),
                    output_file=result_item.output_file,
                    start_time=result_item.encode_start_time,
                    end_time=result_item.encode_end_time,
                    input_size=result_item.file_size,
                    output_size=result_item.encode_output_size,
                    status=result_item.status,
                    encoder=result_item.encode_command,
                    message=result_item.encode_messages
                )
        self.main_panel.update_items(result)
        self.progressbar.setValue(self.progressbar.value() + len(result))
        self.update_status_bar()

    def status_received_event(self, status):
        self.main_panel.update_items([status])
        self.update_status_bar()

    def jobs_complete_event(self, all_results, time_taken):
        self.progressbar.setValue(self.progressbar.maximum())
        self.executor = None
        self.statusBar().showMessage(f"Processed {len(all_results)} files in {time_taken} seconds", msecs=400)
        self.set_window_title()
        self.tool_bar.encoding_finished(file_count=self.main_panel.row_count(),
                                        encoder_name=TransCodaSettings.get_encoder_name(),
                                        output_dir=TransCodaSettings.get_output_dir())
        self.reset_timer()

    def timer_timeout_event(self):
        self.progressbar.setValue(0)
        self.progressbar.setVisible(False)
        self.statusBar().clearMessage()

    def settings_changed(self, setting, _):
        valid_keys = {SettingsKeys.encoder_path}
        if setting in valid_keys:
            self.encoder.setText(TransCodaSettings.get_encoder_name())
        self.tool_bar.set_encode_state(file_count=self.main_panel.row_count(),
                                       encoder_name=TransCodaSettings.get_encoder_name(),
                                       output_dir=TransCodaSettings.get_output_dir())

    def update_status_bar(self):
        cpu = psutil.cpu_percent()
        if cpu > 0:
            cpu = f"\tCPU: {cpu}%"
        else:
            cpu = ""
        self.statusBar().showMessage(f"{self.progressbar.value()} files processed so far, "
                                     f"{self.progressbar.maximum() - self.progressbar.value()} files remaining. {cpu}")
        self.set_window_title(cpu=cpu, progress=self.progressbar.text())
        TransCoda.logger.info(self.statusBar().currentMessage())

    def set_window_title(self, cpu=None, progress=None):
        title = TransCoda.__APP_NAME__
        title += " " + cpu if cpu else ""
        title += " " + progress if progress else ""
        self.setWindowTitle(title)

    def show_encode_logs(self):
        self.terminal_view.show()

    def closeEvent(self, close_event) -> None:
        TransCoda.logger.info("Saving encode list...")
        TransCodaSettings.save_encode_list(self.main_panel.get_items())
        TransCoda.logger.info("Saving UI...")
        TransCodaSettings.settings.save_ui(self, TransCoda.logger)

    def open_paths_in_system_default(self, item_indices, attr, func=None):
        locations = set()
        for index in item_indices:
            item = self.main_panel.get_items(index)
            if hasattr(item, attr):
                if func:
                    locations.add(func(getattr(item, attr)))
                else:
                    locations.add(getattr(item, attr))

        if len(locations) > 3:
            choice = QMessageBox.question(self, "Are you Sure?",
                                          f"You are attempting to open several directories. "
                                          f"Are you sure you want to proceed?")
            if choice == QMessageBox.No:
                return
        for loc in locations:
            CommonUtils.open_file_item(loc)
コード例 #25
0
ファイル: traja-gui.py プロジェクト: nsarpangala/traja
class PlottingWidget(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        # super(PrettyWidget, self).__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(600, 300, 1000, 600)
        self.center()
        self.setWindowTitle("Plot Trajectory")

        mainMenu = self.menuBar()
        fileMenu = mainMenu.addMenu("File")

        saveAction = QAction("Save as...")
        saveAction.setShortcut("Ctrl+S")
        saveAction.setStatusTip("Save plot to file")
        saveAction.setMenuRole(QAction.NoRole)
        saveAction.triggered.connect(self.file_save)
        fileMenu.addAction(saveAction)

        exitAction = QAction("&Exit", self)
        exitAction.setShortcut("Ctrl+Q")
        exitAction.setStatusTip("Exit Application")
        exitAction.setMenuRole(QAction.NoRole)
        exitAction.triggered.connect(self.close)
        fileMenu.addAction(exitAction)

        settingsMenu = mainMenu.addMenu("Settings")
        self.setStyleMenu = QMenu("Set Style", self)
        settingsMenu.addMenu(self.setStyleMenu)
        for style_name in [
                "default", "fast", "ggplot", "grayscale", "seaborn"
        ]:
            styleAction = QAction(style_name, self, checkable=True)
            if style_name is CUR_STYLE:
                styleAction.setChecked(True)
            styleAction.triggered.connect(partial(self.set_style, style_name))
            self.setStyleMenu.addAction(styleAction)
        self.setTimeWindowMenu = QMenu("Set Time Window", self)
        settingsMenu.addMenu(self.setTimeWindowMenu)
        for window_str in ["None", "s", "30s", "H", "D"]:
            windowAction = QAction(window_str, self, checkable=True)
            if window_str is TIME_WINDOW:
                windowAction.setChecked(True)
            windowAction.triggered.connect(
                partial(self.set_time_window, window_str))
            self.setTimeWindowMenu.addAction(windowAction)

        # Grid Layout
        grid = QtWidgets.QGridLayout()
        widget = QtWidgets.QWidget(self)
        self.setCentralWidget(widget)
        widget.setLayout(grid)

        # Import CSV Button
        btn1 = QtWidgets.QPushButton("Import CSV", self)
        btn1.resize(btn1.sizeHint())
        btn1.clicked.connect(self.getCSV)
        grid.addWidget(btn1, 1, 0)

        # Canvas and Toolbar
        self.figure = plt.figure(figsize=(15, 5))
        self.canvas = FigureCanvas(self.figure)
        self.canvas.setContextMenuPolicy(Qt.CustomContextMenu)
        self.canvas.customContextMenuRequested.connect(self.popup)
        grid.addWidget(self.canvas, 2, 0, 1, 2)

        # DropDown mean / comboBox
        self.df = pd.DataFrame()
        self.columns = []
        self.plot_list = []

        self.comboBox = QtWidgets.QComboBox(self)
        self.comboBox.addItems(self.columns)
        grid.addWidget(self.comboBox, 0, 0)

        self.comboBox2 = QtWidgets.QComboBox(self)
        self.comboBox2.addItems(self.plot_list)
        grid.addWidget(self.comboBox2, 0, 1)

        # Plot Button
        btn2 = QtWidgets.QPushButton("Plot", self)
        btn2.resize(btn2.sizeHint())
        btn2.clicked.connect(self.plot)
        grid.addWidget(btn2, 1, 1)

        # Progress bar
        self.progress = QProgressBar(self)
        # self.progress.setRange(0, 1)
        grid.addWidget(self.progress, 3, 0, 1, 2)

        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.show()

    def set_style(self, style_name: str):
        global CUR_STYLE
        self.statusBar.showMessage(f"Style set to {style_name}")
        actions = self.setStyleMenu.actions()
        CUR_STYLE = style_name
        for action in actions:
            if action.text() == CUR_STYLE:
                # print(f"✓ {CUR_STYLE}")
                action.setChecked(True)
            else:
                action.setChecked(False)
        print(f"Style set to {CUR_STYLE}")

    def popup(self, pos):
        menu = QMenu()
        saveAction = menu.addAction("Save...")
        action = menu.exec_(self.canvas.viewport().mapToGlobal(pos))
        if action == saveAction:
            self.file_save()

    def file_save(self, target="figure"):
        name = QtGui.QFileDialog.getSaveFileName(self, "Save File")
        if target == "figure":
            self.figure.savefig(name)

    def update_progress_bar(self, i: int):
        self.progress.setValue(i)
        max = self.progress.maximum()
        self.statusBar.showMessage(f"Loading ... {100*i/max:.0f}%")

    def set_progress_bar_max(self, max: int):
        self.progress.setMaximum(max)

    def clear_progress_bar(self):
        self.progress.hide()
        self.statusBar.showMessage("Completed.")

    def getCSV(self):
        self.statusBar.showMessage("Loading CSV...")
        filepath, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, "Open CSV", (QtCore.QDir.homePath()), "CSV (*.csv *.tsv)")

        if filepath != "":
            self.filepath = filepath
            self.loaderThread = QThread()
            self.loaderWorker = QtFileLoader(filepath)
            self.loaderWorker.moveToThread(self.loaderThread)
            self.loaderThread.started.connect(self.loaderWorker.read_in_chunks)
            self.loaderWorker.intReady.connect(self.update_progress_bar)
            self.loaderWorker.progressMaximum.connect(
                self.set_progress_bar_max)
            # self.loaderWorker.read_in_chunks.connect(self.df)
            self.loaderWorker.completed.connect(self.list_to_df)
            self.loaderWorker.completed.connect(self.clear_progress_bar)
            self.loaderThread.finished.connect(self.loaderThread.quit)
            self.loaderThread.start()

    @pyqtSlot(list)
    def list_to_df(self, dfs: list):
        df = pd.concat(dfs)
        self.df = df
        self.columns = self.df.columns.tolist()
        self.plot_list = [
            "Actogram", "Polar Bar", "Polar Histogram", "Trajectory"
        ]
        self.comboBox.clear()
        self.comboBox.addItems(self.columns)
        self.comboBox2.clear()
        self.comboBox2.addItems(self.plot_list)
        self.statusBar.clearMessage()

    def mousePressEvent(self, QMouseEvent):
        if QMouseEvent.button() == Qt.RightButton:

            print("Right Button Clicked")

    def load_project_structure(self, startpath, tree):
        """
        Load Project structure tree
        :param startpath:
        :param tree:
        :return:
        """
        from PyQt5.QtWidgets import QTreeWidgetItem
        from PyQt5.QtGui import QIcon

        for element in os.listdir(startpath):
            path_info = startpath + "/" + element
            parent_itm = QTreeWidgetItem(tree, [os.path.basename(element)])
            if os.path.isdir(path_info):
                self.load_project_structure(path_info, parent_itm)
                parent_itm.setIcon(0, QIcon("assets/folder.ico"))
            else:
                parent_itm.setIcon(0, QIcon("assets/file.ico"))

    def set_time_window(self, window: str):
        global TIME_WINDOW
        TIME_WINDOW = window
        self.statusBar.showMessage(f"Time window set to {window}")
        actions = self.setTimeWindowMenu.actions()
        for action in actions:
            if action.text() == TIME_WINDOW:
                action.setChecked(True)
            else:
                action.setChecked(False)
        print(f"Time window set to {window}")

    def plot(self):
        plt.clf()

        plot_kind = self.comboBox2.currentText()
        self.statusBar.showMessage(f"Plotting {plot_kind}")
        projection = ("polar" if plot_kind in ["Polar Bar", "Polar Histogram"]
                      else "rectilinear")

        ax = self.figure.add_subplot(111, projection=projection)

        title = f"{basename(self.filepath)}"

        # TODO: Move mapping to separate method
        if plot_kind == "Actogram":
            displacement = traja.trajectory.calc_displacement(self.df)
            if TIME_WINDOW != "None":
                displacement = displacement.rolling(TIME_WINDOW).mean()
                # from pyqtgraph.Qt import QtGui, QtCore
            traja.plotting.plot_actogram(displacement,
                                         ax=ax,
                                         interactive=False)
        elif plot_kind == "Trajectory":
            traja.plotting.plot(self.df, ax=ax, interactive=False)
        elif plot_kind == "Quiver":
            traja.plotting.plot_quiver(self.df, ax=ax, interactive=False)
        elif plot_kind == "Polar Bar":
            traja.plotting.polar_bar(self.df,
                                     ax=ax,
                                     title=title,
                                     interactive=False)
        elif plot_kind == "Polar Histogram":
            traja.plotting.polar_bar(self.df,
                                     ax=ax,
                                     title=title,
                                     overlap=False,
                                     interactive=False)
        plt.tight_layout()
        self.canvas.draw()
        self.statusBar.clearMessage()

    def center(self):
        qr = self.frameGeometry()
        cp = QtWidgets.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
コード例 #26
0
class ProgressGroupBox(QGroupBox):
    """GroupBox для отображения состояния моделирования"""
    def __init__(self, parent=None) -> None:
        QGroupBox.__init__(self, title="Выполнение", parent=parent)
        # Переменная для времени старта моделирования
        self.starting_simulation_time = 0.
        # Переменная для времени старта записи в файл
        self.starting_writing_time = 0.
        # Число выполянемых итераций
        self.count_of_iteration = 0

        # Все компоненты
        # Прогресс бар
        self.bar = QProgressBar()
        self.bar.setRange(0, 10)

        # Строки состояний
        self.simulation_label = QLabel()
        self.iteration_label = QLabel()
        self.writing_label = QLabel()

        # Объеденим все виджеты в лист
        all_widgets = [self.bar,
                       self.simulation_label,
                       self.iteration_label,
                       self.writing_label]

        # Основной контейнер
        layout = QVBoxLayout(self)

        # Для всех виджетов указываем выравнивание и добавим в контейнер
        for widget in all_widgets:
            widget.setAlignment(Qt.AlignCenter)
            layout.addWidget(widget)

    def prepare_for_simulation(self, repeating_time_max: int) -> None:
        """Подготавливает виджеты для перед стартом моделирования

        :param repeating_time_max: Максимальное число повторений
        :type repeating_time_max: int

        :return: None
        """
        # Сохраним время запуска моделирования
        self.starting_simulation_time = perf_counter()

        # Сохраним число моделирований
        self.count_of_iteration = repeating_time_max

        # Очистка надписей
        self.simulation_label.setText(f"Идёт моделирование...")
        self.iteration_label.clear()
        self.writing_label.clear()

        # Псевдоиндикация
        self.bar.setValue(int(0.5 * self.bar.maximum()))

    @pyqtSlot()
    def show_simulation_time(self) -> None:
        """Показывает время моделирования

        :return: None
        """
        # Считаем время моделирования
        ending_simulation_time = perf_counter()
        simulation_time = ending_simulation_time - self.starting_simulation_time
        # Время выполнения одной итерации
        iteration_time = simulation_time / self.count_of_iteration

        # Псевдоиндикация
        self.bar.setValue(int(0.9 * self.bar.maximum()))

        # Покажем время моделирования
        self.simulation_label.setText(f"Моделирование проведено за {simulation_time:.2f} c.")
        self.iteration_label.setText(f"Одна итерация выполняется за {iteration_time:.2f} c.")

        # Если закончилось моделирование, то сейчас идёт запись в файл
        self.writing_label.setText("Идёт запись в файл")
        self.starting_writing_time = perf_counter()

    @pyqtSlot()
    def show_writing_time(self) -> None:
        """Показывает время записи в файл

        :return: None
        """
        # Определение времени записи в файл
        ending_writing_time = perf_counter()
        writing_time = ending_writing_time - self.starting_writing_time

        # Псевдоиндикация
        self.bar.setValue(self.bar.maximum())

        # Покажем время записи в файл
        self.writing_label.setText(f"Запись в файл заняла {writing_time:.2f} c.")
コード例 #27
0
ファイル: welcome.py プロジェクト: ChiNeSeFree/gridsync
class ProgressBarWidget(QWidget):
    def __init__(self):
        super(ProgressBarWidget, self).__init__()

        self.icon_server = QLabel()
        pixmap = QPixmap(resource('cloud.png')).scaled(220, 220)
        self.icon_server.setPixmap(pixmap)
        self.icon_server.setAlignment(Qt.AlignCenter)

        self.icon_overlay = QLabel()
        pixmap = QPixmap(resource('pixel.png')).scaled(75, 75)
        self.icon_overlay.setPixmap(pixmap)
        self.icon_overlay.setAlignment(Qt.AlignHCenter)

        self.icon_connection = QLabel()
        pixmap = QPixmap(resource('wifi.png')).scaled(128, 128)
        self.icon_connection.setPixmap(pixmap)
        self.icon_connection.setAlignment(Qt.AlignCenter)

        self.icon_client = QLabel()
        pixmap = QPixmap(resource('laptop-with-icon.png')).scaled(128, 128)
        self.icon_client.setPixmap(pixmap)
        self.icon_client.setAlignment(Qt.AlignCenter)

        self.checkmark = QLabel()
        pixmap = QPixmap(resource('pixel.png')).scaled(32, 32)
        self.checkmark.setPixmap(pixmap)
        self.checkmark.setAlignment(Qt.AlignCenter)

        self.tor_label = QLabel()
        self.tor_label.setToolTip(
            "This connection is being routed through the Tor network.")
        self.tor_label.setPixmap(
            QPixmap(resource('tor-onion.png')).scaled(24, 24))
        self.tor_label.hide()

        self.progressbar = QProgressBar()
        self.progressbar.setMaximum(10)
        self.progressbar.setTextVisible(False)
        self.progressbar.setValue(0)

        self.message = QLabel()
        self.message.setStyleSheet("color: grey")
        self.message.setAlignment(Qt.AlignCenter)

        self.finish_button = QPushButton("Finish")
        self.finish_button.hide()

        self.cancel_button = QToolButton()
        self.cancel_button.setIcon(QIcon(resource('close.png')))
        self.cancel_button.setStyleSheet('border: 0px; padding: 0px;')

        layout = QGridLayout(self)
        layout.addWidget(self.cancel_button, 0, 5)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 2)
        layout.addWidget(self.icon_server, 1, 3)
        layout.addWidget(self.icon_overlay, 1, 3)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 4)
        layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 5)
        layout.addWidget(self.icon_connection, 2, 3)
        layout.addWidget(self.icon_client, 3, 3)
        layout.addWidget(self.checkmark, 4, 3, 1, 1)
        layout.addWidget(self.tor_label, 5, 1, 1, 1, Qt.AlignRight)
        layout.addWidget(self.progressbar, 5, 2, 1, 3)
        layout.addWidget(self.message, 6, 3)
        layout.addWidget(self.finish_button, 6, 3)
        layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 7, 1)

    def update_progress(self, message):
        step = self.progressbar.value() + 1
        self.progressbar.setValue(step)
        self.message.setText(message)
        if step == 2:  # "Connecting to <nickname>..."
            pixmap = QPixmap(resource('lines_dotted.png')).scaled(128, 128)
            self.icon_connection.setPixmap(pixmap)
            pixmap = QPixmap(resource('cloud_storage.png')).scaled(220, 220)
            self.icon_server.setPixmap(pixmap)
        elif step == 5:  # After await_ready()
            pixmap = QPixmap(resource('lines_solid.png')).scaled(128, 128)
            self.icon_connection.setPixmap(pixmap)
        elif step == self.progressbar.maximum():  # "Done!"
            pixmap = QPixmap(resource('green_checkmark.png')).scaled(32, 32)
            self.checkmark.setPixmap(pixmap)

    def is_complete(self):
        return self.progressbar.value() == self.progressbar.maximum()

    def reset(self):
        self.progressbar.setValue(0)
        self.message.setText('')
        self.finish_button.hide()
        pixmap = QPixmap(resource('pixel.png')).scaled(32, 32)
        self.checkmark.setPixmap(pixmap)
コード例 #28
0
ファイル: download_orbits.py プロジェクト: li8182/InSAR-Tools
class DownloadOrbit(QWidget):
    def __init__(self):
        super().__init__()
        self.get_urls_thread = GetUrlThread()
        self.add_to_idm_thread = AddToIDMThread()
        self.exec_idm_thread = ExecIDMThread()

        self.setWindowTitle("Download Sentinel-1A/B Precise Orbit")
        self.setFont(QFont('Consolas'))
        self.setWindowIcon(QIcon(':/orbit.ico'))
        self.resize(800, 400)
        self.setup_ui()

    def setup_ui(self):
        self.label_mode = QLabel('获取精轨日期模式:')
        self.radio_btn_file = QRadioButton('file mode')
        self.radio_btn_dir = QRadioButton('dir mode')
        self.radio_btn_file.setChecked(True)
        self.label_type = QLabel('文本文件路径:')
        self.le_image_path = QLineEdit()
        self.label_orbit = QLabel('精轨保存路径:')
        self.le_orbit_path = QLineEdit()
        self.label_idm = QLabel('IDMan.exe路径:')
        self.le_idm_path = QLineEdit()
        self.btn_image_path = QPushButton('选择路径')
        self.btn_image_path.setFixedSize(self.btn_image_path.sizeHint())
        self.btn_orbit_path = QPushButton('选择路径')
        self.btn_orbit_path.setFixedSize(self.btn_orbit_path.sizeHint())
        self.btn_idm_path = QPushButton('选择路径')
        self.btn_idm_path.setFixedSize(self.btn_idm_path.sizeHint())
        self.btn_get_urls = QPushButton('抓取精轨链接')
        self.btn_add_to_idm = QPushButton('启动IDM\n 并添加任务 ')
        self.btn_add_to_idm.setSizePolicy(QSizePolicy.Fixed,
                                          QSizePolicy.Expanding)
        self.btn_get_urls.setObjectName('btn_get_urls')
        self.btn_add_to_idm.setObjectName('btn_add_to_idm')
        self.btn_idm_path.setObjectName('btn_idm_path')
        self.btn_image_path.setObjectName('btn_image_path')
        self.btn_orbit_path.setObjectName('btn_orbit_path')
        self.label_progress = QLabel('抓取链接进度:')
        self.pb_progress = QProgressBar()
        self.pb_progress.setValue(self.pb_progress.minimum() - 1)
        self.pb_progress.setFormat("%v/%m")
        self.ted_info = TextEdit()
        self.ted_info.setFontUnderline(False)
        self.ted_info.setTextColor(QColor('black'))
        self.ted_info.setReadOnly(True)
        self.ted_info.setText(
            "@author  : leiyuan \n@version : 3.5\n"
            "@date    : 2020-02-23\n\n"
            "file mode: 从'文本文件'获取Sentinel-1A/B影像名,用于获取影像日期,从而获取精轨日期"
            "\ndir  mode: 从'压缩文件'获取Sentinel-1A/B影像名,用于获取影像日期,从而获取精轨日期"
            "\n\n温馨提示:为了能够更快地完成任务,请尽量翻越长城")
        # 设置布局
        layout = QGridLayout(self)
        self.setLayout(layout)
        layout.setColumnStretch(2, 1)
        layout.setColumnStretch(3, 1)
        layout.setColumnStretch(4, 1)
        # 第一行
        layout.addWidget(self.label_mode, 0, 1, Qt.AlignRight)
        layout.addWidget(self.radio_btn_file, 0, 2)
        layout.addWidget(self.radio_btn_dir, 0, 3)
        # 第二行
        layout.addWidget(self.label_type, 1, 1, Qt.AlignRight)
        layout.addWidget(self.le_image_path, 1, 2, 1, 3)
        layout.addWidget(self.btn_image_path, 1, 5)
        layout.addWidget(self.btn_get_urls, 1, 6, 1, 2)
        # 第三行
        layout.addWidget(self.label_orbit, 2, 1, Qt.AlignRight)
        layout.addWidget(self.le_orbit_path, 2, 2, 1, 3)
        layout.addWidget(self.btn_orbit_path, 2, 5)
        layout.addWidget(self.btn_add_to_idm, 2, 6, 2, 2)
        # 第四行
        layout.addWidget(self.label_idm, 3, 1, Qt.AlignRight)
        layout.addWidget(self.le_idm_path, 3, 2, 1, 3)
        layout.addWidget(self.btn_idm_path, 3, 5)
        # 第五行
        layout.addWidget(self.label_progress, 4, 1, Qt.AlignRight)
        layout.addWidget(self.pb_progress, 4, 2, 1, 6)
        # 第六行
        layout.addWidget(self.ted_info, 5, 1, 3, 7)

        # 信号与槽
        self.btn_get_urls.clicked.connect(self.get_urls)
        self.get_urls_thread.sin_out_task_num.connect(self.task_num)
        self.get_urls_thread.sin_out_process.connect(
            lambda value: self.pb_progress.setValue(value))
        self.get_urls_thread.sin_out_urls.connect(self.assign_urls)
        self.exec_idm_thread.sin_out_warning.connect(self.warning)
        self.add_to_idm_thread.sin_out_success.connect(self.success_add_to_idm)
        self.add_to_idm_thread.sin_out_error_num.connect(self.error_add_to_idm)
        self.pb_progress.valueChanged.connect(
            lambda value: self.success_get_urls(value))
        self.btn_orbit_path.clicked.connect(self.get_orbit_path)
        self.btn_idm_path.clicked.connect(self.get_idm_path)
        self.btn_image_path.clicked.connect(self.get_images_name_by_file)
        self.radio_btn_file.toggled.connect(
            lambda: self.switch_btn_slot(self.radio_btn_file))
        self.radio_btn_dir.toggled.connect(
            lambda: self.switch_btn_slot(self.radio_btn_dir))
        self.btn_add_to_idm.clicked.connect(self.add_to_idm)

    def warning(self, info):
        """弹出警告信息"""
        mb = QMessageBox(QMessageBox.Warning, "Warning", info, QMessageBox.Ok,
                         self)
        mb.show()

    def assign_urls(self, urls):
        self.add_to_idm_thread.urls = urls

    def task_num(self, num):
        if num:
            self.pb_progress.setEnabled(True)
            self.pb_progress.setMaximum(num)
            self.pb_progress.setValue(0)
            self.ted_info.clear()
            self.ted_info.setFontUnderline(False)
            self.ted_info.setTextColor(QColor('black'))
            # 添加一个开始锚点
            self.ted_info.append("<a name='begin'></a>")
            time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            self.ted_info.insertPlainText("{} 需要抓取 {} 个精轨链接\n".format(
                time, num))
        else:
            self.warning("未找到哨兵影像名,请重新设置{}".format(
                self.label_type.text()[:-1]))
            self.pb_progress.setEnabled(False)

    def success_add_to_idm(self, info):
        self.ted_info.setFontUnderline(False)
        self.ted_info.setTextColor(QColor('black'))
        self.ted_info.append(info)

    def error_add_to_idm(self, info):
        self.ted_info.setFontUnderline(False)
        self.ted_info.setTextColor(QColor('black'))
        self.ted_info.append(info)

    def success_get_urls(self, value):
        def get_date(u):
            temp = re.findall(r"\d{8}", u)[-1]
            temp = datetime.datetime(int(temp[:4]), int(temp[4:6]),
                                     int(temp[6:]))
            delta = datetime.timedelta(days=-1)
            date = temp + delta
            return date.strftime('%Y%m%d')

        if value == self.pb_progress.maximum():
            time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            self.ted_info.insertPlainText('\n{} 成功抓取所有精轨链接\n\n{}\n\n'.format(
                time, '*' * 50))
            for url in self.get_urls_thread.urls:
                html = "精轨对应的影像日期(点击右侧日期即可下载):<a href={}>{}</a>".format(
                    url, get_date(url))
                self.ted_info.insertHtml(html)
                self.ted_info.append('\n')
            self.ted_info.append("<a name='end'>{}</a>\n\n".format("*" * 50))
            self.ted_info.scrollToAnchor('begin')

    def add_to_idm(self):
        idm_path = self.le_idm_path.text()
        orbit_path = self.le_orbit_path.text()
        if not idm_path and not orbit_path:
            self.warning("请设置精轨保存路径和IDMan.exe路径")
        elif not idm_path and orbit_path:
            self.warning("请设置IDMan.exe路径")
        elif not orbit_path and idm_path:
            self.warning("请设置精轨保存路径")
        elif not os.path.exists(orbit_path) and not os.path.exists(idm_path):
            self.warning("精轨保存路径和IDMan.exe路径不存在,请重新设置")
        elif not os.path.exists(orbit_path):
            self.warning("精轨保存路径不存在,请重新设置")
        elif not os.path.exists(idm_path):
            self.warning("IDMan.exe路径不存在,请重新设置")
        else:
            self.exec_idm_thread.idm_path = idm_path
            self.add_to_idm_thread.le_orbit_path = orbit_path
            self.add_to_idm_thread.idm_path = idm_path
            if self.add_to_idm_thread.urls:
                self.exec_idm_thread.start()
                self.add_to_idm_thread.start()
                self.ted_info.scrollToAnchor('end')
            else:
                self.warning("请先抓取精轨链接")

    def get_images_name_by_dir(self):
        dir_name = QFileDialog.getExistingDirectory(self, '选择压缩文件路径', './')
        if dir_name:
            self.le_image_path.setText(dir_name)
        self.get_urls_thread.image_path = self.le_image_path.text()

    def get_images_name_by_file(self):
        file_name = QFileDialog.getOpenFileName(
            self, '选择文本文件路径', './示例文件', 'All files(*.*);;txt file(*.txt)',
            'txt file(*.txt)')
        if file_name[0]:
            self.le_image_path.setText(str(file_name[0]))
        self.get_urls_thread.image_path = self.le_image_path.text()

    def get_orbit_path(self):
        dir_name = QFileDialog.getExistingDirectory(self, '选择精轨保存路径', '../')
        self.le_orbit_path.setText(dir_name)

    def get_urls(self):
        path = self.le_image_path.text()
        if not path:
            self.warning("请设置{}".format(self.label_type.text()[:-1]))
        elif not os.path.exists(path):
            self.warning("{}不存在,请重新设置".format(self.label_type.text()[:-1]))
        else:
            self.get_urls_thread.urls = []
            self.get_urls_thread.start()

    def get_idm_path(self):
        file_name = QFileDialog.getOpenFileName(self, '选择IDMan.exe路径',
                                                'C:/thorly/Softwares/IDM',
                                                'IDMan.exe (IDMan.exe)')
        self.le_idm_path.setText(str(file_name[0]))

    def switch_btn_slot(self, radio_btn):
        if radio_btn.text() == 'file mode' and radio_btn.isChecked():
            try:
                self.btn_image_path.clicked.disconnect(
                    self.get_images_name_by_dir)
                self.btn_image_path.clicked.disconnect(
                    self.get_images_name_by_file)
            except:
                pass
            self.btn_image_path.clicked.connect(self.get_images_name_by_file)
            self.label_type.setText('文本文件路径:')
        if radio_btn.text() == 'dir mode' and radio_btn.isChecked():
            try:
                self.btn_image_path.clicked.disconnect(
                    self.get_images_name_by_file)
                self.btn_image_path.clicked.disconnect(
                    self.get_images_name_by_dir)
            except:
                pass
            self.btn_image_path.clicked.connect(self.get_images_name_by_dir)
            self.label_type.setText('压缩文件路径:')
コード例 #29
0
class VCProgressBar(QDialog):
    taskbarprogress = pyqtSignal(float, bool)

    def __init__(self, parent=None, flags=Qt.Dialog | Qt.FramelessWindowHint):
        super(VCProgressBar, self).__init__(parent, flags)
        self.parent = parent
        self.setWindowModality(Qt.ApplicationModal)
        self.setStyleSheet('QDialog { border: 2px solid #000; }')
        self._progress = QProgressBar(self)
        self._progress.setRange(0, 0)
        self._progress.setTextVisible(False)
        self._progress.setStyle(QStyleFactory.create('Fusion'))
        self._label = QLabel(self)
        self._label.setAlignment(Qt.AlignCenter)
        layout = QGridLayout()
        layout.addWidget(self._progress, 0, 0)
        layout.addWidget(self._label, 0, 0)
        self._timerprefix = QLabel('<b>Elapsed time:</b>', self)
        self._timerprefix.setObjectName('progresstimer')
        self._timervalue = QLabel(self)
        self._timervalue.setObjectName('progresstimer')
        timerlayout = QHBoxLayout()
        timerlayout.addWidget(self._timerprefix)
        timerlayout.addWidget(self._timervalue)
        self._timerwidget = QWidget(self)
        self._timerwidget.setLayout(timerlayout)
        self._timerwidget.hide()
        self._time = QTime()
        self._timer = QTimer(self)
        self._timer.timeout.connect(self.updateTimer)
        self.setLayout(layout)
        self.setFixedWidth(550)

    def reset(self, steps: int = 0, timer: bool = False) -> None:
        self.setValue(0)
        self.setRange(0, steps)
        self.setText('Analyzing video source')
        self.showTimer() if timer else self.hideTimer()

    def showTimer(self) -> None:
        self._timerwidget.show()
        # noinspection PyArgumentList
        self.layout().addWidget(self._timerwidget, 1, 0,
                                Qt.AlignHCenter | Qt.AlignTop)
        self._time.start()
        self.updateTimer()
        self._timer.start(1000)

    def hideTimer(self) -> None:
        self._timerwidget.hide()
        self.layout().removeWidget(self._timerwidget)

    @pyqtSlot()
    def updateTimer(self) -> None:
        secs = self._time.elapsed() / 1000
        mins = int(secs / 60) % 60
        hrs = int(secs / 3600)
        secs = int(secs % 60)
        elapsed = '{hrs:02d}:{mins:02d}:{secs:02d}'.format(**locals())
        self._timervalue.setText(elapsed)

    def value(self) -> int:
        return self._progress.value()

    def setStyle(self, style: QStyle) -> None:
        self._progress.setStyle(style)

    def setText(self, val: str) -> None:
        if '<b>' in val:
            css = '<style>b { font-family:"Noto Sans UI"; font-weight:bold; }</style>'
            val = '{0}{1}'.format(css, val)
        self._label.setText(val)

    def setMinimum(self, val: int) -> None:
        self._progress.setMinimum(val)

    def setMaximum(self, val: int) -> None:
        self._progress.setMaximum(val)

    @pyqtSlot(int, int)
    def setRange(self, minval: int, maxval: int) -> None:
        self._progress.setRange(minval, maxval)

    def setValue(self, val: int) -> None:
        if sys.platform.startswith('linux') and self._progress.maximum() != 0:
            self.taskbarprogress.emit(float(val / self._progress.maximum()),
                                      True)
        self._progress.setValue(val)
        if val >= self._progress.maximum() and self._timer.isActive():
            self._timer.stop()

    @pyqtSlot(str)
    def updateProgress(self, text: str) -> None:
        self.setValue(self._progress.value() + 1)
        self.setText(text)
        qApp.processEvents()

    @pyqtSlot()
    def close(self) -> None:
        if sys.platform.startswith('linux'):
            self.taskbarprogress.emit(0.0, False)
        if self._timer.isActive():
            self._timer.stop()
        super(VCProgressBar, self).close()
コード例 #30
0
class Window(QDialog):
    web_queue = Queue()

    def __init__(self):
        super().__init__()
        self.make_window()
        self.read_config()
        self.myweb = MyWeb(self.postal)
        self.update_connection_info()
        self.set_app_title()

    def read_config(self):
        try:
            settings.init()
            cookies.init()
        except KeyError as err:
            msg = f'ERROR: {err} is not defined in setting file'
            self.postal.log(msg)
            QMessageBox.warning(self, 'Setting Error', msg)
            return
        except FileNotFoundError as err:
            self.postal.log(f'ERROR openning ini file: {err}')

    def set_app_title(self):
        project = settings.Config.get('web', 'project', fallback='untitled')
        self.setWindowTitle(f"{AppName} [{project}]")

    def make_window(self):
        self.web_queue_thread = QueueThread(self.web_queue)
        self.setGeometry(400, 400, 500, 500)
        vbox = QVBoxLayout()

        hbox = QHBoxLayout()
        vbox.addWidget(QLabel("Browser Session:"))
        vbox.addLayout(hbox)
        self.connect_settings = QLineEdit("")
        hbox.addWidget(self.connect_settings)
        self.connect_button = QPushButton('Connect')
        hbox.addWidget(self.connect_button)
        self.new_browser_button = QPushButton('New')
        hbox.addWidget(self.new_browser_button)
        self.connect_button.clicked.connect(self.connect_browser)
        self.new_browser_button.clicked.connect(self.launch_browser)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        self.start_button = QPushButton('Start')
        self.start_button.clicked.connect(self.start_progress)
        self.start_button.setDisabled(True)
        self.stop_button = QPushButton('Stop')
        self.stop_button.clicked.connect(self.stop_progress)
        self.stop_button.setDisabled(True)
        hbox.addWidget(self.start_button)
        hbox.addWidget(self.stop_button)
        self.setLayout(vbox)

        vbox.addWidget(QLabel("System log:"))
        self.syslog = QTextEdit()
        self.syslog.setContextMenuPolicy(Qt.CustomContextMenu)
        self.syslog.customContextMenuRequested.connect(
            self.generate_context_menu)
        self.syslog.setReadOnly(True)
        vbox.addWidget(self.syslog)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        hbox.addWidget(QLabel("Initwait:"))
        self.progressbar = QProgressBar()
        self.progressbar.setMaximum(1000)
        self.progressbar.setValue(0)
        hbox.addWidget(self.progressbar)
        self.progressbar.setFormat('0/0')
        self.progressbar.setAlignment(Qt.AlignCenter)
        self.progress_enabled = False
        self.prog_max = 100
        self.prog_count = 0

        self.status_bar = QLabel()
        self.status_bar.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        vbox.addWidget(self.status_bar)

        self.web_queue_thread.receiver.connect(self.web_queue_dispatch)
        self.web_queue_thread.start()
        self.timer = QTimer()
        self.timer.timeout.connect(self.move_progress)

        self.postal = Postal(self)
        self.postal.status('Idle')

        self.show()

    def clear_log_window(self):
        self.syslog.clear()

    def generate_context_menu(self, location):
        menu = self.syslog.createStandardContextMenu(location)

        # add extra items to the menu
        menu.addSeparator()
        clear_action = QAction("Clear system log", self)
        clear_action.triggered.connect(self.clear_log_window)
        menu.addAction(clear_action)

        # show the menu
        menu.exec_(self.mapToGlobal(location))

    def update_connection_info(self):
        try:
            cookies.refresh()
            info = cookies.Cookies['browser']['session']
            self.connect_settings.setText(info)
        except KeyError:
            pass

    def web_queue_dispatch(self, mtype, text):
        if mtype == 'log':
            self.log(text)
        elif mtype == 'status':
            self.status_update(text)
        elif mtype == 'alert':
            self.alert(text)
        elif mtype == 'notify':
            self.status_update(text)
        elif mtype == 'progress':
            self.reset_progress_bar(text)
        else:
            raise Exception(f"Unknown queue type {mtype}")

    def log(self, text):
        self.syslog.moveCursor(QTextCursor.End)
        self.syslog.insertPlainText(text)

    def status_update(self, text):
        fm = QFontMetrics(self.status_bar.font())
        elided = fm.elidedText(text, Qt.ElideRight,
                               self.status_bar.width() - 10)
        self.status_bar.setText(elided)

    def notify(self, text):
        notifyrun(text)

    def alert(self, text):
        if text == 'stop':
            self.stop_progress()

    def start_progress_bar(self):
        self.set_progress_val(0)
        self.progress_enabled = True
        self.timer.start(1000)  # 1sec tick

    def start_progress(self):
        if not self.myweb.is_started():
            QMessageBox.warning(self, 'No Browser',
                                'Browser not nonnected/activated')
            return

        if settings.check_file_modified():
            reply = QMessageBox.question(
                self, 'Load INI', 'INI file has been modified. Reload?',
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if reply == QMessageBox.Yes:
                settings.refresh()

        if self.myweb.check_rule_file_modified():
            if self.myweb.rule_data:
                msg = 'JSON file has been modified. Reload it?'
            else:
                msg = 'JSON file not loaded. Load it?'

            reply = QMessageBox.question(self, 'Load JSON', msg,
                                         QMessageBox.Yes | QMessageBox.No,
                                         QMessageBox.No)
            if reply == QMessageBox.Yes:
                if not self.myweb.load_rules() and self.myweb.rule_data:
                    self.postal.log(
                        "Continue with previously loaded JSON data")

        if self.myweb.rule_data:
            self.myweb.clear()
            self.myweb.pause(False)
            self.web_thread = WebThread(self.myweb)
            self.web_thread.start()
            self.start_button.setDisabled(True)
            self.stop_button.setDisabled(False)
            self.update_connection_info()
            self.postal.log("Control started")
        else:
            self.postal.log("Unable to start. JSON data not loaded")

    def stop_progress_bar(self):
        self.progress_enabled = False
        self.timer.stop()

    def stop_progress(self):
        self.myweb.pause()
        self.web_thread.terminate()
        self.web_thread.wait()
        self.stop_progress_bar()
        self.start_button.setDisabled(False)
        self.stop_button.setDisabled(True)
        self.set_progress_val(0)
        self.postal.status('Idle')
        self.postal.log("Control stopped")

    def reset_progress_bar(self, text):
        assert int(text) <= 1000

        self.stop_progress_bar()
        self.prog_max = int(text)
        self.prog_count = self.prog_max
        self.start_progress_bar()
        self.set_progress_val(self.prog_max)

    def set_progress_val(self, val):
        maxcount = self.prog_max
        if maxcount > 0:
            steps = int(self.progressbar.maximum() / maxcount * val)
        else:
            steps = 0
        self.progressbar.setValue(steps)
        self.progressbar.setFormat(f'{val}/{maxcount}')

    def move_progress(self):
        if not self.progress_enabled:
            return

        # advance progress bar
        if self.prog_count > 0:
            self.prog_count -= 1
        self.set_progress_val(self.prog_count)

    def launch_browser(self):
        if self.myweb.is_started():
            reply = QMessageBox.question(
                self, 'Launch Browser',
                'Current session is still active. Relaunch?',
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if reply != QMessageBox.Yes:
                return

        cmd = f'{sys.executable} web.py'
        process = QProcess()

        def started():
            self.postal.log('Starting new browser')

        def finished():
            rv = process.exitCode()
            if not rv:
                self.update_connection_info()
                self.myweb.end()
                self.connect_browser()
                self.start_button.setDisabled(False)
                self.postal.log('Browser started')
                self.start_progress()

        def read_output(p):
            self.postal.log(str(p.readAllStandardOutput(), 'utf-8'))

        process.started.connect(started)
        process.readyReadStandardOutput.connect(
            functools.partial(read_output, process))
        process.finished.connect(finished)
        process.start(cmd)
        self.browser_process = process

    def connect_browser(self):
        if self.myweb.is_started():
            reply = QMessageBox.question(
                self, 'Connect Browser',
                'Current session is still active. Reconnect?',
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if reply != QMessageBox.Yes:
                return

            self.myweb.end()

        conn_string = self.connect_settings.text()
        rv = re.match(r"(http://\d+\.\d+\.\d+\.\d+:\d+)\s+([\w\-]+)",
                      conn_string)
        if rv:
            exe_url, session_id = rv.groups()
            try:
                self.myweb.start([exe_url, session_id])
                self.update_connection_info()
                self.start_button.setDisabled(False)
            except ConnectionError:
                QMessageBox.warning(
                    self, 'Connection Error',
                    "Unable to connect. Please check to ensure remote session is active."
                )
        else:
            QMessageBox.warning(self, 'Connection Error',
                                "Invalid connection setting. Please verify.")

    def closeEvent(self, event):
        if self.myweb.is_started():
            reply = QMessageBox.question(
                self, 'Close Application',
                'Browser session is active. Exit application?',
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if reply == QMessageBox.Yes:
                self.myweb.end()
                event.accept()
            else:
                event.ignore()
        else:
            event.accept()