Addon Manager: Refactor global button bar

This commit is contained in:
Chris Hennes
2024-02-04 14:48:04 -06:00
parent f44098172b
commit 418ccc870f
4 changed files with 141 additions and 125 deletions

View File

@@ -53,6 +53,7 @@ import addonmanager_utilities as utils
import AddonManager_rc # This is required by Qt, it's not unused
from package_list import PackageList, PackageListItemModel
from package_details import PackageDetails
from Widgets.addonmanager_widget_global_buttons import WidgetGlobalButtonBar
from Addon import Addon
from manage_python_dependencies import (
PythonPackageManager,
@@ -130,6 +131,7 @@ class CommandAddonManager:
self.update_all_worker = None
self.developer_mode = None
self.installer_gui = None
self.button_bar = None
self.update_cache = False
self.dialog = None
@@ -185,21 +187,21 @@ class CommandAddonManager:
w = pref.GetInt("WindowWidth", 800)
h = pref.GetInt("WindowHeight", 600)
self.dialog.resize(w, h)
self.button_bar = WidgetGlobalButtonBar(self.dialog)
# If we are checking for updates automatically, hide the Check for updates button:
autocheck = pref.GetBool("AutoCheck", False)
if autocheck:
self.dialog.buttonCheckForUpdates.hide()
self.button_bar.check_for_updates.hide()
else:
self.dialog.buttonUpdateAll.hide()
self.button_bar.update_all_addons.hide()
# Set up the listing of packages using the model-view-controller architecture
self.packageList = PackageList(self.dialog)
self.item_model = PackageListItemModel()
self.packageList.setModel(self.item_model)
self.dialog.contentPlaceholder.hide()
self.dialog.layout().replaceWidget(self.dialog.contentPlaceholder, self.packageList)
self.packageList.show()
self.dialog.layout().addWidget(self.packageList)
self.dialog.layout().addWidget(self.button_bar)
# Package details start out hidden
self.packageDetails = PackageDetails(self.dialog)
@@ -209,35 +211,30 @@ class CommandAddonManager:
# set nice icons to everything, by theme with fallback to FreeCAD icons
self.dialog.setWindowIcon(QtGui.QIcon(":/icons/AddonManager.svg"))
self.dialog.buttonUpdateAll.setIcon(QtGui.QIcon(":/icons/button_valid.svg"))
self.dialog.buttonCheckForUpdates.setIcon(QtGui.QIcon(":/icons/view-refresh.svg"))
self.dialog.buttonClose.setIcon(
QtGui.QIcon.fromTheme("close", QtGui.QIcon(":/icons/process-stop.svg"))
)
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons")
dev_mode_active = pref.GetBool("developerMode", False)
# enable/disable stuff
self.dialog.buttonUpdateAll.setEnabled(False)
self.button_bar.update_all_addons.setEnabled(False)
self.hide_progress_widgets()
self.dialog.buttonUpdateCache.setEnabled(False)
self.dialog.buttonUpdateCache.setText(translate("AddonsInstaller", "Starting up..."))
self.button_bar.refresh_local_cache.setEnabled(False)
self.button_bar.refresh_local_cache.setText(translate("AddonsInstaller", "Starting up..."))
if dev_mode_active:
self.dialog.buttonDevTools.show()
self.button_bar.developer_tools.show()
else:
self.dialog.buttonDevTools.hide()
self.button_bar.developer_tools.hide()
# connect slots
self.dialog.rejected.connect(self.reject)
self.dialog.buttonUpdateAll.clicked.connect(self.update_all)
self.dialog.buttonClose.clicked.connect(self.dialog.reject)
self.dialog.buttonUpdateCache.clicked.connect(self.on_buttonUpdateCache_clicked)
self.dialog.buttonCheckForUpdates.clicked.connect(
self.button_bar.update_all_addons.clicked.connect(self.update_all)
self.button_bar.close.clicked.connect(self.dialog.reject)
self.button_bar.refresh_local_cache.clicked.connect(self.on_buttonUpdateCache_clicked)
self.button_bar.check_for_updates.clicked.connect(
lambda: self.force_check_updates(standalone=True)
)
self.dialog.buttonUpdateDependencies.clicked.connect(self.show_python_updates_dialog)
self.dialog.buttonDevTools.clicked.connect(self.show_developer_tools)
self.button_bar.python_dependencies.clicked.connect(self.show_python_updates_dialog)
self.button_bar.developer_tools.clicked.connect(self.show_developer_tools)
self.packageList.ui.progressBar.stop_clicked.connect(self.stop_update)
self.packageList.itemSelected.connect(self.table_row_activated)
self.packageList.setEnabled(False)
@@ -415,8 +412,8 @@ class CommandAddonManager:
else:
self.hide_progress_widgets()
self.update_cache = False
self.dialog.buttonUpdateCache.setEnabled(True)
self.dialog.buttonUpdateCache.setText(
self.button_bar.refresh_local_cache.setEnabled(True)
self.button_bar.refresh_local_cache.setText(
translate("AddonsInstaller", "Refresh local cache")
)
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons")
@@ -545,8 +542,10 @@ class CommandAddonManager:
cache_path = FreeCAD.getUserCachePath()
am_path = os.path.join(cache_path, "AddonManager")
utils.rmdir(am_path)
self.dialog.buttonUpdateCache.setEnabled(False)
self.dialog.buttonUpdateCache.setText(translate("AddonsInstaller", "Updating cache..."))
self.button_bar.refresh_local_cache.setEnabled(False)
self.button_bar.refresh_local_cache.setText(
translate("AddonsInstaller", "Updating cache...")
)
self.startup()
# Recaching implies checking for updates, regardless of the user's autocheck option
@@ -608,10 +607,12 @@ class CommandAddonManager:
self.do_next_startup_phase()
return
self.dialog.buttonUpdateAll.setText(translate("AddonsInstaller", "Checking for updates..."))
self.button_bar.update_all_addons.setText(
translate("AddonsInstaller", "Checking for updates...")
)
self.packages_with_updates.clear()
self.dialog.buttonUpdateAll.show()
self.dialog.buttonCheckForUpdates.setDisabled(True)
self.button_bar.update_all_addons.show()
self.button_bar.check_for_updates.setDisabled(True)
self.check_worker = CheckWorkbenchesForUpdatesWorker(self.item_model.repos)
self.check_worker.finished.connect(self.do_next_startup_phase)
self.check_worker.finished.connect(self.update_check_complete)
@@ -636,21 +637,21 @@ class CommandAddonManager:
if number_of_updates:
s = translate("AddonsInstaller", "Apply {} update(s)", "", number_of_updates)
self.dialog.buttonUpdateAll.setText(s.format(number_of_updates))
self.dialog.buttonUpdateAll.setEnabled(True)
self.button_bar.update_all_addons.setText(s.format(number_of_updates))
self.button_bar.update_all_addons.setEnabled(True)
elif hasattr(self, "check_worker") and self.check_worker.isRunning():
self.dialog.buttonUpdateAll.setText(
self.button_bar.update_all_addons.setText(
translate("AddonsInstaller", "Checking for updates...")
)
else:
self.dialog.buttonUpdateAll.setText(
self.button_bar.update_all_addons.setText(
translate("AddonsInstaller", "No updates available")
)
self.dialog.buttonUpdateAll.setEnabled(False)
self.button_bar.update_all_addons.setEnabled(False)
def update_check_complete(self) -> None:
self.enable_updates(len(self.packages_with_updates))
self.dialog.buttonCheckForUpdates.setEnabled(True)
self.button_bar.check_for_updates.setEnabled(True)
def check_python_updates(self) -> None:
PythonPackageManager.migrate_old_am_installations() # Migrate 0.20 to 0.21
@@ -846,8 +847,10 @@ class CommandAddonManager:
self.cleanup_workers()
self.hide_progress_widgets()
self.write_cache_stopfile()
self.dialog.buttonUpdateCache.setEnabled(True)
self.dialog.buttonUpdateCache.setText(translate("AddonsInstaller", "Refresh local cache"))
self.button_bar.refresh_local_cache.setEnabled(True)
self.button_bar.refresh_local_cache.setText(
translate("AddonsInstaller", "Refresh local cache")
)
def write_cache_stopfile(self) -> None:
stopfile = utils.get_cache_file_name("CACHE_UPDATE_INTERRUPTED")

View File

@@ -13,95 +13,7 @@
<property name="windowTitle">
<string>Addon Manager</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QWidget" name="contentPlaceholder" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QPushButton" name="buttonUpdateCache">
<property name="text">
<string>Refresh local cache</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonUpdateAll">
<property name="toolTip">
<string>Download and apply all available updates</string>
</property>
<property name="text">
<string>Update all Addons</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonCheckForUpdates">
<property name="text">
<string>Check for updates</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonUpdateDependencies">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>View and update Python package dependencies</string>
</property>
<property name="text">
<string>Python dependencies...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonDevTools">
<property name="text">
<string>Developer tools...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonClose">
<property name="toolTip">
<string>Close the Addon Manager</string>
</property>
<property name="text">
<string>Close</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
<layout class="QVBoxLayout" name="verticalLayout_4"/>
</widget>
<resources/>
<connections/>

View File

@@ -1,6 +1,7 @@
SET(AddonManagerWidget_SRCS
__init__.py
addonmanager_widget_filter_selector.py
addonmanager_widget_global_buttons.py
addonmanager_widget_progress_bar.py
addonmanager_widget_search.py
addonmanager_widget_view_control_bar.py

View File

@@ -0,0 +1,100 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * *
# * Copyright (c) 2024 FreeCAD Project Association *
# * *
# * This file is part of FreeCAD. *
# * *
# * FreeCAD is free software: you can redistribute it and/or modify it *
# * under the terms of the GNU Lesser General Public License as *
# * published by the Free Software Foundation, either version 2.1 of the *
# * License, or (at your option) any later version. *
# * *
# * FreeCAD is distributed in the hope that it will be useful, but *
# * WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
# * Lesser General Public License for more details. *
# * *
# * You should have received a copy of the GNU Lesser General Public *
# * License along with FreeCAD. If not, see *
# * <https://www.gnu.org/licenses/>. *
# * *
# ***************************************************************************
""" Defines a QWidget-derived class for displaying a set of buttons that affect the Addon
Manager as a whole (rather than a specific Addon). Typically inserted at the bottom of the Addon
Manager main window. """
try:
import FreeCAD
translate = FreeCAD.Qt.translate
except ImportError:
FreeCAD = None
def translate(_: str, text: str):
return text
# Get whatever version of PySide we can
try:
import PySide # Use the FreeCAD wrapper
except ImportError:
try:
import PySide6 # Outside FreeCAD, try Qt6 first
PySide = PySide6
except ImportError:
import PySide2 # Fall back to Qt5 (if this fails, Python will kill this module's import)
PySide = PySide2
from PySide import QtGui, QtWidgets
class WidgetGlobalButtonBar(QtWidgets.QWidget):
"""A QWidget-derived class for displaying a set of buttons that affect the Addon Manager as a
whole (rather than a specific Addon)."""
def __init__(self, parent: QtWidgets.QWidget = None):
super().__init__(parent)
self.horizontal_layout = None
self.refresh_local_cache = None
self.update_all_addons = None
self.check_for_updates = None
self.python_dependencies = None
self.developer_tools = None
self.close = None
self._update_ui()
self.retranslateUi(None)
self._set_icons()
def _update_ui(self):
self.horizontal_layout = QtWidgets.QHBoxLayout()
self.refresh_local_cache = QtWidgets.QPushButton(self)
self.update_all_addons = QtWidgets.QPushButton(self)
self.check_for_updates = QtWidgets.QPushButton(self)
self.python_dependencies = QtWidgets.QPushButton(self)
self.developer_tools = QtWidgets.QPushButton(self)
self.close = QtWidgets.QPushButton(self)
self.horizontal_layout.addWidget(self.refresh_local_cache)
self.horizontal_layout.addWidget(self.update_all_addons)
self.horizontal_layout.addWidget(self.check_for_updates)
self.horizontal_layout.addWidget(self.python_dependencies)
self.horizontal_layout.addWidget(self.developer_tools)
self.horizontal_layout.addStretch()
self.horizontal_layout.addWidget(self.close)
self.setLayout(self.horizontal_layout)
def _set_icons(self):
self.update_all_addons.setIcon(QtGui.QIcon(":/icons/button_valid.svg"))
self.check_for_updates.setIcon(QtGui.QIcon(":/icons/view-refresh.svg"))
self.close.setIcon(QtGui.QIcon.fromTheme("close", QtGui.QIcon(":/icons/process-stop.svg")))
def retranslateUi(self, _):
self.refresh_local_cache.setText(translate("AddonsInstaller", "Close"))
self.update_all_addons.setText(translate("AddonsInstaller", "Update all addons"))
self.check_for_updates.setText(translate("AddonsInstaller", "Check for updates"))
self.python_dependencies.setText(translate("AddonsInstaller", "Python dependencies..."))
self.developer_tools.setText(translate("AddonsInstaller", "Developer tools..."))
self.close.setText(translate("AddonsInstaller", "Close"))