1
0
Fork 0
mirror of synced 2024-06-26 10:11:19 +12:00
Rare/rare/utils/extra_widgets.py

306 lines
10 KiB
Python
Raw Normal View History

import io
2021-02-10 23:48:25 +13:00
import os
from PIL import Image
from PIL.ImageQt import ImageQt
from PyQt5.QtCore import Qt, QRect, QSize, QPoint, pyqtSignal, QUrl, QSettings
from PyQt5.QtGui import QMovie, QPixmap
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
2021-04-29 23:20:20 +12:00
from PyQt5.QtWidgets import QLayout, QStyle, QSizePolicy, QLabel, QFileDialog, QHBoxLayout, QWidget, QPushButton, \
QStyleOptionTab, QStylePainter, QTabBar
from qtawesome import icon
2021-02-10 23:48:25 +13:00
2021-04-08 08:39:23 +12:00
from rare import style_path
from rare.ui.utils.pathedit import Ui_PathEdit
2021-02-10 23:48:25 +13:00
class FlowLayout(QLayout):
def __init__(self, parent=None, margin=-1, hspacing=-1, vspacing=-1):
super(FlowLayout, self).__init__(parent)
self._hspacing = hspacing
self._vspacing = vspacing
self._items = []
self.setContentsMargins(margin, margin, margin, margin)
def __del__(self):
del self._items[:]
def addItem(self, item):
self._items.append(item)
def horizontalSpacing(self):
if self._hspacing >= 0:
return self._hspacing
else:
return self.smartSpacing(
QStyle.PM_LayoutHorizontalSpacing)
def verticalSpacing(self):
if self._vspacing >= 0:
return self._vspacing
else:
return self.smartSpacing(
QStyle.PM_LayoutVerticalSpacing)
def count(self):
return len(self._items)
def itemAt(self, index):
if 0 <= index < len(self._items):
return self._items[index]
def takeAt(self, index):
if 0 <= index < len(self._items):
return self._items.pop(index)
def expandingDirections(self):
return Qt.Orientations(0)
def hasHeightForWidth(self):
return True
def heightForWidth(self, width):
return self.doLayout(QRect(0, 0, width, 0), True)
def setGeometry(self, rect):
super(FlowLayout, self).setGeometry(rect)
self.doLayout(rect, False)
def sizeHint(self):
return self.minimumSize()
def minimumSize(self):
size = QSize()
for item in self._items:
size = size.expandedTo(item.minimumSize())
left, top, right, bottom = self.getContentsMargins()
size += QSize(left + right, top + bottom)
return size
def doLayout(self, rect, testonly):
left, top, right, bottom = self.getContentsMargins()
effective = rect.adjusted(+left, +top, -right, -bottom)
x = effective.x()
y = effective.y()
lineheight = 0
for item in self._items:
widget = item.widget()
hspace = self.horizontalSpacing()
if hspace == -1:
hspace = widget.style().layoutSpacing(
QSizePolicy.PushButton,
QSizePolicy.PushButton, Qt.Horizontal)
vspace = self.verticalSpacing()
if vspace == -1:
vspace = widget.style().layoutSpacing(
QSizePolicy.PushButton,
QSizePolicy.PushButton, Qt.Vertical)
nextX = x + item.sizeHint().width() + hspace
if nextX - hspace > effective.right() and lineheight > 0:
x = effective.x()
y = y + lineheight + vspace
nextX = x + item.sizeHint().width() + hspace
lineheight = 0
if not testonly:
item.setGeometry(
QRect(QPoint(x, y), item.sizeHint()))
x = nextX
lineheight = max(lineheight, item.sizeHint().height())
return y + lineheight - rect.y() + bottom
def smartSpacing(self, pm):
parent = self.parent()
if parent is None:
return -1
elif parent.isWidgetType():
return parent.style().pixelMetric(pm, None, parent)
else:
return parent.spacing()
class PathEdit(QWidget, Ui_PathEdit):
def __init__(self,
text: str = "",
file_type: QFileDialog.FileType = QFileDialog.AnyFile,
type_filter: str = None,
2021-05-02 08:15:42 +12:00
name_filter: str = None,
edit_func: callable = None,
save_func: callable = None):
2021-02-10 23:48:25 +13:00
super(PathEdit, self).__init__()
self.setupUi(self)
self.type_filter = type_filter
self.name_filter = name_filter
self.file_type = file_type
2021-05-02 08:15:42 +12:00
self.edit_func = edit_func
self.save_func = save_func
if text:
self.text_edit.setText(text)
2021-05-02 08:15:42 +12:00
if self.edit_func is not None:
self.text_edit.textChanged.connect(self.edit_func)
if self.save_func is None:
self.save_path_button.setVisible(False)
else:
self.text_edit.textChanged.connect(lambda t: self.save_path_button.setDisabled(False))
self.save_path_button.clicked.connect(self.save)
self.save_path_button.setDisabled(True)
2021-02-10 23:48:25 +13:00
self.path_select.clicked.connect(self.set_path)
def text(self):
return self.text_edit.text()
def setText(self, text: str):
self.text_edit.setText(text)
2021-05-02 08:15:42 +12:00
def save(self):
self.save_func()
self.save_path_button.setDisabled(True)
2021-02-10 23:48:25 +13:00
def set_path(self):
dlg_path = self.text_edit.text()
if not dlg_path:
dlg_path = os.path.expanduser("~/")
dlg = QFileDialog(self, self.tr("Choose Path"), dlg_path)
dlg.setFileMode(self.file_type)
if self.type_filter:
dlg.setFilter([self.type_filter])
if self.name_filter:
dlg.setNameFilter(self.name_filter)
2021-02-10 23:48:25 +13:00
if dlg.exec_():
names = dlg.selectedFiles()
self.text_edit.setText(names[0])
2021-02-28 03:54:26 +13:00
class SideTabBar(QTabBar):
def __init__(self):
super(SideTabBar, self).__init__()
self.setObjectName("settings_bar")
def tabSizeHint(self, index):
# width = QTabBar.tabSizeHint(self, index).width()
return QSize(200, 30)
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)
painter.drawControl(QStyle.CE_TabBarTabLabel, opt);
painter.restore()
2021-02-28 05:20:56 +13:00
2021-02-28 05:20:56 +13:00
class WaitingSpinner(QLabel):
def __init__(self):
super(WaitingSpinner, self).__init__()
self.setStyleSheet("""
margin-left: auto;
margin-right: auto;
""")
self.movie = QMovie(os.path.join(style_path, "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
class SelectViewWidget(QWidget):
toggled = pyqtSignal()
2021-03-09 05:20:28 +13:00
def __init__(self, icon_view: bool):
super(SelectViewWidget, self).__init__()
self.icon_view = icon_view
2021-03-10 06:13:04 +13:00
self.setStyleSheet("""QPushButton{border: none; background-color: transparent}""")
self.icon_view_button = QPushButton()
self.list_view = QPushButton()
if icon_view:
2021-03-26 02:15:18 +13:00
self.icon_view_button.setIcon(icon("mdi.view-grid-outline", color="orange"))
self.list_view.setIcon(icon("fa5s.list", color="white"))
else:
2021-03-26 02:15:18 +13:00
self.icon_view_button.setIcon(icon("mdi.view-grid-outline", color="white"))
self.list_view.setIcon(icon("fa5s.list", color="orange"))
2021-03-09 05:20:28 +13:00
self.icon_view_button.clicked.connect(self.icon)
self.list_view.clicked.connect(self.list)
self.layout = QHBoxLayout()
self.layout.addWidget(self.icon_view_button)
self.layout.addWidget(self.list_view)
self.setLayout(self.layout)
def isChecked(self):
return self.icon_view
2021-03-09 05:20:28 +13:00
def icon(self):
self.icon_view_button.setIcon(icon("mdi.view-grid-outline", color="orange"))
self.list_view.setIcon(icon("fa5s.list", color="white"))
self.icon_view = False
self.toggled.emit()
2021-03-09 05:20:28 +13:00
def list(self):
self.icon_view_button.setIcon(icon("mdi.view-grid-outline", color="white"))
self.list_view.setIcon(icon("fa5s.list", color="orange"))
self.icon_view = True
self.toggled.emit()
class ImageLabel(QLabel):
def __init__(self):
super(ImageLabel, self).__init__()
path = os.path.expanduser("~/.cache/rare/cache")
if p := os.environ.get("XDG_CACHE_HOME"):
path = os.path.join(p, "rare", "cache")
self.path = path
self.manager = QNetworkAccessManager()
def update_image(self, url, name, size: tuple = (240, 320)):
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)):
self.request = self.manager.get(QNetworkRequest(QUrl(url)))
self.request.finished.connect(self.image_ready)
else:
self.show_image()
def image_ready(self):
if self.request:
if self.request.error() == QNetworkReply.NoError:
2021-06-11 22:56:25 +12:00
data = self.request.readAll().data()
image: Image.Image = Image.open(io.BytesIO(data))
image = image.resize((self.img_size[0], self.img_size[1]))
if QSettings().value("cache_images", True, bool):
image.save(os.path.join(self.path, self.name), format="png")
pixmap = QPixmap()
pixmap.fromImage(ImageQt(image))
self.setPixmap(pixmap)
else:
return
def show_image(self):
2021-06-11 22:56:25 +12:00
self.image = QPixmap(os.path.join(self.path, self.name)).scaled(*self.img_size,
transformMode=Qt.SmoothTransformation)
self.setPixmap(self.image)