From 7a3df32471c6c2538ae54b23adbe42354f91b101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Moreira?= Date: Fri, 13 Dec 2019 13:28:23 -0300 Subject: [PATCH] [view] FormComponent --- bauh/api/abstract/view.py | 8 ++++++ bauh/gems/web/controller.py | 27 ++++++++++++------ bauh/gems/web/resources/locale/en | 4 +-- bauh/gems/web/resources/locale/pt | 4 +-- bauh/view/qt/components.py | 46 +++++++++++++++++++++++++++++-- bauh/view/qt/confirmation.py | 7 +++-- 6 files changed, 80 insertions(+), 16 deletions(-) diff --git a/bauh/api/abstract/view.py b/bauh/api/abstract/view.py index ea01ded6..5b80de10 100644 --- a/bauh/api/abstract/view.py +++ b/bauh/api/abstract/view.py @@ -114,3 +114,11 @@ class TextInputComponent(ViewComponent): return self.value.strip() else: return '' + + +class FormComponent(ViewComponent): + + def __init__(self, components: List[ViewComponent], label: str = None, id_: str = None): + super(FormComponent, self).__init__(id_=id_) + self.label = label + self.components = components diff --git a/bauh/gems/web/controller.py b/bauh/gems/web/controller.py index 0dfd01a5..7a046cc3 100644 --- a/bauh/gems/web/controller.py +++ b/bauh/gems/web/controller.py @@ -17,7 +17,7 @@ from bauh.api.abstract.disk import DiskCacheLoader from bauh.api.abstract.handler import ProcessWatcher from bauh.api.abstract.model import SoftwarePackage, PackageAction, PackageSuggestion, PackageUpdate, PackageHistory from bauh.api.abstract.view import MessageType, MultipleSelectComponent, InputOption, SingleSelectComponent, \ - SelectViewType, TextInputComponent + SelectViewType, TextInputComponent, FormComponent from bauh.commons.html import bold from bauh.commons.system import ProcessHandler, get_dir_size, get_human_size_str from bauh.gems.web import INSTALLED_PATH, nativefier, DESKTOP_ENTRY_PATH_PATTERN, URL_FIX_PATTERN @@ -215,6 +215,17 @@ class WebApplicationManager(SoftwareManager): watcher.change_substatus(self.i18n['web.install.substatus.options']) inp_name = TextInputComponent(label=self.i18n['name'], value=app.name) + inp_desc = TextInputComponent(label=self.i18n['description'], value=app.description) + + 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_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']) + + inp_tray = SingleSelectComponent(type_=SelectViewType.COMBO, + options=[tray_op_off, tray_op_default, tray_op_min], + label=self.i18n['web.install.option.tray.label']) + + form_1 = FormComponent(components=[inp_name, inp_desc, 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_max = InputOption(id_='max', label=self.i18n['web.install.option.max.label'], value="--maximize", tooltip=self.i18n['web.install.option.max.tip']) @@ -225,17 +236,12 @@ class WebApplicationManager(SoftwareManager): op_insecure = InputOption(id_='insecure', label=self.i18n['web.install.option.insecure.label'], value="--insecure", tooltip=self.i18n['web.install.option.insecure.tip']) op_igcert = InputOption(id_='ignore_certs', label=self.i18n['web.install.option.ignore_certificate.label'], value="--ignore-certificate", tooltip=self.i18n['web.install.option.ignore_certificate.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_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']) - 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='') - input_tray = SingleSelectComponent(type_=SelectViewType.COMBO, options=[tray_op_off, tray_op_default, tray_op_min], label=self.i18n['web.install.option.tray.label']) bt_continue = self.i18n['continue'].capitalize() res = watcher.request_confirmation(title=self.i18n['web.install.options_dialog.title'], body=self.i18n['web.install.options_dialog.body'].format(bold(bt_continue)), - components=[inp_name, check_options, input_tray], + components=[form_1, check_options], confirmation_label=bt_continue, deny_label=self.i18n['cancel'].capitalize()) @@ -245,7 +251,7 @@ class WebApplicationManager(SoftwareManager): if check_options.values: selected.extend(check_options.get_selected_values()) - tray_mode = input_tray.get_selected_value() + tray_mode = inp_tray.get_selected_value() if tray_mode is not None and tray_mode != 0: selected.append(tray_mode) @@ -254,6 +260,11 @@ class WebApplicationManager(SoftwareManager): if custom_name: app.name = custom_name + custom_desc = inp_desc.get_value() + + if custom_desc: + app.description = inp_desc.get_value() + return res, selected return False, [] diff --git a/bauh/gems/web/resources/locale/en b/bauh/gems/web/resources/locale/en index 850a094b..6eb0e588 100644 --- a/bauh/gems/web/resources/locale/en +++ b/bauh/gems/web/resources/locale/en @@ -12,14 +12,14 @@ web.install.substatus.call_nativefier=Running {} web.install.substatus.shortcut=Generating a menu shortcut web.install.substatus.options=Waiting for the installation options web.install.substatus.checking_fixes=Checking if there are published fixes -web.install.option.single.label=Single +web.install.option.single.label=Single run web.install.option.single.tip=It will not allow the app to be opened again if it is already opened web.install.option.max.label=Open maximized web.install.option.max.tip=If the app should always be opened maximized web.install.option.fullscreen.label=Open in fullscreen web.install.option.fullscreen.tip=If the app should always be opened in fullscreen ( the Alt key opens the upper menu ) web.install.option.noframe.label=No frame -web.install.option.noframe.tip=If the app should not have a frame around it ( like browsers have ) +web.install.option.noframe.tip=If the app should not have a frame ( like browsers have ) web.install.option.nocache.label=No cache web.install.option.nocache.tip=Session data will not be stored after the app is closed web.install.option.insecure.label=Allow insecure content diff --git a/bauh/gems/web/resources/locale/pt b/bauh/gems/web/resources/locale/pt index 9b31b5b4..a6b625a9 100644 --- a/bauh/gems/web/resources/locale/pt +++ b/bauh/gems/web/resources/locale/pt @@ -12,14 +12,14 @@ web.install.substatus.call_nativefier=Executando {} web.install.substatus.shortcut=Criando um atalho no menu web.install.substatus.options=Aguardando as opções de instalação web.install.substatus.checking_fixes=Verificando se há correções publicadas -web.install.option.single.label=Único +web.install.option.single.label=Execução única web.install.option.single.tip=Não permitirá que o aplicativo seja aberto novamente caso o mesmo já esteja web.install.option.max.label=Abrir maximizado web.install.option.max.tip=Se o aplicativo deve sempre ser aberto maximizado web.install.option.fullscreen.label=Abrir em tela cheia web.install.option.fullscreen.tip=Se o aplicativo sempre deve ser aberto em tela cheia ( a tecla Alt abre o menu superior ) web.install.option.noframe.label=Sem moldura -web.install.option.noframe.tip=Se o aplicativo não deve ter uma moldura em volta ( como os navegadores têm ) +web.install.option.noframe.tip=Se o aplicativo não deve ter uma moldura ( como presente nos navegadores ) web.install.option.nocache.label=Sem cache web.install.option.nocache.tip=Dados de sessão não serão armazenados após o aplicativo ser fechado web.install.option.insecure.label=Permitir conteúdo não confiável diff --git a/bauh/view/qt/components.py b/bauh/view/qt/components.py index 03c1dd6b..ef48c916 100644 --- a/bauh/view/qt/components.py +++ b/bauh/view/qt/components.py @@ -1,10 +1,12 @@ +from typing import Tuple + from PyQt5.QtCore import Qt from PyQt5.QtGui import QIcon, QPixmap from PyQt5.QtWidgets import QRadioButton, QGroupBox, QCheckBox, QComboBox, QGridLayout, QWidget, \ - QLabel, QSizePolicy, QLineEdit, QToolButton, QHBoxLayout + QLabel, QSizePolicy, QLineEdit, QToolButton, QHBoxLayout, QFormLayout from bauh.api.abstract.view import SingleSelectComponent, InputOption, MultipleSelectComponent, SelectViewType, \ - TextInputComponent + TextInputComponent, FormComponent from bauh.view.util import resource @@ -135,6 +137,7 @@ class TextInputQt(QGroupBox): if model.value: self.text_input.setText(model.value) + self.text_input.setCursorPosition(0) self.text_input.textChanged.connect(self._update_model) @@ -242,6 +245,45 @@ class IconButton(QWidget): self.setLayout(layout) +class FormQt(QGroupBox): + + def __init__(self, model: FormComponent): + super(FormQt, self).__init__() + self.model = model + self.setLayout(QFormLayout()) + self.setStyleSheet('QLabel { font-weight: bold; }') + + for c in model.components: + if isinstance(c, TextInputComponent): + label, field = self._new_text_input(c) + self.layout().addRow(label, field) + elif isinstance(c, SingleSelectComponent): + label = QLabel(c.label.capitalize() + ':' if c.label else '') + field = ComboBoxQt(c) + self.layout().addRow(label, field) + else: + raise Exception('Unsupported component type {}'.format(c.__class__.__name__)) + + def _new_text_input(self, c: TextInputComponent) -> Tuple[QLabel, QLineEdit]: + line_edit = QLineEdit() + + if c.tooltip: + line_edit.setToolTip(c.tooltip) + + if c.placeholder: + line_edit.setPlaceholderText(c.placeholder) + + if c.value: + line_edit.setText(c.value) + line_edit.setCursorPosition(0) + + def update_model(text: str): + c.value = text + + line_edit.textChanged.connect(update_model) + return QLabel(c.label.capitalize() + ':' if c.label else ''), line_edit + + def new_single_select(model: SingleSelectComponent): if model.type == SelectViewType.RADIO: return RadioSelectQt(model) diff --git a/bauh/view/qt/confirmation.py b/bauh/view/qt/confirmation.py index 654a6d84..f53894df 100644 --- a/bauh/view/qt/confirmation.py +++ b/bauh/view/qt/confirmation.py @@ -3,9 +3,10 @@ from typing import List from PyQt5.QtCore import QSize 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 from bauh.view.qt import css -from bauh.view.qt.components import MultipleSelectQt, new_single_select, TextInputQt +from bauh.view.qt.components import MultipleSelectQt, new_single_select, TextInputQt, FormQt from bauh.view.util.translation import I18n @@ -45,6 +46,8 @@ class ConfirmationDialog(QMessageBox): inst = MultipleSelectQt(comp, None) elif isinstance(comp, TextInputComponent): inst = TextInputQt(comp) + elif isinstance(comp, FormComponent): + inst = FormQt(comp) else: raise Exception("Cannot render instances of " + comp.__class__.__name__)