[appimage] improvement -> manual file installation: trying to auto-fill the 'Name' and 'Version' fields

This commit is contained in:
Vinicius Moreira
2020-08-11 15:38:30 -03:00
parent 244d48f18a
commit ae721f6eea
4 changed files with 78 additions and 15 deletions

View File

@@ -7,7 +7,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [0.9.7] 2020
### Improvements
- AppImage
- Manual file installation default search path set to '~/Downloads'
- Manual file installation:
- default search path set to '~/Downloads'
- trying to auto-fill the 'Name' and 'Version' fields
- Arch
- upgrade summary: displaying the reason a given package must be installed
<p align="center">

View File

@@ -1,6 +1,6 @@
from abc import ABC
from enum import Enum
from typing import List, Set
from typing import List, Set, Optional
class MessageType:
@@ -9,12 +9,22 @@ class MessageType:
ERROR = 2
class ViewObserver:
def on_change(self, change):
pass
class ViewComponent(ABC):
"""
Represents a GUI component
"""
def __init__(self, id_: str):
def __init__(self, id_: str, observers: List[ViewObserver] = None):
self.id = id_
self.observers = observers if observers else []
def add_observer(self, obs):
self.observers.append(obs)
class SpacerComponent(ViewComponent):
@@ -157,6 +167,14 @@ class TextInputComponent(ViewComponent):
else:
return ''
def set_value(self, val: Optional[str], caller: object = None):
self.value = val
if self.observers:
for o in self.observers:
if caller != o:
o.on_change(val)
def get_int_value(self) -> int:
if self.value is not None:
val = self.value.strip() if isinstance(self.value, str) else self.value
@@ -191,6 +209,13 @@ class FileChooserComponent(ViewComponent):
self.max_width = max_width
self.search_path = search_path
def set_file_path(self, fpath: str):
self.file_path = fpath
if self.observers:
for o in self.observers:
o.on_change(self.file_path)
class TabComponent(ViewComponent):

View File

@@ -23,7 +23,7 @@ from bauh.api.abstract.handler import ProcessWatcher, TaskManager
from bauh.api.abstract.model import SoftwarePackage, PackageHistory, PackageUpdate, PackageSuggestion, \
SuggestionPriority, CustomSoftwareAction
from bauh.api.abstract.view import MessageType, ViewComponent, FormComponent, InputOption, SingleSelectComponent, \
SelectViewType, TextInputComponent, PanelComponent, FileChooserComponent
SelectViewType, TextInputComponent, PanelComponent, FileChooserComponent, ViewObserver
from bauh.commons import resource
from bauh.commons.config import save_config
from bauh.commons.html import bold
@@ -42,6 +42,28 @@ DESKTOP_ENTRIES_PATH = '{}/.local/share/applications'.format(str(Path.home()))
RE_DESKTOP_EXEC = re.compile(r'Exec\s*=\s*.+\n')
RE_DESKTOP_ICON = re.compile(r'Icon\s*=\s*.+\n')
RE_ICON_ENDS_WITH = re.compile(r'.+\.(png|svg)$')
RE_APPIMAGE_NAME = re.compile(r'(.+)\.appimage', flags=re.IGNORECASE)
class ManualInstallationFileObserver(ViewObserver):
def __init__(self, name: TextInputComponent, version: TextInputComponent):
self.name = name
self.version = version
def on_change(self, file_path: str):
if file_path:
name_found = RE_APPIMAGE_NAME.findall(file_path.split('/')[-1])
if name_found:
name_split = name_found[0].split('-')
self.name.set_value(name_split[0].strip())
if len(name_split) > 1:
self.version.set_value(name_split[1].strip())
else:
self.name.set_value(None)
self.version.set_value(None)
class AppImageManager(SoftwareManager):
@@ -74,9 +96,13 @@ class AppImageManager(SoftwareManager):
if not os.path.isdir(default_path):
default_path = None
file_chooser = FileChooserComponent(label=self.i18n['file'].capitalize(), allowed_extensions={'AppImage'}, search_path=default_path)
file_chooser = FileChooserComponent(label=self.i18n['file'].capitalize(),
allowed_extensions={'AppImage'},
search_path=default_path)
input_name = TextInputComponent(label=self.i18n['name'].capitalize())
input_version = TextInputComponent(label=self.i18n['version'].capitalize())
file_chooser.observers.append(ManualInstallationFileObserver(input_name, input_version))
input_description = TextInputComponent(label=self.i18n['description'].capitalize())
cat_ops = [InputOption(label=self.i18n['category.none'].capitalize(), value=0)]

View File

@@ -11,7 +11,7 @@ from PyQt5.QtWidgets import QRadioButton, QGroupBox, QCheckBox, QComboBox, QGrid
from bauh.api.abstract.view import SingleSelectComponent, InputOption, MultipleSelectComponent, SelectViewType, \
TextInputComponent, FormComponent, FileChooserComponent, ViewComponent, TabGroupComponent, PanelComponent, \
TwoStateButtonComponent, TextComponent, SpacerComponent, RangeInputComponent
TwoStateButtonComponent, TextComponent, SpacerComponent, RangeInputComponent, ViewObserver
from bauh.view.qt import css
from bauh.view.qt.colors import RED
from bauh.view.util import resource
@@ -428,6 +428,15 @@ class ComboSelectQt(QGroupBox):
self.layout().addWidget(FormComboBoxQt(model), 0, 1)
class QLineEditObserver(QLineEdit, ViewObserver):
def __init__(self, **kwargs):
super(QLineEditObserver, self).__init__(**kwargs)
def on_change(self, change: str):
self.setText(change if change is not None else '')
class TextInputQt(QGroupBox):
def __init__(self, model: TextInputComponent):
@@ -440,7 +449,7 @@ class TextInputQt(QGroupBox):
if self.model.max_width > 0:
self.setMaximumWidth(self.model.max_width)
self.text_input = QLineEdit()
self.text_input = QLineEditObserver()
if model.only_int:
self.text_input.setValidator(QIntValidator())
@@ -457,10 +466,11 @@ class TextInputQt(QGroupBox):
self.text_input.textChanged.connect(self._update_model)
self.model.observers.append(self.text_input)
self.layout().addWidget(self.text_input, 0, 1)
def _update_model(self, text: str):
self.model.value = text
self.model.set_value(val=text, caller=self)
class MultipleSelectQt(QGroupBox):
@@ -754,7 +764,7 @@ class FormQt(QGroupBox):
return tip_icon
def _new_text_input(self, c: TextInputComponent) -> Tuple[QLabel, QLineEdit]:
line_edit = QLineEdit()
line_edit = QLineEditObserver()
if c.only_int:
line_edit.setValidator(QIntValidator())
@@ -773,9 +783,10 @@ class FormQt(QGroupBox):
line_edit.setEnabled(False)
def update_model(text: str):
c.value = text
c.set_value(val=text, caller=line_edit)
line_edit.textChanged.connect(update_model)
c.observers.append(line_edit)
label = QWidget()
label.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
@@ -819,7 +830,7 @@ class FormQt(QGroupBox):
return field_container
def _new_file_chooser(self, c: FileChooserComponent) -> Tuple[QLabel, QLineEdit]:
chooser = QLineEdit()
chooser = QLineEditObserver()
chooser.setReadOnly(True)
if c.max_width > 0:
@@ -828,6 +839,7 @@ class FormQt(QGroupBox):
if c.file_path:
chooser.setText(c.file_path)
c.observers.append(chooser)
chooser.setPlaceholderText(self.i18n['view.components.file_chooser.placeholder'])
def open_chooser(e):
@@ -848,14 +860,12 @@ class FormQt(QGroupBox):
file_path, _ = QFileDialog.getOpenFileName(self, self.i18n['file_chooser.title'], cur_path, exts, options=options)
if file_path:
c.file_path = file_path
chooser.setText(file_path)
c.set_file_path(file_path)
chooser.setCursorPosition(0)
def clean_path():
c.file_path = None
chooser.setText('')
c.set_file_path(None)
chooser.mousePressEvent = open_chooser