[wgem] adding category

This commit is contained in:
Vinícius Moreira
2019-12-13 16:35:00 -03:00
parent 7a3df32471
commit 174349cf5b
17 changed files with 156 additions and 59 deletions

View File

@@ -36,6 +36,8 @@ class ApplicationContext:
self.file_downloader = file_downloader self.file_downloader = file_downloader
self.arch_x86_64 = sys.maxsize > 2**32 self.arch_x86_64 = sys.maxsize > 2**32
self.distro = distro self.distro = distro
self.default_categories = ('AudioVideo', 'Audio', 'Video', 'Development', 'Education', 'Game',
'Graphics', 'Network', 'Office', 'Science', 'Settings', 'System', 'Utility')
def is_system_x86_64(self): def is_system_x86_64(self):
return self.arch_x86_64 return self.arch_x86_64

View File

@@ -5,6 +5,8 @@ from abc import ABC, abstractmethod
from pathlib import Path from pathlib import Path
from typing import List, Set, Type from typing import List, Set, Type
import yaml
from bauh.api.abstract.context import ApplicationContext from bauh.api.abstract.context import ApplicationContext
from bauh.api.abstract.disk import DiskCacheLoader from bauh.api.abstract.disk import DiskCacheLoader
from bauh.api.abstract.handler import ProcessWatcher from bauh.api.abstract.handler import ProcessWatcher
@@ -178,8 +180,15 @@ class SoftwareManager(ABC):
data = pkg.get_data_to_cache() data = pkg.get_data_to_cache()
if data: if data:
with open(pkg.get_disk_data_path(), 'w+') as f: disk_path = pkg.get_disk_data_path()
ext = disk_path.split('.')[-1]
if ext == 'json':
with open(disk_path, 'w+') as f:
f.write(json.dumps(data)) f.write(json.dumps(data))
elif ext in ('yml', 'yaml'):
with open(disk_path, 'w+') as f:
f.write(yaml.dump(data))
if icon_bytes: if icon_bytes:
Path(pkg.get_disk_cache_path()).mkdir(parents=True, exist_ok=True) Path(pkg.get_disk_cache_path()).mkdir(parents=True, exist_ok=True)

View File

@@ -67,7 +67,7 @@ class SingleSelectComponent(InputViewComponent):
self.value = default_option self.value = default_option
self.max_per_line = max_per_line self.max_per_line = max_per_line
def get_selected_value(self): def get_selected(self):
if self.value: if self.value:
return self.value.value return self.value.value
@@ -102,12 +102,13 @@ class TextComponent(ViewComponent):
class TextInputComponent(ViewComponent): class TextInputComponent(ViewComponent):
def __init__(self, label: str, value: str = '', placeholder: str = None, tooltip: str = None, id_: str = None): def __init__(self, label: str, value: str = '', placeholder: str = None, tooltip: str = None, read_only: bool =False, id_: str = None):
super(TextInputComponent, self).__init__(id_=id_) super(TextInputComponent, self).__init__(id_=id_)
self.label = label self.label = label
self.value = value self.value = value
self.tooltip = tooltip self.tooltip = tooltip
self.placeholder = placeholder self.placeholder = placeholder
self.read_only = read_only
def get_value(self) -> str: def get_value(self) -> str:
if self.value is not None: if self.value is not None:

View File

@@ -16,7 +16,7 @@ class HttpClient:
self.sleep = sleep self.sleep = sleep
self.logger = logger self.logger = logger
def get(self, url: str, params: dict = None, headers: dict = None, allow_redirects: bool = True, ignore_ssl: bool = False): def get(self, url: str, params: dict = None, headers: dict = None, allow_redirects: bool = True, ignore_ssl: bool = False, single_call: bool = False):
cur_attempts = 1 cur_attempts = 1
while cur_attempts <= self.max_attempts: while cur_attempts <= self.max_attempts:
@@ -39,6 +39,9 @@ class HttpClient:
if res.status_code == 200: if res.status_code == 200:
return res return res
if single_call:
return
if self.sleep > 0: if self.sleep > 0:
time.sleep(self.sleep) time.sleep(self.sleep)
except Exception as e: except Exception as e:

View File

@@ -1,5 +1,4 @@
import glob import glob
import json
import locale import locale
import os import os
import re import re
@@ -11,6 +10,8 @@ from pathlib import Path
from threading import Thread from threading import Thread
from typing import List, Type, Set, Tuple from typing import List, Type, Set, Tuple
import yaml
from bauh.api.abstract.context import ApplicationContext from bauh.api.abstract.context import ApplicationContext
from bauh.api.abstract.controller import SoftwareManager, SearchResult from bauh.api.abstract.controller import SoftwareManager, SearchResult
from bauh.api.abstract.disk import DiskCacheLoader from bauh.api.abstract.disk import DiskCacheLoader
@@ -39,6 +40,7 @@ except:
RE_PROTOCOL_STRIP = re.compile(r'[a-zA-Z]+://') RE_PROTOCOL_STRIP = re.compile(r'[a-zA-Z]+://')
RE_SEVERAL_SPACES = re.compile(r'\s+') RE_SEVERAL_SPACES = re.compile(r'\s+')
RE_SYMBOLS_SPLIT = re.compile(r'[\-|_\s]')
class WebApplicationManager(SoftwareManager): class WebApplicationManager(SoftwareManager):
@@ -70,13 +72,10 @@ class WebApplicationManager(SoftwareManager):
name = name_tag.text.strip() if name_tag else None name = name_tag.text.strip() if name_tag else None
if not name: if not name:
name = url_no_protocol.split('.')[0] name = url_no_protocol.split('.')[0].strip()
if name: if name:
name = name.replace('|', '').replace('_', ' ') name = RE_SYMBOLS_SPLIT.split(name)[0].strip()
if ' ' in name:
name = RE_SEVERAL_SPACES.sub(' ', name)
return name return name
@@ -115,7 +114,7 @@ class WebApplicationManager(SoftwareManager):
if installed_matches: if installed_matches:
res.installed.extend(installed_matches) res.installed.extend(installed_matches)
else: else:
url_res = self.http_client.get(url, headers={'Accept-language': self._get_lang_header()}, ignore_ssl=True) url_res = self.http_client.get(url, headers={'Accept-language': self._get_lang_header()}, ignore_ssl=True, single_call=True)
if url_res: if url_res:
soup = BeautifulSoup(url_res.text, 'lxml', parse_only=SoupStrainer('head')) soup = BeautifulSoup(url_res.text, 'lxml', parse_only=SoupStrainer('head'))
@@ -149,9 +148,9 @@ class WebApplicationManager(SoftwareManager):
res = SearchResult([], [], 0) res = SearchResult([], [], 0)
if os.path.exists(INSTALLED_PATH): if os.path.exists(INSTALLED_PATH):
for data_path in glob.glob('{}/*/*data.json'.format(INSTALLED_PATH)): for data_path in glob.glob('{}/*/*data.yml'.format(INSTALLED_PATH)):
with open(data_path, 'r') as f: with open(data_path, 'r') as f:
res.installed.append(WebApplication(installed=True, **json.loads(f.read()))) res.installed.append(WebApplication(installed=True, **yaml.safe_load(f.read())))
res.total += 1 res.total += 1
return res return res
@@ -199,12 +198,15 @@ class WebApplicationManager(SoftwareManager):
def get_info(self, pkg: WebApplication) -> dict: def get_info(self, pkg: WebApplication) -> dict:
if pkg.installed: if pkg.installed:
info = {'{}_{}'.format(idx + 1, att): getattr(pkg, att) for idx, att in enumerate(('url', 'description', 'version', 'installation_dir', 'desktop_entry'))} info = {'{}_{}'.format(idx + 1, att): getattr(pkg, att) for idx, att in enumerate(('url', 'description', 'version', 'categories', 'installation_dir', 'desktop_entry'))}
info['6_exec_file'] = pkg.get_exec_path() info['7_exec_file'] = pkg.get_exec_path()
info['7_icon_path'] = pkg.get_disk_icon_path() info['8_icon_path'] = pkg.get_disk_icon_path()
if os.path.exists(pkg.installation_dir): if os.path.exists(pkg.installation_dir):
info['8_size'] = get_human_size_str(get_dir_size(pkg.installation_dir)) info['9_size'] = get_human_size_str(get_dir_size(pkg.installation_dir))
if info.get('4_categories'):
info['4_categories'] = [self.i18n[c.lower()].capitalize() for c in info['4_categories']]
return info return info
@@ -214,9 +216,15 @@ class WebApplicationManager(SoftwareManager):
def _ask_install_options(self, app: WebApplication, watcher: ProcessWatcher) -> Tuple[bool, List[str]]: def _ask_install_options(self, app: WebApplication, watcher: ProcessWatcher) -> Tuple[bool, List[str]]:
watcher.change_substatus(self.i18n['web.install.substatus.options']) watcher.change_substatus(self.i18n['web.install.substatus.options'])
inp_url = TextInputComponent(label=self.i18n['address'], value=app.url, read_only=True)
inp_name = TextInputComponent(label=self.i18n['name'], value=app.name) inp_name = TextInputComponent(label=self.i18n['name'], value=app.name)
inp_desc = TextInputComponent(label=self.i18n['description'], value=app.description) inp_desc = TextInputComponent(label=self.i18n['description'], value=app.description)
cat_ops = [InputOption(label=self.i18n['web.install.option.category.none'].capitalize(), value=0)]
cat_ops.extend([InputOption(label=self.i18n[c.lower()].capitalize(), value=c) for c in self.context.default_categories])
inp_cat = SingleSelectComponent(label=self.i18n['category'], type_=SelectViewType.COMBO, options=cat_ops, default_option=cat_ops[0])
tray_op_off = InputOption(label=self.i18n['web.install.option.tray.off.label'], value=0, tooltip=self.i18n['web.install.option.tray.off.tip']) tray_op_off = InputOption(label=self.i18n['web.install.option.tray.off.label'], value=0, tooltip=self.i18n['web.install.option.tray.off.tip'])
tray_op_default = InputOption(label=self.i18n['web.install.option.tray.default.label'], value='--tray', tooltip=self.i18n['web.install.option.tray.default.tip']) tray_op_default = InputOption(label=self.i18n['web.install.option.tray.default.label'], value='--tray', tooltip=self.i18n['web.install.option.tray.default.tip'])
tray_op_min = InputOption(label=self.i18n['web.install.option.tray.min.label'], value='--tray=start-in-tray', tooltip=self.i18n['web.install.option.tray.min.tip']) tray_op_min = InputOption(label=self.i18n['web.install.option.tray.min.label'], value='--tray=start-in-tray', tooltip=self.i18n['web.install.option.tray.min.tip'])
@@ -225,7 +233,7 @@ class WebApplicationManager(SoftwareManager):
options=[tray_op_off, tray_op_default, tray_op_min], options=[tray_op_off, tray_op_default, tray_op_min],
label=self.i18n['web.install.option.tray.label']) label=self.i18n['web.install.option.tray.label'])
form_1 = FormComponent(components=[inp_name, inp_desc, inp_tray]) form_1 = FormComponent(components=[inp_url, inp_name, inp_desc, inp_cat, inp_tray])
op_single = InputOption(id_='single', label=self.i18n['web.install.option.single.label'], value="--single-instance", tooltip=self.i18n['web.install.option.single.tip']) op_single = InputOption(id_='single', label=self.i18n['web.install.option.single.label'], value="--single-instance", tooltip=self.i18n['web.install.option.single.tip'])
op_max = InputOption(id_='max', label=self.i18n['web.install.option.max.label'], value="--maximize", tooltip=self.i18n['web.install.option.max.tip']) op_max = InputOption(id_='max', label=self.i18n['web.install.option.max.label'], value="--maximize", tooltip=self.i18n['web.install.option.max.tip'])
@@ -238,11 +246,10 @@ class WebApplicationManager(SoftwareManager):
check_options = MultipleSelectComponent(options=[op_single, op_allow_urls, op_max, op_fs, op_nframe, op_ncache, op_insecure, op_igcert], default_options={op_single}, label='') check_options = MultipleSelectComponent(options=[op_single, op_allow_urls, op_max, op_fs, op_nframe, op_ncache, op_insecure, op_igcert], default_options={op_single}, label='')
bt_continue = self.i18n['continue'].capitalize()
res = watcher.request_confirmation(title=self.i18n['web.install.options_dialog.title'], res = watcher.request_confirmation(title=self.i18n['web.install.options_dialog.title'],
body=self.i18n['web.install.options_dialog.body'].format(bold(bt_continue)), body=None,
components=[form_1, check_options], components=[form_1, check_options],
confirmation_label=bt_continue, confirmation_label=self.i18n['continue'].capitalize(),
deny_label=self.i18n['cancel'].capitalize()) deny_label=self.i18n['cancel'].capitalize())
if res: if res:
@@ -251,7 +258,7 @@ class WebApplicationManager(SoftwareManager):
if check_options.values: if check_options.values:
selected.extend(check_options.get_selected_values()) selected.extend(check_options.get_selected_values())
tray_mode = inp_tray.get_selected_value() tray_mode = inp_tray.get_selected()
if tray_mode is not None and tray_mode != 0: if tray_mode is not None and tray_mode != 0:
selected.append(tray_mode) selected.append(tray_mode)
@@ -265,6 +272,11 @@ class WebApplicationManager(SoftwareManager):
if custom_desc: if custom_desc:
app.description = inp_desc.get_value() app.description = inp_desc.get_value()
cat = inp_cat.get_selected()
if cat != 0:
app.categories = [cat]
return res, selected return res, selected
return False, [] return False, []
@@ -385,12 +397,13 @@ class WebApplicationManager(SoftwareManager):
[Desktop Entry] [Desktop Entry]
Type=Application Type=Application
Name={name} ( web ) Name={name} ( web )
Categories=Applications;
Comment={desc} Comment={desc}
Icon={icon} Icon={icon}
Exec={exec_path} Exec={exec_path}
{categories}
""".format(name=pkg.name, exec_path=pkg.get_exec_path(), """.format(name=pkg.name, exec_path=pkg.get_exec_path(),
desc=pkg.description or pkg.url, icon=pkg.get_disk_icon_path()) desc=pkg.description or pkg.url, icon=pkg.get_disk_icon_path(),
categories='Categories={}'.format(';'.join(pkg.categories)) if pkg.categories else '')
def is_enabled(self) -> bool: def is_enabled(self) -> bool:
return self.enabled return self.enabled

View File

@@ -1,4 +1,5 @@
import re import re
from typing import List
from bauh.api.abstract.model import SoftwarePackage from bauh.api.abstract.model import SoftwarePackage
from bauh.commons import resource from bauh.commons import resource
@@ -8,9 +9,11 @@ from bauh.gems.web import ROOT_DIR
class WebApplication(SoftwarePackage): class WebApplication(SoftwarePackage):
def __init__(self, id: str = None, url: str = None, name: str = None, description: str = None, icon_url: str = None, def __init__(self, id: str = None, url: str = None, name: str = None, description: str = None, icon_url: str = None,
installation_dir: str = None, desktop_entry: str = None, installed: bool = False, version: str = None): installation_dir: str = None, desktop_entry: str = None, installed: bool = False, version: str = None,
categories: List[str] = None):
super(WebApplication, self).__init__(id=id if id else url, name=name, description=description, super(WebApplication, self).__init__(id=id if id else url, name=name, description=description,
icon_url=icon_url, installed=installed, version=version) icon_url=icon_url, installed=installed, version=version,
categories=categories)
self.url = url self.url = url
self.installation_dir = installation_dir self.installation_dir = installation_dir
self.desktop_entry = desktop_entry self.desktop_entry = desktop_entry
@@ -23,7 +26,7 @@ class WebApplication(SoftwarePackage):
@staticmethod @staticmethod
def _get_cached_attrs() -> tuple: def _get_cached_attrs() -> tuple:
return 'id', 'name', 'version', 'url', 'description', 'icon_url', 'installation_dir', 'desktop_entry' return 'id', 'name', 'version', 'url', 'description', 'icon_url', 'installation_dir', 'desktop_entry', 'categories'
def can_be_downgraded(self): def can_be_downgraded(self):
return False return False
@@ -41,6 +44,9 @@ class WebApplication(SoftwarePackage):
def get_default_icon_path(self) -> str: def get_default_icon_path(self) -> str:
return resource.get_path('img/web.png', ROOT_DIR) return resource.get_path('img/web.png', ROOT_DIR)
def get_disk_data_path(self):
return '{}/data.yml'.format(self.get_disk_cache_path())
def is_application(self): def is_application(self):
return True return True

View File

@@ -1,10 +1,9 @@
gem.web.info=It allows to install Web applications on your system gem.web.info=It allows to install Web applications on the system through they addresses ( URLs )
web.environment.install=Installing {} web.environment.install=Installing {}
web.waiting.env_updater=Updating environment web.waiting.env_updater=Updating environment
web.env.checking=Checking the Web installation environment web.env.checking=Checking the Web installation environment
web.env.error=It seems there are issues with the Web installation environment. It wil not be possible to install {}. web.env.error=It seems there are issues with the Web installation environment. It wil not be possible to install {}.
web.install.options_dialog.title=Installation options web.install.options_dialog.title=Installation options
web.install.options_dialog.body=Select the wanted installation options and click in the {} button
web.install.error=An error has happened during the {} installation web.install.error=An error has happened during the {} installation
web.install.nativefier.error.unknown=Have a look at the {} to identify the reason web.install.nativefier.error.unknown=Have a look at the {} to identify the reason
web.install.nativefier.error.inner_dir=The app installation directory was not found in {} web.install.nativefier.error.inner_dir=The app installation directory was not found in {}
@@ -35,13 +34,15 @@ web.install.option.tray.default.label=Default
web.install.option.tray.default.tip=The app icon will be attached to the system tray allowing it to be quickly opened web.install.option.tray.default.tip=The app icon will be attached to the system tray allowing it to be quickly opened
web.install.option.tray.min.label=Start minimized web.install.option.tray.min.label=Start minimized
web.install.option.tray.min.tip=The app will be started minimized as an icon in the system tray web.install.option.tray.min.tip=The app will be started minimized as an icon in the system tray
web.install.option.category.none=none
web.uninstall.error.install_dir.not_found=The installation directory {} was not found web.uninstall.error.install_dir.not_found=The installation directory {} was not found
web.uninstall.error.remove_dir=It was not possible to remove {} web.uninstall.error.remove_dir=It was not possible to remove {}
web.info.1_url=URL web.info.1_url=URL
web.info.2_description=description web.info.2_description=description
web.info.3_version=version web.info.3_version=version
web.info.4_installation_dir=installation dir web.info.4_categories=categories
web.info.5_desktop_entry=shortcut web.info.5_installation_dir=installation dir
web.info.6_exec_file=executable web.info.6_desktop_entry=shortcut
web.info.7_icon_path=icon web.info.7_exec_file=executable
web.info.8_size=size web.info.8_icon_path=icon
web.info.9_size=size

View File

@@ -1,10 +1,9 @@
gem.web.info=Permite instalar aplicações Web no seu sistema gem.web.info=Permite instalar aplicações Web no seu sistema através dos seus endereços ( URLs )
web.environment.nativefier=Instalando {} web.environment.nativefier=Instalando {}
web.waiting.env_updater=Atualizando ambiente web.waiting.env_updater=Atualizando ambiente
web.env.checking=Verificando o ambiente de instalação Web web.env.checking=Verificando o ambiente de instalação Web
web.env.error=Parce que existem problemas com o ambiente de instalação Web. Não será possível instalar {}. web.env.error=Parce que existem problemas com o ambiente de instalação Web. Não será possível instalar {}.
web.install.options_dialog.title=Opções de instalação web.install.options_dialog.title=Opções de instalação
web.install.options_dialog.body=Selecione as opções de instalação desejadas e clique no botão {}
wen.install.error=Ocorreu um erro durante a instalação de {} wen.install.error=Ocorreu um erro durante a instalação de {}
web.install.nativefier.error.unknown=Dê uma olhada em {} para identificar o motivo web.install.nativefier.error.unknown=Dê uma olhada em {} para identificar o motivo
web.install.nativefier.error.inner_dir=O diretório de instalação do aplicativo não foi encontrado em {} web.install.nativefier.error.inner_dir=O diretório de instalação do aplicativo não foi encontrado em {}
@@ -35,13 +34,15 @@ web.install.option.tray.default.label=Padrão
web.install.option.tray.default.tip=O ícone do aplicativo será anexado a bandeja do sistema permitindo que o mesma seja rapidamente aberto web.install.option.tray.default.tip=O ícone do aplicativo será anexado a bandeja do sistema permitindo que o mesma seja rapidamente aberto
web.install.option.tray.min.label=Iniciar minimizado web.install.option.tray.min.label=Iniciar minimizado
web.install.option.tray.min.tip=O aplicativo será iniciado minimizado como um ícone da bandeja do sistema web.install.option.tray.min.tip=O aplicativo será iniciado minimizado como um ícone da bandeja do sistema
web.install.option.category.none=nenhuma
web.uninstall.error.install_dir.not_found=O diretório de instalação {} não foi encontrado web.uninstall.error.install_dir.not_found=O diretório de instalação {} não foi encontrado
web.uninstall.error.remove=Não foi possível remover {} web.uninstall.error.remove=Não foi possível remover {}
web.info.1_url=URL web.info.1_url=URL
web.info.2_description=descrição web.info.2_description=descrição
web.info.3_version=versão web.info.3_version=versão
web.info.4_installation_dir=diretório de instalação web.info.4_categories=categorias
web.info.5_desktop_entry=atalho web.info.5_installation_dir=diretório de instalação
web.info.6_exec_file=executável web.info.6_desktop_entry=atalho
web.info.7_icon_path=ícone web.info.7_exec_file=executável
web.info.8_size=tamanho web.info.8_icon_path=ícone
web.info.9_size=tamanho

View File

@@ -277,6 +277,9 @@ class FormQt(QGroupBox):
line_edit.setText(c.value) line_edit.setText(c.value)
line_edit.setCursorPosition(0) line_edit.setCursorPosition(0)
if c.read_only:
line_edit.setEnabled(False)
def update_model(text: str): def update_model(text: str):
c.value = text c.value = text

View File

@@ -1,12 +1,12 @@
from typing import List from typing import List
from PyQt5.QtCore import QSize from PyQt5.QtCore import QSize, Qt
from PyQt5.QtWidgets import QMessageBox, QVBoxLayout, QLabel, QWidget, QScrollArea, QFrame from PyQt5.QtWidgets import QMessageBox, QVBoxLayout, QLabel, QWidget, QScrollArea, QFrame
from bauh.api.abstract.view import ViewComponent, SingleSelectComponent, MultipleSelectComponent, TextInputComponent, \ from bauh.api.abstract.view import ViewComponent, SingleSelectComponent, MultipleSelectComponent, TextInputComponent, \
FormComponent FormComponent
from bauh.view.qt import css from bauh.view.qt import css
from bauh.view.qt.components import MultipleSelectQt, new_single_select, TextInputQt, FormQt from bauh.view.qt.components import MultipleSelectQt, new_single_select, TextInputQt, FormQt, new_spacer
from bauh.view.util.translation import I18n from bauh.view.util.translation import I18n
@@ -28,6 +28,7 @@ class ConfirmationDialog(QMessageBox):
self.layout().addWidget(QLabel(body), 0, 1) self.layout().addWidget(QLabel(body), 0, 1)
width = 0
if components: if components:
scroll = QScrollArea(self) scroll = QScrollArea(self)
scroll.setFrameShape(QFrame.NoFrame) scroll.setFrameShape(QFrame.NoFrame)
@@ -52,13 +53,21 @@ class ConfirmationDialog(QMessageBox):
raise Exception("Cannot render instances of " + comp.__class__.__name__) raise Exception("Cannot render instances of " + comp.__class__.__name__)
height += inst.sizeHint().height() height += inst.sizeHint().height()
if inst.sizeHint().width() > width:
width = inst.sizeHint().width()
comps_container.layout().addWidget(inst) comps_container.layout().addWidget(inst)
height = height if height < int(screen_size.height() / 2.5) else int(screen_size.height() / 2.5) height = height if height < int(screen_size.height() / 2.5) else int(screen_size.height() / 2.5)
scroll.setFixedHeight(height) scroll.setFixedHeight(height)
self.layout().addWidget(scroll, 1, 1) self.layout().addWidget(scroll, 1, 1)
if not body and width > 0:
self.layout().addWidget(QLabel(' ' * int(width / 2)), 0, 1)
self.exec_() self.exec_()
def is_confirmed(self): def is_confirmed(self):

View File

@@ -174,12 +174,14 @@ texteditor=editor de text
server=servidor server=servidor
cloud=núvol cloud=núvol
instantmessaging=missatgeria instantmessaging=missatgeria
messaging=missatgeria
2dgraphics=gràfics 2d 2dgraphics=gràfics 2d
vectorgraphics=gràfics vectorials vectorgraphics=gràfics vectorials
office=oficina office=oficina
devices=dispositius devices=dispositius
security=seguretat security=seguretat
audiovideo=àudio/vídeo audiovideo=àudio/vídeo
audio=àudio
amusement=diversió amusement=diversió
webdevelopment=desenvolupament web webdevelopment=desenvolupament web
filetransfer=transferència de fitxers filetransfer=transferència de fitxers
@@ -203,3 +205,7 @@ emulator=emulador
do_not.install=no instal·leu do_not.install=no instal·leu
repository=dipòsit repository=dipòsit
details=detalls details=detalls
communication=comunicació
administration=administració
settings=configuració
address=adreça

View File

@@ -137,9 +137,11 @@ texteditor=Texteditor
screenshots.bt_next.label=Weiter screenshots.bt_next.label=Weiter
screenshots.bt_back.label=Zurück screenshots.bt_back.label=Zurück
instantmessaging=Kommunikation instantmessaging=Kommunikation
messaging=messaging
2dgraphics=2d Grafik 2dgraphics=2d Grafik
vectorgraphics=Vectorgrafik vectorgraphics=Vectorgrafik
audiovideo=Audio / Video audiovideo=Audio / Video
audio=audio
webdevelopment=Webentwicklung webdevelopment=Webentwicklung
filetransfer=Dateiübertragung filetransfer=Dateiübertragung
packagemanager=Paketmanager packagemanager=Paketmanager
@@ -157,3 +159,7 @@ emulator=emulator
do_not.install=nicht installieren do_not.install=nicht installieren
repository=repository repository=repository
details=details details=details
communication=Kommunikation
administration=Verwaltung
settings=Einstellungen
address=Adresse

View File

@@ -158,3 +158,11 @@ emulator=emulator
do_not.install=don't install do_not.install=don't install
repository=repository repository=repository
details=details details=details
communication=communication
web=web
office=office
messaging=messaging
administration=administration
audio=audio
settings=settings
address=address

View File

@@ -174,12 +174,14 @@ texteditor=editor de texto
server=servidor server=servidor
cloud=nube cloud=nube
instantmessaging=mensajería instantmessaging=mensajería
messaging=mensajería
2dgraphics=gráficos 2d 2dgraphics=gráficos 2d
vectorgraphics=gráficos vectoriales vectorgraphics=gráficos vectoriales
office=oficina office=oficina
devices=dispositivos devices=dispositivos
security=seguridad security=seguridad
audiovideo=audio y vídeo audiovideo=audio y vídeo
audio=audio
amusement=diversión amusement=diversión
webdevelopment=desarrollo web webdevelopment=desarrollo web
filetransfer=transferencia de archivos filetransfer=transferencia de archivos
@@ -202,3 +204,7 @@ emulator=emulador
do_not.install=no instalar do_not.install=no instalar
repository=repositorio repository=repositorio
details=detalles details=detalles
communication=comunicación
administration=administración
settings=configuraciones
address=dirección

View File

@@ -137,9 +137,11 @@ texteditor=editor di testo
screenshots.bt_next.label=prossimo screenshots.bt_next.label=prossimo
screenshots.bt_back.label=precedente screenshots.bt_back.label=precedente
instantmessaging=messaggistica instantmessaging=messaggistica
messaging=messaggistica
2dgraphics=Grafica 2D 2dgraphics=Grafica 2D
vectorgraphics=grafica vettoriale vectorgraphics=grafica vettoriale
audiovideo=audio / video audiovideo=audio / video
audio=audio
webdevelopment=sviluppo web webdevelopment=sviluppo web
filetransfer=trasferimento di file filetransfer=trasferimento di file
packagemanager=gestore pacchetti packagemanager=gestore pacchetti
@@ -158,3 +160,7 @@ emulator=emulatore
do_not.install=non installare do_not.install=non installare
repository=deposito repository=deposito
details=dettagli details=dettagli
communication=comunicazione
administration=amministrazione
settings=impostazioni
address=indirizzo

View File

@@ -172,16 +172,18 @@ news=notícias
weather=tempo weather=tempo
finance=finanças finance=finanças
desktopsettings=configurações desktopsettings=configurações
settings=configurações
texteditor=editor de texto texteditor=editor de texto
server=servidor server=servidor
cloud=nuvem cloud=nuvem
instantmessaging=mensagens instantmessaging=mensagem
2dgraphics=gŕaficos 2d 2dgraphics=gŕaficos 2d
vectorgraphics=gráficos vetoriais vectorgraphics=gráficos vetoriais
office=escritório office=escritório
devices=dispositivos devices=dispositivos
security=segurança security=segurança
audiovideo=áudio / vídeo audiovideo=áudio / vídeo
audio=áudio
amusement=diversão amusement=diversão
webdevelopment=desenvolvimento web webdevelopment=desenvolvimento web
filetransfer=transferência de arquivos filetransfer=transferência de arquivos
@@ -205,3 +207,7 @@ emulator=emulador
do_not.install=não instalar do_not.install=não instalar
repository=repositório repository=repositório
details=detalhes details=detalhes
communication=comunicação
messaging=mensagem
administration=administração
address=endereço

View File

@@ -5,6 +5,8 @@ import time
from threading import Thread, Lock from threading import Thread, Lock
from typing import Type, Dict from typing import Type, Dict
import yaml
from bauh.api.abstract.cache import MemoryCache from bauh.api.abstract.cache import MemoryCache
from bauh.api.abstract.disk import DiskCacheLoader, DiskCacheLoaderFactory from bauh.api.abstract.disk import DiskCacheLoader, DiskCacheLoaderFactory
from bauh.api.abstract.model import SoftwarePackage from bauh.api.abstract.model import SoftwarePackage
@@ -52,11 +54,20 @@ class AsyncDiskCacheLoader(Thread, DiskCacheLoader):
def _fill_cached_data(self, pkg: SoftwarePackage) -> bool: def _fill_cached_data(self, pkg: SoftwarePackage) -> bool:
if self.enabled: if self.enabled:
if os.path.exists(pkg.get_disk_data_path()): if os.path.exists(pkg.get_disk_data_path()):
with open(pkg.get_disk_data_path()) as f: disk_path = pkg.get_disk_data_path()
ext = disk_path.split('.')[-1]
with open(disk_path) as f:
if ext == 'json':
cached_data = json.loads(f.read()) cached_data = json.loads(f.read())
elif ext in {'yml', 'yaml'}:
cached_data = yaml.load(f.read())
else:
raise Exception('The cached data file {} has an unsupported format'.format(disk_path))
if cached_data: if cached_data:
pkg.fill_cached_data(cached_data) pkg.fill_cached_data(cached_data)
cache = self.cache_map.get(pkg.__class__)\ cache = self.cache_map.get(pkg.__class__)
if cache: if cache:
cache.add_non_existing(pkg.id, cached_data) cache.add_non_existing(pkg.id, cached_data)