mirror of
https://github.com/naruxde/revpicommander.git
synced 2025-11-08 08:33:52 +01:00
feat: Add open-source license viewer to help menu
If the application is built with the Target app*, all license information of the packages used is collected. These can now be viewed in the GUI in the help menu.
This commit is contained in:
Binary file not shown.
File diff suppressed because it is too large
Load Diff
84
src/revpicommander/oss_licenses.py
Normal file
84
src/revpicommander/oss_licenses.py
Normal file
@@ -0,0 +1,84 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Open-Source softwrae licenses."""
|
||||
__author__ = "Sven Sager"
|
||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||
__license__ = "GPLv2"
|
||||
|
||||
from json import load
|
||||
from logging import getLogger
|
||||
from os.path import exists
|
||||
from typing import List
|
||||
|
||||
from PyQt5 import QtCore, QtWidgets
|
||||
|
||||
from revpicommander.ui.oss_licenses_ui import Ui_diag_oss_licenses
|
||||
|
||||
log = getLogger(__name__)
|
||||
|
||||
|
||||
class OssLicenses(QtWidgets.QDialog, Ui_diag_oss_licenses):
|
||||
def __init__(self, oss_license_file: str, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self._lst_licenses: List[dict] = []
|
||||
self._oss_license_file = oss_license_file
|
||||
|
||||
self.action_start.setVisible(exists(oss_license_file))
|
||||
|
||||
def _load_license_file(self) -> None:
|
||||
if exists(self._oss_license_file):
|
||||
try:
|
||||
with open(self._oss_license_file) as fh:
|
||||
self._lst_licenses = load(fh)
|
||||
except Exception as e:
|
||||
log.error("Could not load oss license file: '{0}'".format(e))
|
||||
|
||||
for i in range(len(self._lst_licenses)):
|
||||
dict_license = self._lst_licenses[i]
|
||||
tb_item_name = QtWidgets.QTableWidgetItem(dict_license.get("Name", ""))
|
||||
tb_item_name.setData(QtCore.Qt.UserRole, i)
|
||||
tb_item_license = QtWidgets.QTableWidgetItem(dict_license.get("License", ""))
|
||||
tb_item_license.setToolTip(tb_item_license.text())
|
||||
tb_item_license.setData(QtCore.Qt.UserRole, i)
|
||||
|
||||
self.tb_oss_licenses.insertRow(i)
|
||||
self.tb_oss_licenses.setItem(i, 0, tb_item_name)
|
||||
self.tb_oss_licenses.setItem(i, 1, tb_item_license)
|
||||
|
||||
self.tb_oss_licenses.resizeColumnsToContents()
|
||||
|
||||
def exec(self) -> int:
|
||||
# Prevent loading every time the program is starting
|
||||
if not self._lst_licenses:
|
||||
self._load_license_file()
|
||||
|
||||
return super().exec()
|
||||
|
||||
@QtCore.pyqtSlot(QtWidgets.QTableWidgetItem, QtWidgets.QTableWidgetItem)
|
||||
def on_tb_oss_licenses_currentItemChanged(
|
||||
self,
|
||||
current: QtWidgets.QTableWidgetItem,
|
||||
previous: QtWidgets.QTableWidgetItem,
|
||||
):
|
||||
log.debug("Enter slot on_tb_oss_licenses_currentItemChanged")
|
||||
license_index = current.data(QtCore.Qt.UserRole)
|
||||
license_object = self._lst_licenses[license_index]
|
||||
license_object["LicenseText"] = license_object["LicenseText"].replace("\n", "<br>")
|
||||
self.txt_license.setHtml(
|
||||
"""<h2>{Name}</h2>
|
||||
<p>{Description}</p>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Version: {Version}</li>
|
||||
<li>Author: {Author}</li>
|
||||
<li>URL: <a href="{URL}">{URL}</a></li>
|
||||
</ul>
|
||||
</p>
|
||||
<h3>License: {License}</h3>
|
||||
<p>
|
||||
<code>{LicenseText}</code>
|
||||
</p>""".format(
|
||||
**license_object
|
||||
)
|
||||
)
|
||||
@@ -12,6 +12,7 @@ from os.path import dirname, join
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from revpicommander.oss_licenses import OssLicenses
|
||||
from . import __version__
|
||||
from . import helper
|
||||
from . import proginit as pi
|
||||
@@ -90,6 +91,10 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
|
||||
|
||||
self.setWindowFlag(QtCore.Qt.WindowMaximizeButtonHint, False)
|
||||
|
||||
# Load oss licenses dialog, to show licenses, if this is build with app target
|
||||
self.diag_oss_licenses = OssLicenses(pi.open_source_licenses[:-3] + "json", self)
|
||||
self.men_help.addAction(self.diag_oss_licenses.action_start)
|
||||
|
||||
pi.startup_complete()
|
||||
|
||||
def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
|
||||
|
||||
79
src/revpicommander/ui/oss_licenses_ui.py
Normal file
79
src/revpicommander/ui/oss_licenses_ui.py
Normal file
@@ -0,0 +1,79 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'oss_licenses.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_diag_oss_licenses(object):
|
||||
def setupUi(self, diag_oss_licenses):
|
||||
diag_oss_licenses.setObjectName("diag_oss_licenses")
|
||||
diag_oss_licenses.resize(640, 480)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(diag_oss_licenses)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.splitter = QtWidgets.QSplitter(diag_oss_licenses)
|
||||
self.splitter.setOrientation(QtCore.Qt.Vertical)
|
||||
self.splitter.setChildrenCollapsible(False)
|
||||
self.splitter.setObjectName("splitter")
|
||||
self.tb_oss_licenses = QtWidgets.QTableWidget(self.splitter)
|
||||
self.tb_oss_licenses.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||
self.tb_oss_licenses.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
|
||||
self.tb_oss_licenses.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
self.tb_oss_licenses.setCornerButtonEnabled(False)
|
||||
self.tb_oss_licenses.setObjectName("tb_oss_licenses")
|
||||
self.tb_oss_licenses.setColumnCount(2)
|
||||
self.tb_oss_licenses.setRowCount(0)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
self.tb_oss_licenses.setHorizontalHeaderItem(0, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
self.tb_oss_licenses.setHorizontalHeaderItem(1, item)
|
||||
self.tb_oss_licenses.horizontalHeader().setSortIndicatorShown(True)
|
||||
self.tb_oss_licenses.horizontalHeader().setStretchLastSection(True)
|
||||
self.tb_oss_licenses.verticalHeader().setVisible(False)
|
||||
self.txt_license = QtWidgets.QTextEdit(self.splitter)
|
||||
self.txt_license.setTabChangesFocus(True)
|
||||
self.txt_license.setUndoRedoEnabled(False)
|
||||
self.txt_license.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
|
||||
self.txt_license.setReadOnly(True)
|
||||
self.txt_license.setObjectName("txt_license")
|
||||
self.verticalLayout.addWidget(self.splitter)
|
||||
self.btn_box = QtWidgets.QDialogButtonBox(diag_oss_licenses)
|
||||
self.btn_box.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.btn_box.setStandardButtons(QtWidgets.QDialogButtonBox.Close)
|
||||
self.btn_box.setObjectName("btn_box")
|
||||
self.verticalLayout.addWidget(self.btn_box)
|
||||
self.action_start = QtWidgets.QAction(diag_oss_licenses)
|
||||
self.action_start.setObjectName("action_start")
|
||||
|
||||
self.retranslateUi(diag_oss_licenses)
|
||||
self.btn_box.accepted.connect(diag_oss_licenses.accept) # type: ignore
|
||||
self.btn_box.rejected.connect(diag_oss_licenses.reject) # type: ignore
|
||||
self.action_start.triggered.connect(diag_oss_licenses.exec) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(diag_oss_licenses)
|
||||
|
||||
def retranslateUi(self, diag_oss_licenses):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
diag_oss_licenses.setWindowTitle(_translate("diag_oss_licenses", "Open-Source licenses"))
|
||||
self.tb_oss_licenses.setSortingEnabled(True)
|
||||
item = self.tb_oss_licenses.horizontalHeaderItem(0)
|
||||
item.setText(_translate("diag_oss_licenses", "Software"))
|
||||
item = self.tb_oss_licenses.horizontalHeaderItem(1)
|
||||
item.setText(_translate("diag_oss_licenses", "License"))
|
||||
self.action_start.setText(_translate("diag_oss_licenses", "More licenses..."))
|
||||
self.action_start.setToolTip(_translate("diag_oss_licenses", "Show more open-source software licenses"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
diag_oss_licenses = QtWidgets.QDialog()
|
||||
ui = Ui_diag_oss_licenses()
|
||||
ui.setupUi(diag_oss_licenses)
|
||||
diag_oss_licenses.show()
|
||||
sys.exit(app.exec_())
|
||||
@@ -21,6 +21,7 @@ FORMS = ui_dev/aclmanager.ui \
|
||||
ui_dev/debugios.ui \
|
||||
ui_dev/files.ui \
|
||||
ui_dev/mqttmanager.ui \
|
||||
ui_dev/oss_licenses.ui \
|
||||
ui_dev/revpiinfo.ui \
|
||||
ui_dev/revpilogfile.ui \
|
||||
ui_dev/revpioption.ui \
|
||||
|
||||
148
ui_dev/oss_licenses.ui
Normal file
148
ui_dev/oss_licenses.ui
Normal file
@@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>diag_oss_licenses</class>
|
||||
<widget class="QDialog" name="diag_oss_licenses">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>640</width>
|
||||
<height>480</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Open-Source licenses</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QTableWidget" name="tb_oss_licenses">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="cornerButtonEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Software</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>License</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="txt_license">
|
||||
<property name="tabChangesFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="undoRedoEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="lineWrapMode">
|
||||
<enum>QTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="btn_box">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="action_start">
|
||||
<property name="text">
|
||||
<string>More licenses...</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show more open-source software licenses</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>btn_box</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>diag_oss_licenses</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>btn_box</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>diag_oss_licenses</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>action_start</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>diag_oss_licenses</receiver>
|
||||
<slot>exec()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>267</x>
|
||||
<y>237</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user