From b80902e947e54f12029b22266eb11117fcd22097 Mon Sep 17 00:00:00 2001 From: Faerbit Date: Tue, 23 Nov 2021 22:24:34 +0100 Subject: [PATCH] Add ProgressIndicator to ImportTask --- src/fime/import_task.py | 41 ++++++++++++++++++++++++++++++----- src/fime/progressindicator.py | 8 +++---- src/fime/task_completer.py | 30 ++++++++++++++++++++++++- src/fime/worklog.py | 4 ++-- 4 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/fime/import_task.py b/src/fime/import_task.py index 1276876..722e468 100644 --- a/src/fime/import_task.py +++ b/src/fime/import_task.py @@ -1,10 +1,10 @@ -from fime.config import Config - try: - from PySide6 import QtGui, QtWidgets + from PySide6 import QtCore, QtGui, QtWidgets except ImportError: - from PySide2 import QtGui, QtWidgets + from PySide2 import QtCore, QtGui, QtWidgets +from fime.config import Config +from fime.progressindicator import ProgressIndicator from fime.task_completer import TaskCompleter from fime.util import get_icon @@ -14,11 +14,17 @@ class ImportTask(QtWidgets.QDialog): super().__init__(parent, *args, **kwargs) self.setWindowTitle("New Tasks") - self.line_edit = QtWidgets.QLineEdit() + self.line_edit = QtWidgets.QLineEdit(self) completer = TaskCompleter(config) self.line_edit.setCompleter(completer) self.line_edit.textChanged.connect(completer.update_picker) + self.indicator = ProgressIndicator(self) + self.indicator.setAnimationDelay(70) + self.indicator.setDisplayedWhenStopped(False) + completer.running.connect(self.spin) + completer.stopped.connect(self.no_spin) + ok_button = QtWidgets.QPushButton() ok_button.setText("OK") ok_button.setIcon(get_icon("dialog-ok")) @@ -31,17 +37,40 @@ class ImportTask(QtWidgets.QDialog): cancel_button.pressed.connect(self.reject) cancel_button.setAutoDefault(False) + alayout = QtWidgets.QStackedLayout() + alayout.setStackingMode(QtWidgets.QStackedLayout.StackAll) + alayout.addWidget(self.line_edit) + size = self.line_edit.height() + self.indicator.setMaximumSize(QtCore.QSize(size * 0.75, size * 0.75)) + aalayout = QtWidgets.QVBoxLayout() + aalayout.addWidget(self.indicator, alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + marg = aalayout.contentsMargins() + marg.setRight(size * 0.15) + aalayout.setContentsMargins(marg) + aawidget = QtWidgets.QWidget() + aawidget.setLayout(aalayout) + alayout.addWidget(aawidget) + alayout.setCurrentWidget(aawidget) + blayout = QtWidgets.QHBoxLayout() blayout.addSpacing(300) blayout.addWidget(cancel_button) blayout.addWidget(ok_button) layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.line_edit) + layout.addLayout(alayout) layout.addLayout(blayout) self.setLayout(layout) self.resize(500, 0) + @QtCore.Slot() + def spin(self): + self.indicator.startAnimation() + + @QtCore.Slot() + def no_spin(self): + self.indicator.stopAnimation() + @property def task_text(self): return self.line_edit.text() diff --git a/src/fime/progressindicator.py b/src/fime/progressindicator.py index 1fb84ec..eaff1e2 100644 --- a/src/fime/progressindicator.py +++ b/src/fime/progressindicator.py @@ -8,7 +8,7 @@ except ImportError: from PySide2 import QtCore, QtGui, QtWidgets -class QProgressIndicator(QtWidgets.QWidget): +class ProgressIndicator(QtWidgets.QWidget): m_angle = None m_timerId = None m_delay = None @@ -30,7 +30,7 @@ class QProgressIndicator(QtWidgets.QWidget): self.m_color = QtCore.Qt.black # Set size and focus policy - self.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding) self.setFocusPolicy(QtCore.Qt.NoFocus) # Show the widget @@ -43,7 +43,7 @@ class QProgressIndicator(QtWidgets.QWidget): return (self.m_timerId != -1) def isDisplayedWhenStopped(self): - return self.displayedWhenStopped + return self.m_displayedWhenStopped def getColor(self): return self.color @@ -74,7 +74,7 @@ class QProgressIndicator(QtWidgets.QWidget): self.m_timerId = self.startTimer(self.m_delay) def setDisplayedWhenStopped(self, state): - self.displayedWhenStopped = state + self.m_displayedWhenStopped = state self.update() def setColor(self, color): diff --git a/src/fime/task_completer.py b/src/fime/task_completer.py index 0a233a9..f6db724 100644 --- a/src/fime/task_completer.py +++ b/src/fime/task_completer.py @@ -1,6 +1,8 @@ import os import sys +import threading import traceback +from enum import Enum, auto from functools import reduce from queue import Queue, Empty from urllib.parse import urlparse, parse_qs @@ -15,6 +17,13 @@ from fime.config import Config class TaskCompleter(QtWidgets.QCompleter): + class RifState(Enum): + RUNNING = auto() + STOPPED = auto() + + running = QtCore.Signal() + stopped = QtCore.Signal() + def __init__(self, config: Config, parent=None, *args, **kwargs): super().__init__([], parent, *args, **kwargs) self.setFilterMode(QtCore.Qt.MatchFlag.MatchContains) @@ -29,11 +38,22 @@ class TaskCompleter(QtWidgets.QCompleter): self.escalate = False self.update_timer = QtCore.QTimer(self) self.update_timer.timeout.connect(self.process_response) - self.update_timer.setInterval(250) + self.update_timer.setInterval(200) self.queue = Queue() + # Request In Flight + self.rif_counter = 0 + self.rif_counter_lock = threading.Lock() + self.last_rif_state = TaskCompleter.RifState.STOPPED @QtCore.Slot() def process_response(self): + with self.rif_counter_lock: + if self.last_rif_state is TaskCompleter.RifState.STOPPED and self.rif_counter != 0: + self.last_rif_state = TaskCompleter.RifState.RUNNING + self.running.emit() + if self.last_rif_state is TaskCompleter.RifState.RUNNING and self.rif_counter == 0: + self.last_rif_state = TaskCompleter.RifState.STOPPED + self.stopped.emit() try: while not self.queue.empty(): result_dict = self.queue.get_nowait() @@ -68,9 +88,13 @@ class TaskCompleter(QtWidgets.QCompleter): "Accept": "application/json", }, ) + with self.rif_counter_lock: + self.rif_counter += 1 future.add_done_callback(self.picker_response_callback) def picker_response_callback(self, future): + with self.rif_counter_lock: + self.rif_counter -= 1 try: result = future.result() parsed = urlparse(result.request.url) @@ -106,9 +130,13 @@ class TaskCompleter(QtWidgets.QCompleter): "Accept": "application/json", }, ) + with self.rif_counter_lock: + self.rif_counter += 1 future.add_done_callback(self.search_response_callback) def search_response_callback(self, future): + with self.rif_counter_lock: + self.rif_counter -= 1 try: result = future.result() json_result = result.json() diff --git a/src/fime/worklog.py b/src/fime/worklog.py index aac9609..bea07e6 100644 --- a/src/fime/worklog.py +++ b/src/fime/worklog.py @@ -4,7 +4,7 @@ from PySide2.QtQuickWidgets import QQuickWidget from PySide2.QtWidgets import QLabel from fime.ok_icon import OkIcon -from fime.progressindicator import QProgressIndicator +from fime.progressindicator import ProgressIndicator from fime.spinner import Spinner try: @@ -52,7 +52,7 @@ class Worklog(QtWidgets.QDialog): self.tableWidget.setItem(row, 0, item0) size = self.tableWidget.rowHeight(row) if row == 1: - qpi = QProgressIndicator(self) + qpi = ProgressIndicator(self) qpi.setMaximumSize(QtCore.QSize(size * 0.75, size * 0.75)) qpi.setAnimationDelay(70) qpi.startAnimation()