Addon Manager: Refactor progress bar
This commit is contained in:
@@ -214,9 +214,6 @@ class CommandAddonManager:
|
||||
self.dialog.buttonClose.setIcon(
|
||||
QtGui.QIcon.fromTheme("close", QtGui.QIcon(":/icons/process-stop.svg"))
|
||||
)
|
||||
self.dialog.buttonPauseUpdate.setIcon(
|
||||
QtGui.QIcon.fromTheme("pause", QtGui.QIcon(":/icons/media-playback-stop.svg"))
|
||||
)
|
||||
|
||||
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons")
|
||||
dev_mode_active = pref.GetBool("developerMode", False)
|
||||
@@ -236,12 +233,12 @@ class CommandAddonManager:
|
||||
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.buttonPauseUpdate.clicked.connect(self.stop_update)
|
||||
self.dialog.buttonCheckForUpdates.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.packageList.ui.progressBar.stop_clicked.connect(self.stop_update)
|
||||
self.packageList.itemSelected.connect(self.table_row_activated)
|
||||
self.packageList.setEnabled(False)
|
||||
self.packageDetails.execute.connect(self.executemacro)
|
||||
@@ -257,9 +254,6 @@ class CommandAddonManager:
|
||||
mw.frameGeometry().topLeft() + mw.rect().center() - self.dialog.rect().center()
|
||||
)
|
||||
|
||||
# set info for the progress bar:
|
||||
self.dialog.progressBar.setMaximum(1000)
|
||||
|
||||
# begin populating the table in a set of sub-threads
|
||||
self.startup()
|
||||
|
||||
@@ -407,8 +401,8 @@ class CommandAddonManager:
|
||||
if selection:
|
||||
self.startup_sequence.insert(2, functools.partial(self.select_addon, selection))
|
||||
pref.SetString("SelectedAddon", "")
|
||||
self.current_progress_region = 0
|
||||
self.number_of_progress_regions = len(self.startup_sequence)
|
||||
self.current_progress_region = 0
|
||||
self.do_next_startup_phase()
|
||||
|
||||
def do_next_startup_phase(self) -> None:
|
||||
@@ -750,8 +744,8 @@ class CommandAddonManager:
|
||||
def show_information(self, message: str) -> None:
|
||||
"""shows generic text in the information pane"""
|
||||
|
||||
self.dialog.labelStatusInfo.setText(message)
|
||||
self.dialog.labelStatusInfo.repaint()
|
||||
self.packageList.ui.progressBar.set_status(message)
|
||||
self.packageList.ui.progressBar.repaint()
|
||||
|
||||
def show_workbench(self, repo: Addon) -> None:
|
||||
self.packageList.hide()
|
||||
@@ -821,16 +815,12 @@ class CommandAddonManager:
|
||||
def hide_progress_widgets(self) -> None:
|
||||
"""hides the progress bar and related widgets"""
|
||||
|
||||
self.dialog.labelStatusInfo.hide()
|
||||
self.dialog.progressBar.hide()
|
||||
self.dialog.buttonPauseUpdate.hide()
|
||||
self.packageList.ui.progressBar.hide()
|
||||
self.packageList.ui.view_bar.search.setFocus()
|
||||
|
||||
def show_progress_widgets(self) -> None:
|
||||
if self.dialog.progressBar.isHidden():
|
||||
self.dialog.progressBar.show()
|
||||
self.dialog.buttonPauseUpdate.show()
|
||||
self.dialog.labelStatusInfo.show()
|
||||
if self.packageList.ui.progressBar.isHidden():
|
||||
self.packageList.ui.progressBar.show()
|
||||
|
||||
def update_progress_bar(self, current_value: int, max_value: int) -> None:
|
||||
"""Update the progress bar, showing it if it's hidden"""
|
||||
@@ -847,10 +837,10 @@ class CommandAddonManager:
|
||||
completed_region_portion = (self.current_progress_region - 1) * region_size
|
||||
current_region_portion = (float(current_value) / float(max_value)) * region_size
|
||||
value = completed_region_portion + current_region_portion
|
||||
self.dialog.progressBar.setValue(
|
||||
self.packageList.ui.progressBar.set_value(
|
||||
value * 10
|
||||
) # Out of 1000 segments, so it moves sort of smoothly
|
||||
self.dialog.progressBar.repaint()
|
||||
self.packageList.ui.progressBar.repaint()
|
||||
|
||||
def stop_update(self) -> None:
|
||||
self.cleanup_workers()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<width>928</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -24,74 +24,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="layoutUpdateInProgress">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>12</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>Downloading info...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonPauseUpdate">
|
||||
<property name="toolTip">
|
||||
<string>Stop the cache update</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelStatusInfo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">labelStatusInfo</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizeConstraint">
|
||||
|
||||
14
src/Mod/AddonManager/TODO.md
Normal file
14
src/Mod/AddonManager/TODO.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Addon Manager Future Work
|
||||
|
||||
* Restructure widgets into logical groups to better enable showing and hiding those groups all at once.
|
||||
* Reduce coupling between data and UI, switching logical groupings of widgets into a MVC or similar framework.
|
||||
* Particularly in the addons list
|
||||
* Download Addon statistics from central location.
|
||||
* Allow sorting on those statistics.
|
||||
* Download a "rank" from user-specified locations.
|
||||
* Allow sorting on that rank.
|
||||
* Implement a server-side cache of Addon metadata.
|
||||
* Implement an "offline mode" that does not attempt to use remote data for anything.
|
||||
* When installing a Preference Pack, offer to apply it once installed, and to undo after that.
|
||||
* Better support "headless" mode, with no GUI.
|
||||
* Add "Composite" display mode, showing compact list and details at the same time
|
||||
@@ -1,6 +1,7 @@
|
||||
SET(AddonManagerWidget_SRCS
|
||||
__init__.py
|
||||
addonmanager_widget_filter_selector.py
|
||||
addonmanager_widget_progress_bar.py
|
||||
addonmanager_widget_search.py
|
||||
addonmanager_widget_view_control_bar.py
|
||||
addonmanager_widget_view_selector.py
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2022-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 the cache load status. """
|
||||
|
||||
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 QtCore, QtGui, QtWidgets
|
||||
|
||||
_TOTAL_INCREMENTS = 1000
|
||||
|
||||
|
||||
class WidgetProgressBar(QtWidgets.QWidget):
|
||||
|
||||
"""A multipart progress bar widget, including a stop button and a status label. Defaults to a
|
||||
single range with 100 increments, but can be configured with any number of major and minor
|
||||
ranges. Clicking the stop button will emit a signal, but does not otherwise affect the
|
||||
widget."""
|
||||
|
||||
stop_clicked = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent: QtWidgets.QWidget = None):
|
||||
super().__init__(parent)
|
||||
self.vertical_layout = None
|
||||
self.horizontal_layout = None
|
||||
self.progress_bar = None
|
||||
self.status_label = None
|
||||
self.stop_button = None
|
||||
self._setup_ui()
|
||||
|
||||
def _setup_ui(self):
|
||||
self.vertical_layout = QtWidgets.QVBoxLayout(self)
|
||||
self.horizontal_layout = QtWidgets.QHBoxLayout(self)
|
||||
self.progress_bar = QtWidgets.QProgressBar(self)
|
||||
self.status_label = QtWidgets.QLabel(self)
|
||||
self.stop_button = QtWidgets.QToolButton(self)
|
||||
self.progress_bar.setMaximum(_TOTAL_INCREMENTS)
|
||||
self.stop_button.clicked.connect(self.stop_clicked)
|
||||
self.stop_button.setIcon(
|
||||
QtGui.QIcon.fromTheme("stop", QtGui.QIcon(":/icons/media-playback-stop.svg"))
|
||||
)
|
||||
self.vertical_layout.addLayout(self.horizontal_layout)
|
||||
self.vertical_layout.addWidget(self.status_label)
|
||||
self.horizontal_layout.addWidget(self.progress_bar)
|
||||
self.horizontal_layout.addWidget(self.stop_button)
|
||||
self.setLayout(self.vertical_layout)
|
||||
|
||||
def set_status(self, status: str):
|
||||
self.status_label.setText(status)
|
||||
|
||||
def set_value(self, value: int):
|
||||
self.progress_bar.setValue(value)
|
||||
@@ -40,6 +40,7 @@ from addonmanager_metadata import get_first_supported_freecad_version, Version
|
||||
from Widgets.addonmanager_widget_view_control_bar import WidgetViewControlBar
|
||||
from Widgets.addonmanager_widget_view_selector import AddonManagerDisplayStyle
|
||||
from Widgets.addonmanager_widget_filter_selector import StatusFilter, Filter, ContentFilter
|
||||
from Widgets.addonmanager_widget_progress_bar import WidgetProgressBar
|
||||
from addonmanager_licenses import get_license_manager, SPDXLicenseManager
|
||||
|
||||
translate = FreeCAD.Qt.translate
|
||||
@@ -643,4 +644,7 @@ class Ui_PackageList:
|
||||
|
||||
self.verticalLayout.addWidget(self.listPackages)
|
||||
|
||||
self.progressBar = WidgetProgressBar()
|
||||
self.verticalLayout.addWidget(self.progressBar)
|
||||
|
||||
QtCore.QMetaObject.connectSlotsByName(form)
|
||||
|
||||
Reference in New Issue
Block a user