Merge branch 'render-images' into develop

This commit is contained in:
dries.k
2022-12-07 19:13:31 +01:00
10 changed files with 260 additions and 62 deletions

View File

@@ -32,6 +32,9 @@ class Cache(object):
self.cache_dir = os.path.join(path, "cache") self.cache_dir = os.path.join(path, "cache")
os.makedirs(self.cache_dir, exist_ok=True) os.makedirs(self.cache_dir, exist_ok=True)
def directory(self) -> str:
return self.cache_dir
def clear(self): def clear(self):
self.cursor.execute("DELETE FROM cache") self.cursor.execute("DELETE FROM cache")
self.database.commit() self.database.commit()

View File

@@ -19,6 +19,8 @@ DEFAULT_SETTINGS = {
"tray/icon/unread": False, "tray/icon/unread": False,
"watchdog/interval/s": 60, "watchdog/interval/s": 60,
"MessageWidget/image/size": 33, "MessageWidget/image/size": 33,
"MessageWidget/content_image/W_percentage": 1.0,
"MessageWidget/content_image/H_percentage": 0.5,
"MainWindow/label/size": 25, "MainWindow/label/size": 25,
"MainWindow/button/size": 33, "MainWindow/button/size": 33,
"MainWindow/application/icon/size": 40, "MainWindow/application/icon/size": 40,

View File

@@ -16,6 +16,8 @@ from gotify_tray.tasks import (
GetApplicationsTask, GetApplicationsTask,
GetApplicationMessagesTask, GetApplicationMessagesTask,
GetMessagesTask, GetMessagesTask,
ProcessMessageTask,
ProcessMessagesTask,
ServerConnectionWatchdogTask, ServerConnectionWatchdogTask,
) )
from gotify_tray.gui.themes import set_theme from gotify_tray.gui.themes import set_theme
@@ -74,6 +76,8 @@ class MainApplication(QtWidgets.QApplication):
self.application_model = ApplicationModel() self.application_model = ApplicationModel()
self.main_window = MainWindow(self.application_model, self.messages_model) self.main_window = MainWindow(self.application_model, self.messages_model)
self.main_window.show() # The initial .show() is necessary to get the correct sizes when adding MessageWigets
QtCore.QTimer.singleShot(0, self.main_window.hide)
self.refresh_applications() self.refresh_applications()
@@ -195,43 +199,39 @@ class MainApplication(QtWidgets.QApplication):
), ),
) )
def get_messages_finished_callback(self, page: gotify.GotifyPagedMessagesModel):
"""Process messages before inserting them into the main window
"""
def insert_helper(row: int, message: gotify.GotifyMessageModel):
if item := self.application_model.itemFromId(message.appid):
self.insert_message(
row, message, item.data(ApplicationItemDataRole.ApplicationRole),
)
self.processEvents()
self.process_messages_task = ProcessMessagesTask(page)
self.process_messages_task.message_processed.connect(insert_helper)
self.process_messages_task.start()
def application_selection_changed_callback( def application_selection_changed_callback(
self, item: Union[ApplicationModelItem, ApplicationAllMessagesItem] self, item: Union[ApplicationModelItem, ApplicationAllMessagesItem]
): ):
self.messages_model.clear() self.messages_model.clear()
if isinstance(item, ApplicationModelItem): if isinstance(item, ApplicationModelItem):
def get_application_messages_callback(
page: gotify.GotifyPagedMessagesModel,
):
for i, message in enumerate(page.messages):
self.insert_message(
i, message, item.data(ApplicationItemDataRole.ApplicationRole),
)
self.get_application_messages_task = GetApplicationMessagesTask( self.get_application_messages_task = GetApplicationMessagesTask(
item.data(ApplicationItemDataRole.ApplicationRole).id, item.data(ApplicationItemDataRole.ApplicationRole).id,
self.gotify_client, self.gotify_client,
) )
self.get_application_messages_task.success.connect( self.get_application_messages_task.success.connect(
get_application_messages_callback self.get_messages_finished_callback
) )
self.get_application_messages_task.start() self.get_application_messages_task.start()
elif isinstance(item, ApplicationAllMessagesItem): elif isinstance(item, ApplicationAllMessagesItem):
def get_messages_callback(page: gotify.GotifyPagedMessagesModel):
for i, message in enumerate(page.messages):
if item := self.application_model.itemFromId(message.appid):
self.insert_message(
i,
message,
item.data(ApplicationItemDataRole.ApplicationRole),
)
self.get_messages_task = GetMessagesTask(self.gotify_client) self.get_messages_task = GetMessagesTask(self.gotify_client)
self.get_messages_task.success.connect(get_messages_callback) self.get_messages_task.success.connect(self.get_messages_finished_callback)
self.get_messages_task.start() self.get_messages_task.start()
def add_message_to_model(self, message: gotify.GotifyMessageModel): def add_message_to_model(self, message: gotify.GotifyMessageModel):
@@ -240,6 +240,8 @@ class MainApplication(QtWidgets.QApplication):
if selected_application_item := self.application_model.itemFromIndex( if selected_application_item := self.application_model.itemFromIndex(
application_index application_index
): ):
def insert_message_helper():
if isinstance(selected_application_item, ApplicationModelItem): if isinstance(selected_application_item, ApplicationModelItem):
# A single application is selected # A single application is selected
if ( if (
@@ -255,14 +257,27 @@ class MainApplication(QtWidgets.QApplication):
ApplicationItemDataRole.ApplicationRole ApplicationItemDataRole.ApplicationRole
), ),
) )
elif isinstance(selected_application_item, ApplicationAllMessagesItem): elif isinstance(
selected_application_item, ApplicationAllMessagesItem
):
# "All messages' is selected # "All messages' is selected
self.insert_message( self.insert_message(
0, 0,
message, message,
application_item.data(ApplicationItemDataRole.ApplicationRole), application_item.data(
ApplicationItemDataRole.ApplicationRole
),
) )
self.process_message_task = ProcessMessageTask(message)
self.process_message_task.finished.connect(insert_message_helper)
self.process_message_task.start()
else:
logger.error(
f"App id {message.appid} could not be found. Refreshing applications."
)
self.refresh_applications()
def new_message_callback(self, message: gotify.GotifyMessageModel): def new_message_callback(self, message: gotify.GotifyMessageModel):
self.add_message_to_model(message) self.add_message_to_model(message)
@@ -335,11 +350,6 @@ class MainApplication(QtWidgets.QApplication):
if image_popup := getattr(self, "image_popup", None): if image_popup := getattr(self, "image_popup", None):
image_popup.close() image_popup.close()
def refresh_callback(self):
# Manual refresh -> also reset the image cache
Cache().clear()
self.refresh_applications()
def theme_change_requested_callback(self, theme: str): def theme_change_requested_callback(self, theme: str):
# Set the theme # Set the theme
set_theme(self, theme) set_theme(self, theme)
@@ -400,7 +410,7 @@ class MainApplication(QtWidgets.QApplication):
self.tray.messageClicked.connect(self.tray_notification_clicked_callback) self.tray.messageClicked.connect(self.tray_notification_clicked_callback)
self.tray.activated.connect(self.tray_activated_callback) self.tray.activated.connect(self.tray_activated_callback)
self.main_window.refresh.connect(self.refresh_callback) self.main_window.refresh.connect(self.refresh_applications)
self.main_window.delete_all.connect(self.delete_all_messages_callback) self.main_window.delete_all.connect(self.delete_all_messages_callback)
self.main_window.application_selection_changed.connect( self.main_window.application_selection_changed.connect(
self.application_selection_changed_callback self.application_selection_changed_callback

View File

@@ -171,6 +171,22 @@ class Ui_Dialog(object):
self.horizontalLayout_4.addItem(spacerItem5) self.horizontalLayout_4.addItem(spacerItem5)
self.gridLayout_2.addLayout(self.horizontalLayout_4, 0, 0, 1, 1) self.gridLayout_2.addLayout(self.horizontalLayout_4, 0, 0, 1, 1)
self.verticalLayout.addWidget(self.groupbox_image_popup) self.verticalLayout.addWidget(self.groupbox_image_popup)
self.groupBox_cache = QtWidgets.QGroupBox(self.tab_advanced)
self.groupBox_cache.setObjectName("groupBox_cache")
self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.groupBox_cache)
self.horizontalLayout_6.setObjectName("horizontalLayout_6")
self.pb_clear_cache = QtWidgets.QPushButton(self.groupBox_cache)
self.pb_clear_cache.setObjectName("pb_clear_cache")
self.horizontalLayout_6.addWidget(self.pb_clear_cache)
self.pb_open_cache_dir = QtWidgets.QPushButton(self.groupBox_cache)
self.pb_open_cache_dir.setObjectName("pb_open_cache_dir")
self.horizontalLayout_6.addWidget(self.pb_open_cache_dir)
self.label_cache = QtWidgets.QLabel(self.groupBox_cache)
self.label_cache.setObjectName("label_cache")
self.horizontalLayout_6.addWidget(self.label_cache)
spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_6.addItem(spacerItem6)
self.verticalLayout.addWidget(self.groupBox_cache)
self.groupBox_logging = QtWidgets.QGroupBox(self.tab_advanced) self.groupBox_logging = QtWidgets.QGroupBox(self.tab_advanced)
self.groupBox_logging.setObjectName("groupBox_logging") self.groupBox_logging.setObjectName("groupBox_logging")
self.gridLayout_6 = QtWidgets.QGridLayout(self.groupBox_logging) self.gridLayout_6 = QtWidgets.QGridLayout(self.groupBox_logging)
@@ -178,8 +194,8 @@ class Ui_Dialog(object):
self.combo_logging = QtWidgets.QComboBox(self.groupBox_logging) self.combo_logging = QtWidgets.QComboBox(self.groupBox_logging)
self.combo_logging.setObjectName("combo_logging") self.combo_logging.setObjectName("combo_logging")
self.gridLayout_6.addWidget(self.combo_logging, 0, 1, 1, 1) self.gridLayout_6.addWidget(self.combo_logging, 0, 1, 1, 1)
spacerItem6 = QtWidgets.QSpacerItem(190, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem7 = QtWidgets.QSpacerItem(190, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.gridLayout_6.addItem(spacerItem6, 0, 3, 1, 1) self.gridLayout_6.addItem(spacerItem7, 0, 3, 1, 1)
self.pb_open_log = QtWidgets.QPushButton(self.groupBox_logging) self.pb_open_log = QtWidgets.QPushButton(self.groupBox_logging)
self.pb_open_log.setMaximumSize(QtCore.QSize(30, 16777215)) self.pb_open_log.setMaximumSize(QtCore.QSize(30, 16777215))
self.pb_open_log.setObjectName("pb_open_log") self.pb_open_log.setObjectName("pb_open_log")
@@ -188,8 +204,8 @@ class Ui_Dialog(object):
self.label_logging.setObjectName("label_logging") self.label_logging.setObjectName("label_logging")
self.gridLayout_6.addWidget(self.label_logging, 0, 0, 1, 1) self.gridLayout_6.addWidget(self.label_logging, 0, 0, 1, 1)
self.verticalLayout.addWidget(self.groupBox_logging) self.verticalLayout.addWidget(self.groupBox_logging)
spacerItem7 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
self.verticalLayout.addItem(spacerItem7) self.verticalLayout.addItem(spacerItem8)
self.tabWidget.addTab(self.tab_advanced, "") self.tabWidget.addTab(self.tab_advanced, "")
self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1) self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1)
@@ -238,6 +254,10 @@ class Ui_Dialog(object):
self.label_2.setToolTip(_translate("Dialog", "Maximum pop-up height")) self.label_2.setToolTip(_translate("Dialog", "Maximum pop-up height"))
self.label_2.setText(_translate("Dialog", "Height")) self.label_2.setText(_translate("Dialog", "Height"))
self.spin_popup_h.setToolTip(_translate("Dialog", "Maximum pop-up height")) self.spin_popup_h.setToolTip(_translate("Dialog", "Maximum pop-up height"))
self.groupBox_cache.setTitle(_translate("Dialog", "Cache"))
self.pb_clear_cache.setText(_translate("Dialog", "Clear"))
self.pb_open_cache_dir.setText(_translate("Dialog", "Open"))
self.label_cache.setText(_translate("Dialog", "TextLabel"))
self.groupBox_logging.setTitle(_translate("Dialog", "Logging")) self.groupBox_logging.setTitle(_translate("Dialog", "Logging"))
self.pb_open_log.setToolTip(_translate("Dialog", "Open logfile")) self.pb_open_log.setToolTip(_translate("Dialog", "Open logfile"))
self.pb_open_log.setText(_translate("Dialog", "...")) self.pb_open_log.setText(_translate("Dialog", "..."))

View File

@@ -400,6 +400,49 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QGroupBox" name="groupBox_cache">
<property name="title">
<string>Cache</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QPushButton" name="pb_clear_cache">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pb_open_cache_dir">
<property name="text">
<string>Open</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_cache">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="groupBox_logging"> <widget class="QGroupBox" name="groupBox_logging">
<property name="title"> <property name="title">

View File

@@ -104,7 +104,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def insert_message_widget( def insert_message_widget(
self, message_item: MessagesModelItem, image_path: str = "" self, message_item: MessagesModelItem, image_path: str = ""
): ):
message_widget = MessageWidget(message_item, image_path=image_path) message_widget = MessageWidget(
self.listView_messages, message_item, image_path=image_path
)
self.listView_messages.setIndexWidget( self.listView_messages.setIndexWidget(
self.messages_model.indexFromItem(message_item), message_widget self.messages_model.indexFromItem(message_item), message_widget
) )

View File

@@ -4,9 +4,11 @@ from PyQt6 import QtCore, QtGui, QtWidgets
from ..models.MessagesModel import MessageItemDataRole, MessagesModelItem from ..models.MessagesModel import MessageItemDataRole, MessagesModelItem
from ..designs.widget_message import Ui_Form from ..designs.widget_message import Ui_Form
from gotify_tray.database import Downloader
from gotify_tray.database import Settings from gotify_tray.database import Settings
from gotify_tray.utils import convert_links from gotify_tray.utils import convert_links, get_image
from gotify_tray.gui.themes import get_theme_file from gotify_tray.gui.themes import get_theme_file
from gotify_tray.gotify.models import GotifyMessageModel
settings = Settings("gotify-tray") settings = Settings("gotify-tray")
@@ -16,13 +18,18 @@ class MessageWidget(QtWidgets.QWidget, Ui_Form):
deletion_requested = QtCore.pyqtSignal(MessagesModelItem) deletion_requested = QtCore.pyqtSignal(MessagesModelItem)
image_popup = QtCore.pyqtSignal(str, QtCore.QPoint) image_popup = QtCore.pyqtSignal(str, QtCore.QPoint)
def __init__(self, message_item: MessagesModelItem, image_path: str = ""): def __init__(
self,
parent: QtWidgets.QWidget,
message_item: MessagesModelItem,
image_path: str = "",
):
super(MessageWidget, self).__init__() super(MessageWidget, self).__init__()
self.parent = parent
self.setupUi(self) self.setupUi(self)
self.setAutoFillBackground(True) self.setAutoFillBackground(True)
self.message_item = message_item self.message_item = message_item
message = message_item.data(MessageItemDataRole.MessageRole) message: GotifyMessageModel = message_item.data(MessageItemDataRole.MessageRole)
# Fonts # Fonts
self.set_fonts() self.set_fonts()
@@ -31,13 +38,19 @@ class MessageWidget(QtWidgets.QWidget, Ui_Form):
self.label_title.setText(message.title) self.label_title.setText(message.title)
self.label_date.setText(message.date.strftime("%Y-%m-%d, %H:%M")) self.label_date.setText(message.date.strftime("%Y-%m-%d, %H:%M"))
if ( if markdown := (
markdown := message.get("extras", {}) message.get("extras", {}).get("client::display", {}).get("contentType")
.get("client::display", {}) == "text/markdown"
.get("contentType") ):
) == "text/markdown":
self.label_message.setTextFormat(QtCore.Qt.TextFormat.MarkdownText) self.label_message.setTextFormat(QtCore.Qt.TextFormat.MarkdownText)
# If the message is only an image URL, then instead of showing the message,
# download the image and show it in the message label
if image_url := get_image(message.message):
downloader = Downloader()
filename = downloader.get_filename(image_url)
self.set_message_image(filename)
else:
self.label_message.setText(convert_links(message.message)) self.label_message.setText(convert_links(message.message))
# Show the application icon # Show the application icon
@@ -91,6 +104,27 @@ class MessageWidget(QtWidgets.QWidget, Ui_Form):
self.pb_delete.setIcon(QtGui.QIcon(get_theme_file("trashcan.svg"))) self.pb_delete.setIcon(QtGui.QIcon(get_theme_file("trashcan.svg")))
self.pb_delete.setIconSize(QtCore.QSize(24, 24)) self.pb_delete.setIconSize(QtCore.QSize(24, 24))
def set_message_image(self, filename: str):
pixmap = QtGui.QPixmap(filename)
# Make sure the image fits within the listView
W = settings.value("MessageWidget/content_image/W_percentage", type=float) * (
self.parent.width() - self.label_image.width()
)
H = (
settings.value("MessageWidget/content_image/H_percentage", type=float)
* self.parent.height()
)
if pixmap.width() > W or pixmap.height() > H:
pixmap = pixmap.scaled(
QtCore.QSize(int(W), int(H)),
aspectRatioMode=QtCore.Qt.AspectRatioMode.KeepAspectRatio,
transformMode=QtCore.Qt.TransformationMode.SmoothTransformation,
)
self.label_message.setPixmap(pixmap)
def link_hovered_callback(self, link: str): def link_hovered_callback(self, link: str):
if not settings.value("ImagePopup/enabled", type=bool): if not settings.value("ImagePopup/enabled", type=bool):
return return

View File

@@ -2,12 +2,12 @@ import logging
import platform import platform
import os import os
from gotify_tray.database import Settings from gotify_tray.database import Cache, Settings
from gotify_tray.gotify import GotifyMessageModel from gotify_tray.gotify import GotifyMessageModel
from gotify_tray.gui.models import MessagesModelItem from gotify_tray.gui.models import MessagesModelItem
from . import MessageWidget from . import MessageWidget
from gotify_tray.utils import get_icon, verify_server, open_file from gotify_tray.utils import get_icon, verify_server, open_file
from gotify_tray.tasks import ExportSettingsTask, ImportSettingsTask from gotify_tray.tasks import ExportSettingsTask, ImportSettingsTask, CacheSizeTask, ClearCacheTask
from gotify_tray.gui.themes import get_themes from gotify_tray.gui.themes import get_themes
from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6 import QtCore, QtGui, QtWidgets
@@ -91,9 +91,12 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
) )
self.spin_popup_w.setValue(settings.value("ImagePopup/w", type=int)) self.spin_popup_w.setValue(settings.value("ImagePopup/w", type=int))
self.spin_popup_h.setValue(settings.value("ImagePopup/h", type=int)) self.spin_popup_h.setValue(settings.value("ImagePopup/h", type=int))
self.label_cache.setText("0 MB")
self.compute_cache_size()
def add_message_widget(self): def add_message_widget(self):
self.message_widget = MessageWidget( self.message_widget = MessageWidget(
self,
MessagesModelItem( MessagesModelItem(
GotifyMessageModel( GotifyMessageModel(
{ {
@@ -107,6 +110,11 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
) )
self.layout_fonts_message.addWidget(self.message_widget) self.layout_fonts_message.addWidget(self.message_widget)
def compute_cache_size(self):
self.cache_size_task = CacheSizeTask()
self.cache_size_task.size.connect(lambda size: self.label_cache.setText(f"{round(size/1e6, 1)} MB"))
self.cache_size_task.start()
def change_server_info_callback(self): def change_server_info_callback(self):
self.server_changed = verify_server(force_new=True, enable_import=False) self.server_changed = verify_server(force_new=True, enable_import=False)
@@ -179,6 +187,11 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
settings.clear() settings.clear()
self.quit_requested.emit() self.quit_requested.emit()
def clear_cache_callback(self):
self.clear_cache_task = ClearCacheTask()
self.clear_cache_task.start()
self.label_cache.setText("0 MB")
def link_callbacks(self): def link_callbacks(self):
self.buttonBox.button( self.buttonBox.button(
QtWidgets.QDialogButtonBox.StandardButton.Apply QtWidgets.QDialogButtonBox.StandardButton.Apply
@@ -223,6 +236,8 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
self.groupbox_image_popup.toggled.connect(self.settings_changed_callback) self.groupbox_image_popup.toggled.connect(self.settings_changed_callback)
self.spin_popup_w.valueChanged.connect(self.settings_changed_callback) self.spin_popup_w.valueChanged.connect(self.settings_changed_callback)
self.spin_popup_h.valueChanged.connect(self.settings_changed_callback) self.spin_popup_h.valueChanged.connect(self.settings_changed_callback)
self.pb_clear_cache.clicked.connect(self.clear_cache_callback)
self.pb_open_cache_dir.clicked.connect(lambda: open_file(Cache().directory()))
def apply_settings(self): def apply_settings(self):
# Priority # Priority

View File

@@ -1,13 +1,17 @@
import abc import abc
import glob
import logging import logging
import time import time
import os
from functools import reduce
from PyQt6 import QtCore from PyQt6 import QtCore
from PyQt6.QtCore import pyqtSignal from PyQt6.QtCore import pyqtSignal
from gotify_tray.database import Settings from gotify_tray.database import Cache, Downloader, Settings
from gotify_tray.gotify.api import GotifyClient from gotify_tray.gotify.api import GotifyClient
from gotify_tray.gotify.models import GotifyVersionModel from gotify_tray.gotify.models import GotifyVersionModel
from gotify_tray.utils import get_image
from . import gotify from . import gotify
@@ -199,3 +203,48 @@ class ImportSettingsTask(BaseTask):
def task(self): def task(self):
settings.load(self.path) settings.load(self.path)
self.success.emit() self.success.emit()
class ProcessMessageTask(BaseTask):
def __init__(self, message: gotify.GotifyMessageModel):
super(ProcessMessageTask, self).__init__()
self.message = message
def task(self):
if image_url := get_image(self.message.message):
downloader = Downloader()
downloader.get_filename(image_url)
class ProcessMessagesTask(BaseTask):
message_processed = pyqtSignal(int, gotify.GotifyMessageModel)
def __init__(self, page: gotify.GotifyPagedMessagesModel):
super(ProcessMessagesTask, self).__init__()
self.page = page
def task(self):
downloader = Downloader()
for i, message in enumerate(self.page.messages):
if image_url := get_image(message.message):
downloader.get_filename(image_url)
self.message_processed.emit(i, message)
# Prevent locking up the UI when there are a lot of messages with images ready at the same time
time.sleep(0.001)
class CacheSizeTask(BaseTask):
size = pyqtSignal(int)
def task(self):
cache_dir = Cache().directory()
if os.path.exists(cache_dir):
cache_size_bytes = reduce(lambda x, f: x + os.path.getsize(f), glob.glob(os.path.join(cache_dir, "*")), 0)
self.size.emit(cache_size_bytes)
class ClearCacheTask(BaseTask):
def task(self):
cache = Cache()
cache.clear()

View File

@@ -4,6 +4,7 @@ import re
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from typing import Optional
def verify_server(force_new: bool = False, enable_import: bool = True) -> bool: def verify_server(force_new: bool = False, enable_import: bool = True) -> bool:
@@ -44,6 +45,25 @@ def convert_links(text):
return _link.sub(replace, text) return _link.sub(replace, text)
def get_image(s: str) -> Optional[str]:
"""If `s` contains only an image URL, this function returns that URL.
This function also extracts a URL in the `![](<url>)` markdown image format.
"""
s = s.strip()
# Return True if 's' is a url and has an image extension
RE = r'(?:(https://|http://)|(www\.))(\S+\b/?)([!"#$%&\'()*+,\-./:;<=>?@[\\\]^_`{|}~]*).(jpg|jpeg|png|bmp|gif)(\s|$)'
if re.compile(RE, re.I).fullmatch(s) is not None:
return s
# Return True if 's' has the markdown image format
RE = r'!\[[^\]]*\]\((.*?)\s*("(?:.*[^"])")?\s*\)'
if re.compile(RE, re.I).fullmatch(s) is not None:
return re.compile(RE, re.I).findall(s)[0][0]
return None
def get_abs_path(s) -> str: def get_abs_path(s) -> str:
h = Path(__file__).parent.parent h = Path(__file__).parent.parent
p = Path(s) p = Path(s)