mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-08 23:24:15 +02:00
screenshots panel improved
This commit is contained in:
@@ -7,7 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
## [0.7.0]
|
## [0.7.0]
|
||||||
### Features
|
### Features
|
||||||
- AppImage support ( see below )
|
- AppImage support ( see below )
|
||||||
- **Screenshots** button
|
- **Screenshots** button and panel
|
||||||
- **Categories** filter
|
- **Categories** filter
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
@@ -29,8 +29,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
|
|
||||||
### AppImage support
|
### AppImage support
|
||||||
- Search, install, uninstall, downgrade, launch and retrieve the applications history
|
- Search, install, uninstall, downgrade, launch and retrieve the applications history
|
||||||
- Supported sources: [AppImageHub](https://appimage.github.io).
|
- Supported sources: [AppImageHub](https://appimage.github.io) ( **applications with no releases published to GitHub are currently not available** )
|
||||||
- Applications with no releases published to GitHub are not available
|
|
||||||
- Adds desktop entries ( menu shortcuts ) for the installed applications ( **~/.local/share/applications **)
|
- Adds desktop entries ( menu shortcuts ) for the installed applications ( **~/.local/share/applications **)
|
||||||
|
|
||||||
## [0.6.4] 2019-10-13
|
## [0.6.4] 2019-10-13
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ will be pre-downloaded faster ( it does **NOT** modify your **pacman** settings
|
|||||||
|
|
||||||
### AppImage support ( appimage gem )
|
### AppImage support ( appimage gem )
|
||||||
- The user is able to search, install, uninstall, downgrade, launch and retrieve the applications history
|
- The user is able to search, install, uninstall, downgrade, launch and retrieve the applications history
|
||||||
- Supported sources: [AppImageHub](https://appimage.github.io) ( **applications with no releases published to GitHub are not available yet** )
|
- Supported sources: [AppImageHub](https://appimage.github.io) ( **applications with no releases published to GitHub are currently not available** )
|
||||||
- Faster downloads if **aria2c** is installed. Same behavior described in the **AUR support** section.
|
- Faster downloads if **aria2c** is installed. Same behavior described in the **AUR support** section.
|
||||||
- Installed applications are store at **~/.local/share/bauh/appimage/installed**
|
- Installed applications are store at **~/.local/share/bauh/appimage/installed**
|
||||||
- Desktop entries ( menu shortcuts ) of the installed applications are stored at **~/.local/share/applications**
|
- Desktop entries ( menu shortcuts ) of the installed applications are stored at **~/.local/share/applications**
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ def main():
|
|||||||
config=user_config,
|
config=user_config,
|
||||||
context=context,
|
context=context,
|
||||||
http_client=http_client,
|
http_client=http_client,
|
||||||
|
logger=logger,
|
||||||
notifications=bool(args.system_notifications))
|
notifications=bool(args.system_notifications))
|
||||||
|
|
||||||
if args.tray:
|
if args.tray:
|
||||||
|
|||||||
@@ -130,6 +130,8 @@ class AppImageManager(SoftwareManager):
|
|||||||
app.url_download_latest_version = tup[3]
|
app.url_download_latest_version = tup[3]
|
||||||
|
|
||||||
break
|
break
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
finally:
|
finally:
|
||||||
self._close_connection(DB_APPS_PATH, con)
|
self._close_connection(DB_APPS_PATH, con)
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,32 @@
|
|||||||
|
import logging
|
||||||
|
from threading import Thread
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtGui import QIcon, QPixmap
|
from PyQt5.QtGui import QIcon, QPixmap
|
||||||
from PyQt5.QtWidgets import QDialog, QLabel, QGridLayout, QPushButton
|
from PyQt5.QtWidgets import QDialog, QLabel, QGridLayout, QPushButton
|
||||||
|
|
||||||
from bauh.api.abstract.cache import MemoryCache
|
from bauh.api.abstract.cache import MemoryCache
|
||||||
|
from bauh.api.http import HttpClient
|
||||||
from bauh.view.qt import qt_utils
|
from bauh.view.qt import qt_utils
|
||||||
from bauh.view.qt.view_model import PackageView
|
from bauh.view.qt.view_model import PackageView
|
||||||
|
|
||||||
|
|
||||||
class ScreenshotsDialog(QDialog):
|
class ScreenshotsDialog(QDialog):
|
||||||
|
|
||||||
def __init__(self, pkg: PackageView, icon_cache: MemoryCache, i18n: dict, screenshots: List[QPixmap]):
|
MAX_HEIGHT = 600
|
||||||
|
MAX_WIDTH = 800
|
||||||
|
|
||||||
|
def __init__(self, pkg: PackageView, http_client: HttpClient, icon_cache: MemoryCache, i18n: dict, screenshots: List[QPixmap], logger: logging.Logger):
|
||||||
super(ScreenshotsDialog, self).__init__()
|
super(ScreenshotsDialog, self).__init__()
|
||||||
self.setWindowTitle(str(pkg))
|
self.setWindowTitle(str(pkg))
|
||||||
self.screenshots = screenshots
|
self.screenshots = screenshots
|
||||||
|
self.logger = logger
|
||||||
|
self.loaded_imgs = []
|
||||||
|
self.download_threads = []
|
||||||
self.resize(1280, 720)
|
self.resize(1280, 720)
|
||||||
self.i18n = i18n
|
self.i18n = i18n
|
||||||
|
self.http_client = http_client
|
||||||
|
|
||||||
icon_data = icon_cache.get(pkg.model.icon_url)
|
icon_data = icon_cache.get(pkg.model.icon_url)
|
||||||
|
|
||||||
@@ -36,30 +47,73 @@ class ScreenshotsDialog(QDialog):
|
|||||||
|
|
||||||
self.img = QLabel()
|
self.img = QLabel()
|
||||||
self.layout().addWidget(self.img, 1, 1)
|
self.layout().addWidget(self.img, 1, 1)
|
||||||
|
self.img_label = QLabel()
|
||||||
|
self.img_label.setStyleSheet('QLabel { font-weight: bold; text-align: center }')
|
||||||
|
self.layout().addWidget(self.img_label, 2, 1)
|
||||||
|
|
||||||
|
self.img_idx = 0
|
||||||
|
|
||||||
|
for idx, s in enumerate(self.screenshots):
|
||||||
|
t = Thread(target=self._download_img, args=(idx, s))
|
||||||
|
t.start()
|
||||||
|
|
||||||
self.idx = 0
|
|
||||||
self._load_img()
|
self._load_img()
|
||||||
|
|
||||||
def _load_img(self):
|
def _load_img(self):
|
||||||
pixmap = self.screenshots[self.idx]
|
if len(self.loaded_imgs) > self.img_idx:
|
||||||
self.img.setPixmap(pixmap)
|
img = self.loaded_imgs[self.img_idx]
|
||||||
|
|
||||||
|
if isinstance(img, QPixmap):
|
||||||
|
self.img_label.setText('')
|
||||||
|
self.img.setPixmap(img)
|
||||||
|
else:
|
||||||
|
self.img_label.setText(img)
|
||||||
|
self.img.setPixmap(QPixmap())
|
||||||
|
else:
|
||||||
|
self.img.setPixmap(QPixmap())
|
||||||
|
self.img_label.setText('...{}...'.format(self.i18n['screenshots,download.running']))
|
||||||
|
|
||||||
if len(self.screenshots) == 1:
|
if len(self.screenshots) == 1:
|
||||||
self.bt_back.setVisible(False)
|
self.bt_back.setVisible(False)
|
||||||
self.bt_next.setVisible(False)
|
self.bt_next.setVisible(False)
|
||||||
else:
|
else:
|
||||||
self.bt_back.setVisible(self.idx != 0)
|
self.bt_back.setEnabled(self.img_idx != 0)
|
||||||
self.bt_next.setVisible(self.idx != len(self.screenshots) - 1)
|
self.bt_next.setEnabled(self.img_idx != len(self.screenshots) - 1)
|
||||||
|
|
||||||
self.adjustSize()
|
self.adjustSize()
|
||||||
qt_utils.centralize(self)
|
qt_utils.centralize(self)
|
||||||
|
|
||||||
|
def _download_img(self, idx: int, url: str):
|
||||||
|
self.logger.info('Downloading image [{}] from {}'.format(idx, url))
|
||||||
|
res = self.http_client.get(url)
|
||||||
|
|
||||||
|
if res:
|
||||||
|
if not res.content:
|
||||||
|
self.logger.warning("Image [{}] from {} has no content".format(idx, url))
|
||||||
|
self.screenshots.append(self.i18n['screenshots.download.no_content'])
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.logger.info('Image [{}] successfully downloaded'.format(idx))
|
||||||
|
pixmap = QPixmap()
|
||||||
|
pixmap.loadFromData(res.content)
|
||||||
|
|
||||||
|
if pixmap.size().height() > self.MAX_HEIGHT or pixmap.size().width() > self.MAX_WIDTH:
|
||||||
|
pixmap = pixmap.scaled(self.MAX_WIDTH, self.MAX_HEIGHT, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||||||
|
|
||||||
|
self.loaded_imgs.append(pixmap)
|
||||||
|
|
||||||
|
if self.img_idx == idx:
|
||||||
|
self._load_img()
|
||||||
|
else:
|
||||||
|
self.logger.info("Could not retrieve image [{}] from {}".format(idx, url))
|
||||||
|
self.screenshots.append(self.i18n['screenshots.download.no_response'])
|
||||||
|
|
||||||
def back(self):
|
def back(self):
|
||||||
self.idx -= 1
|
self.img_idx -= 1
|
||||||
self._load_img()
|
self._load_img()
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
self.idx += 1
|
self.img_idx += 1
|
||||||
self._load_img()
|
self._load_img()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from threading import Thread
|
|
||||||
from typing import List, Type, Set
|
from typing import List, Type, Set
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from PyQt5.QtCore import QThread, pyqtSignal, Qt
|
from PyQt5.QtCore import QThread, pyqtSignal
|
||||||
from PyQt5.QtGui import QPixmap
|
|
||||||
|
|
||||||
from bauh.api.abstract.cache import MemoryCache
|
from bauh.api.abstract.cache import MemoryCache
|
||||||
from bauh.api.abstract.controller import SoftwareManager
|
from bauh.api.abstract.controller import SoftwareManager
|
||||||
@@ -486,42 +484,14 @@ class CustomAction(AsyncAction):
|
|||||||
|
|
||||||
|
|
||||||
class GetScreenshots(AsyncAction):
|
class GetScreenshots(AsyncAction):
|
||||||
MAX_HEIGHT = 600
|
|
||||||
MAX_WIDTH = 800
|
|
||||||
|
|
||||||
def __init__(self, manager: SoftwareManager, http_client: HttpClient, pkg: PackageView = None):
|
def __init__(self, manager: SoftwareManager, pkg: PackageView = None):
|
||||||
super(GetScreenshots, self).__init__()
|
super(GetScreenshots, self).__init__()
|
||||||
self.pkg = pkg
|
self.pkg = pkg
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
self.http_client = http_client
|
|
||||||
|
|
||||||
def _get_img(self, url: str, imgs: list):
|
|
||||||
res = self.http_client.get(url)
|
|
||||||
|
|
||||||
if res and res.status_code == 200 and res.content:
|
|
||||||
pixmap = QPixmap()
|
|
||||||
pixmap.loadFromData(res.content)
|
|
||||||
|
|
||||||
if pixmap.size().height() > self.MAX_HEIGHT or pixmap.size().width() > self.MAX_WIDTH:
|
|
||||||
pixmap = pixmap.scaled(self.MAX_WIDTH, self.MAX_HEIGHT, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
||||||
|
|
||||||
imgs.append(pixmap)
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if self.pkg:
|
if self.pkg:
|
||||||
imgs = []
|
self.notify_finished({'pkg': self.pkg, 'screenshots': self.manager.get_screenshots(self.pkg.model)})
|
||||||
screenshots = self.manager.get_screenshots(self.pkg.model)
|
|
||||||
|
|
||||||
if screenshots:
|
|
||||||
threads = []
|
|
||||||
for url in screenshots:
|
|
||||||
t = Thread(target=self._get_img, args=(url, imgs))
|
|
||||||
t.start()
|
|
||||||
threads.append(t)
|
|
||||||
|
|
||||||
for t in threads:
|
|
||||||
t.join()
|
|
||||||
|
|
||||||
self.notify_finished({'pkg': self.pkg, 'screenshots': imgs})
|
|
||||||
|
|
||||||
self.pkg = None
|
self.pkg = None
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import logging
|
||||||
import operator
|
import operator
|
||||||
import time
|
import time
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
@@ -51,9 +52,11 @@ class ManageWindow(QWidget):
|
|||||||
|
|
||||||
def __init__(self, i18n: dict, icon_cache: MemoryCache, manager: SoftwareManager, disk_cache: bool,
|
def __init__(self, i18n: dict, icon_cache: MemoryCache, manager: SoftwareManager, disk_cache: bool,
|
||||||
download_icons: bool, screen_size, suggestions: bool, display_limit: int, config: Configuration,
|
download_icons: bool, screen_size, suggestions: bool, display_limit: int, config: Configuration,
|
||||||
context: ApplicationContext, notifications: bool, http_client: HttpClient, tray_icon=None):
|
context: ApplicationContext, notifications: bool, http_client: HttpClient, logger: logging.Logger,
|
||||||
|
tray_icon=None):
|
||||||
super(ManageWindow, self).__init__()
|
super(ManageWindow, self).__init__()
|
||||||
self.i18n = i18n
|
self.i18n = i18n
|
||||||
|
self.logger = logger
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
self.tray_icon = tray_icon
|
self.tray_icon = tray_icon
|
||||||
self.working = False # restrict the number of threaded actions
|
self.working = False # restrict the number of threaded actions
|
||||||
@@ -227,7 +230,7 @@ class ManageWindow(QWidget):
|
|||||||
self.thread_suggestions = self._bind_async_action(FindSuggestions(man=self.manager), finished_call=self._finish_search, only_finished=True)
|
self.thread_suggestions = self._bind_async_action(FindSuggestions(man=self.manager), finished_call=self._finish_search, only_finished=True)
|
||||||
self.thread_run_app = self._bind_async_action(LaunchApp(self.manager), finished_call=self._finish_run_app, only_finished=False)
|
self.thread_run_app = self._bind_async_action(LaunchApp(self.manager), finished_call=self._finish_run_app, only_finished=False)
|
||||||
self.thread_custom_action = self._bind_async_action(CustomAction(manager=self.manager), finished_call=self._finish_custom_action)
|
self.thread_custom_action = self._bind_async_action(CustomAction(manager=self.manager), finished_call=self._finish_custom_action)
|
||||||
self.thread_screenshots = self._bind_async_action(GetScreenshots(self.manager, http_client), finished_call=self._finish_get_screenshots)
|
self.thread_screenshots = self._bind_async_action(GetScreenshots(self.manager), finished_call=self._finish_get_screenshots)
|
||||||
|
|
||||||
self.thread_apply_filters = ApplyFilters()
|
self.thread_apply_filters = ApplyFilters()
|
||||||
self.thread_apply_filters.signal_finished.connect(self._finish_apply_filters_async)
|
self.thread_apply_filters.signal_finished.connect(self._finish_apply_filters_async)
|
||||||
@@ -868,7 +871,12 @@ class ManageWindow(QWidget):
|
|||||||
self.finish_action()
|
self.finish_action()
|
||||||
|
|
||||||
if res.get('screenshots'):
|
if res.get('screenshots'):
|
||||||
diag = ScreenshotsDialog(pkg=res['pkg'], icon_cache=self.icon_cache, i18n=self.i18n, screenshots=res['screenshots'])
|
diag = ScreenshotsDialog(pkg=res['pkg'],
|
||||||
|
http_client=self.http_client,
|
||||||
|
icon_cache=self.icon_cache,
|
||||||
|
logger=self.logger,
|
||||||
|
i18n=self.i18n,
|
||||||
|
screenshots=res['screenshots'])
|
||||||
diag.exec_()
|
diag.exec_()
|
||||||
else:
|
else:
|
||||||
dialog.show_message(title=self.i18n['error'],
|
dialog.show_message(title=self.i18n['error'],
|
||||||
|
|||||||
@@ -134,3 +134,6 @@ screenshots.bt_back.label=previous
|
|||||||
instantmessaging=messaging
|
instantmessaging=messaging
|
||||||
2dgraphics=2d graphics
|
2dgraphics=2d graphics
|
||||||
vectorgraphics=vector graphics
|
vectorgraphics=vector graphics
|
||||||
|
screenshots,download.running=downloading image
|
||||||
|
screenshots.download.no_content=No content to display
|
||||||
|
screenshots.download.no_response=Image not found
|
||||||
@@ -171,3 +171,6 @@ screenshots.bt_back.label=anterior
|
|||||||
instantmessaging=mensajens
|
instantmessaging=mensajens
|
||||||
2dgraphics=gŕaficos 2d
|
2dgraphics=gŕaficos 2d
|
||||||
vectorgraphics=gráficos vectoriales
|
vectorgraphics=gráficos vectoriales
|
||||||
|
screenshots,download.running=descargando imagen
|
||||||
|
screenshots.download.no_content=No hay contenido para mostrar
|
||||||
|
screenshots.download.no_response=Imagen no encontrada
|
||||||
@@ -173,3 +173,6 @@ screenshots.bt_back.label=anterior
|
|||||||
instantmessaging=mensagens
|
instantmessaging=mensagens
|
||||||
2dgraphics=gŕaficos 2d
|
2dgraphics=gŕaficos 2d
|
||||||
vectorgraphics=gráficos vetoriais
|
vectorgraphics=gráficos vetoriais
|
||||||
|
screenshots,download.running=baixando imagem
|
||||||
|
screenshots.download.no_content=Sem conteúdo para exibir
|
||||||
|
screenshots.download.no_response=Imagem não encontrada
|
||||||
Reference in New Issue
Block a user