diff --git a/comictaggerlib/issueselectionwindow.py b/comictaggerlib/issueselectionwindow.py
index e76ba0d..0699215 100644
--- a/comictaggerlib/issueselectionwindow.py
+++ b/comictaggerlib/issueselectionwindow.py
@@ -143,6 +143,7 @@ class IssueSelectionWindow(SelectionWindow):
self.accept()
def update_row(self, row: int, issue: GenericMetadata) -> None: # type: ignore[override]
+ self.twList.setStyleSheet(self.twList.styleSheet())
item_text = issue.issue or ""
item = self.twList.item(row, 0)
item.setText(item_text)
diff --git a/comictaggerlib/seriesselectionwindow.py b/comictaggerlib/seriesselectionwindow.py
index 99489a3..dbdc769 100644
--- a/comictaggerlib/seriesselectionwindow.py
+++ b/comictaggerlib/seriesselectionwindow.py
@@ -23,7 +23,7 @@ from collections import deque
import natsort
from PyQt5 import QtCore, QtGui, QtWidgets, uic
-from PyQt5.QtCore import QUrl, pyqtSignal
+from PyQt5.QtCore import Qt, QUrl, pyqtSignal
from comicapi import utils
from comicapi.comicarchive import ComicArchive
@@ -149,6 +149,7 @@ class SelectionWindow(QtWidgets.QDialog):
literal: bool = False,
) -> None:
super().__init__(parent)
+ self.setWindowModality(Qt.WindowModality.WindowModal)
with self.ui_file.open(encoding="utf-8") as uifile:
uic.loadUi(uifile, self)
@@ -497,7 +498,6 @@ class SeriesSelectionWindow(SelectionWindow):
selector = MatchSelectionWindow(
self, issues, self.comic_archive, talker=self.talker, config=self.config
)
- selector.setModal(True)
selector.exec()
if selector.result():
# we should now have a list index
@@ -523,9 +523,8 @@ class SeriesSelectionWindow(SelectionWindow):
break
self.selector.setWindowTitle(title + "Select Issue")
- self.selector.setModal(True)
self.selector.finished.connect(self.issue_selected)
- self.selector.open()
+ self.selector.show()
def issue_selected(self, result) -> None:
if result and self.selector:
diff --git a/comictaggerlib/settingswindow.py b/comictaggerlib/settingswindow.py
index cb13f98..e19266b 100644
--- a/comictaggerlib/settingswindow.py
+++ b/comictaggerlib/settingswindow.py
@@ -669,7 +669,6 @@ class SettingsWindow(QtWidgets.QDialog):
def show_template_help(self) -> None:
template_help_win = TemplateHelpWindow(self)
- template_help_win.setModal(False)
template_help_win.show()
diff --git a/comictaggerlib/taggerwindow.py b/comictaggerlib/taggerwindow.py
index 04cc2a3..6684d83 100644
--- a/comictaggerlib/taggerwindow.py
+++ b/comictaggerlib/taggerwindow.py
@@ -1090,8 +1090,7 @@ class TaggerWindow(QtWidgets.QMainWindow):
self.selector.setWindowTitle(f"Search: '{series_name}' - Select Series")
self.selector.finished.connect(self.finish_query)
- self.selector.setModal(True)
- self.selector.open()
+ self.selector.show()
def finish_query(self, result) -> None:
if result and self.selector:
@@ -1154,20 +1153,22 @@ class TaggerWindow(QtWidgets.QMainWindow):
self.metadata_to_form()
def on_ratelimit(self, full_time: float, sleep_time: float) -> None:
- toast = Toast(self)
- # Convert to milliseconds, make it end half a second before the ratelimit triggers again, make sure we have a positive time
- toast.setDuration(abs(int(sleep_time * 1000) - 500))
- toast.setResetDurationOnHover(False)
- toast.setTitle("Rate Limit Hit!")
- toast.setText(
+ self.toast = Toast(self)
+ if qtutils.is_dark_mode():
+ self.toast.applyPreset(ToastPreset.WARNING_DARK)
+ else:
+ self.toast.applyPreset(ToastPreset.WARNING)
+
+ # Convert to milliseconds, add 200ms because python is slow
+ self.toast.setDuration(abs(int(sleep_time * 1000) + 200))
+ self.toast.setResetDurationOnHover(False)
+ self.toast.setFadeOutDuration(50)
+ self.toast.setTitle("Rate Limit Hit!")
+ self.toast.setText(
f"Rate limit reached: {full_time:.0f}s until next request. Waiting {sleep_time:.0f}s for ratelimit"
)
- if qtutils.is_dark_mode():
- toast.applyPreset(ToastPreset.WARNING_DARK)
- else:
- toast.applyPreset(ToastPreset.WARNING)
- toast.setPositionRelativeToWidget(self)
- toast.show()
+ self.toast.setPositionRelativeToWidget(self)
+ self.toast.show()
def write_tags(self) -> None:
if self.metadata is not None and self.comic_archive is not None:
@@ -1395,7 +1396,6 @@ class TaggerWindow(QtWidgets.QMainWindow):
def show_settings(self) -> None:
settingswin = SettingsWindow(self, self.config, self.talkers)
- settingswin.setModal(True)
settingswin.exec()
settingswin.result()
self.adjust_source_combo()
@@ -1779,8 +1779,7 @@ class TaggerWindow(QtWidgets.QMainWindow):
return
self.atprogdialog = AutoTagProgressWindow(self, self.current_talker())
- self.atprogdialog.setModal(True)
- self.atprogdialog.show()
+ self.atprogdialog.open()
self.atprogdialog.progressBar.setMaximum(len(ca_list))
self.atprogdialog.setWindowTitle("Auto-Tagging")
@@ -1862,7 +1861,6 @@ class TaggerWindow(QtWidgets.QMainWindow):
self.config[0],
self.current_talker(),
)
- matchdlg.setModal(True)
matchdlg.exec()
self.fileSelectionList.update_selected_rows()
new_ca = self.fileSelectionList.get_current_archive()
@@ -1980,7 +1978,6 @@ class TaggerWindow(QtWidgets.QMainWindow):
"File Rename", "If you rename files now, unsaved data in the form will be lost. Are you sure?"
):
dlg = RenameWindow(self, ca_list, self.selected_read_tags, self.config, self.talkers)
- dlg.setModal(True)
if dlg.exec() and self.comic_archive is not None:
self.fileSelectionList.update_selected_rows()
self.load_archive(self.comic_archive)
diff --git a/comictaggerlib/ui/issueselectionwindow.ui b/comictaggerlib/ui/issueselectionwindow.ui
index 2571374..4998283 100644
--- a/comictaggerlib/ui/issueselectionwindow.ui
+++ b/comictaggerlib/ui/issueselectionwindow.ui
@@ -49,6 +49,15 @@
7
+
+ QTableWidget[rowCount="0"] {
+ background-image: url(":/graphics/about.png");
+ background-attachment: fixed;
+ background-position: top center;
+ background-repeat: no-repeat;
+ background-color: white;
+}
+
QAbstractItemView::SingleSelection
diff --git a/comictaggerlib/ui/pyqttoast/constants.py b/comictaggerlib/ui/pyqttoast/constants.py
index 17e921b..2a0e8ea 100644
--- a/comictaggerlib/ui/pyqttoast/constants.py
+++ b/comictaggerlib/ui/pyqttoast/constants.py
@@ -3,7 +3,6 @@ from __future__ import annotations
from PyQt5.QtGui import QColor
UPDATE_POSITION_DURATION = 200
-DURATION_BAR_UPDATE_INTERVAL = 1
DROP_SHADOW_SIZE = 5
SUCCESS_ACCENT_COLOR = QColor("#3E9141")
WARNING_ACCENT_COLOR = QColor("#E8B849")
@@ -23,7 +22,6 @@ DEFAULT_CLOSE_BUTTON_ICON_COLOR_DARK = QColor("#C9C9C9")
__all__ = [
"UPDATE_POSITION_DURATION",
- "DURATION_BAR_UPDATE_INTERVAL",
"DROP_SHADOW_SIZE",
"SUCCESS_ACCENT_COLOR",
"WARNING_ACCENT_COLOR",
diff --git a/comictaggerlib/ui/pyqttoast/toast.py b/comictaggerlib/ui/pyqttoast/toast.py
index 15a4d29..8e28bd6 100644
--- a/comictaggerlib/ui/pyqttoast/toast.py
+++ b/comictaggerlib/ui/pyqttoast/toast.py
@@ -2,7 +2,18 @@ from __future__ import annotations
import math
-from PyQt5.QtCore import QEvent, QMargins, QPoint, QPropertyAnimation, QRect, QSize, Qt, QTimer, pyqtSignal
+from PyQt5.QtCore import (
+ QAbstractAnimation,
+ QEvent,
+ QMargins,
+ QPoint,
+ QPropertyAnimation,
+ QRect,
+ QSize,
+ Qt,
+ QTimer,
+ pyqtSignal,
+)
from PyQt5.QtGui import QColor, QFont, QFontMetrics, QGuiApplication, QIcon, QPixmap, QScreen
from PyQt5.QtWidgets import QDialog, QGraphicsOpacityEffect, QLabel, QPushButton, QWidget
@@ -19,7 +30,6 @@ from .constants import (
DEFAULT_TITLE_COLOR,
DEFAULT_TITLE_COLOR_DARK,
DROP_SHADOW_SIZE,
- DURATION_BAR_UPDATE_INTERVAL,
ERROR_ACCENT_COLOR,
INFORMATION_ACCENT_COLOR,
SUCCESS_ACCENT_COLOR,
@@ -95,7 +105,6 @@ class Toast(QDialog):
self.__close_button_margins = QMargins(0, -8, 0, -8)
self.__text_section_spacing = 8
- self.__elapsed_time = 0
self.__fading_out = False
self.__used = False
@@ -145,7 +154,6 @@ class Toast(QDialog):
# Duration bar chunk
self.__duration_bar_chunk = QWidget(self.__duration_bar_container)
- self.__duration_bar_chunk.setFixedHeight(20)
self.__duration_bar_chunk.move(0, -16)
# Set defaults
@@ -173,10 +181,6 @@ class Toast(QDialog):
self.__duration_timer.setSingleShot(True)
self.__duration_timer.timeout.connect(self.hide)
- # Timer for updating the duration bar
- self.__duration_bar_timer = QTimer(self)
- self.__duration_bar_timer.timeout.connect(self.__update_duration_bar)
-
# Apply stylesheet
self.setStyleSheet((css_path / "toast.css").read_text(encoding="utf-8"))
@@ -205,14 +209,13 @@ class Toast(QDialog):
"""
# Reset timer if hovered and resetting is enabled
- if self.__duration != 0 and self.__duration_timer.isActive() and self.__reset_duration_on_hover:
+ if self.__reset_duration_on_hover and self.__duration != 0 and self.__duration_timer.isActive():
self.__duration_timer.stop()
# Reset duration bar if enabled
if self.__show_duration_bar:
- self.__duration_bar_timer.stop()
- self.__duration_bar_chunk.setFixedWidth(self.width())
- self.__elapsed_time = 0
+ self.__bar_animation.stop()
+ self.__duration_bar_chunk.setGeometry(QRect(0, 0, self.__duration_bar_container.width(), 4))
def leaveEvent(self, event: QEvent) -> None:
"""Event that happens every time the mouse leaves this widget.
@@ -222,12 +225,21 @@ class Toast(QDialog):
"""
# Start timer again when leaving notification and reset is enabled
- if self.__duration != 0 and not self.__duration_timer.isActive() and self.__reset_duration_on_hover:
+ if self.__reset_duration_on_hover and self.__duration != 0 and not self.__duration_timer.isActive():
self.__duration_timer.start(self.__duration)
# Restart duration bar animation if enabled
if self.__show_duration_bar:
- self.__duration_bar_timer.start(DURATION_BAR_UPDATE_INTERVAL)
+ self.__start_duration_bar_animation()
+
+ def __start_duration_bar_animation(self) -> None:
+ self.__bar_animation = QPropertyAnimation(self.__duration_bar_chunk, b"geometry")
+ self.__bar_animation.setDuration(self.__duration)
+ self.__bar_animation.setStartValue(QRect(0, 0, self.__duration_bar.width(), 4))
+ self.__bar_animation.setEndValue(QRect(0, 0, 0, 4))
+ self.__bar_animation.setDirection(QAbstractAnimation.Direction.Forward)
+
+ self.__bar_animation.start()
def show(self) -> None:
"""Show the toast notification"""
@@ -244,16 +256,12 @@ class Toast(QDialog):
# Setup UI
self.__setup_ui()
+ # Calculate position and show (animate position too if not first notification)
+ x, y = self.__calculate_position()
# Start duration timer
if self.__duration != 0:
self.__duration_timer.start(self.__duration)
-
- # Start duration bar update timer
- if self.__duration != 0 and self.__show_duration_bar:
- self.__duration_bar_timer.start(DURATION_BAR_UPDATE_INTERVAL)
-
- # Calculate position and show (animate position too if not first notification)
- x, y = self.__calculate_position()
+ self.__start_duration_bar_animation()
# If not first toast on screen, also do a fade down/up animation
if len(Toast.__currently_shown) > 1:
@@ -327,7 +335,6 @@ class Toast(QDialog):
if self in Toast.__currently_shown:
Toast.__currently_shown.remove(self)
- self.__elapsed_time = 0
self.__fading_out = False
# Emit signal
@@ -343,21 +350,6 @@ class Toast(QDialog):
timer.timeout.connect(Toast.__show_next_in_queue)
timer.start(self.__fade_in_duration)
- def __update_duration_bar(self) -> None:
- """Update the duration bar chunk with the elapsed time"""
-
- self.__elapsed_time += DURATION_BAR_UPDATE_INTERVAL
-
- if self.__elapsed_time >= self.__duration:
- self.__duration_bar_timer.stop()
- return
-
- new_chunk_width = math.floor(
- self.__duration_bar_container.width()
- - self.__elapsed_time / self.__duration * self.__duration_bar_container.width()
- )
- self.__duration_bar_chunk.setFixedWidth(new_chunk_width)
-
def __update_position_xy(self, animate: bool = True) -> None:
"""Update the x and y position of the toast with an optional animation
@@ -893,14 +885,11 @@ class Toast(QDialog):
self.__close_button.setVisible(False)
# Resize, move, and show duration bar if enabled
- if self.__show_duration_bar:
- self.__duration_bar_container.setFixedWidth(width)
- self.__duration_bar_container.move(0, height - duration_bar_height)
- self.__duration_bar.setFixedWidth(width)
- self.__duration_bar_chunk.setFixedWidth(width)
- self.__duration_bar_container.setVisible(True)
- else:
- self.__duration_bar_container.setVisible(False)
+ self.__duration_bar_container.setFixedWidth(width)
+ self.__duration_bar_container.move(0, height - duration_bar_height)
+ self.__duration_bar.setFixedWidth(width)
+
+ self.__duration_bar_container.setVisible(self.__show_duration_bar)
def __install_widget_event_filter(self) -> None:
"""Install an event filter on parent"""