import shutil import subprocess from collections.abc import Iterable from subprocess import Popen from typing import Optional from PyQt5.QtCore import Qt from PyQt5.QtGui import QIcon, QCursor from PyQt5.QtWidgets import QDialog, QVBoxLayout, QGroupBox, \ QLineEdit, QLabel, QGridLayout, QPushButton, QPlainTextEdit, QScrollArea, QFrame, QWidget, QSizePolicy, \ QHBoxLayout from bauh.api.abstract.cache import MemoryCache from bauh.commons.regex import RE_URL from bauh.view.qt.components import new_spacer from bauh.view.qt.qt_utils import get_current_screen_geometry from bauh.view.util.translation import I18n IGNORED_ATTRS = {'name', '__app__'} class InfoDialog(QDialog): def __init__(self, pkg_info: dict, icon_cache: MemoryCache, i18n: I18n, can_open_url: bool): super(InfoDialog, self).__init__() self.setWindowTitle(str(pkg_info['__app__'])) self.i18n = i18n self._can_open_url = can_open_url layout = QVBoxLayout() self.setLayout(layout) scroll = QScrollArea(self) scroll.setFrameShape(QFrame.NoFrame) scroll.setWidgetResizable(True) comps_container = QWidget() comps_container.setObjectName('root_container') comps_container.setLayout(QVBoxLayout()) scroll.setWidget(comps_container) # shows complete field string self.text_field = QPlainTextEdit() self.text_field.setObjectName('full_field') self.text_field.setReadOnly(True) comps_container.layout().addWidget(self.text_field) self.text_field.hide() self.gbox_info = QGroupBox() self.gbox_info.setObjectName('fields') self.gbox_info.setLayout(QGridLayout()) comps_container.layout().addWidget(self.gbox_info) # THERE ARE CRASHES WITH SOME RARE ICONS ( like insomnia ). IT CAN BE A QT BUG. IN THE MEANTIME, ONLY THE TYPE ICON WILL BE RENDERED # # icon_data = icon_cache.get(app['__app__'].model.icon_url) # # if icon_data and icon_data.get('icon'): # self.setWindowIcon(icon_data.get('icon')) self.setWindowIcon(QIcon(pkg_info['__app__'].model.get_type_icon_path())) for idx, attr in enumerate(sorted(pkg_info.keys())): if attr not in IGNORED_ATTRS and pkg_info[attr] is not None: i18n_key = pkg_info['__app__'].model.gem_name + '.info.' + attr.lower() val = pkg_info[attr] if not isinstance(val, str) and isinstance(pkg_info[attr], Iterable): val = ' '.join([str(e).strip() for e in pkg_info[attr] if e]) show_val = '\n'.join(['* ' + str(e).strip() for e in pkg_info[attr] if e]) else: val = str(pkg_info[attr]).strip() show_val = val i18n_val = i18n.get(f"{i18n_key}.{val.lower()}") if i18n_val: val = i18n_val show_val = val text = QLineEdit() text.setObjectName('field_value') text.setToolTip(show_val) text.setText(val) text.setCursorPosition(0) text.setReadOnly(True) label = QLabel(i18n.get(i18n_key, i18n.get(attr.lower(), attr)).capitalize()) label.setObjectName('field_name') self.gbox_info.layout().addWidget(label, idx, 0) self.gbox_info.layout().addWidget(text, idx, 1) self._gen_show_button(idx=idx, val=show_val) layout.addWidget(scroll) lower_container = QWidget() lower_container.setObjectName('lower_container') lower_container.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) lower_container.setLayout(QHBoxLayout()) self.bt_back = QPushButton('< {}'.format(self.i18n['back'].capitalize())) self.bt_back.setObjectName('back') self.bt_back.setVisible(False) self.bt_back.setCursor(QCursor(Qt.PointingHandCursor)) self.bt_back.clicked.connect(self.back_to_info) lower_container.layout().addWidget(self.bt_back) lower_container.layout().addWidget(new_spacer()) self.bt_close = QPushButton(self.i18n['close'].capitalize()) self.bt_close.setObjectName('close') self.bt_close.setCursor(QCursor(Qt.PointingHandCursor)) self.bt_close.clicked.connect(self.close) lower_container.layout().addWidget(self.bt_close) layout.addWidget(lower_container) self.setMinimumWidth(int(self.gbox_info.sizeHint().width() * 1.2)) screen_height = get_current_screen_geometry().height() self.setMaximumHeight(int(screen_height * 0.8)) self.adjustSize() @staticmethod def open_url(url: str): Popen(["xdg-open", url], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdin=subprocess.DEVNULL) def _show_full_field_val(self, val: str): self.gbox_info.hide() self.bt_back.setVisible(True) self.text_field.show() self.text_field.setPlainText(val) def _gen_show_button(self, idx: int, val: str): is_url = self._can_open_url and bool(RE_URL.match(val)) if val else False if is_url: bt_label = self.i18n["manage_window.info.open_url"] def _show_field(): self.open_url(val) else: bt_label = self.i18n["show"].capitalize() def _show_field(): self._show_full_field_val(val) bt_full_field = QPushButton(bt_label) bt_full_field.setObjectName("show") bt_full_field.setCursor(QCursor(Qt.PointingHandCursor)) bt_full_field.clicked.connect(_show_field) self.gbox_info.layout().addWidget(bt_full_field, idx, 2) def back_to_info(self): self.text_field.setPlainText("") self.text_field.hide() self.gbox_info.show() self.bt_back.setVisible(False)