2021-02-10 23:48:25 +13:00
|
|
|
import os
|
2021-06-18 10:17:01 +12:00
|
|
|
from logging import getLogger
|
2021-10-11 09:08:31 +13:00
|
|
|
from typing import Callable, Tuple
|
2021-02-10 23:48:25 +13:00
|
|
|
|
2021-12-24 22:09:50 +13:00
|
|
|
from PyQt5.QtCore import (
|
|
|
|
Qt,
|
|
|
|
QCoreApplication,
|
|
|
|
QRect,
|
|
|
|
QSize,
|
|
|
|
QPoint,
|
|
|
|
pyqtSignal,
|
|
|
|
QFileInfo,
|
|
|
|
)
|
2021-11-11 10:07:28 +13:00
|
|
|
from PyQt5.QtGui import QMovie, QPixmap, QFontMetrics, QImage
|
2021-12-24 22:09:50 +13:00
|
|
|
from PyQt5.QtWidgets import (
|
|
|
|
QStyle,
|
|
|
|
QSizePolicy,
|
|
|
|
QLabel,
|
|
|
|
QFileDialog,
|
|
|
|
QHBoxLayout,
|
|
|
|
QWidget,
|
|
|
|
QPushButton,
|
|
|
|
QStyleOptionTab,
|
|
|
|
QStylePainter,
|
|
|
|
QTabBar,
|
|
|
|
QLineEdit,
|
|
|
|
QToolButton,
|
|
|
|
QTabWidget,
|
|
|
|
QCompleter,
|
|
|
|
QFileSystemModel,
|
|
|
|
QStyledItemDelegate,
|
|
|
|
QFileIconProvider,
|
2022-03-19 05:03:14 +13:00
|
|
|
QVBoxLayout,
|
|
|
|
QScrollArea,
|
2021-12-24 22:09:50 +13:00
|
|
|
)
|
2021-02-10 23:48:25 +13:00
|
|
|
|
2022-02-17 12:04:53 +13:00
|
|
|
from rare.utils.paths import tmp_dir
|
2021-08-23 08:22:17 +12:00
|
|
|
from rare.utils.qt_requests import QtRequestManager
|
2022-07-27 02:58:17 +12:00
|
|
|
from rare.utils.misc import icon as qta_icon
|
2021-04-28 03:40:10 +12:00
|
|
|
|
2021-06-18 10:17:01 +12:00
|
|
|
logger = getLogger("ExtraWidgets")
|
2021-04-28 03:40:10 +12:00
|
|
|
|
2021-02-10 23:48:25 +13:00
|
|
|
|
2022-01-14 07:49:39 +13:00
|
|
|
class IndicatorReasons:
|
|
|
|
dir_not_empty = QCoreApplication.translate("IndicatorReasons", "Directory is not empty")
|
|
|
|
wrong_format = QCoreApplication.translate("IndicatorReasons", "Given text has wrong format")
|
2022-05-05 08:11:41 +12:00
|
|
|
game_not_installed = QCoreApplication.translate(
|
|
|
|
"IndicatorReasons", "Game is not installed or does not exist"
|
|
|
|
)
|
2022-01-14 07:49:39 +13:00
|
|
|
dir_not_exist = QCoreApplication.translate("IndicatorReasons", "Directory does not exist")
|
2022-03-23 09:48:20 +13:00
|
|
|
file_not_exist = QCoreApplication.translate("IndicatorReasons", "File does not exist")
|
2022-01-14 07:49:39 +13:00
|
|
|
wrong_path = QCoreApplication.translate("IndicatorReasons", "Wrong Directory")
|
|
|
|
|
|
|
|
|
2021-10-10 00:33:54 +13:00
|
|
|
class IndicatorLineEdit(QWidget):
|
|
|
|
textChanged = pyqtSignal(str)
|
2022-01-14 07:49:39 +13:00
|
|
|
reasons = IndicatorReasons()
|
2021-10-10 00:33:54 +13:00
|
|
|
|
2021-12-24 22:09:50 +13:00
|
|
|
def __init__(
|
2022-05-05 08:11:41 +12:00
|
|
|
self,
|
|
|
|
text: str = "",
|
|
|
|
placeholder: str = "",
|
|
|
|
completer: QCompleter = None,
|
|
|
|
edit_func: Callable[[str], Tuple[bool, str, str]] = None,
|
|
|
|
save_func: Callable[[str], None] = None,
|
|
|
|
horiz_policy: QSizePolicy = QSizePolicy.Expanding,
|
|
|
|
parent=None,
|
2021-12-24 22:09:50 +13:00
|
|
|
):
|
2021-10-10 00:33:54 +13:00
|
|
|
super(IndicatorLineEdit, self).__init__(parent=parent)
|
2022-05-05 08:11:41 +12:00
|
|
|
self.setObjectName(type(self).__name__)
|
|
|
|
layout = QHBoxLayout(self)
|
|
|
|
layout.setObjectName(f"{self.objectName()}Layout")
|
|
|
|
layout.setContentsMargins(0, 0, 0, 0)
|
2021-11-06 04:48:56 +13:00
|
|
|
# Add line_edit
|
2021-10-10 00:33:54 +13:00
|
|
|
self.line_edit = QLineEdit(self)
|
2022-05-05 08:11:41 +12:00
|
|
|
self.line_edit.setObjectName(f"{type(self).__name__}Edit")
|
2022-03-15 11:29:54 +13:00
|
|
|
self.line_edit.setPlaceholderText(placeholder)
|
2021-10-10 00:33:54 +13:00
|
|
|
self.line_edit.setSizePolicy(horiz_policy, QSizePolicy.Fixed)
|
2021-11-06 04:48:56 +13:00
|
|
|
# Add hint_label to line_edit
|
|
|
|
self.line_edit.setLayout(QHBoxLayout())
|
|
|
|
self.hint_label = QLabel()
|
2022-05-05 08:11:41 +12:00
|
|
|
self.hint_label.setObjectName(f"{type(self).__name__}Label")
|
2021-11-06 04:48:56 +13:00
|
|
|
self.hint_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
|
|
|
self.line_edit.layout().setContentsMargins(0, 0, 10, 0)
|
|
|
|
self.line_edit.layout().addWidget(self.hint_label)
|
|
|
|
# Add completer
|
2021-11-05 05:28:29 +13:00
|
|
|
if completer is not None:
|
|
|
|
completer.popup().setItemDelegate(QStyledItemDelegate(self))
|
2021-11-06 00:16:58 +13:00
|
|
|
completer.popup().setAlternatingRowColors(True)
|
2021-11-05 05:28:29 +13:00
|
|
|
self.line_edit.setCompleter(completer)
|
2022-05-05 08:11:41 +12:00
|
|
|
layout.addWidget(self.line_edit)
|
2021-10-10 00:33:54 +13:00
|
|
|
if edit_func is not None:
|
|
|
|
self.indicator_label = QLabel()
|
2022-05-05 08:11:41 +12:00
|
|
|
self.indicator_label.setPixmap(qta_icon("ei.info-circle", color="gray").pixmap(16, 16))
|
2021-10-10 00:33:54 +13:00
|
|
|
self.indicator_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
2022-05-05 08:11:41 +12:00
|
|
|
layout.addWidget(self.indicator_label)
|
2021-10-10 00:33:54 +13:00
|
|
|
|
2022-03-15 11:29:54 +13:00
|
|
|
if not placeholder:
|
2022-09-04 10:14:43 +12:00
|
|
|
_translate = QCoreApplication.instance().translate
|
2022-05-05 08:11:41 +12:00
|
|
|
self.line_edit.setPlaceholderText(_translate(self.__class__.__name__, "Default"))
|
2021-10-10 00:33:54 +13:00
|
|
|
|
2022-09-04 10:14:43 +12:00
|
|
|
self.is_valid = False
|
2021-05-02 08:15:42 +12:00
|
|
|
self.edit_func = edit_func
|
|
|
|
self.save_func = save_func
|
2021-10-10 00:33:54 +13:00
|
|
|
self.line_edit.textChanged.connect(self.__edit)
|
|
|
|
if self.edit_func is None:
|
|
|
|
self.line_edit.textChanged.connect(self.__save)
|
|
|
|
|
2021-10-17 09:21:36 +13:00
|
|
|
# lk: this can be placed here to trigger __edit
|
2022-09-04 10:14:43 +12:00
|
|
|
# lk: it is going to save the input again if it is valid which
|
2021-10-17 09:21:36 +13:00
|
|
|
# lk: is ok to do given the checks don't misbehave (they shouldn't)
|
|
|
|
# lk: however it is going to edit any "understood" bad input to good input
|
|
|
|
# lk: and we might not want that (but the validity check reports on the edited string)
|
|
|
|
# lk: it is also going to trigger this widget's textChanged signal but that gets lost
|
|
|
|
if text:
|
|
|
|
self.line_edit.setText(text)
|
|
|
|
|
2021-10-10 00:33:54 +13:00
|
|
|
def text(self) -> str:
|
|
|
|
return self.line_edit.text()
|
|
|
|
|
|
|
|
def setText(self, text: str):
|
|
|
|
self.line_edit.setText(text)
|
|
|
|
|
2021-11-06 04:48:56 +13:00
|
|
|
def setHintText(self, text: str):
|
|
|
|
self.hint_label.setFrameRect(self.line_edit.rect())
|
|
|
|
self.hint_label.setText(text)
|
|
|
|
|
2022-01-14 07:49:39 +13:00
|
|
|
def __indicator(self, res, reason=None):
|
2021-10-10 00:33:54 +13:00
|
|
|
color = "green" if res else "red"
|
2022-05-05 08:11:41 +12:00
|
|
|
self.indicator_label.setPixmap(qta_icon("ei.info-circle", color=color).pixmap(16, 16))
|
2022-01-14 07:49:39 +13:00
|
|
|
if reason:
|
|
|
|
self.indicator_label.setToolTip(reason)
|
|
|
|
else:
|
|
|
|
self.indicator_label.setToolTip("")
|
2021-10-10 00:33:54 +13:00
|
|
|
|
|
|
|
def __edit(self, text):
|
2021-05-02 08:15:42 +12:00
|
|
|
if self.edit_func is not None:
|
2021-10-10 00:33:54 +13:00
|
|
|
self.line_edit.blockSignals(True)
|
2022-01-14 07:49:39 +13:00
|
|
|
|
|
|
|
self.is_valid, text, reason = self.edit_func(text)
|
2021-11-04 10:18:03 +13:00
|
|
|
if text != self.line_edit.text():
|
|
|
|
self.line_edit.setText(text)
|
2021-10-10 00:33:54 +13:00
|
|
|
self.line_edit.blockSignals(False)
|
2022-01-14 07:49:39 +13:00
|
|
|
self.__indicator(self.is_valid, reason)
|
2021-10-10 00:33:54 +13:00
|
|
|
if self.is_valid:
|
|
|
|
self.__save(text)
|
2021-10-15 10:57:23 +13:00
|
|
|
self.textChanged.emit(text)
|
2021-09-09 08:08:41 +12:00
|
|
|
|
2021-10-10 00:33:54 +13:00
|
|
|
def __save(self, text):
|
|
|
|
if self.save_func is not None:
|
|
|
|
self.save_func(text)
|
2021-02-10 23:48:25 +13:00
|
|
|
|
|
|
|
|
2021-11-05 05:28:29 +13:00
|
|
|
class PathEditIconProvider(QFileIconProvider):
|
|
|
|
icons = [
|
2022-01-06 03:44:29 +13:00
|
|
|
("mdi.file-cancel", "fa.file-excel-o"), # Unknown
|
|
|
|
("mdi.desktop-classic", "fa.desktop"), # Computer
|
|
|
|
("mdi.desktop-mac", "fa.desktop"), # Desktop
|
|
|
|
("mdi.trash-can", "fa.trash"), # Trashcan
|
|
|
|
("mdi.server-network", "fa.server"), # Network
|
|
|
|
("mdi.harddisk", "fa.desktop"), # Drive
|
|
|
|
("mdi.folder", "fa.folder"), # Folder
|
|
|
|
("mdi.file", "fa.file"), # File
|
|
|
|
("mdi.cog", "fa.cog"), # Executable
|
2021-11-05 05:28:29 +13:00
|
|
|
]
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
super(PathEditIconProvider, self).__init__()
|
|
|
|
self.icon_types = dict()
|
2022-01-06 03:44:29 +13:00
|
|
|
for idx, (icn, fallback) in enumerate(self.icons):
|
|
|
|
self.icon_types.update({idx - 1: qta_icon(icn, fallback, color="#eeeeee")})
|
2021-11-05 05:28:29 +13:00
|
|
|
|
|
|
|
def icon(self, info_type):
|
|
|
|
if isinstance(info_type, QFileInfo):
|
|
|
|
if info_type.isRoot():
|
|
|
|
return self.icon_types[4]
|
|
|
|
if info_type.isDir():
|
|
|
|
return self.icon_types[5]
|
|
|
|
if info_type.isFile():
|
|
|
|
return self.icon_types[6]
|
|
|
|
if info_type.isExecutable():
|
|
|
|
return self.icon_types[7]
|
|
|
|
return self.icon_types[-1]
|
|
|
|
return self.icon_types[int(info_type)]
|
|
|
|
|
|
|
|
|
2021-10-10 00:33:54 +13:00
|
|
|
class PathEdit(IndicatorLineEdit):
|
2021-12-24 22:09:50 +13:00
|
|
|
def __init__(
|
2022-05-05 08:11:41 +12:00
|
|
|
self,
|
|
|
|
path: str = "",
|
|
|
|
file_type: QFileDialog.FileType = QFileDialog.AnyFile,
|
|
|
|
type_filter: str = "",
|
|
|
|
name_filter: str = "",
|
|
|
|
placeholder: str = "",
|
|
|
|
edit_func: Callable[[str], Tuple[bool, str, str]] = None,
|
|
|
|
save_func: Callable[[str], None] = None,
|
|
|
|
horiz_policy: QSizePolicy = QSizePolicy.Expanding,
|
|
|
|
parent=None,
|
2021-12-24 22:09:50 +13:00
|
|
|
):
|
2022-09-04 10:14:43 +12:00
|
|
|
self.completer = QCompleter()
|
|
|
|
self.compl_model = QFileSystemModel()
|
|
|
|
|
2022-01-06 03:44:29 +13:00
|
|
|
try:
|
|
|
|
self.compl_model.setOptions(
|
|
|
|
QFileSystemModel.DontWatchForChanges
|
|
|
|
| QFileSystemModel.DontResolveSymlinks
|
|
|
|
| QFileSystemModel.DontUseCustomDirectoryIcons
|
|
|
|
)
|
|
|
|
except AttributeError as e: # Error on Ubuntu
|
|
|
|
logger.warning(e)
|
2021-11-05 05:28:29 +13:00
|
|
|
self.compl_model.setIconProvider(PathEditIconProvider())
|
|
|
|
self.compl_model.setRootPath(path)
|
2021-11-06 00:16:58 +13:00
|
|
|
self.completer.setModel(self.compl_model)
|
2022-03-16 08:34:39 +13:00
|
|
|
|
2022-05-05 08:11:41 +12:00
|
|
|
edit_func = self.__wrap_edit_function(edit_func)
|
2022-03-16 08:34:39 +13:00
|
|
|
|
2021-12-24 22:09:50 +13:00
|
|
|
super(PathEdit, self).__init__(
|
|
|
|
text=path,
|
2022-03-15 11:29:54 +13:00
|
|
|
placeholder=placeholder,
|
2021-12-24 22:09:50 +13:00
|
|
|
completer=self.completer,
|
|
|
|
edit_func=edit_func,
|
|
|
|
save_func=save_func,
|
|
|
|
horiz_policy=horiz_policy,
|
|
|
|
parent=parent,
|
|
|
|
)
|
2022-05-05 08:11:41 +12:00
|
|
|
self.setObjectName(type(self).__name__)
|
|
|
|
self.line_edit.setMinimumSize(QSize(250, 0))
|
2021-10-10 00:33:54 +13:00
|
|
|
self.path_select = QToolButton(self)
|
2022-05-05 08:11:41 +12:00
|
|
|
self.path_select.setObjectName(f"{type(self).__name__}Button")
|
|
|
|
layout = self.layout()
|
|
|
|
layout.addWidget(self.path_select)
|
2021-10-10 00:33:54 +13:00
|
|
|
|
2022-09-04 10:14:43 +12:00
|
|
|
_translate = QCoreApplication.instance().translate
|
2021-10-10 00:33:54 +13:00
|
|
|
self.path_select.setText(_translate("PathEdit", "Browse..."))
|
2021-05-21 11:47:03 +12:00
|
|
|
|
2021-10-10 00:33:54 +13:00
|
|
|
self.type_filter = type_filter
|
|
|
|
self.name_filter = name_filter
|
|
|
|
self.file_type = file_type
|
2021-05-02 08:15:42 +12:00
|
|
|
|
2021-10-10 00:33:54 +13:00
|
|
|
self.path_select.clicked.connect(self.__set_path)
|
|
|
|
|
|
|
|
def __set_path(self):
|
|
|
|
dlg_path = self.line_edit.text()
|
2021-04-30 04:05:04 +12:00
|
|
|
if not dlg_path:
|
|
|
|
dlg_path = os.path.expanduser("~/")
|
2021-05-30 03:24:33 +12:00
|
|
|
dlg = QFileDialog(self, self.tr("Choose path"), dlg_path)
|
2021-04-30 04:05:04 +12:00
|
|
|
dlg.setFileMode(self.file_type)
|
|
|
|
if self.type_filter:
|
|
|
|
dlg.setFilter([self.type_filter])
|
2021-04-28 03:40:10 +12:00
|
|
|
if self.name_filter:
|
|
|
|
dlg.setNameFilter(self.name_filter)
|
2021-02-10 23:48:25 +13:00
|
|
|
if dlg.exec_():
|
|
|
|
names = dlg.selectedFiles()
|
2021-10-10 00:33:54 +13:00
|
|
|
self.line_edit.setText(names[0])
|
2021-11-05 05:28:29 +13:00
|
|
|
self.compl_model.setRootPath(names[0])
|
2021-02-28 03:54:26 +13:00
|
|
|
|
2022-05-05 08:11:41 +12:00
|
|
|
def __wrap_edit_function(self, edit_function: Callable[[str], Tuple[bool, str, str]]):
|
2022-03-16 08:34:39 +13:00
|
|
|
if edit_function:
|
|
|
|
return lambda text: edit_function(os.path.expanduser(text)
|
|
|
|
if text.startswith("~") else text)
|
|
|
|
else:
|
|
|
|
return edit_function
|
|
|
|
|
2021-02-28 03:54:26 +13:00
|
|
|
|
|
|
|
class SideTabBar(QTabBar):
|
2021-10-10 00:33:54 +13:00
|
|
|
def __init__(self, parent=None):
|
|
|
|
super(SideTabBar, self).__init__(parent=parent)
|
2021-10-15 10:57:23 +13:00
|
|
|
self.setObjectName("SideTabBar")
|
2021-10-09 09:02:11 +13:00
|
|
|
self.fm = QFontMetrics(self.font())
|
2021-02-28 03:54:26 +13:00
|
|
|
|
|
|
|
def tabSizeHint(self, index):
|
|
|
|
# width = QTabBar.tabSizeHint(self, index).width()
|
2021-10-09 09:02:11 +13:00
|
|
|
return QSize(200, self.fm.height() + 18)
|
2021-02-28 03:54:26 +13:00
|
|
|
|
|
|
|
def paintEvent(self, event):
|
|
|
|
painter = QStylePainter(self)
|
|
|
|
opt = QStyleOptionTab()
|
|
|
|
|
|
|
|
for i in range(self.count()):
|
|
|
|
self.initStyleOption(opt, i)
|
|
|
|
painter.drawControl(QStyle.CE_TabBarTabShape, opt)
|
|
|
|
painter.save()
|
|
|
|
|
|
|
|
s = opt.rect.size()
|
|
|
|
s.transpose()
|
|
|
|
r = QRect(QPoint(), s)
|
|
|
|
r.moveCenter(opt.rect.center())
|
|
|
|
opt.rect = r
|
|
|
|
|
|
|
|
c = self.tabRect(i).center()
|
|
|
|
painter.translate(c)
|
|
|
|
painter.rotate(90)
|
|
|
|
painter.translate(-c)
|
2021-10-10 00:33:54 +13:00
|
|
|
painter.drawControl(QStyle.CE_TabBarTabLabel, opt)
|
2021-02-28 03:54:26 +13:00
|
|
|
painter.restore()
|
2021-02-28 05:20:56 +13:00
|
|
|
|
2021-03-10 04:52:51 +13:00
|
|
|
|
2022-03-19 05:03:14 +13:00
|
|
|
class SideTabContainer(QWidget):
|
|
|
|
def __init__(self, widget: QWidget, title: str = str(), parent: QWidget = None):
|
|
|
|
super(SideTabContainer, self).__init__(parent=parent)
|
|
|
|
self.title = QLabel(self)
|
|
|
|
self.setTitle(title)
|
|
|
|
|
|
|
|
self.scroll = QScrollArea(self)
|
|
|
|
self.scroll.setWidgetResizable(True)
|
|
|
|
self.scroll.setSizeAdjustPolicy(QScrollArea.AdjustToContents)
|
|
|
|
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
|
|
|
self.scroll.setFrameStyle(QScrollArea.NoFrame)
|
|
|
|
if widget.layout():
|
|
|
|
widget.layout().setAlignment(Qt.AlignTop)
|
|
|
|
widget.layout().setContentsMargins(0, 0, 9, 0)
|
|
|
|
widget.title = self.title
|
|
|
|
widget.title.setTitle = self.setTitle
|
2022-03-29 10:14:11 +13:00
|
|
|
self.scroll.setMinimumWidth(
|
|
|
|
widget.sizeHint().width()
|
|
|
|
+ self.scroll.verticalScrollBar().sizeHint().width()
|
|
|
|
)
|
2022-03-19 05:03:14 +13:00
|
|
|
self.scroll.setWidget(widget)
|
|
|
|
|
|
|
|
layout = QVBoxLayout()
|
|
|
|
layout.addWidget(self.title)
|
|
|
|
layout.addWidget(self.scroll)
|
|
|
|
self.setLayout(layout)
|
|
|
|
|
|
|
|
def setTitle(self, text: str) -> None:
|
|
|
|
self.title.setText(f"<h2>{text}</h2>")
|
|
|
|
self.title.setVisible(bool(text))
|
|
|
|
|
|
|
|
|
2021-10-12 06:09:20 +13:00
|
|
|
class SideTabWidget(QTabWidget):
|
|
|
|
back_clicked = pyqtSignal()
|
|
|
|
|
|
|
|
def __init__(self, show_back: bool = False, parent=None):
|
|
|
|
super(SideTabWidget, self).__init__(parent=parent)
|
|
|
|
self.setTabBar(SideTabBar())
|
2021-11-19 09:44:11 +13:00
|
|
|
self.setDocumentMode(True)
|
2021-10-12 06:09:20 +13:00
|
|
|
self.setTabPosition(QTabWidget.West)
|
|
|
|
if show_back:
|
2022-03-19 05:03:14 +13:00
|
|
|
super(SideTabWidget, self).addTab(
|
|
|
|
QWidget(), qta_icon("mdi.keyboard-backspace", "ei.backward"), self.tr("Back")
|
|
|
|
)
|
2021-10-12 06:09:20 +13:00
|
|
|
self.tabBarClicked.connect(self.back_func)
|
|
|
|
|
|
|
|
def back_func(self, tab):
|
|
|
|
# shortcut for tab == 0
|
|
|
|
if not tab:
|
|
|
|
self.back_clicked.emit()
|
|
|
|
|
2022-03-19 05:03:14 +13:00
|
|
|
def addTab(self, widget: QWidget, a1: str, title: str = str()) -> int:
|
|
|
|
container = SideTabContainer(widget, title, parent=self)
|
|
|
|
return super(SideTabWidget, self).addTab(container, a1)
|
|
|
|
|
2021-10-12 06:09:20 +13:00
|
|
|
|
2021-02-28 05:20:56 +13:00
|
|
|
class WaitingSpinner(QLabel):
|
|
|
|
def __init__(self):
|
|
|
|
super(WaitingSpinner, self).__init__()
|
2021-12-24 22:09:50 +13:00
|
|
|
self.setStyleSheet(
|
|
|
|
"""
|
2021-02-28 05:20:56 +13:00
|
|
|
margin-left: auto;
|
|
|
|
margin-right: auto;
|
2021-12-24 22:09:50 +13:00
|
|
|
"""
|
|
|
|
)
|
2021-12-10 09:59:07 +13:00
|
|
|
self.movie = QMovie(":/images/loader.gif")
|
2021-02-28 05:20:56 +13:00
|
|
|
self.setMovie(self.movie)
|
|
|
|
self.movie.start()
|
2021-03-09 05:20:28 +13:00
|
|
|
|
|
|
|
|
2021-03-10 04:52:51 +13:00
|
|
|
class SelectViewWidget(QWidget):
|
|
|
|
toggled = pyqtSignal()
|
2021-03-09 05:20:28 +13:00
|
|
|
|
2021-03-10 04:52:51 +13:00
|
|
|
def __init__(self, icon_view: bool):
|
|
|
|
super(SelectViewWidget, self).__init__()
|
|
|
|
self.icon_view = icon_view
|
2022-05-05 08:11:41 +12:00
|
|
|
self.setStyleSheet("""QPushButton{border: none; background-color: transparent}""")
|
2022-06-23 05:00:00 +12:00
|
|
|
self.icon_button = QPushButton()
|
|
|
|
self.list_button = QPushButton()
|
2021-03-10 04:52:51 +13:00
|
|
|
if icon_view:
|
2022-06-23 05:00:00 +12:00
|
|
|
self.icon_button.setIcon(
|
2022-01-06 03:44:29 +13:00
|
|
|
qta_icon("mdi.view-grid-outline", "ei.th-large", color="orange")
|
2021-12-24 22:09:50 +13:00
|
|
|
)
|
2022-06-23 05:00:00 +12:00
|
|
|
self.list_button.setIcon(qta_icon("fa5s.list", "ei.th-list"))
|
2021-03-10 04:52:51 +13:00
|
|
|
else:
|
2022-06-23 05:00:00 +12:00
|
|
|
self.icon_button.setIcon(qta_icon("mdi.view-grid-outline", "ei.th-large"))
|
|
|
|
self.list_button.setIcon(qta_icon("fa5s.list", "ei.th-list", color="orange"))
|
2021-03-09 05:20:28 +13:00
|
|
|
|
2022-06-23 05:00:00 +12:00
|
|
|
self.icon_button.clicked.connect(self.icon)
|
|
|
|
self.list_button.clicked.connect(self.list)
|
2021-03-10 04:52:51 +13:00
|
|
|
|
2022-06-23 05:00:00 +12:00
|
|
|
layout = QHBoxLayout()
|
|
|
|
layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
layout.addWidget(self.icon_button)
|
|
|
|
layout.addWidget(self.list_button)
|
2021-03-10 04:52:51 +13:00
|
|
|
|
2022-06-23 05:00:00 +12:00
|
|
|
self.setLayout(layout)
|
2021-03-10 04:52:51 +13:00
|
|
|
|
|
|
|
def isChecked(self):
|
|
|
|
return self.icon_view
|
2021-03-09 05:20:28 +13:00
|
|
|
|
2021-03-10 04:52:51 +13:00
|
|
|
def icon(self):
|
2022-06-23 05:00:00 +12:00
|
|
|
self.icon_button.setIcon(
|
2022-05-05 08:11:41 +12:00
|
|
|
qta_icon("mdi.view-grid-outline", "ei.th-large", color="orange")
|
|
|
|
)
|
2022-06-23 05:00:00 +12:00
|
|
|
self.list_button.setIcon(qta_icon("fa5s.list", "ei.th-list"))
|
2021-03-10 04:52:51 +13:00
|
|
|
self.icon_view = False
|
|
|
|
self.toggled.emit()
|
2021-03-09 05:20:28 +13:00
|
|
|
|
2021-03-10 04:52:51 +13:00
|
|
|
def list(self):
|
2022-06-23 05:00:00 +12:00
|
|
|
self.icon_button.setIcon(qta_icon("mdi.view-grid-outline", "ei.th-large"))
|
|
|
|
self.list_button.setIcon(qta_icon("fa5s.list", "ei.th-list", color="orange"))
|
2021-03-10 04:52:51 +13:00
|
|
|
self.icon_view = True
|
|
|
|
self.toggled.emit()
|
2021-06-11 00:13:28 +12:00
|
|
|
|
|
|
|
|
|
|
|
class ImageLabel(QLabel):
|
2021-10-10 00:33:54 +13:00
|
|
|
image = None
|
|
|
|
img_size = None
|
2022-09-04 10:14:43 +12:00
|
|
|
name = ""
|
2021-06-11 00:13:28 +12:00
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
super(ImageLabel, self).__init__()
|
2022-09-08 10:27:37 +12:00
|
|
|
self.path = tmp_dir()
|
2021-08-08 09:42:40 +12:00
|
|
|
self.manager = QtRequestManager("bytes")
|
2021-06-11 00:13:28 +12:00
|
|
|
|
2021-09-13 07:19:51 +12:00
|
|
|
def update_image(self, url, name="", size: tuple = (240, 320)):
|
2021-06-11 00:13:28 +12:00
|
|
|
self.setFixedSize(*size)
|
|
|
|
self.img_size = size
|
|
|
|
self.name = name
|
|
|
|
for c in r'<>?":|\/* ':
|
|
|
|
self.name = self.name.replace(c, "")
|
2021-06-11 22:56:25 +12:00
|
|
|
if self.img_size[0] > self.img_size[1]:
|
|
|
|
name_extension = "wide"
|
|
|
|
else:
|
|
|
|
name_extension = "tall"
|
|
|
|
self.name = f"{self.name}_{name_extension}.png"
|
|
|
|
if not os.path.exists(os.path.join(self.path, self.name)):
|
2021-08-23 08:22:17 +12:00
|
|
|
self.manager.get(url, self.image_ready)
|
2021-08-08 09:42:40 +12:00
|
|
|
# self.request.finished.connect(self.image_ready)
|
2021-06-11 00:13:28 +12:00
|
|
|
else:
|
|
|
|
self.show_image()
|
|
|
|
|
2021-08-08 09:42:40 +12:00
|
|
|
def image_ready(self, data):
|
2021-11-07 13:19:37 +13:00
|
|
|
try:
|
|
|
|
self.setPixmap(QPixmap())
|
|
|
|
except Exception:
|
|
|
|
logger.warning("C++ object already removed, when image ready")
|
2021-08-26 06:25:10 +12:00
|
|
|
return
|
2021-11-11 10:07:28 +13:00
|
|
|
image = QImage()
|
|
|
|
image.loadFromData(data)
|
2021-12-24 22:09:50 +13:00
|
|
|
image = image.scaled(
|
|
|
|
*self.img_size[:2],
|
|
|
|
Qt.KeepAspectRatio,
|
|
|
|
transformMode=Qt.SmoothTransformation,
|
|
|
|
)
|
2021-11-11 10:07:28 +13:00
|
|
|
|
2022-02-06 04:03:21 +13:00
|
|
|
image.save(os.path.join(self.path, self.name))
|
|
|
|
|
2021-11-11 10:07:28 +13:00
|
|
|
pixmap = QPixmap().fromImage(image)
|
2021-08-08 09:42:40 +12:00
|
|
|
self.setPixmap(pixmap)
|
2021-06-11 00:13:28 +12:00
|
|
|
|
|
|
|
def show_image(self):
|
2021-12-24 22:09:50 +13:00
|
|
|
self.image = QPixmap(os.path.join(self.path, self.name)).scaled(
|
|
|
|
*self.img_size, transformMode=Qt.SmoothTransformation
|
|
|
|
)
|
2021-06-11 00:13:28 +12:00
|
|
|
self.setPixmap(self.image)
|
2021-06-21 08:22:36 +12:00
|
|
|
|
|
|
|
|
|
|
|
class ButtonLineEdit(QLineEdit):
|
|
|
|
buttonClicked = pyqtSignal()
|
|
|
|
|
|
|
|
def __init__(self, icon_name, placeholder_text: str, parent=None):
|
|
|
|
super(ButtonLineEdit, self).__init__(parent)
|
|
|
|
|
|
|
|
self.button = QToolButton(self)
|
2021-11-05 05:28:29 +13:00
|
|
|
self.button.setIcon(qta_icon(icon_name, color="white"))
|
2021-12-24 22:09:50 +13:00
|
|
|
self.button.setStyleSheet("border: 0px; padding: 0px;")
|
2021-06-21 08:22:36 +12:00
|
|
|
self.button.setCursor(Qt.ArrowCursor)
|
|
|
|
self.button.clicked.connect(self.buttonClicked.emit)
|
2021-06-30 10:38:42 +12:00
|
|
|
self.setPlaceholderText(placeholder_text)
|
2021-06-21 08:22:36 +12:00
|
|
|
frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
|
|
|
|
buttonSize = self.button.sizeHint()
|
|
|
|
|
2021-12-24 22:09:50 +13:00
|
|
|
self.setStyleSheet(
|
|
|
|
"QLineEdit {padding-right: %dpx; }" % (buttonSize.width() + frameWidth + 1)
|
|
|
|
)
|
|
|
|
self.setMinimumSize(
|
2022-05-05 08:11:41 +12:00
|
|
|
max(self.minimumSizeHint().width(), buttonSize.width() + frameWidth * 2 + 2),
|
2021-12-24 22:09:50 +13:00
|
|
|
max(
|
|
|
|
self.minimumSizeHint().height(),
|
|
|
|
buttonSize.height() + frameWidth * 2 + 2,
|
|
|
|
),
|
|
|
|
)
|
2021-06-21 08:22:36 +12:00
|
|
|
|
|
|
|
def resizeEvent(self, event):
|
|
|
|
buttonSize = self.button.sizeHint()
|
|
|
|
frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
|
2021-12-24 22:09:50 +13:00
|
|
|
self.button.move(
|
|
|
|
self.rect().right() - frameWidth - buttonSize.width(),
|
|
|
|
(self.rect().bottom() - buttonSize.height() + 1) // 2,
|
|
|
|
)
|
2021-06-21 08:22:36 +12:00
|
|
|
super(ButtonLineEdit, self).resizeEvent(event)
|