diff --git a/CHANGELOG.md b/CHANGELOG.md
index 562f0454..354bff3c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+- Snap
+ - new settings property **install_channel**: it allows to select an available channel during the application installation. Default: false.
+
+
+
+
+
+
+
### Improvements
- AppImage
diff --git a/README.md b/README.md
index cfa0039c..17fbbd61 100644
--- a/README.md
+++ b/README.md
@@ -120,6 +120,10 @@ installation_level: null # defines a default installation level: user or system.
- Supported actions: search, install, uninstall, launch, downgrade
- Custom actions: refresh
+- The configuration file is located at **~/.config/bauh/snap.yml** and it allows the following customizations:
+```
+install_channel: false # it allows to select an available channel during the application installation. Default: false
+```
- Required dependencies:
- Any distro: **snapd** ( it must be enabled after its installation. Details at https://snapcraft.io/docs/installing-snapd )
diff --git a/bauh/api/abstract/controller.py b/bauh/api/abstract/controller.py
index 67a61d29..deef917b 100644
--- a/bauh/api/abstract/controller.py
+++ b/bauh/api/abstract/controller.py
@@ -350,7 +350,7 @@ class SoftwareManager(ABC):
"""
pass
- def save_settings(self, component: ViewComponent) -> Tuple[bool, List[str]]:
+ def save_settings(self, component: ViewComponent) -> Tuple[bool, Optional[List[str]]]:
"""
:return: a tuple with a bool informing if the settings were saved and a list of error messages
"""
diff --git a/bauh/gems/appimage/controller.py b/bauh/gems/appimage/controller.py
index 686db47f..066c9708 100644
--- a/bauh/gems/appimage/controller.py
+++ b/bauh/gems/appimage/controller.py
@@ -723,7 +723,7 @@ class AppImageManager(SoftwareManager):
return PanelComponent([FormComponent(updater_opts, self.i18n['appimage.config.db_updates'])])
- def save_settings(self, component: PanelComponent) -> Tuple[bool, List[str]]:
+ def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
config = read_config()
panel = component.components[0]
diff --git a/bauh/gems/arch/controller.py b/bauh/gems/arch/controller.py
index 93f7876b..2dbc0573 100644
--- a/bauh/gems/arch/controller.py
+++ b/bauh/gems/arch/controller.py
@@ -2682,7 +2682,7 @@ class ArchManager(SoftwareManager):
return PanelComponent([FormComponent(fields, spaces=False)])
- def save_settings(self, component: PanelComponent) -> Tuple[bool, List[str]]:
+ def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
config = read_config()
form_install = component.components[0]
diff --git a/bauh/gems/flatpak/controller.py b/bauh/gems/flatpak/controller.py
index 81b86365..fc03d487 100644
--- a/bauh/gems/flatpak/controller.py
+++ b/bauh/gems/flatpak/controller.py
@@ -5,7 +5,7 @@ from datetime import datetime
from math import floor
from pathlib import Path
from threading import Thread
-from typing import List, Set, Type, Tuple
+from typing import List, Set, Type, Tuple, Optional
from bauh.api.abstract.controller import SearchResult, SoftwareManager, ApplicationContext, UpgradeRequirements, \
UpgradeRequirement, TransactionResult
@@ -570,7 +570,7 @@ class FlatpakManager(SoftwareManager):
return PanelComponent([FormComponent(fields, self.i18n['installation'].capitalize())])
- def save_settings(self, component: PanelComponent) -> Tuple[bool, List[str]]:
+ def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
config = read_config()
config['installation_level'] = component.components[0].components[0].get_selected()
diff --git a/bauh/gems/snap/__init__.py b/bauh/gems/snap/__init__.py
index bfd47893..0a3521c2 100644
--- a/bauh/gems/snap/__init__.py
+++ b/bauh/gems/snap/__init__.py
@@ -1,10 +1,11 @@
import os
-from bauh.api.constants import CACHE_PATH
+from bauh.api.constants import CACHE_PATH, CONFIG_PATH
from bauh.commons import resource
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
SNAP_CACHE_PATH = CACHE_PATH + '/snap'
+CONFIG_FILE = '{}/snap.yml'.format(CONFIG_PATH)
CATEGORIES_FILE_PATH = SNAP_CACHE_PATH + '/categories.txt'
URL_CATEGORIES_FILE = 'https://raw.githubusercontent.com/vinifmor/bauh-files/master/snap/categories.txt'
SUGGESTIONS_FILE = 'https://raw.githubusercontent.com/vinifmor/bauh-files/master/snap/suggestions.txt'
diff --git a/bauh/gems/snap/config.py b/bauh/gems/snap/config.py
new file mode 100644
index 00000000..99d87637
--- /dev/null
+++ b/bauh/gems/snap/config.py
@@ -0,0 +1,7 @@
+from bauh.commons.config import read_config as read
+from bauh.gems.snap import CONFIG_FILE
+
+
+def read_config(update_file: bool = False) -> dict:
+ template = {'install_channel': False}
+ return read(CONFIG_FILE, template, update_file=update_file)
diff --git a/bauh/gems/snap/controller.py b/bauh/gems/snap/controller.py
index 0bc67433..b241e287 100644
--- a/bauh/gems/snap/controller.py
+++ b/bauh/gems/snap/controller.py
@@ -2,7 +2,7 @@ import re
import time
import traceback
from threading import Thread
-from typing import List, Set, Type, Optional
+from typing import List, Set, Type, Optional, Tuple
from bauh.api.abstract.controller import SoftwareManager, SearchResult, ApplicationContext, UpgradeRequirements, \
TransactionResult
@@ -10,13 +10,17 @@ from bauh.api.abstract.disk import DiskCacheLoader
from bauh.api.abstract.handler import ProcessWatcher, TaskManager
from bauh.api.abstract.model import SoftwarePackage, PackageHistory, PackageUpdate, PackageSuggestion, \
SuggestionPriority, CustomSoftwareAction, PackageStatus
-from bauh.api.abstract.view import SingleSelectComponent, SelectViewType, InputOption
+from bauh.api.abstract.view import SingleSelectComponent, SelectViewType, InputOption, ViewComponent, PanelComponent, \
+ FormComponent
from bauh.commons import resource, internet
from bauh.commons.category import CategoriesDownloader
+from bauh.commons.config import save_config
from bauh.commons.html import bold
from bauh.commons.system import SystemProcess, ProcessHandler, new_root_subprocess, get_human_size_str
+from bauh.commons.view_utils import new_select
from bauh.gems.snap import snap, URL_CATEGORIES_FILE, SNAP_CACHE_PATH, CATEGORIES_FILE_PATH, SUGGESTIONS_FILE, \
- get_icon_path, snapd
+ get_icon_path, snapd, CONFIG_FILE
+from bauh.gems.snap.config import read_config
from bauh.gems.snap.model import SnapApplication
from bauh.gems.snap.snapd import SnapdClient
@@ -175,7 +179,20 @@ class SnapManager(SoftwareManager):
installed_names = {s['name'] for s in SnapdClient(self.logger).list_all_snaps()}
- res, output = ProcessHandler(watcher).handle_simple(snap.install_and_stream(pkg.name, pkg.confinement, root_password))
+ client = SnapdClient(self.logger)
+ snap_config = read_config()
+
+ try:
+ channel = self._request_channel_installation(pkg=pkg, snap_config=snap_config, snapd_client=client, watcher=watcher)
+ pkg.channel = channel
+ except:
+ watcher.print('Aborted by user')
+ return TransactionResult.fail()
+
+ res, output = ProcessHandler(watcher).handle_simple(snap.install_and_stream(app_name=pkg.name,
+ confinement=pkg.confinement,
+ root_password=root_password,
+ channel=channel))
if 'error:' in output:
res = False
@@ -247,6 +264,8 @@ class SnapManager(SoftwareManager):
task_man.finish_task('snap_cats')
def prepare(self, task_manager: TaskManager, root_password: str, internet_available: bool):
+ Thread(target=read_config, args=(True,), daemon=True).start()
+
CategoriesDownloader(id_='snap', manager=self, http_client=self.http_client, logger=self.logger,
url_categories_file=URL_CATEGORIES_FILE, disk_cache_dir=SNAP_CACHE_PATH,
categories_path=CATEGORIES_FILE_PATH,
@@ -382,3 +401,56 @@ class SnapManager(SoftwareManager):
def get_screenshots(self, pkg: SnapApplication) -> List[str]:
return pkg.screenshots if pkg.has_screenshots() else []
+
+ def get_settings(self, screen_width: int, screen_height: int) -> ViewComponent:
+ snap_config = read_config()
+
+ install_channel = new_select(label=self.i18n['snap.config.install_channel'],
+ opts=[(self.i18n['yes'].capitalize(), True, None),
+ (self.i18n['no'].capitalize(), False, None)],
+ value=bool(snap_config['install_channel']),
+ id_='install_channel',
+ max_width=200,
+ tip=self.i18n['snap.config.install_channel.tip'])
+
+ return PanelComponent([FormComponent([install_channel], self.i18n['installation'].capitalize())])
+
+ def save_settings(self, component: ViewComponent) -> Tuple[bool, Optional[List[str]]]:
+ config = read_config()
+ config['install_channel'] = component.components[0].components[0].get_selected()
+
+ try:
+ save_config(config, CONFIG_FILE)
+ return True, None
+ except:
+ return False, [traceback.format_exc()]
+
+ def _request_channel_installation(self, pkg: SnapApplication, snap_config: dict, snapd_client: SnapdClient, watcher: ProcessWatcher) -> Optional[str]:
+ if snap_config['install_channel']:
+ try:
+ data = [r for r in snapd_client.find_by_name(pkg.name) if r['name'] == pkg.name]
+ except:
+ self.logger.warning("snapd client could not retrieve channels for '{}'".format(pkg.name))
+ return
+
+ if not data:
+ self.logger.warning("snapd client could find a match for name '{}' when retrieving its channels".format(pkg.name))
+ else:
+ if not data[0].get('channels'):
+ self.logger.info("No channel available for '{}'. Skipping selection.".format(pkg.name))
+ else:
+ opts = [InputOption(label=c, value=c) for c in sorted(data[0]['channels'].keys())]
+ def_opt = [o for o in opts if o.value == 'latest/{}'.format(data[0].get('channel', 'stable'))]
+ select = SingleSelectComponent(label='',
+ options=opts,
+ default_option=def_opt[0] if def_opt else opts[0],
+ type_=SelectViewType.RADIO)
+
+ if not watcher.request_confirmation(title=self.i18n['snap.install.available_channels.title'],
+ body=self.i18n['snap.install.channel.body'] + ':',
+ components=[select],
+ confirmation_label=self.i18n['proceed'].capitalize(),
+ deny_label=self.i18n['cancel'].capitalize()):
+ raise Exception('aborted')
+ else:
+ return select.get_selected()
diff --git a/bauh/gems/snap/resources/locale/ca b/bauh/gems/snap/resources/locale/ca
index 935f9ae1..14c84ee5 100644
--- a/bauh/gems/snap/resources/locale/ca
+++ b/bauh/gems/snap/resources/locale/ca
@@ -2,6 +2,8 @@ gem.snap.info=Aplicacions publicades a https://snapcraft.io/store
snap.action.refresh.confirm=Actualitza {} ?
snap.action.refresh.label=Actualitza
snap.action.refresh.status=S’està actualitzant
+snap.config.install_channel=Display channels
+snap.config.install_channel.tip=It allows to select one of the available channels for the given application to be installed
snap.info.channel=channel
snap.info.commands=ordres
snap.info.contact=contacte
@@ -18,6 +20,7 @@ snap.info.version=versió
snap.install.available_channels.help=Seleccioneu-ne un si voleu continuar
snap.install.available_channels.message=No hi ha un canal {} (stable) disponible per a {}. Però més avall n’hi ha els següents
snap.install.available_channels.title=Canals disponibles
+snap.install.channel.body=Select a channel to proceed
snap.notification.snap.disable=Si no voleu utilitzar aplicacions snap, desmarqueu {} a {}
snap.notification.snapd_unavailable=Sembla que no s’ha iniciat o activat {}. Els paquets {} no estaran disponibles.
snap.notifications.api.unavailable=Sembla que l’API de {} no està disponible en aquests moments. No podreu cercar aplicacions {} noves.
\ No newline at end of file
diff --git a/bauh/gems/snap/resources/locale/de b/bauh/gems/snap/resources/locale/de
index 7a672965..ed62a619 100644
--- a/bauh/gems/snap/resources/locale/de
+++ b/bauh/gems/snap/resources/locale/de
@@ -2,6 +2,8 @@ gem.snap.info=Anwendungen von https://snapcraft.io/store
snap.action.refresh.confirm=Erneuern {} ?
snap.action.refresh.label=Erneuern
snap.action.refresh.status=Erneuern
+snap.config.install_channel=Display channels
+snap.config.install_channel.tip=It allows to select one of the available channels for the given application to be installed
snap.info.channel=channel
snap.info.commands=Kommandos
snap.info.contact=Kontakt
@@ -18,6 +20,7 @@ snap.info.version=Version
snap.install.available_channels.help=Wähle einen aus um fortzufahren
snap.install.available_channels.message=Es ist kein {} Channel verfügbar für {}. Es gibt jedoch folgende
snap.install.available_channels.title=Verfügbare Channels
+snap.install.channel.body=Select a channel to proceed
snap.notification.snap.disable=Um keine Snap Anwerndungen zu nutzen deaktivieren {} unter {}
snap.notification.snapd_unavailable={} wurde nicht gestartet oder ist deaktiviert. {} Pakete werden nicht verfügbar sein.
snap.notifications.api.unavailable=Es scheint als ob die {} API aktuell nicht verfügbar ist. Die Suche nach neuen {} Anwendungen ist nicht möglich.
\ No newline at end of file
diff --git a/bauh/gems/snap/resources/locale/en b/bauh/gems/snap/resources/locale/en
index 46ed39d0..185466fb 100644
--- a/bauh/gems/snap/resources/locale/en
+++ b/bauh/gems/snap/resources/locale/en
@@ -2,6 +2,8 @@ gem.snap.info=Applications published at https://snapcraft.io/store
snap.action.refresh.confirm=Refresh {} ?
snap.action.refresh.label=Refresh
snap.action.refresh.status=Refreshing
+snap.config.install_channel=Display channels
+snap.config.install_channel.tip=It allows to select one of the available channels for the given application to be installed
snap.info.channel=channel
snap.info.commands=commands
snap.info.contact=contact
@@ -18,6 +20,7 @@ snap.info.version=version
snap.install.available_channels.help=Select one if you want to continue
snap.install.available_channels.message=There is no {} channel available for {}. But there are these below
snap.install.available_channels.title=Available channels
+snap.install.channel.body=Select a channel to proceed
snap.notification.snap.disable=If you do not want to use Snap applications, uncheck {} in {}
snap.notification.snapd_unavailable={} seems not to be started or enabled. {} packages will not be available.
snap.notifications.api.unavailable=It seems the {} API is unavailable at the moment. It will not be possible to search for new {} applications.
\ No newline at end of file
diff --git a/bauh/gems/snap/resources/locale/es b/bauh/gems/snap/resources/locale/es
index d2d612f3..cfd58062 100644
--- a/bauh/gems/snap/resources/locale/es
+++ b/bauh/gems/snap/resources/locale/es
@@ -2,6 +2,8 @@ gem.snap.info=Aplicativos publicados en https://snapcraft.io/store
snap.action.refresh.confirm=Actualizar {} ?
snap.action.refresh.label=Actualizar
snap.action.refresh.status=Actualizando
+snap.config.install_channel=Mostrar canales
+snap.config.install_channel.tip=Permite seleccionar uno de los canales disponibles para la aplicación a instalar
snap.info.channel=canal
snap.info.commands=comandos
snap.info.contact=contacto
@@ -18,6 +20,7 @@ snap.info.version=versión
snap.install.available_channels.help=Seleccione uno si desea continuar
snap.install.available_channels.message=No hay un canal {} ( stable ) disponible para {}. Pero hay estos otros abajo
snap.install.available_channels.title=Canales disponibles
+snap.install.channel.body=Seleccione un canal para continuar
snap.notification.snap.disable=Si no desea usar aplicativos Snap, desmarque {} en {}
snap.notification.snapd_unavailable={} parece no estar inicializado o habilitado. Los paquetes {} estarán indisponibles.
snap.notifications.api.unavailable=Parece que la API de {} no está disponible en este momento. No será posible buscar nuevos aplicativos {}.
\ No newline at end of file
diff --git a/bauh/gems/snap/resources/locale/it b/bauh/gems/snap/resources/locale/it
index 254cfadc..a5448426 100644
--- a/bauh/gems/snap/resources/locale/it
+++ b/bauh/gems/snap/resources/locale/it
@@ -2,6 +2,8 @@ gem.snap.info=Applicazioni pubblicate su https://snapcraft.io/store
snap.action.refresh.confirm=Ripristina {} ?
snap.action.refresh.label=Ripristina
snap.action.refresh.status=Ripristinare
+snap.config.install_channel=Display channels
+snap.config.install_channel.tip=It allows to select one of the available channels for the given application to be installed
snap.info.channel=channel
snap.info.commands=commands
snap.info.contact=contact
@@ -18,6 +20,7 @@ snap.info.version=version
snap.install.available_channels.help=Selezionane uno se vuoi continuare
snap.install.available_channels.message=Non esiste un {} canale disponibile per {}. Ma ci sono questi sotto
snap.install.available_channels.title=Canali disponibili
+snap.install.channel.body=Select a channel to proceed
snap.notification.snap.disable=Se non si desidera utilizzare le applicazioni Snap, deselezionare {} in {}
snap.notification.snapd_unavailable={} sembra non essere avviato o abilitato. {} i pacchetti non saranno disponibili.
snap.notifications.api.unavailable=Sembra che l'API {} non sia al momento disponibile. Non sarà possibile cercare nuove {} applicazioni.
\ No newline at end of file
diff --git a/bauh/gems/snap/resources/locale/pt b/bauh/gems/snap/resources/locale/pt
index 54fafa34..415175f9 100644
--- a/bauh/gems/snap/resources/locale/pt
+++ b/bauh/gems/snap/resources/locale/pt
@@ -2,6 +2,8 @@ gem.snap.info=Aplicativos publicados em https://snapcraft.io/store
snap.action.refresh.confirm=Atualizar {} ?
snap.action.refresh.label=Atualizar
snap.action.refresh.status=Atualizando
+snap.config.install_channel=Exibir canais
+snap.config.install_channel.tip=Permite-se selecionar um dos canais disponíveis para o aplicativo a ser instalado
snap.info.channel=canal
snap.info.commands=comandos
snap.info.contact=contato
@@ -18,6 +20,7 @@ snap.info.version=versão
snap.install.available_channels.help=Selecione algum se quiser continuar
snap.install.available_channels.message=Não há um canal {} ( stable ) disponível para {}. Porém existem estes outros abaixo
snap.install.available_channels.title=Canais disponíveis
+snap.install.channel.body=Selecione um canal para continuar
snap.notification.snap.disable=Se não deseja usar aplicativos Snap, desmarque {} em {}
snap.notification.snapd_unavailable={} parece não estar inicializado ou habilitado. Os pacotes {} estarão indisponíveis.
snap.notifications.api.unavailable=Parece que a API de {} está indisponível no momento. Não será possível buscar novos aplicativos {}.
\ No newline at end of file
diff --git a/bauh/gems/snap/resources/locale/ru b/bauh/gems/snap/resources/locale/ru
index 76fc3d96..747292d2 100644
--- a/bauh/gems/snap/resources/locale/ru
+++ b/bauh/gems/snap/resources/locale/ru
@@ -2,6 +2,8 @@ gem.snap.info=Приложения, опубликованные на https://sn
snap.action.refresh.confirm=Обновить {} ?
snap.action.refresh.label=Обновить
snap.action.refresh.status=Обновляется
+snap.config.install_channel=Display channels
+snap.config.install_channel.tip=It allows to select one of the available channels for the given application to be installed
snap.info.channel=channel
snap.info.commands=Команды
snap.info.contact=Контакт
@@ -18,6 +20,7 @@ snap.info.version=Версия
snap.install.available_channels.help=Выберите один, если вы хотите продолжить
snap.install.available_channels.message=Нет одного канала {}, доступного для {}. Но есть такие ниже
snap.install.available_channels.title=Доступные каналы
+snap.install.channel.body=Select a channel to proceed
snap.notification.snap.disable=Если вы не хотите использовать приложения Snap, снимите флажок {} в {}
snap.notification.snapd_unavailable={} кажется, не запускается и не включается. {} пакеты будут недоступны.
snap.notifications.api.unavailable=Похоже, что API {} в данный момент недоступен. Невозможно будет искать новые приложения {}.
\ No newline at end of file
diff --git a/bauh/gems/snap/resources/locale/tr b/bauh/gems/snap/resources/locale/tr
index 9799d921..9b0861a3 100644
--- a/bauh/gems/snap/resources/locale/tr
+++ b/bauh/gems/snap/resources/locale/tr
@@ -2,6 +2,8 @@ gem.snap.info=https://snapcraft.io/store adresinde yayınlanan uygulamalar
snap.action.refresh.confirm=Yenile {} ?
snap.action.refresh.label=Yenile
snap.action.refresh.status=Yenileniyor
+snap.config.install_channel=Display channels
+snap.config.install_channel.tip=It allows to select one of the available channels for the given application to be installed
snap.info.channel=channel
snap.info.commands=komutlar
snap.info.contact=iletişim
@@ -18,6 +20,7 @@ snap.info.version=sürüm
snap.install.available_channels.help=Devam etmek istiyorsanız birini seçin
snap.install.available_channels.message={} için hiçbir {} kanalı yok. Ama aşağıda bunlar var
snap.install.available_channels.title=Kullanılabilir kanallar
+snap.install.channel.body=Select a channel to proceed
snap.notification.snap.disable=Snap uygulamalarını kullanmak istemiyorsanız, {} içindeki {} işaretini kaldırın
snap.notification.snapd_unavailable={} başlatılmamış veya etkinleştirilmemiş gibi görünüyor. {} paketler mevcut olmayacak.
snap.notifications.api.unavailable=Görünüşe göre {} API şu anda kullanılamıyor. Yeni {} uygulamaları aramak mümkün olmayacak.
diff --git a/bauh/gems/snap/snap.py b/bauh/gems/snap/snap.py
index 0558df23..244f61cd 100644
--- a/bauh/gems/snap/snap.py
+++ b/bauh/gems/snap/snap.py
@@ -1,7 +1,7 @@
import os
import subprocess
from io import StringIO
-from typing import Tuple
+from typing import Tuple, Optional
from bauh.commons.system import run_cmd, SimpleProcess
@@ -18,13 +18,16 @@ def uninstall_and_stream(app_name: str, root_password: str) -> SimpleProcess:
shell=True)
-def install_and_stream(app_name: str, confinement: str, root_password: str) -> SimpleProcess:
+def install_and_stream(app_name: str, confinement: str, root_password: str, channel: Optional[str] = None) -> SimpleProcess:
install_cmd = [BASE_CMD, 'install', app_name] # default
if confinement == 'classic':
install_cmd.append('--classic')
+ if channel:
+ install_cmd.append('--channel={}'.format(channel))
+
return SimpleProcess(install_cmd, root_password=root_password, shell=True)
diff --git a/bauh/gems/web/controller.py b/bauh/gems/web/controller.py
index 6361aec2..bfc0bfad 100644
--- a/bauh/gems/web/controller.py
+++ b/bauh/gems/web/controller.py
@@ -9,7 +9,7 @@ import traceback
from math import floor
from pathlib import Path
from threading import Thread
-from typing import List, Type, Set, Tuple
+from typing import List, Type, Set, Tuple, Optional
import requests
import yaml
@@ -996,7 +996,7 @@ class WebApplicationManager(SoftwareManager):
return PanelComponent([form_env])
- def save_settings(self, component: PanelComponent) -> Tuple[bool, List[str]]:
+ def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
config = read_config()
form_env = component.components[0]
diff --git a/bauh/view/qt/components.py b/bauh/view/qt/components.py
index e247b12a..1e827cba 100644
--- a/bauh/view/qt/components.py
+++ b/bauh/view/qt/components.py
@@ -266,6 +266,7 @@ class RadioButtonQt(QRadioButton):
self.model = model
self.model_parent = model_parent
self.toggled.connect(self._set_checked)
+ self.setCursor(QCursor(Qt.PointingHandCursor))
if model.icon_path:
if model.icon_path.startswith('/'):